Rules

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 TypeAttributesExampleEdgeCloudDescription
truetype{ "type" : "true" }YesYesAlways evaluates true
falsetype{ "type" : "false" }YesYesAlways evaluates false
equaltype, property, value{ "type" : "equal", "property" : "speed", "value" : "65" }YesYes
not_equaltype, property, value{ "type" : "not_equal", "property" : "speed", "value" : "65" }YesYes
less_thantype, property, value{ "type" : "less_than", "property" : "speed", "value" : "65" }YesYes
less_than_equaltype, property, value{ "type" : "less_than_equal", "property" : "speed", "value" : "65" }YesYes
greater_thantype, property, value{ "type" : "greater_than", "property" : "speed", "value" : "65" }YesYes
greater_than_equaltype, property, value{ "type" : "greater_than_equal", "property" : "speed", "value" : "65" }YesYes
intype, property, value_array{ "type" : "in", "property" : "rate", "value_array" : [2, 2, 3, 4] }YesYes
not_intype, property, value_array{ "type" : "not_in", "property" : "rate", "value_array" : [1, 2, 3, 4] }YesYes
moving_averagetype, property, value, value_type{ "type" : "moving_average", "property": "rate", "value": 5, "value_type": "absolute" }YesNoEvaluates 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_changedtype, property{ "type" : "value_changed", "property": "rate" }YesNoEvaluates 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_errortype, error_type{ "type" : "device_error", "error_type" : "example_error_type" }YesYes
status_changedtype{ "type" : "status_changed" }NoYesEvaluates true if either the 'config_status' or the 'connections_status' differs from the previous statuses
heartbeat_status_changedtype{ "type" : "heartbeat_status_changed" }NoYesEvaluates 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 TypeAttributesExampleEdgeCloud
andtype, rule_conditions{"type" : "and", "rule_conditions" : [ …array of rule conditions…] }YesYes
ortype, rule_conditions{"type" : "or" , "rule_conditions" : [ …array of rule conditions…] }YesYes

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 TypeDescriptionEdgeCloud
notificationFormats a message from a report using a template, and creates a notification in the cloud.NoYes
relayRelays 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.YesNo
mqttRelays the report to the specified MQTT server topic.YesNo
http_requestFormats a message from a report using a template, and sends the message to the specified URL.YesYes
tcpFormats a message from a report using a template, and sends the message to the specified TCP socket address.YesNo
emailFormats a message from a report using a template, and sends an email using an email integration.YesYes
smsFormats a message from a report using a template, and sends an SMS using an sms integration.YesYes
aws_iotRelays the report to Amazon AWS-IoT.YesNo
bluemix_iotRelays the report to IBM Bluemix.YesNo
azure_iotRelays the report to Microsoft Azure IoT.YesNo

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"
  }
}