pub struct Rules {
pub rules: Vec<Rule>,
}Expand description
A set of rules, as a file a fleet shares.
{ "$schema": "https://pamoja.molex.cloud/schema/rules-1.json", "rules": [ ... ] }The $schema is optional; it names the format the file is written in, and an editor
reads it to check the file as it is typed. A field the format does not have is
refused, with the nearest one it does.
Fields§
§rules: Vec<Rule>The rules, in the order they are checked against each message.
Implementations§
Source§impl Rules
impl Rules
Sourcepub const SCHEMA: &'static str = "https://pamoja.molex.cloud/schema/rules-1.json"
pub const SCHEMA: &'static str = "https://pamoja.molex.cloud/schema/rules-1.json"
The address of the published JSON Schema for the rule file format this build
writes, which to_json names as the file’s $schema.
Sourcepub fn from_json(text: &str) -> Result<Self>
pub fn from_json(text: &str) -> Result<Self>
Loads rules from their JSON file.
§Arguments
text- the file’s contents.
§Returns
The rules.
§Errors
Returns [Error::Codec] if the text is not a rule file, is written in a format
this build does not read, carries a field the format does not have, or holds a rule
check refuses. A misspelled field is reported with the name it was
probably meant to be.
§Examples
use pamoja_profile::Rules;
let file = r#"{
"$schema": "https://pamoja.molex.cloud/schema/rules-1.json",
"rules": [
{ "name": "vent-when-hot",
"when": { "topic": "greenhouse/air", "above": 30.0, "hysteresis": 3.0 },
"then": [ { "drive": "roof-vent", "on": true } ],
"otherwise": [ { "drive": "roof-vent", "on": false } ] }
]
}"#;
let rules = Rules::from_json(file)?;
assert_eq!(rules.rules[0].when.threshold, 30.0);
let typo = file.replace("\"hysteresis\"", "\"hysterisis\"");
let refused = Rules::from_json(&typo).unwrap_err().to_string();
assert!(refused.contains("did you mean `hysteresis`?"), "{refused}");Sourcepub fn check(&self) -> Result<()>
pub fn check(&self) -> Result<()>
Checks the rules for what a file can say that no engine could run.
§Returns
Nothing when every rule is usable.
§Errors
Returns [Error::Codec] naming the first problem and the rule it is in: a rule
without a name or with a name another rule has, a condition without a topic or
watching a filter with + or #, a threshold that is not a finite number, a
hysteresis that is not a finite number of zero or more, a rule with nothing to
do, or an action naming no actuator, no topic, or a filter to publish to.
§Examples
use pamoja_profile::{Action, Condition, Rule, Rules};
// A rule on a filter would subscribe to every bed and match none of them, since a
// rule compares each message's topic with its own exactly.
let every_bed = Rules::new().with(
Rule::new("water-when-dry", Condition::below("garden/+/moisture", 30.0))
.then(Action::Drive { actuator: "bed-valve".into(), on: true }),
);
let refused = every_bed.check().unwrap_err().to_string();
assert!(refused.contains("a rule watches one topic exactly"));