This example implements a temperature control model (a thermostat) with these features:
• One detector model you define that can monitor and control multiple areas. (A detector instance will be created for each area.)
• Each detector instance receives temperature data from multiple sensors placed in each control area.
• You can change the desired temperature (the set point) for each area at any time.
• You can define the operational parameters for each area and change these parameters at any time.
• You can add sensors to or delete sensors from an area at any time.
• You can enable a minimum run for time heating and cooling units to protect them from damage.
• The detectors will reject, and report, anomalous sensor readings.
• You can define emergency temperature set points. If any one sensor reports a temperature above or below the set points you have defined, heating or cooling units will be engaged immediately, and the detector will report that temperature spike.
This example demonstrates the following functional capabilities:
• Create event detector models.
• Create inputs.
• Ingest inputs into a detector model.
• Evaluate trigger conditions.
• Refer to state variables in conditions and set the values of variables depending on conditions.
• Refer to timers in conditions and set timers depending on conditions.
• Take actions that send Amazon SNS and MQTT messages.
Input definitions
A "seedTemperatureInput" is used to create a detector instance for an area and define its operational parameters.
Input definitions
CLI command used:
aws iotevents create-input --cli-input-json file://seedInput.json
File: seedInput.json {
"inputName": "seedTemperatureInput",
"inputDescription": "Temperature seed values.", "inputDefinition": {
"attributes": [
{ "jsonPath": "areaId" },
{ "jsonPath": "desiredTemperature" }, { "jsonPath": "allowedError" }, { "jsonPath": "rangeHigh" }, { "jsonPath": "rangeLow" }, { "jsonPath": "anomalousHigh" }, { "jsonPath": "anomalousLow" }, { "jsonPath": "sensorCount" }, { "jsonPath": "noDelay" } ]
} }
Response:
{ "inputConfiguration": { "status": "ACTIVE",
"inputArn": "arn:aws:iotevents:us-west-2:123456789012:input/seedTemperatureInput", "lastUpdateTime": 1557519620.736,
"creationTime": 1557519620.736, "inputName": "seedTemperatureInput",
"inputDescription": "Temperature seed values."
} }
A "temperatureInput" should be sent by each sensor in each area, as necessary.
CLI command used:
aws iotevents create-input --cli-input-json file://temperatureInput.json
File: temperatureInput.json
{ "inputName": "temperatureInput",
"inputDescription": "Temperature sensor unit data.", "inputDefinition": {
"attributes": [
{ "jsonPath": "sensorId" }, { "jsonPath": "areaId" },
Detector model definition
{ "inputConfiguration": { "status": "ACTIVE",
"inputArn": "arn:aws:iotevents:us-west-2:123456789012:input/temperatureInput", "lastUpdateTime": 1557519707.399,
"creationTime": 1557519707.399, "inputName": "temperatureInput",
"inputDescription": "Temperature sensor unit data."
} }
Detector model definition
The "areaDetectorModel" defines how each detector instance works. Each "state machine"
instance will ingest temperature sensor readings, then change state and send control messages depending on these readings.
Detector model definition
"eventName": "initialize",
"condition": "$input.seedTemperatureInput.sensorCount > 0", "actions": [
Detector model definition
Detector model definition
}, {
"eventName": "changeDesired",
"condition": "$input.seedTemperatureInput.desiredTemperature !=
$variable.desiredTemperature",
"condition": "$input.temperatureInput.sensorData.temperature <
$variable.anomalousHigh && $input.temperatureInput.sensorData.temperature >
"condition": "$input.temperatureInput.sensorData.temperature >=
$variable.anomalousHigh || $input.temperatureInput.sensorData.temperature <=
"condition": "$input.temperatureInput.sensorData.temperature >
$variable.rangeHigh",
Detector model definition
"condition": "$input.temperatureInput.sensorData.temperature <
$variable.rangeLow",
"condition": "(((($variable.averageTemperature * ($variable.sensorCount - 1)) + $input.temperatureInput.sensorData.temperature) / $variable.sensorCount) >
($variable.desiredTemperature + $variable.allowedError))",
Detector model definition
{
"eventName": "lowTemperatureThreshold",
"condition": "(((($variable.averageTemperature * ($variable.sensorCount - 1)) + $input.temperatureInput.sensorData.temperature) / $variable.sensorCount) <
($variable.desiredTemperature - $variable.allowedError))",
"condition": "!$variable.noDelay && $variable.enteringNewState", "actions": [
Detector model definition
"condition": "$input.seedTemperatureInput.desiredTemperature !=
$variable.desiredTemperature",
"condition": "$input.temperatureInput.sensorData.temperature <
$variable.anomalousHigh && $input.temperatureInput.sensorData.temperature >
Detector model definition
"condition": "$input.temperatureInput.sensorData.temperature >=
$variable.anomalousHigh || $input.temperatureInput.sensorData.temperature <=
"condition": "$input.temperatureInput.sensorData.temperature >
$variable.rangeHigh",
"condition": "$input.temperatureInput.sensorData.temperature <
$variable.rangeLow",
Detector model definition
"condition": "(((($variable.averageTemperature * ($variable.sensorCount - 1)) + $input.temperatureInput.sensorData.temperature) / $variable.sensorCount) <=
($variable.desiredTemperature - $variable.allowedError)) && $variable.goodToGo == true", "actions": [
"condition": "!$variable.noDelay && $variable.enteringNewState", "actions": [
Detector model definition
"condition": "$input.seedTemperatureInput.desiredTemperature !=
$variable.desiredTemperature",
"condition": "$input.temperatureInput.sensorData.temperature <
$variable.anomalousHigh && $input.temperatureInput.sensorData.temperature >
$variable.anomalousLow", "actions": [ {
"setVariable": {
Detector model definition
"condition": "$input.temperatureInput.sensorData.temperature >=
$variable.anomalousHigh || $input.temperatureInput.sensorData.temperature <=
"condition": "$input.temperatureInput.sensorData.temperature >
$variable.rangeHigh",
Detector model definition
"condition": "$input.temperatureInput.sensorData.temperature <
$variable.rangeLow",
"condition": "(((($variable.averageTemperature * ($variable.sensorCount - 1)) + $input.temperatureInput.sensorData.temperature) / $variable.sensorCount) >=
($variable.desiredTemperature + $variable.allowedError)) && $variable.goodToGo == true", "actions": [
{ "detectorModelConfiguration": { "status": "ACTIVATING",
"lastUpdateTime": 1557523491.168,
"roleArn": "arn:aws:iam::123456789012:role/IoTEventsRole", "creationTime": 1557523491.168,
"detectorModelArn": "arn:aws:iotevents:us-west-2:123456789012:detectorModel/
BatchUpdateDetector example
BatchUpdateDetector example
In this example, "BatchUpdateDetector" is used to change operational parameters for a working detector instance.
"detectorModelName": "areaDetectorModel", "keyValue": "Area51",
BatchPutMessage examples
"value": "0"
}, {
"name": "reportedTemperature", "value": "0.1"
}, {
"name": "resetMe", "value": "true"
} ],
"timers": [ ]
} } ] }
Response:
{ "batchUpdateDetectorErrorEntries": []
}
BatchPutMessage examples
In this example, "BatchPutMessage" is used to create a detector instance for an area and define the initial operating parameters.
CLI command used:
aws iotevents-data batch-put-message --cli-input-json file://seedExample.json
File: seedExample.json
{ "messages": [ {
"messageId": "00001",
"inputName": "seedTemperatureInput",
"payload": "{\"areaId\": \"Area51\", \"desiredTemperature\": 20.0, \"allowedError\":
0.7, \"rangeHigh\": 30.0, \"rangeLow\": 15.0, \"anomalousHigh\": 60.0, \"anomalousLow\":
0.0, \"sensorCount\": 10, \"noDelay\": false}"
} ] }
Response:
{ "BatchPutMessageErrorEntries": []
}
In this example, "BatchPutMessage" is used to report temperature sensor readings for a single sensor
BatchPutMessage examples
File: temperatureExample.json {
"messages": [ {
"messageId": "00005",
"inputName": "temperatureInput",
"payload": "{\"sensorId\": \"05\", \"areaId\": \"Area51\", \"sensorData\":
{\"temperature\": 23.12} }"
} ] }
Response:
{
"BatchPutMessageErrorEntries": []
}
In this example, "BatchPutMessage" is used to change the desired temperature for an area.
CLI command used:
aws iotevents-data batch-put-message --cli-input-json file://seedSetDesiredTemp.json
File: seedSetDesiredTemp.json {
"messages": [ {
"messageId": "00001",
"inputName": "seedTemperatureInput",
"payload": "{\"areaId\": \"Area51\", \"desiredTemperature\": 23.0}"
} ] }
Response:
{
"BatchPutMessageErrorEntries": []
}
Examples of Amazon SNS messages generated by the Area51 detector instance:
Heating system off command> { "eventTime":1557520274729, "payload":{
"actionExecutionId":"f3159081-bac3-38a4-96f7-74af0940d0a4", "detector":{
"detectorModelName":"areaDetectorModel", "keyValue":"Area51",
"detectorModelVersion":"1"
},
"eventTriggerDetails":{
"inputName":"seedTemperatureInput", "messageId":"00001",
BatchPutMessage examples
}, "state":{
"stateName":"start", "variables":{
"detectorModelName":"areaDetectorModel", "keyValue":"Area51",
"detectorModelVersion":"1"
},
"eventTriggerDetails":{
"inputName":"seedTemperatureInput", "messageId":"00001",
"triggerType":"Message"
}, "state":{
"stateName":"start", "variables":{
BatchPutMessage examples
AWS IoT Core rules engine examples
"name": "goodToGo", "value": "false"
} ],
"stateName": "idle", "timers": [
{
"timestamp": 1557520454.0, "name": "idleTimer"
} ] },
"keyValue": "Area51",
"detectorModelName": "areaDetectorModel", "detectorModelVersion": "1"
} }
AWS IoT Core rules engine examples
The following rules republish AWS IoT Events MQTT messages as shadow update request messages. We assume that AWS IoT Core things are defined for a heating unit and a cooling unit for each area that is controlled by the detector model.
In this example, we have defined things named "Area51HeatingUnit" and "Area51CoolingUnit".
CLI command used:
aws iot create-topic-rule --cli-input-json file://ADMShadowCoolOffRule.json
File: ADMShadowCoolOffRule.json
{ "ruleName": "ADMShadowCoolOff", "topicRulePayload": {
"sql": "SELECT topic(3) as state.desired.command FROM 'hvac/Cooling/Off'",
"description": "areaDetectorModel mqtt topic publish to cooling unit shadow request", "ruleDisabled": false,
"awsIotSqlVersion": "2016-03-23", "actions": [
{
"republish": {
"topic": "$$aws/things/${payload.detector.keyValue}CoolingUnit/shadow/update", "roleArn": "arn:aws:iam::123456789012:role/service-role/ADMShadowRole"
} } ] }}
Response: [empty]
CLI command used:
aws iot create-topic-rule --cli-input-json file://ADMShadowCoolOnRule.json
AWS IoT Core rules engine examples
"topicRulePayload": {
"sql": "SELECT topic(3) as state.desired.command FROM 'hvac/Cooling/On'",
"description": "areaDetectorModel mqtt topic publish to cooling unit shadow request", "ruleDisabled": false,
"awsIotSqlVersion": "2016-03-23", "actions": [
{
"republish": {
"topic": "$$aws/things/${payload.detector.keyValue}CoolingUnit/shadow/update", "roleArn": "arn:aws:iam::123456789012:role/service-role/ADMShadowRole"
}
"sql": "SELECT topic(3) as state.desired.command FROM 'hvac/Heating/Off'",
"description": "areaDetectorModel mqtt topic publish to heating unit shadow request", "ruleDisabled": false,
"awsIotSqlVersion": "2016-03-23", "actions": [
{
"republish": {
"topic": "$$aws/things/${payload.detector.keyValue}HeatingUnit/shadow/update", "roleArn": "arn:aws:iam::123456789012:role/service-role/ADMShadowRole"
}
"sql": "SELECT topic(3) as state.desired.command FROM 'hvac/Heating/On'",
"description": "areaDetectorModel mqtt topic publish to heating unit shadow request", "ruleDisabled": false,
"awsIotSqlVersion": "2016-03-23", "actions": [
{
"republish": {
"topic": "$$aws/things/${payload.detector.keyValue}HeatingUnit/shadow/update",
Cranes
} } ] } }
Response: [empty]
Cranes
Background story
An operator of many cranes wants to detect when the machines need maintenance or replacement and trigger appropriate notifications. Each crane has a motor. A motor emits messages (inputs) with information about pressure and temperature. The operator wants two levels of event detectors:
• A crane-level event detector
• A motor-level event detector
Using messages from the motors (that contain metadata with both the "craneId" and the
"motorId"), the operator can execute both levels of event detectors using appropriate routing. When event conditions are met, notifications should be sent to appropriate Amazon SNS topics. The operator can configure the detector models so that duplicate notifications are not raised.
This example demonstrates the following functional capabilities:
• Create, Read, Update, Delete (CRUD) of inputs.
• Create, Read, Update, Delete (CRUD) of event detector models and different versions of event detectors.
• Routing one input to multiple event detectors.
• Ingestion of inputs into a detector model.
• Evaluation of trigger conditions and lifecycle events.
• Ability to refer to state variables in conditions and set their values depending on conditions.
• Runtime orchestration with definition, state, trigger evaluator, and actions executor.
• Execution of actions in ActionsExecutor with an SNS target.
Commands
#Create Pressure Input
aws iotevents create-input --cli-input-json file://pressureInput.json aws iotevents describe-input --input-name PressureInput
aws iotevents update-input --cli-input-json file://pressureInput.json aws iotevents list-inputs
aws iotevents delete-input --input-name PressureInput
#Create Temperature Input