This Rust IoT project began its life as a 5-day MVP with a team of 3 developers.
This fork takes that initial work and builds on it significantly.
Run the local demo with
cargo run --bin demoRun the demo with STDOUT logs (at "error", "warn", "info", "debug", or "trace" level)
RUST_LOG=info cargo run --bin demoCreate the required Docker container images with
docker build -t environment -f environment.Dockerfile . &&
docker build -t actuator_temperature -f actuator_temperature.Dockerfile . &&
docker build -t sensor_temperature -f sensor_temperature.Dockerfile . &&
docker build -t controller -f controller.Dockerfile ....and run the containers with
docker run -d -p 5454:5454 environment &&
docker run -d -p 9898:9898 actuator_temperature &&
docker run -d -p 8787:8787 sensor_temperature &&
docker run -d -p 6565:6565 controllerThen, test it out! Ask the environment for a Datum with...
curl localhost:5454/datum/example-id --header "kind: float" --header "unit: °C"
# {"value":"0.21278754","unit":"°C","timestamp":"2024-01-05T16:07:33.108909834+00:00"}...or send a command to an actuator with...
curl -v localhost:9898/command -d '{"name":"HeatBy","value":"25"}'
# HTTP/1.1 200 OK...or query a sensor for its latest Datum with...
curl localhost:8787/datum
# [{"value":"-1.8094378","unit":"°C","timestamp":"2024-01-05T17:05:30.272467221+00:00"}]...or get the latest Datum from every sensor by querying the environment
curl localhost:6565/datum
# [{"id":"thermo-5000","datum":[{"value":"28.747364","unit":"°C","timestamp":"2024-01-05T17:14:39.963327462+00:00"}]}]Don't forget to check out the Web UI at http://localhost:6565/ui, as well.
rust-mvp is nearly dependency-free, it requires only a few crates beyond the standard library, and one JavaScript dependency
mdns-sdfor mDNS networkingchronofor UTC timestamps and timestamp de/serializationrandfor random number generationlocal-ip-addressfor local IP address discoveryphffor compile-time staticMapslogtherust-langofficial logging frameworkenv_loggera minimal logging implementationplotlyfor graphing data in the Web UI
This Cargo workspace project contains a few crates. Each crate has a simple name which aligns with the ubiquitous language used throughout this repository.
This is a library crate (no main.rs file) which defines the basic interface and the communication layer for an IoT sensor running as a standalone device (at its own IP address). It is possible in this demo to define multiple sensors.
A sensor gathers information from the environment and provides it to the controller when requested.
Concrete (demo) implementations of sensors are held in directories with names starting with sensor_. Those crates are binary crates which can be containerized and run on a container runtime like Docker.
This is another library crate which defines the basic interface and the communication layer for an IoT actuator running as a standalone device. It is possible in this demo to define multiple actuators. In this demo, each sensor is paired with exactly one actuator.
An actuator receives commands from the controller and can affect the environment.
Concrete (demo) implementations of actuators are held in directories with names starting with actuator_. Those crates are binary crates which can be containerized and run on a container runtime like Docker.
This is a library crate holding logic common to any mDNS device on the network.
This is a binary crate which provides a concrete implementation of a controller, including all of its domain and communication logic. In this demo, there is only a single controller, which acts as the "hub" in this IoT system.
The controller collects data from one or more sensors, analyzes that data, and sends commands to one or more actuators.
In this demo, we use mDNS to connect the controller to the sensors and actuators; they are automatically detected as they join the network. We also use a pull mechanism wherein the controller queries the sensors for data (rather than the sensors pushing data to the controller) ; this allows for backpressure and ensures the controller is never overwhelmed by requests or data.
The controller crate can be containerized and run on a container runtime like Docker.
This is a demo-only binary crate which acts as a mock environment for our IoT system. It contains information about the current state of the system, which may include mock temperature, humidity, and lighting data, among others.
The environment is mutated by the actuators and is probed by the sensors. In our demo, this occurs via communication over the network, like all other point-to-point communication.
The environment crate can be containerized and run on a container runtime like Docker.
Datum is the singular form of data; a datum describes a single observation / measurement of some aspect of the environment. In our implementation, every datum has a value, an associated unit, and a timestamp.
This is the entrypoint to the demo. It contains a main.rs file which can be run locally to spin up our example IoT system and observe its behaviour.
