Automation Rule

Introduction

One very powerful capability of a site controller is the possibility of take actions based in the parameters that have been measured from the devices. This feature set is provided by the the module Automation Controller (AC). This module allows us to configure complex rules that will execute action in the system. In this document we will document its capabilities and configuration.

On this page:

Processing logic

The AC operates with a set of rules, given by its configuration. Each of the rules is processed independent to other rules and their data (a configuration of only one rule for the AC would be OK), but the outcome of one rule may affect other rules.

Workflow

The AC uses configured action rules that define triggers for the start of a rule. The rule itself evaluates the results from the trigger and defines a set of conditions perform actions:

  • Publish Result, e.g. set temperature sensor result to 25 degrees
  • Publish Event, e.g. send an event temperature alarm critical
  • Execute Action, e.g. switch on the red light

Timers can be used to delay or to schedule periodic execution, e.g. turn on the red light every two minutes.

Use Cases

Some example use cases to show the power of the AC. Below assumes a configured set of sensors, virtual sensors and outputs.

  • Turn on the yellow light if the temperature exceed 25 degrees
  • Turn on the yellow light for 20 seconds if the temperature exceed 25 degrees
  • Turn on the green light for 5 seconds every 5 minutes if there are no alarms
  • Turn on the red light if there the temperature reading is above 30 degree or a wrong keypad code was entered or the door was opened
  • Reset all alarms if a correct access code is entered
  • Show all temperature alarms in one single Temperature_Alarm sensors
    • you can have multiple temperature readings and update a global a virtual sensor that holds the overall temperature state
  • Call the API for a connected Cisco Camera to make a snapshot if the door is opened
  • Switch on the outdoor light if a vibration on the enclosure is detected for more than 5 seconds


Rule Structure

The AC operates with a set of rules, given by its configuration and requires the following mandatory parameters:

  • unique name for the rule
  • one or more triggers

all other sets like events, actions or states are optional and can be combined deeply. Below is a bare skeleton of a rule.

<rule rule_id="Monitor_Chute_Changes">
    <triggers>
        ...
    </triggers>
    <timers>
    </timers>
    <conditions>
        ...
    </conditions>
</rule> 

Triggers

Each rule must have one or more triggers. A trigger is either a calibrated result or a sensor event. While updating its own configuration the AC subscribes for the calibrated results or sensor events which are defined in the trigger section of the rule configuration.


Following example will fire if one of these triggers are detected:

  1. If sensor Motion_Control changes its state (event)
  2. If sensor Temperature changes its reading (calibrated result)
  3. If sensor Access_Alarm changes its reading (calibrated result)
<rule rule_id="BreakIn"> 
    <triggers>
        <trigger value_name="motion" trigger_topic="calibrated_result" sensor_id="BTS_Motion_Control_AdamDI3" value_type="boolean"/>
        <trigger value_name="door_open" trigger_topic="calibrated_result" sensor_id="BTS_ShelterDoor_AdamDI0" value_type="boolean"/>
        <trigger value_name="arm_state" trigger_topic="calibrated_result" sensor_id="BTS_arm_state" value_type="string"/>
    </triggers>
    ...
</rule>


The same calibrated result or sensor event can be trigger for more then one rule.

Each time the AC receives a trigger, all rules which have a trigger with that sensor_id are processed sequential. The order of sequential processing (which rule comes first) is not defined.

A sensor_id must be uinque within the triggers of one rule. This means, the same sensor cannot be used as trigger event and trigger cal_result within one rule (which makes also no sense). An error message is logged if such a configuration occurs.

Combined Triggers

An advanced usage are combined triggers that use different source sensors resulting in the same variable_name. This allows you to listen on many sensors to set a single final result. For example listening to different SNMP traps of switch ports.

The important parameter here is evaluate="true" which allows us to reuse result of the triggers in the condition instead of using a direct variable. Both triggers use the same value_name, so there is only one state with the name res in this rule. res will always contain the latest received value (from one of the both triggers). The published value will be the latest received value.

