pub struct Profile {
pub name: String,
pub topic: String,
pub control: ControlSpec,
pub power: PowerSchedule,
pub presentation: Option<Presentation>,
}Expand description
A named, pre-wired bundle of control policy, publish topic, and power schedule.
A profile is the unit a builder instantiates instead of wiring pins and tuning
constants, and it is plain data: it serializes to and from a manifest a community
can write, store in a file, and share. Pick a preset such as
vaccine_fridge_monitor or load one with
from_json, hand it a sensor, an actuator, a transport, and
a codec, and the resulting Node reads, decides, drives the
output, and publishes on its own. Every field is public, so a deployment can
adjust the policy, topic, or power schedule in place.
§Examples
use pamoja_profile::{ControlSpec, Profile};
let profile = Profile::vaccine_fridge_monitor();
assert_eq!(profile.name, "vaccine-fridge-monitor");
assert!(matches!(profile.control, ControlSpec::Setpoint { .. }));Fields§
§name: StringA stable, human-readable name, such as "vaccine-fridge-monitor".
topic: StringThe topic each reading is published to.
control: ControlSpecThe control policy applied to each reading.
power: PowerScheduleThe power schedule that sets how often the node samples as the battery drains.
presentation: Option<Presentation>How this profile presents itself on the dashboard - its custom sensors, node
stats, and theme. A profile that introduces no element beyond the dashboard’s
built-in set leaves this None.
Implementations§
Source§impl Profile
impl Profile
Sourcepub fn vaccine_fridge_monitor() -> Self
pub fn vaccine_fridge_monitor() -> Self
A cold-chain fridge monitor: hold 5 C and alert on a spoilage excursion.
Switches a cooler to hold the contents near 5 C and raises an
Alert::OutOfRange the moment the temperature
leaves the 2-8 C safe range. Data integrity outweighs power here, so it keeps
sampling often even as the battery drains.
§Returns
The cold-chain monitoring profile.
Sourcepub fn irrigation_node() -> Self
pub fn irrigation_node() -> Self
An irrigation node: hold soil moisture near a target by opening a valve.
Treats the valve as a “heater” for soil moisture, opening it when the soil dries below the band and closing it once it is wet enough, and alerts if the soil falls critically dry. Samples less often than the fridge, since soil changes slowly and battery life matters more.
§Returns
The irrigation profile.
Sourcepub fn well_level() -> Self
pub fn well_level() -> Self
A well-level monitor: report depth and warn before the well runs dry.
Observes the water level without driving an output and raises an
Alert::RunningOut once the level is on course to
reach the dry mark within a few more samples.
§Returns
The well-level monitoring profile.
Sourcepub fn flood_sensor() -> Self
pub fn flood_sensor() -> Self
A flash-flood sensor: warn when a river level rises dangerously fast.
Watches a river or stream gauge and raises an
Alert::ChangingFast when the level rises more
than 0.3 m in a single sample, the signature of a flash flood. It samples
often, because a flood gives little warning.
§Returns
The flash-flood monitoring profile.
§Examples
use pamoja_profile::{Alert, Profile};
let mut control = Profile::flood_sensor().controller();
control.evaluate(1.0); // first fix establishes the level
let reaction = control.evaluate(1.5); // the river jumped 0.5 m
assert!(matches!(reaction.alert, Some(Alert::ChangingFast { .. })));Sourcepub fn controller(&self) -> Controller
pub fn controller(&self) -> Controller
Assembles this profile’s ControlSpec into a live Controller.
§Returns
A fresh controller implementing the profile’s policy, with its control state reset.
Sourcepub fn with_presentation(self, presentation: Presentation) -> Self
pub fn with_presentation(self, presentation: Presentation) -> Self
Attaches a dashboard Presentation declaring this profile’s custom elements.
A profile that measures something the dashboard does not draw out of the box - a turbidity probe, a custom node stat - carries the graphic, band, and label for it here, so the dashboard offers and renders it with no code.
§Arguments
presentation- how this profile presents itself on the dashboard.
§Returns
The profile, for chaining.
§Examples
use pamoja_profile::{ElementSpec, Presentation, Profile, Viz};
// A water-monitoring profile that adds a turbidity gauge the dashboard would not
// otherwise know how to draw.
let profile = Profile::well_level().with_presentation(
Presentation::new().with_element(
ElementSpec::new("water_turbidity", "ntu", "Turbidity", Viz::Gauge)
.with_band(0.0, 5.0),
),
);
let elements = &profile.presentation.unwrap().elements;
assert_eq!(elements[0].viz.kind(), "radial");Source§impl Profile
impl Profile
Sourcepub fn from_json(manifest: &str) -> Result<Self>
pub fn from_json(manifest: &str) -> Result<Self>
Loads a profile from a JSON manifest.
This is how a shared profile reaches a device: a community publishes a manifest file, and the runtime loads it into a profile to assemble a node from.
§Arguments
manifest- the JSON text of the profile.
§Returns
The profile described by manifest.
§Errors
Returns Error::Codec if manifest is not valid
JSON or does not describe a profile.
§Examples
use pamoja_profile::Profile;
// A well-level monitor, shared as a manifest. The power thresholds are
// optional and default when omitted.
let manifest = r#"{
"name": "tank-level",
"topic": "water/tank/level",
"control": { "kind": "level", "empty": 0.0, "warn_within": 5 },
"power": { "active_secs": 600, "saver_secs": 1800, "critical_secs": 3600 }
}"#;
let profile = Profile::from_json(manifest).expect("valid manifest");
assert_eq!(profile.name, "tank-level");
let mut control = profile.controller();
control.evaluate(10.0); // first reading establishes a level
assert!(control.evaluate(2.0).alert.is_some()); // falling fast toward empty