Expand description
The whole pamoja device SDK in one crate.
pamoja is one memory-safe Rust core with a crate per capability, so a build
carries only the crates it names. This crate is the other way in: every
capability sits behind a feature, all on by default, so cargo add pamoja is
the whole framework, the way npm install pamoja, pip install pamoja, and
dotnet add package Pamoja are in the bindings.
Each module re-exports the crate of the same name: pamoja::codec is
pamoja-codec, pamoja::mqtt is pamoja-mqtt, and pamoja::core is
pamoja-core, the traits every capability implements. The types, the
documentation, and the examples are those of the crate, so code moves between
use pamoja::codec::CborCodec and use pamoja_codec::CborCodec with no other change.
[dependencies]
pamoja = "0.1"A build that needs only some capabilities names them, and takes on only their dependencies:
[dependencies]
pamoja = { version = "0.1", default-features = false, features = ["std", "codec", "security"] }§Example
A reading taken off a wire, smoothed, packed for a metered link, and signed so the gateway that receives it can tell which device sent it, with nothing plugged in:
use pamoja::codec::{decode_deltas, encode_deltas};
use pamoja::kit::Smoother;
use pamoja::security::{DeviceIdentity, PublicIdentity};
use pamoja::sensors::ds18b20::{temperature_from_celsius, Resolution, Scratchpad};
// A stand-in for the thermometer. On a running node these nine bytes arrive from
// the 1-Wire bus; here the library builds what a part at 25.0625 C would send.
let off_the_bus = Scratchpad::new(
temperature_from_celsius(25.0625, Resolution::Bits12),
Resolution::Bits12,
75,
-10,
)
.to_bytes();
// The part checksums every read, so a value mangled on a long run is an error
// rather than a plausible temperature a couple of degrees off.
let celsius = Scratchpad::parse(&off_the_bus)
.expect("the checksum matches")
.temperature_celsius();
assert_eq!(celsius, 25.0625);
// Readings jitter, so smooth them and send a batch rather than one at a time.
let mut smoother = Smoother::new(0.5);
let batch: Vec<i64> = [celsius, celsius + 0.5, celsius + 0.4]
.into_iter()
.map(|sample| (smoother.update(sample) * 100.0).round() as i64)
.collect();
let packed = encode_deltas(&batch);
assert!(packed.len() < batch.len() * 8);
// Sign the batch. The signature travels with the payload as one message, so a
// gateway holding only the public key gets the payload back once it checks out.
let device = DeviceIdentity::from_seed(&[7u8; 32]);
let message = device.sign_message(&packed);
let known = PublicIdentity::from_bytes(&device.public().to_bytes())?;
let payload = known.verify_message(&message)?;
assert_eq!(decode_deltas(payload).expect("a valid batch"), batch);§Features
One feature per capability, named as its crate is without the prefix, and all on by default:
| Feature | Module | Crate |
|---|---|---|
| (always) | pamoja::core | pamoja-core |
security | pamoja::security | pamoja-security |
codec | pamoja::codec | pamoja-codec |
kit | pamoja::kit | pamoja-kit |
serial | pamoja::serial | pamoja-serial |
modbus | pamoja::modbus | pamoja-modbus |
can | pamoja::can | pamoja-can |
gpio | pamoja::gpio | pamoja-gpio |
sensors | pamoja::sensors | pamoja-sensors |
actuators | pamoja::actuators | pamoja-actuators |
lora | pamoja::lora | pamoja-lora |
lorawan | pamoja::lorawan | pamoja-lorawan |
mesh | pamoja::mesh | pamoja-mesh |
routing | pamoja::routing | pamoja-routing |
mavlink | pamoja::mavlink | pamoja-mavlink |
audit | pamoja::audit | pamoja-audit |
session | pamoja::session | pamoja-session |
update | pamoja::update | pamoja-update |
power | pamoja::power | pamoja-power |
telemetry | pamoja::telemetry | pamoja-telemetry |
mqtt | pamoja::mqtt | pamoja-mqtt |
coap | pamoja::coap | pamoja-coap |
loopback | pamoja::loopback | pamoja-loopback |
sync | pamoja::sync | pamoja-sync |
ladder | pamoja::ladder | pamoja-ladder |
bus | pamoja::bus | pamoja-bus |
sim | pamoja::sim | pamoja-sim |
profile | pamoja::profile | pamoja-profile |
ros2 | pamoja::ros2 | pamoja-ros2 |
zenoh | pamoja::zenoh | pamoja-zenoh |
dashboard (off by default) | pamoja::dashboard | pamoja-dashboard |
Six of those capabilities’ chapters hold more than one capability, and each has a feature that turns on exactly its own, so a build can name a domain instead of listing its parts. They are checked against the capability map, so a new capability cannot fall out of its group:
| Group feature | Turns on |
|---|---|
field-io | serial, modbus, can, gpio |
sensing | sensors, actuators |
radio | lora, lorawan, mesh, routing |
trust | audit, session, update, power, telemetry |
transports | mqtt, coap, loopback, sync, ladder, bus, sim |
profiles | profile, ros2, zenoh |
[dependencies]
pamoja = { version = "0.1", default-features = false, features = ["std", "field-io"] }std, on by default, turns on the standard-library layer of the crates that
have one (pamoja-core, pamoja-lora, pamoja-mavlink) and implies alloc,
which adds the owned channel plans, tables, and message shapes of pamoja-lora,
pamoja-mesh, pamoja-routing, and pamoja-mavlink. With both off and only
no_std capabilities named, the crate builds for a bare-metal target; CI
compiles it for thumbv7em-none-eabihf. The crates keep their finer switches
(the LoRa region set, the kit’s helper groups, the MAVLink serial driver), so
depend on the crate itself when you need one of those. dashboard adds the
fleet dashboard, a web server, and is off by default.
Re-exports§
pub use pamoja_core as core;pub use pamoja_actuators as actuators;pub use pamoja_audit as audit;pub use pamoja_bus as bus;pub use pamoja_can as can;pub use pamoja_coap as coap;pub use pamoja_codec as codec;pub use pamoja_gpio as gpio;pub use pamoja_kit as kit;pub use pamoja_ladder as ladder;pub use pamoja_loopback as loopback;pub use pamoja_lora as lora;pub use pamoja_lorawan as lorawan;pub use pamoja_mavlink as mavlink;pub use pamoja_mesh as mesh;pub use pamoja_modbus as modbus;pub use pamoja_mqtt as mqtt;pub use pamoja_power as power;pub use pamoja_profile as profile;pub use pamoja_ros2 as ros2;pub use pamoja_routing as routing;pub use pamoja_security as security;pub use pamoja_sensors as sensors;pub use pamoja_serial as serial;pub use pamoja_session as session;pub use pamoja_sim as sim;pub use pamoja_sync as sync;pub use pamoja_telemetry as telemetry;pub use pamoja_update as update;pub use pamoja_zenoh as zenoh;