Filter results by

Develop Rules for devices

ARTIK Cloud Rules are a way to trigger device Actions based on ARTIK Cloud messages. Any ARTIK Cloud device owner can quickly and intuitively define smart device interactions via the Rules UI in My ARTIK Cloud. Using the Rules APIs, developers can programmatically create and manage Rules for a device owner within an application.

ARTIK Cloud Rules overview

This article is an introduction to development using the Rules API. Below, we cover some basic Rules APIs, explain how the Rule body is structured, and describe a case of invalid Rules.

Rules administration

Some basic APIs are summarized below. For the complete Rules API reference, see the API reference.

When the Rule body is returned, it is formatted as a JSON object. The structure is explained in The Rule Body.

To get, create, and update Rules, the application must have READ on the source device and WRITE on the target device of the Rule.

Getting Rules

GET /users/<userID>/rules

This call returns a user's Rules. You must pass the user ID. See the API here.

Getting a specific Rule

GET /rules/<ruleId>

You can also retrieve a Rule by its unique Rule ID, ruleId. This returns the Rule body in JSON format, along with information such as the corresponding user ID, the Rule name and description, and whether or not the Rule is enabled. See the API here.

Creating a Rule

POST /rules

To create a Rule, you must POST the Rule name and body in the request body. The optional scope parameter specifies whether the Rule is accessible to all applications or to the current application only (default).

You may also optionally include the Rule description and enable or disable the Rule. See the API here.

Updating a Rule

PUT /rules/<ruleId>

The same request body parameters used to create a Rule can be modified with this call, using the Rule ID. See the API here.

Testing an Action

POST /rules/<ruleId>/actions

With this call you can test-run the Actions associated with the Rule, using the Rule ID (ruleId).

To test Actions, the application must have WRITE on the target device of the Rule.

Any testable Actions will actually be sent to your device, so be prepared!

An Action is testable if the definition of the Action is static. This means:

In case any Action is not testable, the POST request returns a 400 error and no Action will be executed (including those which are testable). See Invalid Rules for the error code format.

The Rule body

As seen above, the Rule body is formatted in JSON. At the top level, the body has two objects as below. An "if" object defines the conditions; a "then" object defines the Actions to send to a specified destination device once the conditions are met.

1
2
3
4
5
6
7
8
{ 
  "if": { 
    ...
  },
  "then": {
    ...
  }
}

Conditions

ARTIK Cloud checks all incoming messages against the conditions specified in each Rule.

In order to trigger a Rule, all conditions must be met.

Rule conditions are defined in an "if" structure wrapped by an "and" operator.

1
2
3
4
5
6
{ 
  "if": { 
    "and": [
    ]
  } 
}

Rules do not support "or" operators. To accomplish this logic, you can create two Rules.

A condition is defined with at least one ARTIK Cloud device field. A Rule can be scheduled by using a field to define an optional date/time condition. Predicted field values or anomalies can also be evaluated in a Rule using machine learning.

An operator compares the field value from the incoming message to a user-specified operand value.

1
2
3
4
5
6
7
8
9
10
{ 
  "if": { 
    "and": [ { 
      "sdid": ... the device ...,
      "field": ... the field ...,
      "operator": ... the operator ...,
      "operand": { "value": ... the value ... }
    } ]
  } 
}

Conditions linked by the "and" operator do not need to be met synchronically.

A duration condition can optionally be added. This condition matches only if the field and operand values match the operator condition during a specified period of time.

value sets the time duration in seconds. acceptUpdate is a Boolean that determines how the duration is tested when the device returns a valid state:

  • acceptUpdate = true: The duration condition matches even if the field is updated during the period, assuming the operator condition matches.
  • acceptUpdate = false: The duration condition matches only if the field is not updated during the period, even if the operator condition matches.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{ 
  "if": { 
    "and": [ { 
      "sdid": ... the device ...,
      "field": ... the field ...,
      "operator": ... the operator ...,
      "operand": { "value": ... the value... },
      "duration": {
        "value": ... duration in seconds ...,
        "acceptUpdate": ... true/false ...
      }
    } ]
  } 
}

Now let's look at each piece of the Rule condition.

Define a source device

You can define the source device sdid that triggers a Rule condition by specifying its device ID.

1
2
3
4
{
  "sdid": "d1111aaaa",
  ...
}

Alternatively, a Rule condition can trigger if "any" device (owned by the user) of a device type matches the condition. Use dtid to specify the device type ID.

