Rule Engine DSL Grammar

A rule is an asset (belongs to a context, is created by a user, has an access list, is audited) in WolkAbout IoT Platform and it is used to create a business logic as a set of conditions and actions. Once all rule conditions are satisfied, each action defined by the rule should be executed.

Rule Engine DSL is used to describe the rule’s conditions and actions. The DSL defines a total of four equally important parts:

  • Things - List of semantics, feeds, and actuators which will be used in the rule
  • Triggers - List of events that can occur on a ‘thing’ that can trigger the checking of conditions specified in the list of conditions. For now, only the UPDATE trigger can be used
  • Conditions - Conditions that must be satisfied for the rule to execute actions. If there are more conditions in the list, ALL must be satisfied
  • Actions - When ALL conditions (from the list of conditions) are satisfied, actions will be executed.

An example of the rule with things, triggers, conditions, and actions:

Things

Each thing is described by its name, its type, and, optionally, a set of descriptors.

Declaration

things:

Content

thing1name : feed [ propertyName = propertyValue, property2name = property2value]
thing2name : actuator [ property1name = thing1name.propertyName, property2name = thing1name]

An example of a thing definition:

Name

A thing has a name by which it is referenced later in the rule. Name must start with a letter and can contain any combination of upper and lower case letters, numbers and underscores. Name cannot be the same as keyword.

Property

Thing can have one or more properties which will be used to uniquely identify it. If no property is defined for thing then the name property is set to thing’s name.

PropertyValue can be numeric literal, string literal, or a reference to the property of another thing.

Feed

Allowed properties:

  • name
Actuator

Thing that can be a target of actuation action.

Allowed properties:

  • name

Descriptors

Descriptors are defined by property, matcher, and value:

  • Properties are defined based on thing type.
  • Matcher can be an exact matcher “=” or a partial matcher “starts with”.
  • Value is any numerical or textual value.

In case a thing type is a semantic, descriptors can be:

  • ID of the semantic.
  • Name of the semantic
  • ID of the parent. Alias: “parent”
  • Hierarchical path
  • Semantic template of the semantic

In case a thing type is a feed, descriptors can be:

  • Name of the feed
  • Value of the feed
  • ID of the parent. Alias: “parent”
  • Hierarchical path

In case a thing type is an actuator, descriptors can be:

  • Name of the actuator
  • Value of the actuator
  • ID of the parent. Alias: “parent”
  • Hierarchical path

Scope

Scope defines the boundaries of the rule. It defines them by providing the lowest possible semantic node in the hierarchy and restricts the rule evaluation for things in that branch of the semantic tree.

Only exact semantic matching is available. This means that exactly one semantic (and it’s elements) can be affected by the rule.

Declaration

scope:

Content

One or many strings separated by ‘/’

An example of a scope definition:

Triggers

Triggers define what kind of an “event” can start rule evaluation.

Declaration

triggers:

Content

At least one definition of a trigger.

Trigger Update Event

Update events trigger ‘listens‘ for VALUE_UPDATED events on specified things.

It is defined by the name of the thing followed by a case-sensitive keyword: “UPDATE”.

Assuming the following things are defined:

An appropriate trigger would be:

In the previous example, “trigger” is a keyword that defines the start of the trigger definition, “temperature” is a reference to the previously defined feed thing, and “UPDATE” is the type of event that the rule will listen for.

In the given example, any value update on any feed named “temperature” that belongs to any semantic of semantic template “Office” would start rule evaluation and potential execution of any actions defined by the rule.

Conditions

Conditions represent a logical expression that needs to be positively evaluated before a rule can execute its actions.

Logical expressions are always evaluated to be either “true” or “false”. The top-level expression MUST be a logical expression.

Expressions can be one of six types:

  1. Value Mathematical expression
  2. Value String expression
  3. Logical Math expression
  4. Logical String expression
  5. Logical Not expression
  6. Logical Boolean expression

Value expressions are always evaluated to a specific value that can be compared with another value.

Basic value expression - Mathematical expression

Mathematical value expressions represent either a numeric value or a mathematical operation on one or more mathematical values.

