[package] name = "flowrs-connect" version.workspace = true edition.workspace = true publish.workspace = true rust-version.workspace = true authors.workspace = true license.workspace = true description = "Config-driven resources + integration endpoints for FlowRS: declare components (model + connection) and MQTT/HTTP endpoints as data — the Viam / ESPHome / Node-RED idea, swap a sensor in config and the graph keeps working." [lib] crate-type = ["rlib"] [dependencies] # The one implementation of sin, exp, ln, atan2, powf and the rest, the same bits in the # browser and in a generated program (crates/flowrs-math). flowrs-math = { path = "../flowrs-math" } serde = { workspace = true } thiserror = { workspace = true } serde_json = { workspace = true } # Resolve a component's `model` to a generated driver from the driver registry — # the "config → running resources" step (Viam's viam-server pulling drivers). flowrs-drivers = { path = "../flowrs-drivers" } # The ROS 2 edge (src/ros2.rs): message types, their RIHS01 hashes and the units their # definitions state come from the hashed interface model's embedded Lyrical catalog... flowrs-iface = { path = "../flowrs-iface" } # ...and messages are encoded by flowRS's one CDR codec, the one MCAP recordings use # (flowrs_capture::mcap::cdr), so what a generated node publishes is what flowRS records. flowrs-capture = { path = "../flowrs-capture" } # The MAVLink bridge (src/mavlink.rs, feature `mavlink`): frames are decoded, encoded and # signed (MAVLink 2 signing) by the `mavlink` crate (MIT OR Apache-2.0), generated from the # MIT message definitions it bundles; flowRS reads the same XML (dialects/mavlink) for what # each field means. mavgen and pymavlink (LGPLv3) are never linked. Pinned: the vendored XML # is the copy this exact release compiles. No transport features (the bridge owns its # sockets, so a frame the crate would drop on a checksum mismatch is seen and reported); # extension fields kept (`mav2-message-extensions`), serde for reading a decoded message's # fields by name. mavlink = { version = "=0.21.0", optional = true, default-features = false, features = ["std", "serde", "dialect-ardupilotmega", "mav2-message-signing", "mav2-message-extensions"] } # SHA-256 for the pure-Rust MAVLink peer's own signing check (independent of the crate's) # and for the hash an approval binds a command to. Already in the lock (flowrs-iface). sha2 = { version = "0.11", optional = true } # A MAVLink command that moves the vehicle is sent only under an approval taken from a # proposal the safety envelope claimed for execution (flowrs_instruments::proposal). flowrs-instruments = { path = "../flowrs-instruments", optional = true } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] reqwest = { version = "0.13.4", optional = true } # The provider an https endpoint's TLS runs on: aws-lc-rs with X25519MLKEM768 offered first, # installed as the process default before the client is built (reqwest reads it from there). flowrs-tls = { path = "../flowrs-tls", optional = true } # No TLS feature: `Endpoint::Mqtt` has no TLS field and `MqttSink::connect` uses # rumqttc's default plain-TCP transport, so the default `use-rustls` only pulled in # rustls-webpki 0.102 (RUSTSEC-2026-0049/0098/0099/0104) and rustls-pemfile # (unmaintained) for code nothing called. When an mqtts endpoint lands, enable # `use-native-tls` (or a rumqttc whose rustls stack is current) together with it. # The scaffold already emits `default-features = false` for generated projects. rumqttc = { version = "0.25.1", optional = true, default-features = false } tokio = { version = "1.52.3", features = ["rt", "net", "time", "macros"], optional = true } # The ROS 2 runtime a generated node runs on (src/ros2/rt.rs): Atostek's pure-Rust client on # RustDDS (Apache-2.0), so a node builds and runs with no ROS install. Pinned: the generated # node's Cargo.toml pins the same version and picks the ROS distribution feature (humble, # jazzy, kilted, lyrical) itself, so none is chosen here. Never Connext; Cyclone DDS # (EPL/EDL) appears only in the interop test environments, never linked. ros2-client = { version = "=0.11.1", optional = true, default-features = false, features = ["dds"] } # RustDDS's and ros2-client's own diagnostics, printed when FLOWROS_LOG asks (ros2::rt). log = { version = "0.4", optional = true } # The event a RustDDS data reader raises when a sample arrives (its `mio_06::Evented`): a # subscription waits on it instead of sleeping between polls. The same mio 0.6 RustDDS 0.14 # itself runs on, so nothing new enters the lockfile. mio = { version = "0.6.23", optional = true } # The CAN edge's runtime (src/can/rt.rs): frames from SocketCAN or the virtual bus # (flowrs-device, without its instrument transports) in flowrs-hal's frame type. flowrs-device = { path = "../flowrs-device", default-features = false, optional = true } flowrs-hal = { path = "../flowrs-hal", optional = true } [features] default = [] # Live endpoint I/O: actually connect the MQTT / HTTP endpoints a Config declares. # Native-only and off by default — the base crate stays pure-serde and wasm-clean, # so the browser build never pulls a network stack. live = ["dep:rumqttc", "dep:reqwest", "dep:tokio", "dep:flowrs-tls"] # The runtime of the generated ROS 2 nodes (ros2::rt): native only, off by default, so the # browser build and every crate that does not run a node never compile a DDS stack. ros2 = ["dep:ros2-client", "dep:log", "dep:mio"] # MAVLink's model (mavlink, without the runtime): the dialects, the connect-time dialect # check, unit conversion, the approval gate, command and setpoint building, the frame codec # and the generated bridge's planning. Pure Rust, no `mavlink` crate, so the editor (wasm) # validates mavlink.* nodes, states their ports' units and shows what a command would send. mavlink-model = ["dep:sha2", "dep:flowrs-instruments"] # The MAVLink bridge: the model, the runtime the generated bridge and the mavlink.* graph # nodes run on (over the `mavlink` crate), and a pure-Rust vehicle peer built from the same # XML. Native only, off by default: the browser build never compiles it. mavlink = ["mavlink-model", "dep:mavlink"] # The runtime of the generated CAN nodes (can::rt): DBC signals off a CAN bus as typed ROS 2 # messages. Native only, off by default. can-ros = ["ros2", "dep:flowrs-device", "dep:flowrs-hal"] [dev-dependencies] # Connect a config's endpoints and publish — needs the native `live` stack. [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] }