pub struct PolicyRegistry<R = f32, C = bool> { /* private fields */ }Expand description
What resolves a manifest’s control kind to the code that decides it.
The four built-in kinds resolve to a Controller. A kind pamoja never shipped
resolves to the factory registered under its name, which reads the parameters the
manifest carried beside the kind and builds the policy, so a fleet can share a
manifest for a policy of its own the same way it shares one for a setpoint. A
registry is generic over the reading and command its policies work in;
resolve exists for the f32 reading and bool command
the built-in kinds share, and custom for any other pair.
§Examples
use pamoja_core::Error;
use pamoja_profile::{Alert, BoxedPolicy, Policy, PolicyRegistry, Profile, Reaction};
struct FrostGuard {
warn_below: f32,
}
impl Policy for FrostGuard {
type Reading = f32;
type Command = bool;
fn evaluate(&mut self, reading: &f32) -> Reaction {
let cold = *reading < self.warn_below;
Reaction {
actuator: Some(cold),
alert: cold.then_some(Alert::Custom { code: "FrostRisk", value: *reading }),
}
}
}
// The manifest names a kind the library has never heard of, with its parameter
// beside it, exactly as a built-in kind carries its own.
let manifest = r#"{
"name": "orchard-frost",
"topic": "orchard/air/temperature",
"control": { "kind": "frost_guard", "warn_below": 2.0 },
"power": { "active_secs": 60, "saver_secs": 300, "critical_secs": 900 }
}"#;
let profile = Profile::from_json(manifest)?;
let registry = PolicyRegistry::new().register("frost_guard", |params| {
let warn_below = params
.number("warn_below")
.ok_or(Error::Unsupported("frost_guard needs a `warn_below` parameter"))?;
Ok(Box::new(FrostGuard { warn_below: warn_below as f32 }) as BoxedPolicy)
});
let mut policy = registry.resolve(&profile.control)?;
assert_eq!(policy.evaluate(&1.0).alert.map(Alert::kind), Some("FrostRisk"));
assert_eq!(policy.evaluate(&5.0).actuator, Some(false));
// A built-in kind resolves through the same registry.
let mut fridge = registry.resolve(&Profile::vaccine_fridge_monitor().control)?;
assert_eq!(fridge.evaluate(&9.0).actuator, Some(true));Implementations§
Source§impl<R, C> PolicyRegistry<R, C>
impl<R, C> PolicyRegistry<R, C>
Sourcepub fn new() -> Self
pub fn new() -> Self
Starts a registry with no custom kinds.
§Returns
A registry that resolves only what is registered on it.
Sourcepub fn custom(&self, kind: &str, params: &Params) -> Result<BoxedPolicy<R, C>>
pub fn custom(&self, kind: &str, params: &Params) -> Result<BoxedPolicy<R, C>>
Builds the policy for a custom kind from its parameters.
§Arguments
kind- the kind as a manifest names it.params- the parameters the manifest carried beside it.
§Returns
The policy, ready to evaluate readings.
§Errors
Returns [Error::Codec] naming the kind when no factory is registered for it, or
whatever the factory returns when the parameters are not what it needs.
Source§impl PolicyRegistry<f32, bool>
impl PolicyRegistry<f32, bool>
Sourcepub fn resolve(&self, spec: &ControlSpec) -> Result<BoxedPolicy<f32, bool>>
pub fn resolve(&self, spec: &ControlSpec) -> Result<BoxedPolicy<f32, bool>>
Resolves a manifest’s control kind: a built-in kind to its Controller, a
custom kind to the policy its factory builds.
§Arguments
spec- the control policy a profile carries.
§Returns
The policy, ready to evaluate readings.
§Errors
Returns [Error::Codec] naming the kind when it is custom and no factory is
registered for it, or whatever the factory returns.