pamoja 0.1.17

The whole pamoja device SDK in one crate: every capability behind a feature, all on by default, for IoT, robotics, and drones.
Documentation
<!-- Generated by `cargo xtask docs` from this crate's lib.rs; edit the crate doc, not this file. -->

# pamoja

The whole pamoja device SDK in one crate: every capability behind a feature, all on by default, for IoT, robotics, and drones.

<a href="https://pamoja.molex.cloud/docs/reference/rust/pamoja/index.html"><img height="28" alt="API reference" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-api.svg"></a>
<a href="https://crates.io/crates/pamoja"><img height="28" alt="crates.io" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-cratesio.svg"></a>
<a href="https://docs.rs/pamoja"><img height="28" alt="docs.rs" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-docsrs.svg"></a>
<a href="https://www.npmjs.com/package/pamoja"><img height="28" alt="npm" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-npm.svg"></a>
<a href="https://pypi.org/project/pamoja/"><img height="28" alt="PyPI" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-pypi.svg"></a>
<a href="https://www.nuget.org/packages/Pamoja"><img height="28" alt="NuGet" src="https://raw.githubusercontent.com/molexxxx/pamoja/main/.github/badges/btn-nuget.svg"></a>

The full API reference is [on the site](https://pamoja.molex.cloud/docs/reference/rust/pamoja/index.html), and the copy for each published version is on [docs.rs](https://docs.rs/pamoja).

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.

```toml
[dependencies]
pamoja = "0.1"
```

A build that needs only some capabilities names them, and takes on only
their dependencies:

```toml
[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:

```rust
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]https://docs.rs/pamoja-core |
| `security` | `pamoja::security` | [pamoja-security]https://docs.rs/pamoja-security |
| `codec` | `pamoja::codec` | [pamoja-codec]https://docs.rs/pamoja-codec |
| `kit` | `pamoja::kit` | [pamoja-kit]https://docs.rs/pamoja-kit |
| `serial` | `pamoja::serial` | [pamoja-serial]https://docs.rs/pamoja-serial |
| `modbus` | `pamoja::modbus` | [pamoja-modbus]https://docs.rs/pamoja-modbus |
| `can` | `pamoja::can` | [pamoja-can]https://docs.rs/pamoja-can |
| `gpio` | `pamoja::gpio` | [pamoja-gpio]https://docs.rs/pamoja-gpio |
| `sensors` | `pamoja::sensors` | [pamoja-sensors]https://docs.rs/pamoja-sensors |
| `actuators` | `pamoja::actuators` | [pamoja-actuators]https://docs.rs/pamoja-actuators |
| `lora` | `pamoja::lora` | [pamoja-lora]https://docs.rs/pamoja-lora |
| `lorawan` | `pamoja::lorawan` | [pamoja-lorawan]https://docs.rs/pamoja-lorawan |
| `mesh` | `pamoja::mesh` | [pamoja-mesh]https://docs.rs/pamoja-mesh |
| `routing` | `pamoja::routing` | [pamoja-routing]https://docs.rs/pamoja-routing |
| `mavlink` | `pamoja::mavlink` | [pamoja-mavlink]https://docs.rs/pamoja-mavlink |
| `audit` | `pamoja::audit` | [pamoja-audit]https://docs.rs/pamoja-audit |
| `session` | `pamoja::session` | [pamoja-session]https://docs.rs/pamoja-session |
| `update` | `pamoja::update` | [pamoja-update]https://docs.rs/pamoja-update |
| `power` | `pamoja::power` | [pamoja-power]https://docs.rs/pamoja-power |
| `telemetry` | `pamoja::telemetry` | [pamoja-telemetry]https://docs.rs/pamoja-telemetry |
| `mqtt` | `pamoja::mqtt` | [pamoja-mqtt]https://docs.rs/pamoja-mqtt |
| `coap` | `pamoja::coap` | [pamoja-coap]https://docs.rs/pamoja-coap |
| `loopback` | `pamoja::loopback` | [pamoja-loopback]https://docs.rs/pamoja-loopback |
| `sync` | `pamoja::sync` | [pamoja-sync]https://docs.rs/pamoja-sync |
| `ladder` | `pamoja::ladder` | [pamoja-ladder]https://docs.rs/pamoja-ladder |
| `bus` | `pamoja::bus` | [pamoja-bus]https://docs.rs/pamoja-bus |
| `sim` | `pamoja::sim` | [pamoja-sim]https://docs.rs/pamoja-sim |
| `profile` | `pamoja::profile` | [pamoja-profile]https://docs.rs/pamoja-profile |
| `ros2` | `pamoja::ros2` | [pamoja-ros2]https://docs.rs/pamoja-ros2 |
| `zenoh` | `pamoja::zenoh` | [pamoja-zenoh]https://docs.rs/pamoja-zenoh |
| `dashboard` (off by default) | `pamoja::dashboard` | [pamoja-dashboard]https://docs.rs/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` |

```toml
[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.

## License

MIT - part of the [pamoja](https://github.com/molexxxx/pamoja) workspace: one memory-safe Rust core with bindings for every language.