Example of combination of values:
<rule rule_id="Check_Switch_port">
	<triggers>
    	<trigger value_name="res" trigger_topic="calibrated_result" sensor_id="SNMP_Trap_Port_7" value_type="decimal"/>
	    <trigger value_name="res" trigger_topic="calibrated_result" sensor_id="SNMP_Get_Port_7" value_type="decimal"/>
	</triggers>
	<conditions>
	    <condition expr="True">
	        <true>
	            <result_list>
            	    <result sensor_id="VS_ZyxelPort7" result_value="res" evaluate="true" value_type="decimal"/>
        	    </result_list>
    	    </true>
	    </condition>
	</conditions>
</rule>

States

The triggers of a rule define as well the states within that rule. Each calibrated result has one value and each event has one state. The value_name of a trigger defines the name of the state for a rule and the value_type of that trigger the type of this state within that rule. The incoming values for the states get casted to their value_type. Possible types are boolean, decimal (cast to integer), float and string.

The states of a rule are only valid for that rule. A state of another rule with the same name is independent.

Regarding to the rule-example above the rule BreakIn has thus the states motion, door_open and arm_state.


Before the AC goes to the next step, the condition handling, it check if any of the rule- states has changed. If none of the states has changed, the further processing of that rule for that trigger is skipped.

The name of a state (value_name) might be chosen almost free.

But following names are forbidden:

  • uid
  • sensor_id
  • topic
  • value

Expressions

Each rule must contain at least one expression. One expression is part of one conditions in the rule configuration. The expression is a string which gets evaluated by python. In the XML config the expression name is abbreviated.

Example of an expression for a condition


Example of an expression
<conditions> 
    <condition expr="arm_state == 'armed' and (motion or door_open)">
</conditions>

The result of the evaluation of an expression is always logically true or false. Expressions like expr="True" are possible.

The states of a rule are are available as local variables for the expressions.


Actions

The documentation of SiteController actions is not part of this document. In short words: Publishing an action to MQTT lets a specific actuator module do something, e.g. setting a coil of a digittal output device to  a configured value. The AC publishes actions if configured in the <true> or the <false> branch of a condition.

<conditions>           
    <condition expr="access == 'granted'">
        <true>
            <action_list>
                <action action_id="Switch_M2M_WTSC_Relay" command="ON"/>
                <action action_id="Switch_M2M_WTSC_DO_1_red_LED" command="OFF"/>
                <action action_id="Switch_M2M_WTSC_DO_2_green_LED" command="ON"/>
            </action_list>
        </true>
    </condition>
</conditions>


Results

The AC publishes calibrated results if configured in the <true> or the <false>branch of a condition.

<conditions>           
    <condition expr="arm_button == True">
        <true>
            <result_list>
                <result sensor_id="BTS_arm_state" result_value="armed" timer="T1" value_type="string"/>
                <result ... />
            </result_list>
        </true>
    </condition>
</conditions>

The timer in the example above will be discussed in the section timers of this document. The result_value will be casted to the given value_type when published. At the moment it is not necessary to define the sensor with the used sensor_id in the sensor section of the sensor configuration XML.

Results with evaluated result_value


<rule rule_id="LastValidVal">
    <triggers>
        <trigger value_name="res" trigger_topic="calibrated_result" sensor_id="snmpZyxel_port7" value_type="decimal"/>
        <trigger value_name="res" trigger_topic="calibrated_result" sensor_id="snmpgetzyxel_port7" value_type="decimal"/>
    </triggers>
    <conditions>
       <condition expr="True">
            <true>
                <result_list>
                    <result sensor_id="VS_ZyxelPort7" result_value="res" evaluate="true" value_type="decimal"/>
                </result_list>
            </true>
        </condition>
    </conditions>
</rule>

In the example above the optinal attribute evaluate="true" is used. If this attribute is set to true the result value will be evaluated like an expression. Both triggers use the same value_name, so there is only one state with the name res in this rule. res will always contain the latest received value (from one of the both triggers). Because the result_value is evaluated, the calibrated result will contain the latest received value when published. This way the AC reduces several inputs to one output.