1
2
3
4
5
6
7
{ 
  "sdid": {
    "selector": "any",
    "dtid": "dt777eeee"
  },
  ...
}

A Rule condition can also trigger if "every" device (owned by the user) of a device type matches the condition.

1
2
3
4
5
6
7
{ 
  "sdid": {
    "selector": "every",
    "dtid": "dt777eeee"
  },
  ...
}

If your Rule has multiple conditions, you can only define one "any" for a specific device type. To have more than one condition using this "any" device, do the following:

The first condition using this "any" device should specify an "any" selector. The following conditions that also use this "any" device should specify a "matched" selector.

All conditions should match on the same source device.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{ 
  "if": { 
    "and": [ { 
        "sdid": {
          "selector": "any",
          "dtid": "dt1”
        },
        ...
      },{ 
        "sdid": {
          "selector": "any",
          "dtid": "dt2”
        },
        ...
      }, {
        "sdid": {
          "selector": "matched",
          "dtid": "dt2”
        },
        ...
      }, {
        "sdid": {
          "selector": "matched",
          "dtid": "dt1”
        },
        ...
      }
    ]
  } 
}

Define the device field

A Rule condition tests the specified device field. This must be a valid field for the specified source device, sdid.

1
2
3
4
5
{
  "sdid": "d1111aaaa",
  "field": "steps.walking.count",
  ...
}

Some fields can be defined using groups in a hierarchy. Above, the groups and the final field count are separated with "."

Read our blog post about the Simple Manifest to learn more about device fields and groups.

Apply machine learning

You can optionally define a prediction condition or anomaly detection condition that uses machine learning on a device field from a source device.

  • A prediction condition tests a predicted data value, in a delta time from now, for the device field. "Now" is the time when the Rule is evaluated, i.e. when a new message is received for the device or when the Rule is evaluated because of other conditions (including date/time conditions).
  • An anomaly detection condition tests a boolean that indicates whether a new data value is an anomaly.

To apply machine learning to a Rule, add transformer to the Rule body along with the condition type and its necessary parameters.

A prediction condition requires the parameter predictIn. This specifies the time in seconds from now that a value will be predicted. This must be a positive value (greater than 0).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{ 
  "if": { 
    "and": [ { 
      "sdid": ... the device ...,
      "field": ... the field ...,
      "transformer": {
        "type": "prediction"
        "parameters": { 
          "predictIn": 10
          }
        },
        ...
      } 
    ]
  } 
}

An anomalyDetection condition requires the parameter anomalyDetectionSensitivity. This is a value that specifies how many anomalies should be detected, from 0 (very few) to 100 (many).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{ 
  "if": { 
    "and": [ { 
      "sdid": ... the device...,
      "field": ... the field...,
      "transformer": {
        "type": "anomalyDetection"
        "parameters": { 
          "anomalyDetectionSensitivity": 50
          }
        },
        ...
      } 
    ]
  } 
}

The Rule may return a warning if the machine learning model is not yet ready to use. See Invalid Rules for possible error cases.

Define the operator

The operator tests whether or not the condition is true.

1
2
3
4
5
6
{
  "sdid": "d1111aaaa",
  "field": "state",
  "operator": "=",
  ...
}

Below are the possible operators, dependent on the valueClass of the field:

valueClass of the field valid operators
all valueClasses =, !=

is in message, is not in message
String <, <=, >, >=

contains, does not contain
Long, Double, Float <, <=, >, >=
Boolean No additional operators

Define the operand

The operator compares the operand value to the last value of the incoming message field. If machine learning has been applied, the operand is compared to the predicted value of the message field or the result of anomaly detection.

1
2
3
4
5
6
{
  "sdid": "d1111aaaa",
  "field": "state",
  "operator": "=",
  "operand": { "value": "on" }
}

Define a date/time condition

A Rule can be scheduled by using the optional field datetime with operator and operand in the below format.

1
2
3
4
5
6
7
8
9
10
11
{
  "if": { 
    "and": [ {
      "field": "datetime",
      "operator": ">=",
      "operand": { "value": "0 20 * * *" } // cron format
      }
    ]
  },
...
}

Valid operators are <, <=, =, >, >=.

The date/time value in the operand is written as a cron expression:

1
2
3
4
5
6
7
8
 ┌───────────── min (0 - 59)
 │ ┌────────────── hour (0 - 23)
 │ │ ┌─────────────── day of month (1 - 31)
 │ │ │ ┌──────────────── month (1 - 12)
 │ │ │ │ ┌───────────────── day of week (0 - 6 or names) (0 to 6 are Sunday to Saturday; 7 is also Sunday)
 │ │ │ │ │ ┌───────────────── year (YYYY)
 │ │ │ │ │ │ ┌───────────────── timezone (TZ [timezone]; e.g. "America/Los_Angeles")
 * * * * * * *

Specify timezone with "TZ" followed by a string in the "continent/city" format. If not specified, the default timezone is GMT+0.

The operator compares the date/time to the cron. Below are examples of how the cron is interpreted (for more information, read this tutorial):

Operator Operand Condition
= 0 10 * * * at 10 AM every day
= 0 10 1 1 ? at 10 AM on January 1
<= 0 20 * * * * before 8 PM every day
<= 15 * * * * the first 15 minutes of every hour, every day
>= 0 9 ? * 1-5 * after 9 AM, from Monday to Friday
<= 0 9 ? 10-12 SAT,SUN 2015 before 9 AM, every Saturday and Sunday in October, November, and December in 2015
= 0 20 * * * * TZ Asia/Seoul at 8 PM Seoul time (Korea Standard Time) every day

Rules are evaluated at the beginning of each time interval.

  • A Rule with the date/time condition <= 0 20 * * * * (before 8 PM every day) will be evaluated at cron 0 0 * * * * (at midnight every day).
  • A Rule with the date/time condition <= 30 * * * * * (the first half hour of every hour, every day) will be evaluated at cron 0 * * * * * (the beginning of every hour, every day).

Multiple date/time conditions can be used in a Rule. For example, >= 30 9 * * * AND <= 0 10 * * * defines a Rule that is evaluated between 9:30 and 10:00 AM every day.

Define a duration

An optional duration condition can be added. The value parameter indicates the number of seconds during which the operator condition must match.

The duration condition is tested according to behavior set by acceptUpdate. If this parameter is true, the operand and field values must match for the length of the duration, including any field updates received.

If the parameter is false, the operand and field values must match once with no field updates received for the length of the duration.

1
2
3
4
5
6
7
8
9
{
  "sdid": "d1111aaaa",
  "field": "state",
  "operator": "=",
  "operand": { "value": "on" },
  "duration": {
    "value": 30,
    "acceptUpdate": true
}

Example conditions

Below are examples of conditions, using the syntax described above.

If the state of my bedroom's lightbulb is on:

1
2
3
4
5
6
7
8
9
10
11
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    } ]
  },
  ...
}

If the state of any of my lightbulbs is on:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "if": {
    "and": [ {
      "sdid": {
        "selector": "any",
        "dtid": "dt777eeee"
      },
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    } ]
  },
  ...
}

If the state of any of my lightbulbs is on and the light color is red:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "if": {
    "and": [ {
      "sdid": {
        "selector": "any",
        "dtid": "dt777eeee"
      },
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    }, {
      "sdid": {
        "selector": "matched",
        "dtid": "dt777eeee"
      },
      "field": "color",
      "operator": "=",
      "operand": { "value": "red" }
    } ]
  },
  ...
}

If all of my lightbulbs are on:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "if": {
    "and": [ {
      "sdid": {
        "selector": "every",
        "dtid": "dt777eeee"
      },
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    } ]
  },
  ...
}

If the predicted state of my bedroom's lightbulb is on in one hour:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "transformer": {
        "type": "prediction"
        "parameters": { 
          "predictIn": 3600
          }
        },
      "operator": "=",
      "operand": { "value": "on" }
    } ]
  },
  ...
}

If the state of my bedroom's lightbulb is an anomaly detected with high sensitivity:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "transformer": {
        "type": "anomalyDetection"
        "parameters": { 
          "anomalyDetectionSensitivity": 100
          }
        },
      "operator": "=",
      "operand": { "value": true }
    } ]
  },
  ...
}

If the state of my bedroom's lightbulb is on after 9 AM, from Monday to Friday:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    }, {
      "sdid": "d1111aaaa",
      "field": "datetime",
      "operator": ">=",
      "operand": { "value": "0 9 ? * 1-5 *" }
    } ]
  },
  ...
}

If the state of my bedroom's lightbulb is on for 30 seconds:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" },
      "duration": {
        "value": 30,
        "acceptUpdate": true
    } ]
  },
  ...
}

If the state of my bedroom's lightbulb is on and lightbulb does not send any value for 30 seconds:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" },
      "duration": {
        "value": 30,
        "acceptUpdate": false
    } ]
  },
  ...
}

Actions

If conditions of a Rule are met, the Actions of the Rule are sent.

Actions triggered by a Rule are subject to special rate limits.

Rule Actions are defined in a "then" structure:

1
2
3
4
5
{ 
  "then": {
    ...
  }
}

An Action is defined with a destination device that receives the Action, and an Action to send with some parameters (see below).

ARTIK Cloud supports multiple Actions for each Rule. If the Rule conditions are met, all Actions will be sent.

Define a destination device

You can define the destination device ddid that receives Rule Actions by specifying its device ID.

1
2
3
4
{
  "ddid": "d1111aaaa",
  ...
}

Alternatively, you can use the device that matched one of the "any" conditions of the Rule:

1
2
3
4
5
6
7
{ 
  "ddid": {
    "selector": "matched",
    "dtid": "dt777eeee"
  },
  ...
}

And you can also send the Action to "every" device of a device type:

1
2
3
4
5
6
7
{ 
  "ddid": {
    "selector": "every",
    "dtid": "dt777eeee"
  },
  ...
}

Define the Action to send

A Rule sends the specified action. This must be a valid Action for the specified destination device, ddid.

1
2
3
4
5
{
  "ddid": "d1111aaaa",
  "action": "setOn",
  ...
}

To learn more about Actions, read Posting a message with Actions.

Define the Action parameters

Some Actions include parameters. Below, the value of the parameter is defined under parameters:

1
2
3
4
5
6
7
8
9
{
  "ddid": "d1111aaaa",
  "action": "setColor",
  "parameters": {
    "colorName": {
      "value": "red"
    }
  }
}

Below is a compound parameter:

1
2
3
4
5
6
7
8
9
10
11
12
13
{
  "ddid": "d1111aaaa",
  "action": "setColor",
  "parameters": {
    "colorRGB": {
      "value": {
        "r": { "value": 255 },
        "g": { "value": 0 },
        "b": { "value": 0 },
      }
    }
  }
}

And here are multiple parameters:

1
2
3
4
5
6
7
8
9
{
  "ddid": "d1111aaaa",
  "action": "setColor",
  "parameters": {
    "r": { "value": 255 },
    "g": { "value": 0 },
    "b": { "value": 0 },
  }
}

HTTP request Actions

You can specify the Action httpRequest to make a request to a web service. Parameter values include the HTTP method (GET, POST, PUT, DELETE), headers, URL, and body.

This is useful for prototyping a web application triggered by a Rule, making a call to your personal web server.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
  "then": [
    {
      "action": "httpRequest",
      "parameters": {
        "method": {
          "value": "GET"
        },
        "headers": [
          {
            "key": "Authorization",
            "value": {
              "concat": [
                {
                  "value": "Bearer: "
                },
                {
                  "valueFrom": {
                    "sdid": "3333cccc",
                    "field": "auth"
                  }
                }
              ]
            }
          },
          {
            "key": "Content-Type",
            "value": {
              "value": "application/json"
            }
          }
        ],
        "url": {
          "value": "https//endpoint-to-call.com/test"
        },
        "body": {
          "value": "some data"
        }
      }
    }
  ]
}

Example Rules

Below are examples of Actions with conditions, using the syntax described above.

If the state of my bedroom's first lightbulb is on, then turn on my bedroom's second lightbulb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "if": {
    "and": [ {
      "sdid": "d1111aaaa",
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    } ]
  },
  "then": [ {
    "ddid": "d2222aaaa",
    "action": "setOn",
  } ]
}

If the state of any of my lightbulbs is on, then set their color to red:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "if": {
    "and": [ {
      "sdid": {
        "selector": "any",
        "dtid": "dt777eeee"
      },
      "field": "state",
      "operator": "=",
      "operand": { "value": "on" }
    } ]
  },
  "then": [ {
    "ddid": "d1111aaaa",
    "action": "setColor",
    "parameters": {
    "colorName": {
      "value": "red"
    }
  } ]
}

