Skip to main content

Crate pamoja

Crate pamoja 

Source
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:

FeatureModuleCrate
(always)pamoja::corepamoja-core
securitypamoja::securitypamoja-security
codecpamoja::codecpamoja-codec
kitpamoja::kitpamoja-kit
serialpamoja::serialpamoja-serial
modbuspamoja::modbuspamoja-modbus
canpamoja::canpamoja-can
gpiopamoja::gpiopamoja-gpio
sensorspamoja::sensorspamoja-sensors
actuatorspamoja::actuatorspamoja-actuators
lorapamoja::lorapamoja-lora
lorawanpamoja::lorawanpamoja-lorawan
meshpamoja::meshpamoja-mesh
routingpamoja::routingpamoja-routing
mavlinkpamoja::mavlinkpamoja-mavlink
auditpamoja::auditpamoja-audit
sessionpamoja::sessionpamoja-session
updatepamoja::updatepamoja-update
powerpamoja::powerpamoja-power
telemetrypamoja::telemetrypamoja-telemetry
mqttpamoja::mqttpamoja-mqtt
coappamoja::coappamoja-coap
loopbackpamoja::loopbackpamoja-loopback
syncpamoja::syncpamoja-sync
ladderpamoja::ladderpamoja-ladder
buspamoja::buspamoja-bus
simpamoja::simpamoja-sim
profilepamoja::profilepamoja-profile
ros2pamoja::ros2pamoja-ros2
zenohpamoja::zenohpamoja-zenoh
dashboard (off by default)pamoja::dashboardpamoja-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 featureTurns on
field-ioserial, modbus, can, gpio
sensingsensors, actuators
radiolora, lorawan, mesh, routing
trustaudit, session, update, power, telemetry
transportsmqtt, coap, loopback, sync, ladder, bus, sim
profilesprofile, 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_dashboard as dashboard;
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_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;