The evaluation of result_value is encapsulated by exception handling. If an exception occures (for insatance: addition of None values) an error is written to the log of AC and no result is procudeced in that case.

Events

Similiar to calibrated results AC may publish events as well. Here is a short snippet (must be inside a <true> or <false> condition case):


<event_list>
    <event sensor_id="VS_opened_door" state="CRITICAL" output="Door is open!" value_type="string"/>
</event_list>

The publishing of an event cannot be delayed

Timers

The publishing of actions and calibrated results caused by the condition cases of a rule expression can be delayed by timers. The definition of timers in the XML takes place between the trigger definition and the defintion of conditions.

...           
</triggers>
<timers>
    <timer delay="10" timer_id="T1"/>
    <timer delay="20" timer_id="T2"/>
</timers>
<conditions>
    <condition expr=...">
...

The delay is measured in seconds. The timer_id is an arbritrary string, it must me uniquie for its rule. To get an action or a result published with delay, add the attribute timer="T1" (or other id then "T1") to its definition. Times can be killed within a rule (see section 'timer kills').

If the same timer is used again before it ran out (e.g. same condition case is triggered again), then the timer will be restarted.

Within a rule one timer (one timer_id) should be used only for one action or calibrated result. Do not use the same timer_id parallel.


Timer kills

Please refer to the section timers in this document. The publishing of some things in a rule can be delayed by timers. The change of a state of a rule could make it necessary to kill the delayed publishing.

<condition expr="arm_state == 'armed'">
    <true>
        <kill_timers>
            <timer_id>T1</timer_id>
            <timer_id>T2</timer_id>
        </kill_timers>
    </true>
</condition>

Timer Example 1 - Delaying

The below example will turn on the green light after ten seconds and the red light after twenty seconds.

Example of timer definition and usage
<triggers>
    <trigger sensor_id="Front_Door" trigger_topic="events" value_name="front_door" value_type="string" />
</triggers>
<timers>
    <timer delay="10" timer_id="T1" />
    <timer delay="20" timer_id="T2" />
</timers>
<conditions>
    <condition expr="front_door == 'Opened'">
        <true>
            <action_list>
                <action action_id="Switch_Green_Light" command="ON" timer="T1" />
                <action action_id="Switch_Red_Light" command="ON" timer="T2" />
            </action_list>
        </true>
    </condition>
</conditions>


Example 2 - Periodic Scheduling 

An advanced example is the periodic scheduling for recurring actions you want to take, e.g. periodically turning on a light. for 5 seconds A small trick is required to have an periodic trigger, simply create a new sensor that is always True and reference it in the trigger. 

The sensor Periodic_Trigger_Sensor is always true and we did set it to volatile which will trigger a new result even if it hasn't changed. Two timers are used, T1 is the overall period and T2 is the duration of our action turning on the Green Light. T2 will trigger an OFF command after five seconds.

Periodic Scheduling
<sensor sensor_id="Periodic_Trigger_Sensor">
    <sensor_class>boolean</sensor_class>
    <state_evaluation_expressions>
        <state_evaluation_expression>
            <expression>True</expression>
            <true volatile="true">Start</true>
        </state_evaluation_expression>
    </state_evaluation_expressions>
</sensor>
...
<rule rule_id="Periodic_Image">
    <triggers>
        <trigger sensor_id="Periodic_Trigger_Sensor" trigger_topic="calibrated_result" value_name="snap" value_type="boolean" />
    </triggers>
    <timers>
        <timer delay="300" timer_id="T1" />
        <timer delay="5" timer_id="T2" />
    </timers>
    <conditions>
        <condition expr="True">
            <true>
                <action_list>
                    <action action_id="Switch_Green_Light" command="ON" timer="T1" />
                    <action action_id="Switch_Green_Light" command="OFF" timer="T2" />
                </action_list>
            </true>
        </condition>
    </conditions>
</rule>



Of course the timer kill may take place in the <false> branch of a condition as well. In the example above the timers with the ID T1 and T2 will be killed. Please note: The used timers are not repeating. So, if a timer has finished it will disappear by itself. The AC is stable against killing of non existent timers.