Supported mathematical operations are:

  1. Addition: A+B
  2. Subtraction: A-B
  3. Multiplication: A*B
  4. Division: A/B
  5. To the power of: POW(A, B)
  6. Minimum: MIN(A, B, C…)
  7. Maximum: MAX(A, B, C…)
  8. Absolute: ABS(A), |A|
  9. Negative: -A
  10. Squared: SQUARE(A)

Assuming that this is the rule definition:

A few examples of mathematical values would be:

5
temp.value
temp.value + 5
(temp.value + temp2.value) / 2

Value expression - String expression

String value expressions represent textual values.

Assuming that this is the rule definition:

A few examples of string values would be:

“ON”
'OFF'
ac.value

Logical expression - Mathematical expression

Mathematical logical expressions represent a simple comparison between two mathematical value expressions.

Supported comparisons are:

  1. Equals: A==B
  2. Not Equals: A!=B
  3. Greater than: A>B
  4. Lesser than: A<B
  5. Greater or equal: A >= B
  6. Lesser or equal: A<=B

Assuming that this is the rule definition:

A few examples of mathematical comparisons would be:

temp.value > 30
temp.value > temp2.value + 5
(temp.value + temp2.value) / 2 > 30
|temp.value - temp2.value| > 5

Logical expression - String expression

String logical expressions represent a simple validation between two string expressions.

Supported validations are:

  1. Equals: A==B
  2. Not Equals: A!=B
  3. Starts with: A starts with B
  4. Contains: A contains B

Assuming that this is the rule definition:

A few examples of string validation would be:

ac.value == 'OFF'
ac.value starts with 'O'
ac.name contains 'ac'

Logical expression - Boolean expression

Logical boolean expression is an amalgamation of any number of logical expressions connected by a logical operator.

Supported boolean operations are:

  1. AND: A and B, A && B
  2. OR: A or B, A || B
  3. XOR: A xor B, A ^ B

Assuming that this is the rule definition:

A few examples of logical expressions would be:

temperature.value > 25 and ac.value == 'OFF'
temperature.value <= 25 and ac.value == 'ON'
(temperature.value <= 10 or temperature.value >= 30) and ac.value == ‘OFF’

Logical expression - Not expression

Logical not expression reverses the evaluation result of any logical expression.

It is represented by a “!” symbol.

Rule

Inside the DSL editor, you will also come across a rule definition, which is identical to defining conditions and actions separately.

Declaration

rule:

or

condition:
actions:

Content

Zero or one definition of conditions followed by one or more actions

action
{ action1; action2 }
{ action1
  action2 }
if condition then action
if condition -> action

Condition

Numeric comparison

Comparison between variables, numeric values or expressions which yield numeric value:

value1 > value2
value1 < value2
value1 >= value2
value1 <= value2
value1 == value2
value1 != value2

Value can be a numeric literal, numeric expression, or variable.

A few examples:

temperature > 30
temperature.value < 25
abs(temp - temp2) >= 5
temp * 0.2 == 4

String comparison

Comparison between variables or string values

value1 == value2
value1 != value2
value1 contains value2
value1 starts with value2

Value is either a string literal or variable.

Example:

message == “test”
alarm1.value != alarm2.value
alarm contains “ERROR”
text starts with “Hello”

Logical expression

All comparison conditions evaluate to boolean value i.e. true or false, which can then be used in logical expressions. Expressions can be grouped using parentheses:

not condition
!condition
condition1 and condition2
condition1 && condition2
condition1 or condition2
condition1 || condition2
condition1 xor condition2
condition1 ^ condition2
condition1 and (condition2 or condition3)

Example:

not temperature > 30
temperature > 25 and AC == “OFF”
temperature > 25 and (AC == “OFF” or between 07:00 and 17:00)

Actions

Once a rule has been satisfied, all of its actions will be executed.

Actions are defined within the “Rule” part of the DSL, after the conditions, separated by “->” symbols.

Rule engine supports five action types:

  1. Actuate
  2. Set state
  3. Generate message
  4. Send email
  5. Send push notification

Most actions require string parameters to work correctly.

String parameters also support value placeholders in the form of ${thing.property}.

High temperature in ${room.name}.
Flood detected at ${house.name}.

In the examples given above, “room” and “house” are semantic things.

Multiple actions must be surrounded by braces and separated by semicolon or newline.

