Created
March 19, 2021 03:43
-
-
Save dannyrandall/7cf61f155f931c86c6627539f8c1ef5d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ruleset manage_sensor { | |
meta { | |
name "Manage Sensor" | |
author "Daniel Randall" | |
use module io.picolabs.subscription alias subscription | |
shares sensors, temperatures, profiles, sensor_subs, temperature_reports | |
} | |
global { | |
rulesets = { | |
"io.picolabs.wovyn.emitter": { | |
"url": meta:rulesetConfig{["rulesets", "io.picolabs.wovyn.emitter", "url"]}.defaultsTo("") | |
}, | |
"sensor_profile": { | |
"url": meta:rulesetConfig{["rulesets", "sensor_profile", "url"]}.defaultsTo("") | |
}, | |
"wovyn_base": { | |
"url": meta:rulesetConfig{["rulesets", "wovyn_base", "url"]}.defaultsTo("") | |
}, | |
"temperature_store": { | |
"url": meta:rulesetConfig{["rulesets", "temperature_store", "url"]}.defaultsTo("") | |
} | |
} | |
defaults = { | |
"threshold": meta:rulesetConfig{["defaults", "threshold"]}.defaultsTo(100), | |
"notification_to": meta:rulesetConfig{["defaults", "notification_to"]}.defaultsTo("") | |
} | |
sensors = function() { | |
ent:sensors.defaultsTo({}) | |
} | |
sensor_subs = function() { | |
subscription:established("Tx_role", "sensor").map(function(v) { | |
v.get(["Tx"]) | |
}) | |
} | |
temperatures = function() { | |
sensor_subs().map(function(s) { | |
{}.put(s, ctx:query(s, "temperature_store", "temperatures").defaultsTo([]).reverse().head()) | |
}) | |
} | |
profiles = function() { | |
sensor_subs().map(function(s) { | |
{}.put(s, ctx:query(s, "sensor_profile", "profile").defaultsTo({})) | |
}) | |
} | |
temperature_reports = function() { | |
ent:temperature_reports.defaultsTo({}) | |
} | |
} | |
rule add_sensor { | |
select when sensor new_sensor | |
pre { | |
name = event:attrs{"name"} | |
duplicate = ent:sensors && ent:sensors >< name | |
} | |
if duplicate then | |
send_directive("error", {"error": "cannot create duplicate child"}) | |
notfired { | |
raise wrangler event "new_child_request" attributes { | |
"name": name | |
} | |
} | |
} | |
rule sensor_added { | |
select when wrangler new_child_created | |
foreach rulesets setting(rule) | |
pre { | |
name = event:attrs{"name"} | |
eci = event:attrs{"eci"} | |
} | |
if name && eci then | |
event:send({ | |
"eci": eci, | |
"domain": "wrangler", | |
"type": "install_ruleset_request", | |
"attrs": { | |
"url": rule{"url"}, | |
"config": rule{"config"}, | |
} | |
}) | |
fired { | |
ent:sensors := ent:sensors.defaultsTo({}).put(name, eci) on final | |
raise sensor event "sensor_added" attributes { | |
"name": name | |
} on final | |
} | |
} | |
rule configure_sensor { | |
select when sensor sensor_added where event:attrs{"name"} && ent:sensors{event:attrs{"name"}} | |
pre { | |
name = event:attrs{"name"} | |
eci = ent:sensors{name} | |
} | |
event:send({ | |
"eci": eci, | |
"domain": "sensor", | |
"type": "profile_updated", | |
"attrs": { | |
"name": name, | |
"temperature_threshold": defaults{"threshold"}, | |
"notification_to": defaults{"notification_to"} | |
} | |
}) | |
} | |
rule create_subscription { | |
select when sensor sensor_added where event:attrs{"name"} && ent:sensors{event:attrs{"name"}} | |
pre { | |
name = event:attrs{"name"} | |
eci = ent:sensors{name} | |
} | |
always { | |
raise wrangler event "subscription" attributes { | |
"name": name, | |
"wellKnown_Tx": eci, | |
"channel_type": "sensor_management", | |
"Rx_role": "sensor_manager", | |
"Tx_role": "sensor" | |
} | |
} | |
} | |
rule introduce_sensor { | |
select when sensor introduce | |
pre { | |
name = event:attrs{"name"} | |
eci = event:attrs{"eci"} | |
} | |
always { | |
raise wrangler event "subscription" attributes { | |
"name": name, | |
"wellKnown_Tx": eci, | |
"channel_type": "sensor_management", | |
"Rx_role": "sensor_manager", | |
"Tx_role": "sensor" | |
} | |
} | |
} | |
rule delete_all_sensors { | |
select when sensor delete_all_sensors | |
foreach ent:sensors setting(eci, name) | |
always { | |
raise wrangler event "child_deletion_request" attributes { | |
"eci": eci | |
} | |
clear ent:sensors{name} | |
} | |
} | |
rule delete_sensor { | |
select when sensor unneeded_sensor where event:attrs{"name"} && ent:sensors{event:attrs{"name"}} | |
pre { | |
name = event:attrs{"name"} | |
eci = ent:sensors{name} | |
} | |
always { | |
raise wrangler event "child_deletion_request" attributes { | |
"eci": eci | |
} | |
clear ent:sensors{name} | |
} | |
} | |
rule sub_sensor_threshold_violation { | |
select when sensor_manager sub_sensor_threshold_violation | |
always { | |
raise sensor_manager_profile event "send_sms" attributes { | |
"msg": "detected threshold violation at " + event:attrs{"timestamp"} + ". temperature: " + event:attrs{"temperature"} | |
} | |
} | |
} | |
rule start_temperature_report { | |
select when sensor_manager start_temperature_report | |
foreach sensor_subs() setting(eci) | |
pre { | |
reportID = event:attrs{"reportID"} | |
} | |
event:send({ | |
"eci": eci, | |
"domain": "wovyn", | |
"type": "report_temperature", | |
"attrs": { | |
"reportID": reportID, | |
"sensorID": eci | |
} | |
}) | |
always { | |
ent:temperature_reports := ent:temperature_reports.defaultsTo({}).put([reportID, "started"], time:now()) on final | |
ent:temperature_reports := ent:temperature_reports.defaultsTo({}).put([reportID, "total_sensors"], sensor_subs().length()) on final | |
} | |
} | |
rule collect_temperature_report { | |
select when sensor_manager temperature_report | |
pre { | |
sensorID = event:attrs{"sensorID"} | |
reportID = event:attrs{"reportID"} | |
temp = event:attrs{"temperature"} | |
reporting_sensors = ent:temperature_reports.defaultsTo({}).get([reportID, "reporting_sensors"]).defaultsTo(0)+1 | |
total_sensors = ent:temperature_reports.defaultsTo({}).get([reportID, "total_sensors"]) | |
} | |
if total_sensors && reporting_sensors >= total_sensors then | |
noop() | |
fired { | |
ent:temperature_reports := ent:temperature_reports.defaultsTo({}).put([reportID, "ended"], time:now()) | |
} finally { | |
ent:temperature_reports := ent:temperature_reports.defaultsTo({}).put([reportID, "reporting_sensors"], reporting_sensors) | |
ent:temperature_reports := ent:temperature_reports.defaultsTo({}).put([reportID, "reports", sensorID], temp) | |
} | |
} | |
rule clear_temperature_reports { | |
select when manage_sensor clear_temperature_reports | |
always { | |
ent:temperature_reports := {} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment