Rules

The Rules service allows for "macros" to be run at the edge, triggered by a time-based schedule or a telemetry-based condition ("listeners").

A macro can run an Action on a Thing, publish an Event for a Thing, set a Property on a Thing, or publish telemetry as a Thing. A macro can be created and managed using the REST API or by creating a specific Thing schema and setting the appropriate property values.

A time-based schedule can trigger a macro at a specified time (once) or repeatedly (cron based; accepted formats are the standard 5-field format, the nonstandard predefined scheduling definitions as well as the Quartz 6-field format). A schedule can be created and managed using the REST API (recommended) or by creating a specific Thing schema and setting the appropriate property values.

A telemetry-based condition can trigger a macro when a Thing's Property value meets specific requirements, such as comparing against a pre-defined value or telemetry data coming from a different Property/Thing. A listener can be created and managed using the REST API or by creating a specific Thing schema and setting the appropriate Property values.

The macros, schedules and listeners have various configuration options which are described in more detail on the API documentation pages. See also the explanations for various configuration options listed with the Rules schemas, notable for macroId and thingId lists.

When configuration is done using Thing schemas the REST API should not be used to make changes to these configurations. They should only be managed through the Property values of the Things.

Timezone

The Rules service can be instantiated using a timezone following the definitions of the IANA Timezone Database (https://www.iana.org/time-zones); for example, America/New_York.

If the timezone is not specified for the service, UTC will be used.

The timezone can be retrieved or set using the following API endpoints (see API documentation for the link):

GET     /support/rules/timezone
PUT     /support/rules/timezone

API Documentation

The API documentation can be found in the ECP Docs section of https://openapi.swx.altairone.com/. The various configuration options are described in detail in the request body schema definitions as well as in the provided examples.

Available endpoints:

For listeners:

POST    /support/rules/listeners
GET     /support/rules/listeners
GET     /support/rules/listeners/{listener-id}
PUT     /support/rules/listeners/{listener-id}
DELETE  /support/rules/listeners/{listener-id}

For macros:

POST    /support/rules/macros
GET     /support/rules/macros
GET     /support/rules/macros/{macro-id}
PUT     /support/rules/macros/{macro-id}
DELETE  /support/rules/macros/{macro-id}

For schedules:

POST    /support/rules/schedules
GET     /support/rules/schedules
GET     /support/rules/schedules/{schedule-id}
PUT     /support/rules/schedules/{schedule-id}
DELETE  /support/rules/schedules/{schedule-id}

Schemas

Create a Thing on the edge using one of the schemas below and then set the Property values (start with enabled=false). The edge will perform validation and update the value of "verification-status" accordingly. When valid, the enabled property can be set to true and the macro will be instantiated on the edge.

Listeners

A listener uses incoming telemetry data to verify if a pre-defined condition is met. The ECP uses the publishTag "raw" for telemetry data coming from end devices. Plugin services are allowed to pulished processed telemetry data with a custom publishTag. The Rules services can be configured to use publishTags other than "raw" to listen for telemetry data. That is why the publishTag should be specified on the listener schemas.

The config section uses compareFrom and compareTo sections, the conditional, the repeats and within properties and the pause property. The conditional can be one of: "eq", "neq", "gt", "gte", "lt" or "lte". The repeats property can be set to specify the number of times the condition should be met consecutively before triggering the macro. If the within property is set, then this has to take place within this many seconds. The pause property can be set to not trigger again until at least this many seconds have passed.

For a property threshold schema:
{
    "@type": [
        "swx:listener-property-threshold"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "compareFrom": {
                    "properties": {
                        "count": {
                            "type": "integer"
                        },
                        "mode": {
                            "enum": [
                                "mean",
                                "std-dev"
                            ],
                            "type": "string"
                        },
                        "property": {
                            "type": "string"
                        }
                    },
                    "type": "object"
                },
                "compareTo": {
                    "properties": {
                        "value": {
                            "type": "string"
                        }
                    },
                    "type": "object"
                },
                "conditional": {
                    "enum": [
                        "eq",
                        "neq",
                        "gt",
                        "gte",
                        "lt",
                        "lte"
                    ],
                    "type": "string"
                },
                "pause": {
                    "type": "integer"
                },
                "repeats": {
                    "type": "integer"
                },
                "within": {
                    "type": "integer"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "macroId": {
            "type": "string"
        },
        "publishTag": {
            "type": "string"
        },
        "thingId": {
            "type": "string"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "listener-property-threshold"
}

The compareFrom section needs to specify the Property of the Thing (thingId on the root) used to compare from. If count is set to greater than one then this many data point will be collected before doing the calculation specified in mode (this can be mean or std-dev). If count and mode are not specified then a single data point will be used for the comparison.

The compareTo section specifies the value used to compare to. This will be type cast to match the type of the incoming telemetry data.

The macroId can be a single valid Macro ID or a comma separated list (no spaces) of valid Macro IDs.

For a property value schema:
{
    "@type": [
        "swx:listener-property-value"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "compareFrom": {
                    "properties": {
                        "count": {
                            "type": "integer"
                        },
                        "mode": {
                            "enum": [
                                "mean",
                                "std-dev"
                            ],
                            "type": "string"
                        },
                        "property": {
                            "type": "string"
                        }
                    },
                    "type": "object"
                },
                "compareTo": {
                    "properties": {
                        "count": {
                            "type": "integer"
                        },
                        "mode": {
                            "enum": [
                                "all",
                                "any",
                                "mean",
                                "std-dev"
                            ],
                            "type": "string"
                        },
                        "property": {
                            "type": "string"
                        },
                        "thingId": {
                            "type": "string"
                        }
                    },
                    "type": "object"
                },
                "conditional": {
                    "enum": [
                        "eq",
                        "neq",
                        "gt",
                        "gte",
                        "lt",
                        "lte"
                    ],
                    "type": "string"
                },
                "pause": {
                    "type": "integer"
                },
                "repeats": {
                    "type": "integer"
                },
                "within": {
                    "type": "integer"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "macroId": {
            "type": "string"
        },
        "publishTag": {
            "type": "string"
        },
        "thingId": {
            "type": "string"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "listener-property-value"
}

The compareFrom section is the same as for the property threshold schema.

The compareTo section needs to specifiy the thingId and property of which to use the telemetry data to compare to. If count is set to greater than one then this many data point will be collected before doing the calculation specified in mode (this can be mean or std-dev). If count and mode are not specified then a single data point will be used for the comparison.

The macroId can be a single valid Macro ID or a comma separated list (no spaces) of valid Macro IDs.

Macros

For a macro action schema:
{
    "@type": [
        "swx:macro-action"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "action": {
                    "type": "string"
                },
                "input": {
                    "type": "string"
                },
                "thingId": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "macro-action"
}

The config section is used to specify which Action should be run on which Thing. The input is constructed as a JSON string. The input structure should match the input defined on the action of the Thing schema (on which to run the action). Dynamic replacement using the conditional value can be used. See the API documentation for more information.

The thingId can be a single valid Thing UID or a comma separated list (no spaces) of valid Thing UIDs. When specifying a list make sure that all Things have the same schema structure.

For a macro event schema:
{
    "@type": [
        "swx:macro-event"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "event": {
                    "type": "string"
                },
                "message": {
                    "type": "string"
                },
                "thingId": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "macro-event"
}

The config section is used to specify which Event should be published on which Thing. An optional message can be set to be included in the payload of the Event. The payload already includes the trigger condition values.

The thingId can be a single valid Thing UID or a comma separated list (no spaces) of valid Thing UIDs. When specifying a list make sure that all Things have the same schema structure.

For a macro property schema:
{
    "@type": [
        "swx:macro-property"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "property": {
                    "type": "string"
                },
                "thingId": {
                    "type": "string"
                },
                "value": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "macro-property"
}

The config section is used to specify which property of which Thing should be set. Dynamic replacement using the conditional value can be used. See the API documentation for more information.

The thingId can be a single valid Thing UID or a comma separated list (no spaces) of valid Thing UIDs. When specifying a list make sure that all Things have the same schema structure.

For a macro rest schema:
{
    "@type": [
        "swx:macro-rest"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "url": {
                    "type": "string"
                },
                "method": {
                    "type": "string"
                },
                "body": {
                    "type": "string"
                },
                "auth": {
                    "type": "object",
                    "properties": {
                        "type": {
                            "type": "string"
                        },
                        "username": {
                            "type": "string"
                        },
                        "password": {
                            "type": "string"
                        },
                        "clientId": {
                            "type": "string"
                        },
                        "clientSecret": {
                            "type": "string"
                        },
                        "scope": {
                            "type": "string"
                        }
                    }
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "macro-rest"
}

The config section is used to specify URL, request method and request body for the API request, as well as the type of authentication used. See the API documentation for more details.

For a macro telemetry schema:
{
    "@type": [
        "swx:macro-telemetry"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "data": {
                    "type": "string"
                },
                "thingId": {
                    "type": "string"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "macro-telemetry"
}

The config section is used to specify what telemetry to publish for which Thing. The data section is constructed as a JSON string should contain an object with property keys as defined on the Thing itself. Dynamic replacement using the conditional value can be used. See the API documentation for more information.

The thingId can be a single valid Thing UID or a comma separated list (no spaces) of valid Thing UIDs. When specifying a list make sure that all Things have the same schema structure.

Schedules

For a schedule once schema:
{
    "@type": [
        "swx:schedule-once"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "properties": {
                "day": {
                    "type": "integer"
                },
                "hour": {
                    "type": "integer"
                },
                "minute": {
                    "type": "integer"
                },
                "month": {
                    "type": "integer"
                },
                "second": {
                    "type": "integer"
                },
                "timezone": {
                    "type": "string"
                },
                "year": {
                    "type": "integer"
                }
            },
            "type": "object"
        },
        "enabled": {
            "type": "boolean"
        },
        "macroId": {
            "type": "string"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "schedule-once"
}

The config section is used to set the date and time of the trigger. The timezone is optional, by default the timezone the Rules service was instantiated with will be used.

The macroId can be a single valid Macro ID or a comma separated list (no spaces) of valid Macro IDs.

For a repeat schedule schema:
{
    "@type": [
        "swx:schedule-repeat"
    ],
    "actions": {},
    "description": "",
    "events": {},
    "properties": {
        "config": {
            "type": "string"
        },
        "enabled": {
            "type": "boolean"
        },
        "macroId": {
            "type": "string"
        },
        "verification-status": {
            "type": "string"
        }
    },
    "title": "schedule-repeat"
}

The config section is used to set a repeat schedule using a cron format as described here: https://en.wikipedia.org/wiki/Cron. The timezone used is the one the Rules service was instantiated with.

The macroId can be a single valid Macro ID or a comma separated list (no spaces) of valid Macro IDs.