Action - Actuate

Actuate action will attempt to actuate an actuator with the given value.

It requires a reference to an actuator thing and a new value.

thingName = value
thingName.value = value
SET thingName to value
SET thingName.value to value

ThingName must be defined in things section as an actuator.

Value is either string literal, numeric literal, or variable.

Example of a rule that contains an actuate action:

Action - Set State

Set state action will change the state of a thing.

Set state action requires a reference to a thing, a new state, and a message.

Available states (case-sensitive) are NORMAL, WARNING, and ERROR.

Valid statements are:

thingName = alarmState message textMessage
thingName.state = alarmState message textMessage
SET thingName to alarmState message textMessage
SET thingName.state to alarmState message textMessage

ThingName must be defined in things section.

TextMessage is string literal.

Example of a rule that contains a “set state” action:

Action - Generate Message

Generate message action will create a new message based on the provided parameters.

It requires three parameters: message type, message body, and a list of recipients.

Message types (case-sensitive) are INFO, WARNING, ALARM.

Valid statements are:

send message messageType body bodyText to user userEmail
send message messageType bodyText to users userEmail1, userEmail2
send message messageType body bodyText to group groupName
send message messageType bodyText to groups groupName1, groupName2

BodyText, userEmail and groupName are string literals.

MessageType is INFO, WARNING, ALARM, or OFF.

Example of a rule that contains a “generate message” action:

Action - Send Email

Send email will send a new email based on the provided parameters.

It requires three parameters: title, body, and a list of recipients.

Valid statements are:

send email title titleText, body bodyText to user userEmail
send email titleText, bodyText to users userEmail1, userEmail2
send email title titleText, body bodyText to group groupName
send email titleText, bodyText to groups groupName1, groupName2

TitleText, bodyText, userEmail, and groupName are string literals.

Example of a rule that contains a “send email” action:

Action - Send Push Notification

Send push notification action will attempt to send a push notification to Android and/or iOS devices.

It requires three parameters: title, body, and a list of recipients.

Valid statements are:

send notification title titleText, body bodyText to user userEmail
send notification titleText, bodyText to users userEmail1, userEmail2
send notification title titleText, body bodyText to group groupName
send notification titleText, bodyText to groups groupName1, groupName2

TitleText, bodyText, userEmail, and groupName are string literals.

Example of a rule that contains a “send push notification” action:

Types

String literal

String literal is any text surrounded by “double” or ‘single’ quotes.

Example:

“Some text” - Some text
‘Some other text’ - Some other text
“Some text containing ‘quotes’” - Some text containing ‘quotes’
‘Some other text containing “quotes”’ - Some other text containing “quotes”

Numeric literal

Example:

15
7.23
-0.06

Numeric expression

value
value1 + value2
value1 - value2
value1 * value2
value1 / value2
-value
abs(value)
|value|
square(value)
pow(value1, value2)
min(value1, value2)
max(value1, value2)

Value is a numeric literal, numeric expression or variable.

Example:

15 + 45.3
15 - 45.3
15 * 45.3
15 / 45.3
-temp
abs(temp)
square(temp)
pow(temp, 3)
min(temp, 25)
max(temp, 25)

Variable

Value of another thing’s property. The thing must be defined in things section.

thingName.propertyName
thingName

If property name is not specified then the ‘value’ property is used.

Example:

ac.value - Accesses the value property of thing ac
office.name - Accesses the name property of thing office
temperature - Accesses the value property of thing temperature

Keywords

Keywords are reserved for use and cannot be used for naming things. Keywords can be used normally in strings.

Case-Insensitive keywords

things, scope, triggers, rule, condition, actions, title, body, user, users, group, groups, actuator, feed, and, or, xor, not, contains, starts with, abs, pow, square, root, sqrt, min, max, if, then, else, set, send, to, on, message, email, notification

Case-Sensitive keywords

UPDATE, ERROR, WARNING, NORMAL, INFO, ALARM, OFF

Example:

things:
   JD_Building: semantic
   temperature: feed
   ac: actuator
scope:
   JD_Building.Offices
trigger:
   temperature UPDATE
rule:
   if temperature > 25 and ac == 'OFF' -> ac = 'ON'