If the temperature of the room is more than 72°F, then turn on my bedroom's light and set the color to red:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
{
  "if": {
    "and": [ {
      "sdid": "d333bbbb",
      "field": "temperature",
      "operator": ">=",
      "operand": { "value": 72 }
    } ]
  },
  "then": [ {
      "ddid": "d1111aaaa",
      "action": "setOn",
    }, {
      "ddid": "d1111aaaa",
      "action": "setColor",
      "parameters": {
        "colorRGB": {
          "value": {
            "r": { "value": 255 },
            "g": { "value": 0 },
            "b": { "value": 0 },
          }
        }
      }
    }
  ]
}

Advanced Rules

So far, we have discussed how to construct a Rule body to define basic Rules. ARTIK Cloud also allows developers to create advanced Rules, which we describe below.

Dynamic value definitions

Rather than specifying a static value in your Rule (e.g., for the condition operand or an Action parameter), you may want to use a value from an incoming message or a specific device. Or you might want to compare the field value from an incoming message to the value in another device.

You can dynamically define the value from a device field. This is accomplished by replacing value in the Rule with valueFrom, where a device and field are also specified:

1
2
3
4
"valueFrom": {
  "sdid": ...,
  "field": ...
}

Read this blog post to learn how values can be dynamically defined within My ARTIK Cloud.

Define valueFrom device

The source device sdid can be defined from its device ID:

1
2
3
4
"valueFrom": {
  "sdid": "d1111aaaa",
  "field": ...
}

You can also use a "matched" selector. This selects a device of a specified device type that has been matched in an "any" condition:

1
2
3
4
5
6
7
"valueFrom": {
  "sdid": {
    "selector": "matched",
    "dtid": "dt777eeee"
  },
  "field": ...
}

Define valueFrom field

The device field is defined as in a Rule condition.

Applying operations to values

Before using a value from a device field as a parameter or condition value, you may also perform an operation on the value, using a combination of value and valueFrom.

An operation replaces value or valueFrom. For example, if a temperature value is normally specified as:

1
"value": 72

You can use the following operation to specify the temperature plus 5 degrees.

1
2
3
4
5
6
7
8
9
10
"add": [ 
  {
    "valueFrom":  {
      "sdid": "d333bbbb",
      "field": "temperature"
    }
  }, { 
    "value": 5 
  }
]

Operations can be used to specify the value of both the condition and the Action parameter. The following example Rule sends an Action that displays the temperature in a string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
{
  "if": {
    "and": [ {
      "sdid": "d333bbbb",
      "field": "temperature",
      "operator": ">=",
      "operand": { 
        "add": [ 
          {
            "valueFrom":  {
              "sdid": "d444cccc",
              "field": "temperature"
            }
          }, {
            "value": 5
          } 
       ]
     }
  },
  "then": [ {
      "ddid": "d5555cccc",
      "action": "display",
      "parameters": {
        "text": {
          "concat": [ 
            { 
              "value": "Temperature is " 
            }, {
              "valueFrom": {
                "sdid": "d333bbbb",
                "field": "temperature"
              }
            }, {
              "value": "°F"
            }
          ]
        }
      }
    }
  ]
}

These are the possible operations:

Operator Description Result type Cast rules
concat concatenate String Numbers are casted to String

Boolean are casted to "true/"false"
add addition Number Strings are casted to a number if possible; otherwise the string is replaced by "0"

Booleans are casted to 1/0
sub subtraction Number Strings are casted to a number if possible; otherwise the string is replaced by "0"

Booleans are casted to 1/0

Invalid Rules

A Rule may become invalid if, for example, the source or destination devices are deleted. In this case, rather than returning the Rule body in data, the APIs will return an error code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  {
    "error": {
      "code": 4001
      "message": "Validation Error",
      "errors": [  [
            {
               "field":"location of the error ('.' separated string)",
               "messages":["Reason of the error"]
            }, ...
      ] ]
    }
  }
...
}

Rules using machine learning may return a warning if the machine learning model is not yet ready to use.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
  "uid":"aaaa1111",
  "aid":"bbbb2222",
  "id":"cccc3333",
  {
    "warning": {
      "code": 6316
      "message": "Transformers warnings",
      "warnings": [  [
            {
              "modelId":"0000",
              "messages":["is training"]
            },
            {
               "modelId":"0001",
               "messages":["in error", ....]
            }, ...
      ] ]
    }
  }
...
}

Rate limits on Rules

Actions of a Rule must conform to the following rate limits:

  • 5 emails per minute and 50 emails per day
  • 5 HTTP calls per minute and 50 HTTP calls per day

These limits are enforced for Rules created both in My ARTIK Cloud and via the API.