""" On status NORMAL notify """, { rulename: "on-temp-status-back-to-normal", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ CheckPayloadPropertyValue("value", "NORMAL"), CheckPayloadPropertyValueNotIn("old_value", (None,)) # skip initial state ], processing: [ Route(message="temp-status-back-to-normal", dispatch_policy=DispatchPolicyConst.DIRECT), SetSubjectProperty("m_lastTempStatusChanged", _(lambda _: datetime.now().isoformat())) ], }, }, """ Status COLD or OVERHEATED schedule a new check """, { rulename: "on-temp-status-bad", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ CheckPayloadPropertyValueIn("value", ("COLD", "OVERHEATED")), ],
processing = Const.PROCESSING rulesdata = [ """ On status NORMAL notify """, { rulename: "on-temp-status-back-to-normal-websocket-notifier", subscribe_to: "temp-status-back-to-normal", ruledata: { processing: [ PyCall( requests.post, os.environ["MATTERMOST_CHANNEL_URL"], json=_( lambda _self: { "text": " :sunglasses: device *{}* temp status back to normal! " .format(_self.subject.name) })), ], }, }, """ Status COLD or OVERHEATED """, { rulename: "on-temp-status-bad-websocket-notifier", subscribe_to: "temp-status-bad", ruledata: { processing: [ PyCall( requests.post,
rulename = Const.RULENAME subscribe_to = Const.SUBSCRIBE_TO ruledata = Const.RULEDATA filters = Const.FILTERS processing = Const.PROCESSING rulesdata = [ """ Store temp property """, { rulename: "on-data-received-store-temp", subscribe_to: "data-received", ruledata: { filters: [Check(_(lambda _self: "tempc" in _self.payload["data"]))], processing: [ SetSubjectProperty( "tempc", _(lambda _self: float(_self.payload["data"]["tempc"]))) ] } }, """ Set temp_status COLD """, { rulename: "on-tempc-changed-check-cold", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [
processing = Const.PROCESSING rulesdata = [ """ tempc websocket notifier """, { rulename: "on-tempc-changed-websocket-notifier", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ OnSubjectPropertyChanged("tempc"), ], processing: [ WebsocketDevicePublishMessage( _(lambda _self: {"value": _self.payload.get("value")})), ] }, }, """ On status NORMAL notify """, { rulename: "on-temp-status-back-to-normal-websocket-notifier", subscribe_to: "temp-status-back-to-normal", ruledata: { processing: [ WebsocketDevicePublishMessage({ "event": "Temp status back to normal! ", "event_class":
subscribe_to = Const.SUBSCRIBE_TO ruledata = Const.RULEDATA filters = Const.FILTERS processing = Const.PROCESSING rulesdata = [ """ Location changed (changed from a known location) """, { rulename: "on-location-changed-moving-notify-slack", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ OnSubjectPropertyChanged("location"), Check(_(lambda _self: _self.payload["old_value"] is not None) ) # moving ], processing: [ PyCall( requests.post, os.environ["MATTERMOST_CHANNEL_URL"], json=_( lambda _self: { "text": ":rocket: device *{}* moved to {}".format( _self.subject.name, _self.payload.get("value")) })), ] } },
""" Save raw data """, { rulename: 'mongo-store-full-data', subscribe_to: TopicsDefault.RESULTS, ruledata: { processing: [ WithDatabase(DBNAME), WithCollection("metrics", indexes=[IndexModel([("origin_id", HASHED)])], capped=True, size=1000000), SetPayloadProperty( "origin_id", _(lambda _self: _self.payload["payload"]["_event_info"][ "Originid"])), SetPayloadProperty( "time", _(lambda _self: parse(_self.payload["payload"][ "_event_info"]["Time"]))), MongoDBInsertOne(_(lambda _self: _self.payload)), ] } }, """ Store errors in a specific collection """, { rulename: 'mongo-store-errors', subscribe_to: TopicsDefault.RESULTS, ruledata: {
Notify onboarded (READY) """, { rulename: "on-device-ready-notify", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ CheckPayloadPropertyValue("value", "READY"), ], processing: [ PyCall(requests.post, os.environ["MATTERMOST_CHANNEL_URL"], json=_( lambda _self: { "type": "mrkdwn", "text": ":+1: device *{}* on board! ".format( _self.subject.name) })), ], }, }, """ Notify ACTIVE """, { rulename: "on-device-active-notify", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ CheckPayloadPropertyValue("value", "ACTIVE"),
""" Notify onboarded (READY) """, { rulename: "on-device-ready-notify-websocket", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ CheckPayloadPropertyValue("value", "READY"), ], processing: [ WebsocketDevicePublishMessage( _( lambda _self: { "device_class": _self.subject.get_ext("deviceclass" ), "status": _self.subject.status, "event": "Onboarded", "event_class": NotificationEventClass.CHEERING, })) ], }, }, """ Notify ACTIVE """, { rulename: "on-device-active-notify-websocket", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ CheckPayloadPropertyValue("value", "ACTIVE"),
rulesdata = [ """ Send all coords variations """, { rulename: "on-coords-changed-notify-websocket", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ OnSubjectPropertyChanged("coords"), ], processing: [ WebsocketDevicePublishMessage( _(lambda _self: { "value": _self.payload["value"], })), ] } }, """ Send location (cheering) """, { rulename: "on-location-changed-notify-websocket-cheering", subscribe_to: messages.SUBJECT_PROPERTY_CHANGED, ruledata: { filters: [ OnSubjectPropertyChanged("location"), Check(_(lambda _self: _self.payload["old_value"] is None)) ],
rulename: "on-data-received-set-status-active", subscribe_to: "data-received", ruledata: { filters: [ IsEnabled(), ], processing: [ SetSubjectProperty("status", 'ACTIVE'), Schedule("set-device-status", payload={'value': 'INACTIVE'}, when=lambda _self: datetime.now() + timedelta( seconds=int(_self.subject.rate)), replace=True) ], }, }, """ Set device status, used to set INACTIVE by the scheduler """, { rulename: 'on-set-device-status', subscribe_to: "set-device-status", ruledata: { processing: [ SetSubjectProperty("status", _(lambda _self: _self.payload["value"])) ] } }, ]
""" Subscribe to storage, import csv """, { rulename: "on-csv-upload-import-devices", subscribe_to: "google.storage.object.finalize", ruledata: { filters: [ SubjectMatch("onboarding/import/(?P<deviceclass>.+)/(?P<filename>.+)", payload_dest="path_info"), CheckPayloadPropertyValue("contentType", "text/csv"), ], processing: [ ProcessCSV_AsDict( driver=GoogleStorageDriver, bucket=_(lambda _self: _self.payload["bucket"]), path=_(lambda _self: _self.payload["name"]), func=lambda device_data, _self: ( message_router_factory().route( "onboard-device", subject_factory(device_data.pop("deviceid"), event_info=_self.subject.event_info()), { "data": device_data, "class": _self.payload["path_info"]["deviceclass"] }), ) ) ], } },
OnSubjectPropertyChanged("location"), ], processing: [ Route( "do-extapi-post", payload=_( lambda _self: { "url": os.environ[ "EXTAPI_URL" ], # https://europe-west3-krules-dev-254113.cloudfunctions.net/store_devices_location "req_kwargs": { "headers": { "x-api-key": os.environ["EXTAPI_X_API_KEY"] }, "json": { "device": _self.subject.name, "timestamp": datetime.utcnow().replace(tzinfo=pytz.UTC). isoformat(), "coords": _self.subject.coords, "location": _self.payload["value"], } } })) ] } }, """ Do call api
filters = Const.FILTERS processing = Const.PROCESSING rulesdata = [ """ give the chance to subscribe specific error conditions from the source originating the error """, { rulename: 'on-errors-propagate', subscribe_to: TopicsDefault.RESULTS, ruledata: { filters: [CheckPayload(lambda p: p["got_errors"] is True)], processing: [ Route( _(lambda _self: "{}-errors".format(_self.payload[ "_event_info"]["Source"])), _(lambda _self: _self.payload["subject"]), _(lambda _self: _self.payload), ) ] } }, """ Notify on mattermost """, { rulename: 'on-errors-notify', subscribe_to: TopicsDefault.RESULTS, ruledata: { filters: [CheckPayload(lambda p: p["got_errors"] is True)], processing: [
# ) results_rx_factory().subscribe(on_next=publish_results_all, ) rulename = Const.RULENAME subscribe_to = Const.SUBSCRIBE_TO ruledata = Const.RULEDATA filters = Const.FILTERS processing = Const.PROCESSING rulesdata = [ """ Set the basic properties of the device and the initial status as 'READY' The status will become 'ACTIVE' upon receipt of the first message """, { rulename: "on-onboard-device-store-properties", subscribe_to: "onboard-device", ruledata: { filters: [CheckPayload(lambda x: "data" in x and "class" in x)], processing: [ FlushSubject(), # just4dev... SetSubjectProperties(_(lambda _self: _self.payload["data"])), SetSubjectExtendedProperty( "deviceclass", _(lambda _self: _self.payload["class"])), SetSubjectProperty('status', 'READY'), SetEnabled(), ], }, } ]
processing = Const.PROCESSING rulesdata = [ """ Just emit "data-received" event Data should be handled by application specific logic """, { rulename: "on-data-received-propagate", subscribe_to: "google.pubsub.topic.publish", ruledata: { filters: [ IsNotOutdated(lambda _self: "data-received#{}".format( _self.payload.get("deviceid"))) ], processing: [ SetSubjectProperty("m_lastSeen", datetime.now().isoformat()), Route( "data-received", # message _(lambda _self: _self.payload.pop("deviceid")), # subject _( lambda _self: { # payload "receivedAt": _self.payload["_event_info"]["Time"], "data": _self.payload })), ], } } ]