Named, ready-to-run device profiles from plain data or a JSON manifest. One capability of pamoja, one memory-safe Rust core with bindings for TypeScript, Python, and C#.
npm install @pamoja/profile
This pulls in @pamoja/native, the compiled engine. npm install pamoja is the whole framework in one package.
The test that runs in CI, spliced here as it ran.
From bindings/node/guides/profile.ts:
import { AlertKind, ControlKind, Profile } from '@pamoja/profile'
// A profile is plain data, so a fleet ships one as a file rather than as code. The two
// power thresholds are optional and fall back to the documented defaults.
const manifest = `{
"name": "brooder-heater",
"topic": "poultry/brooder/temperature",
"control": {
"kind": "setpoint", "setpoint": 32.0, "hysteresis": 0.5,
"cooling": false, "safe_band": 4.0
},
"power": { "active_secs": 120, "saver_secs": 600, "critical_secs": 1800 }
}`
const profile = Profile.fromJson(manifest)
console.log(`${profile.name} reports on ${profile.topic}`)
console.log(`wakes every ${profile.power.activeSecs}s while the battery is healthy`)
console.log(`saver mode below ${(profile.power.saverBelow * 100).toFixed(0)}% charge`)
// The manifest is the whole control loop. At 27.5 C the reading is below the deadband, so
// the lamp switches on, and it is more than 4 C from target, so the chicks are cold.
const cold = profile.controller().evaluate(27.5)
console.log(`at 27.5 C: lamp ${cold.actuator}, alert ${cold.alert?.kind}`)
// Back inside the deadband the lamp is left as it was, and nothing is raised.
const settled = profile.controller().evaluate(32.2)
console.log(`at 32.2 C: lamp ${settled.actuator}, alert ${settled.alert}`)
// Serializing writes the defaulted fields out in full, so a profile edited on a device and
// shared back carries no value the next reader has to infer.
const shared = profile.toJson()
console.log(`shared form names its defaults: ${shared.includes('saver_below')}`)
| Language | Package | Reference |
|---|---|---|
| Rust | pamoja-profile |
reference, docs.rs, install |
| TypeScript | @pamoja/profile |
reference, install |
| Python | pamoja-profile |
reference, install |
| C# | Pamoja.Profile |
reference, install |
@pamoja/profile reference, every class, function, and type this package exports.MIT
Ergonomic facade over the generated device-profile binding.
A profile is a named, pre-wired bundle: a control policy, a publish topic, and a power schedule. Instantiate one rather than choosing algorithms and tuning constants by hand.
A profile is the manifest, which loads from and saves to JSON so it ships as a file. A controller is the decision logic that manifest describes: hand it a reading and it says what the output should do and whether the reading crossed a threshold worth raising. The presentation a dashboard reads travels inside the manifest JSON.
The alert and control kinds are re-exported as runtime objects, because the generated enums are types-only.