Policies are defined in the API as rules. A rule consists of several pieces:
description
– a text description.active
– boolean indicating if the rule is active.cloud_rule
– boolean indicating if the rule should be evaluated in the EdgeIQ Cloud. Some conditions are only available in the cloud.condition
– an object representing the rule condition to apply. This may be a nested object depending on the type of condition it is or it may not be if the condition is, for instance, a simple comparison of equality. The attributes of this object vary based on the type. These differences are documented later.then_actions
– an array of rule action objects. These are the actions that will take place if the condition(s) of the rule are met. More details on the attributes and types of these actions follow.else_actions
– an array of rule action objects. These are the actions that will take place if the rule conditions are not met. The types of actions and attributes for else_actions are the same specification as then_actions.
Cloud vs Edge Rules
Rules can be executed either in the cloud or on a downstream device such as a gateway device type running EdgeIQ's edge software. If the rule cloud_rule
parameter is true, the rule will be evaluated in the EdgeIQ Cloud ingest Rules Engine. If it is false, the rule will not be executed in the cloud. Rule conditions may be available on both environments. Actions are generally only available in one environment, although some may be available in both. For more information, see the /rules/actions/types
and /rules/conditions/types
paths in the API (also see below in the executable API documentation). The EdgeIQ Portal will also help you craft a rule taking these details into account.
Rule Conditions
Below is a list of rule conditions and their attributes with example JSON representing them:
Rule Condition Type | Attributes | Example | Edge | Cloud | Description |
---|---|---|---|---|---|
true | type | { "type" : "true" } | Yes | Yes | Always evaluates true |
false | type | { "type" : "false" } | Yes | Yes | Always evaluates false |
equal | type, property, value | { "type" : "equal", "property" : "speed", "value" : "65" } | Yes | Yes | |
not_equal | type, property, value | { "type" : "not_equal", "property" : "speed", "value" : "65" } | Yes | Yes | |
less_than | type, property, value | { "type" : "less_than", "property" : "speed", "value" : "65" } | Yes | Yes | |
less_than_equal | type, property, value | { "type" : "less_than_equal", "property" : "speed", "value" : "65" } | Yes | Yes | |
greater_than | type, property, value | { "type" : "greater_than", "property" : "speed", "value" : "65" } | Yes | Yes | |
greater_than_equal | type, property, value | { "type" : "greater_than_equal", "property" : "speed", "value" : "65" } | Yes | Yes | |
in | type, property, value_array | { "type" : "in", "property" : "rate", "value_array" : [2, 2, 3, 4] } | Yes | Yes | |
not_in | type, property, value_array | { "type" : "not_in", "property" : "rate", "value_array" : [1, 2, 3, 4] } | Yes | Yes | |
moving_average | type, property, value, value_type | { "type" : "moving_average", "property": "rate", "value": 5, "value_type": "absolute" } | Yes | No | Evaluates true if the difference of the report 'property' value's moving average of the past 25 reports' data is greater than or equal to 'value'. The difference can be calculated as an absolute value or percentage change using 'value_type' = 'absolute' or 'percent |
value_changed | type, property | { "type" : "value_changed", "property": "rate" } | Yes | No | Evaluates true if report 'property' value differs from the previous report. If 'property' is set to '' or 'any', the condition evaluates true if any property values differ from the previous report |
device_error | type, error_type | { "type" : "device_error", "error_type" : "example_error_type" } | Yes | Yes | |
status_changed | type | { "type" : "status_changed" } | No | Yes | Evaluates true if either the 'config_status' or the 'connections_status' differs from the previous statuses |
heartbeat_status_changed | type | { "type" : "heartbeat_status_changed" } | No | Yes | Evaluates true if the 'heartbeat_status' value differs from the previous heartbeat report |
In addition to these comparison rule conditions, join conditions exist as well. Join conditions have an array of other conditions (even other join conditions) to perform logic with varying levels of dependency. The join conditions are below:
Rule Condition Type | Attributes | Example | Edge | Cloud |
---|---|---|---|---|
and | type, rule_conditions | {"type" : "and", "rule_conditions" : [ …array of rule conditions…] } | Yes | Yes |
or | type, rule_conditions | {"type" : "or" , "rule_conditions" : [ …array of rule conditions…] } | Yes | Yes |
Rule Actions
Rule actions are what happens when a rule’s criteria are either met (then_actions) or not met (else_actions). Below is a list of available actions, their properties, and example JSON:
Rule Action Type | Description | Edge | Cloud |
---|---|---|---|
notification | Formats a message from a report using a template, and creates a notification in the cloud. | No | Yes |
relay | Relays the report to the EdgeIQ cloud platform. Note that this is intended for testing and verification only, not for production use. Messages are limited to 1 per 10 seconds per device. | Yes | No |
mqtt | Relays the report to the specified MQTT server topic. | Yes | No |
http_request | Formats a message from a report using a template, and sends the message to the specified URL. | Yes | Yes |
tcp | Formats a message from a report using a template, and sends the message to the specified TCP socket address. | Yes | No |
email | Formats a message from a report using a template, and sends an email using an email integration. | Yes | Yes |
sms | Formats a message from a report using a template, and sends an SMS using an sms integration. | Yes | Yes |
aws_iot | Relays the report to Amazon AWS-IoT. | Yes | No |
bluemix_iot | Relays the report to IBM Bluemix. | Yes | No |
azure_iot | Relays the report to Microsoft Azure IoT. | Yes | No |
Action Frequency
The action_frequency field is helpful to limit the number to times an action fires when a condition is continuously met. For example, if your device is reporting a temperature > 100 every 5 seconds, you probably don't want to get an SMS every 5 seconds. The action_frequency can be an integer number of seconds between executing the action or the string 'once' which keeps the action from executing until after the rule has been cleared.
action_frequency
can be a string constant or a number.
If the value is a number, it is the minimum number of seconds between executing the action.
If the value is once
the rule action will only fire once until the rule is cleared.
If at any time the rule is cleared (goes from :fail to :pass for a then_action), the counter is reset.
Forwarding or Relaying Message
For any action that allows a message, for instance, but not limited to, http
, email
or sms
, body templates are allowed to give the user control over the forwarded message body. To forward the payload of the report field as is, leave the body template field blank. You may also use our body templating features to control the contents of the message.
Body Templates
For any action that allows a message, for instance, but not limited to, http
, email
or sms
, templates are allowed to give the user control over the forwarded message body. The contents of the body_template
attribute of the action will have access to the following objects:
.Rule
.Report
.Device
.DeviceType
.DeviceError
.DeviceConfig
.Rule
, .Device
, .DeviceType
, .DeviceError
, and .DeviceConfig
are objects of that type from the API, and expose the values of those objects for use in the template. See also documentation on Devices and Device Types for more information.
The parameters of those objects are addressable using dot notation, placed within double braces. For example, the device's unique id is referenced as {{ .Device.UniqueId }}
. "UpperCamelCase" is required for referencing all variables.
The .Report
object contains whatever custom data is in the report in a parameter called Payload
- thus, to reference a custom report value called foo
, the template must contain {{ .Report.Payload.foo }}
. The parameters on the payload will be in whatever case they are in the payload - unchanged by the system.
Also please note that for historical reasons, all Id
fields, including Unique ID are upper case ID
on cloud rules and mixed-case Id
on edge.
Examples
Here is an example body template referencing the device unique id and an example temp
parameter from an endpoint device report.
{...
"body_template": "{{ .Device.UniqueId }} received report containing temperature: {{ .Report.Payload.temp }}"
}
Below are a few examples of JSON that could be passed into the platform to create a rule:
If a payload value is greater than some threshold:
{
"rule": {
"description": "greater than",
"active": true,
"cloud_rule": true,
"condition": {
"type": "greater_than",
"property": "speed",
"value": "65"
},
"then_actions": [
{
"type": "email",
"send_to": "[email protected]"
}
],
"else_actions": []
}
}
A few conditions that must all be true…
{
"rule": {
"description": "everything must be",
"active": true,
"cloud_rule": true,
"condition": {
"type": "and",
"rule_conditions": [
{
"type": "less_than_equal",
"property": "gps_accuracy",
"value": "4"
},
{
"type": "equal",
"property": "longitude",
"value": "134"
},
{
"type": "greater_than_equal",
"property": "speed",
"value": "50"
}
]
},
"then_actions": [
{
"type": "sms",
"send_to": "13035551212"
}
],
"else_actions": [
{
"type": "email",
"send_to": "[email protected]"
}
]
}
}
This example shows a moving average rule condition, which is useful for detecting trends in the report data. The rule examines the most recent reports containing the specified property
(minimum of 10 reports, maximum of 25). The average property
value of the most recent 5 reports is calculated and is compared to the average property
value of the earlier reports in the set. If the average has changed by at least value
(in either direction), the rule condition evaluates to true
.
{
"rule": {
"description": "moving average changed by at least 2.0",
"active": true,
"cloud_rule": true,
"condition": {
"type": "moving_average",
"property": "speed",
"value": 2,
"value_type": "absolute"
},
"then_actions": [
{
"type": "email",
"send_to": "[email protected]"
}
],
"else_actions": []
}
}
The moving average rule condition can also calculate based on a percent change in average. For example, this rule will trigger when the moving average has changed by at least 10%:
{
"rule": {
"description": "moving average changed by at least 2.0",
"active": true,
"cloud_rule": true,
"condition": {
"type": "moving_average",
"property": "speed",
"value": 10,
"value_type": "percent"
},
"then_actions": [
{
"type": "email",
"send_to": "[email protected]"
}
],
"else_actions": []
}
}
Nested Payloads
Finally, knowing that some devices may have nested payloads and the property we seek to compare against may be several levels deep, we have allowed for dot notation to access n levels of nesting. For example, see the altered JSON below. In it, we have specified the "property" for the greater_than to be "tractor.speed".
{
"rule": {
"description": "greater than",
"active": true,
"cloud_rule": true,
"condition": {
"type": "greater_than",
"property": "tractor.speed",
"value": "65"
},
"then_actions": [
{
"type": "email",
"send_to": "[email protected]"
}
],
"else_actions": []
}
}
So then, if we were to inspect the payload JSON below, we would find the appropriate field and compare against it given the condition in the rule:
{
"payload": {
"tractor": {
"speed" : 75,
"heading" :93.4
},
"trailer" : {
"status" : "empty"
}
}
}
Preserving Object Structures
Sometimes you may want to pass along an object from the report as-is, but send other data along with it, perhaps from the device's data. There is a "function" called json_object
which will do so. Here's an example:
{
"part_number": "{{.Device.Metadata.part_number}}",
"payload": {{json_object .Report.Payload}}
}
Given a report like this:
{
"temperature": "30",
"battery_charge": "88"
}
This will produce a json object with the entire report's payload in the payload
field, and part_number
at the top level of the object:
{
"part_number": "SKU123",
"payload": {
"temperature": "30",
"battery_charge": "88"
}
}