?> Rules expand the functionality of Tasmota with flexible and user configurable logic
Tasmota provides a Rule feature heavily inspired by the ESPEasy implementation while maintaining a small memory footprint. Automation solutions can be implemented without having to add dedicated code or use external solutions.
Rules perform actions based on triggers (e.g., switch state change, temperature threshold, events like system boot, a defined timer elapsing, custom defined events, etc.) They are stored in flash and therefore will survive a reboot.
[!NOTE] Most pre-compiled builds have the Rules feature enabled. If you are >compiling your own firmware, in order to use rules, include
#define USE_RULES
inuser_config_override.h
.
Complete list of Rules Commands
Rule definition statement:
ON <trigger> DO <command> [ENDON | BREAK]
ON
- marks the beginning of a rule definition<trigger>
- what condition needs to occur for the rule to executeDO
- what the rule is to perform if the<trigger>
condition is metENDON
- marks the end of a rule. It can be followed by another rule.BREAK
- marks the end of a rule.BREAK
will stop the execution of the remaining rules that follow this rule within the rule set. If a rule that ends withBREAK
is triggered, the following rules in that rule set will not be executed. This allows the rules to somewhat simulate an "IF/ELSE" statement.
Rule sets are defined by using the Rule<x>
command. After defining a rule set, you have to enable it (turn it on) using Rule<x> 1
. Similarly you can disable the rule set using Rule<x> 0
.
There are three separate rule sets called Rule1
, Rule2
and Rule3
. Each rule set can contain as many rules as can fit within the 511 character limit. Whenever a rule set is enabled all the rules in it will be active. If the character count of the rules in the set exceed the limit, split the rules into another rule set. If you have a long list of rules, verify the rules have all fit by inspecting the resulting log.
Rules inside a rule set Rule<x>
are concatenated and entered as a single statement.
Rule<x> ON <trigger1> DO <command> ENDON ON <trigger2> DO <command> ENDON ...
Spaces after ON
, around DO
, and before ENDON
or BREAK
are mandatory. A rule is not case sensitive.
A rule trigger can consist of:
[TriggerName]#[ValueName]
[TriggerName]#[ValueName][comparison][value]
[SensorName]#[ValueName]
[SensorName]#[ValueName][comparison][value]
Tele-[SensorName]#[ValueName]
A trigger may be used in more than one rule. This may be required for some cases of using IF/ELSE
since an IF
statement cannot be used within a Backlog
.
Operator | Function |
---|---|
= |
equal to (used for string comparison) |
== |
equal to (used for numerical comparison) |
> |
greater than |
< |
lesser than |
!= |
not equal to |
>= |
greater than or equal to |
<= |
lesser than or equal to |
| |
used for modulo operation with remainder = 0 (exact division) |
Trigger | When it occurs |
---|---|
Analog#A0div10 | when the A0 input changes by more than 1% it provides a value between 0 and 100 |
Button2#State | when a button changes state:0 = OFF1 = ON2 = TOGGLE3 = HOLD |
Clock#Timer=3 | when global Timer3 is activated |
Dimmer#Boot | occurs after Tasmota starts |
Dimmer#State | when the value for Dimmer is changed |
Event#eventName | when command Event eventName is executed. You can define your own event values and trigger them with the Event command. |
FanSpeed#Data=3 | when the fan speed is set to 3 |
Mem<x>#State | when the value for Mem<x> is changed |
Http#Initialized | |
Mqtt#Connected | when MQTT is connected |
Mqtt#Disconnected | when MQTT is disconnected |
Power1#Boot | Relay1 state before Wi-Fi and MQTT are connected and before Time sync but after PowerOnState is executed. Power#Boot triggers before System#Boot.This trigger's value will be the last state of Relay1 if PowerOnState is set to its default value (3 ). |
Power1#State | when a power output is changed use Power1#state=0 and Power1#state=1 for comparison, not =off or =onPower2 for Relay2, etc. |
Rules#Timer=1 | when countdown RuleTimer1 expires |
Switch1#Boot | occurs after Tasmota starts before it is initializated. |
Switch1#State | when a switch changes to state use Switch1#state=0 and Switch1#state=1 for comparison, not =off or =on0 = OFF1 = ON2 = TOGGLE3 = HOLD( SwitchTopic 0 must be set for this to trigger) |
System#Boot | occurs once after Tasmota is fully intialized (after the INFO1, INFO2 and INFO3 console messages). System#Boot triggers after Wi-Fi and MQTT (if enabled) are connected. If you need a trigger prior to every service being initialized, use Power1#Boot |
System#Save | executed just before a planned restart |
Time#Initialized | once when NTP is initialized and time is in sync |
Time#Initialized>120 | once, 120 seconds after NTP is initialized and time is in sync |
Time#Minute | every minute |
Time#Minute|5 | every five minutes |
Time#Minute=241 | every day once at 04:01 (241 minutes after midnight) |
Time#Set | every hour when NTP makes time in sync |
Var<x>#State | when the value for Var<x> is changed |
Wifi#Connected | when Wi-Fi is connected |
Wifi#Disconnected | when Wi-Fi is disconnected |
Tele-Wifi1#AP | when a teleperiod message is sent with the number of the used AP |
Tele-Wifi1#Ssid | when a teleperiod message is sent with the name of the used AP |
Tele-Wifi1#Bssid | when a teleperiod message is sent with the name of the bSSID |
Tele-Wifi1#Channel | when a teleperiod message is sent with the number of the wifi channel used |
Tele-Wifi1#RSSI | when a teleperiod message is sent with the RSSI LEVEL |
Tele-Wifi1#LinkCount | when a teleperiod message is sent with the number of wifi disconnections |
Tele-Wifi1#Downtime | when a teleperiod message is sent with the total seconds of wifi disconnections |
Every command with a JSON payload response has an associated rule trigger.
Trigger | When it occurs |
---|---|
<command>#Data | A one level JSON payload such as {"command":"value"} . For example, for {"Fanspeed":3}, the trigger isFanspeed#Data . |
<command>#level1#level2#levelN | A multi-level level JSON payload such as {"level1":{"level2":{"levelN":"value"}}} does NOT have the #Data trigger. Instead, the trigger for these responses is level1#level2#levelN . For example, for {"PulseTime2":{"Set":0,"Remaining":0}}, the triggers are PulseTime2#Set and PulseTime2#Remaining . |
Connected sensors can be a trigger in the form as they are represented in the TelePeriod
and Status 8
JSON payloads.
Trigger | When it occurs |
---|---|
DS18B20#Temperature | whenever the temperature of sensor DS18B20 changes |
DS18B20#Temperature<20 | whenever the temperature of sensor DS18B20 is below 20 degrees |
BME280#Humidity==55.5 | whenever the humidity of sensor BEM280 equals 55.5% |
INA219#Current>0.100 | whenever the current drawn is more than 0.1A |
Energy#Power>100 | whenever the power used is more than 100W |
When the payload consists of an array of data eg: ENERGY":{Current":[1.320,2.100]}
Trigger | When it occurs |
---|---|
Energy#Current[N] | N = Number of the field. 1 for the first 1.320 , 2 for the second 2.100 etc. |
Energy#Current[1]>1.000 | whenever the first value of Energy#Current is higher than 1.000. |
To trigger only at TelePeriod time, prefix the sensor with the word Tele-
.
Trigger | When it occurs |
---|---|
Tele-AM2301#Temperature | sensor AM2301 Temperature value when the TelePeriod JSON payload is output |
Hardware and software serial interface, RF, IR and TuyaMCU are also supported based on their JSON status message:
Trigger | When it occurs |
---|---|
TuyaReceived#Data=<hex_string> | whenever <hex_string> is received with TuyaMCU component |
SerialReceived#Data=<string> | whenever <string> is received via hardware serial |
SSerialReceived#Data=<string> | whenever <string> is received via software serial |
IrReceived#Data=801 | whenever an IR signal for a RC5 remote control button 1 is received |
IrReceived#Data=0x00FF9867 | whenever an IR signal with hex code 0x00FF9867 is received |
RfReceived#RfKey=4 | whenever the RF Bridge receives a recognized RfKey 4 signal |
RfReceived#Data=0xE8329E | whenever an RF signal with hex code 0xE8329E is received |
A rule command can be any command listed in the Commands list. The command's <parameter>
can be replaced with %value%
which will use the value of the trigger.
ON Switch1#State DO Power %value% ENDON
To accomplish a rule with one trigger but several commands, you need to use Backlog
:
ON <trigger> DO Backlog <command1>; <command2>; <command3> ENDON
Appending new rule onto an existing rule set
Use the +
character to append a new rule to the rule set. For example:
Existing Rule1: ON Rules#Timer=1 DO Mem2 %time% ENDON
Rule to append: ON Button1#state DO POWER TOGGLE ENDON
Command: Rule1 + ON button1#state DO POWER TOGGLE ENDON
Resulting in
Rule1 ON Rules#Timer=1 DO Mem2 %time% ENDON ON Button1#state DO POWER TOGGLE ENDON
You can duplicate the same trigger on many lines.
Rule
on power2#state=1 do power1 1 endon
on power2#state=1 do RuleTimer1 100 endon
There are ten available variables (double precision reals) in Tasmota, Var1..Var5
and Mem1..Mem5
. All Var
will be empty strings when the program starts. The value of all Mem
persists after a reboot. They provide a means to store the trigger %value%
to be used in any rule.
The value of a Var<x>
and Mem<x>
can be:
- any number
- any text
- %var1% to %var5%
- %mem1% to %mem5%
- %time%
- %timestamp%
- %uptime%
- %sunrise%
- %sunset%
- %utctime%
- %topic%
To set the value for Var<x>
and Mem<x>
use the command
Var<x> <value>
Mem<x> <value>
The <value>
can also be the value of the trigger of the rule.
- Set Var2 to the temperature of the AM2301 sensor -
ON AM2301#Temperature DO Var2 %value% ENDON
- Set Var4 to Var2's value -
ON Event#temp DO Var4 %Var2% ENDON
- Set Mem2 to the current time (minutes elapsed since midnight) -
ON Rules#Timer=1 DO Mem2 %time% ENDON
- After a Wi-Fi reconnect event, publish a payload containing timestamps of when Wi-Fi was disconnected in From: and when Wi-Fi re-connected in To: to
stat/topic/BLACKOUT
.Rule1 ON wifi#disconnected DO Var1 %timestamp% ENDON ON wifi#connected DO Var2 %timestamp% ENDON ON mqtt#connected DO Publish stat/topic/BLACKOUT {"From":"%Var1%","To":"%Var2%"} ENDON
To clear / delete a rule you need to set it with one quote:
Rule1 "
!> This feature is not included in precompiled binaries.
To use it you must compile your build. Add the following to user_config_override.h
:
#define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
#define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem)
- Support IF, ELSEIF, ELSE
- Support for
<comparison>
and<logical expression>
as condition - Support for executing multiple commands
- Support for nested IF statements
- Available free RAM is the only limit for logical operators, parenthesis, and nested IF statements.
<if-statement>
IF (<logical-expression>) <statement-list> {ELSEIF (<logical-expression>) <statement-list>} [ELSE <statement-list>] ENDIF
<logical-expression>
<comparison-expression>
(
<comparison-expression>
|<logical-expression>
)
{{AND
|OR
}<logical-expression>
}(
<logical-expression>
)
{AND
|OR
}<logical expression>
}
<comparison-expression>
<expression>
{=
|<
|>
||
|==
|<=
|>=
|!=
}<expression>
<statement-list>
<statement>
{;
<statement>
}
<statement>
- {
<Tasmota-command>
|<if-statement>
}
IF statement supports 3 formats:
IF (<logical-expression>) <statement-list> ENDIF
IF (<logical-expression>) <statement-list> ELSE <statement-list> ENDIF
IF (<logical-expression>) <statement-list> [ELSEIF (<logical-expression>) <statement-list> ] ELSE <statement-list> ENDIF
The outermost <if-statement>
cannot be chained with other Tasmota commands in a Backlog
. For example, Backlog Power1 0; IF var1==1 Power1 1 ENDIF
, is NOT permitted. Commands chained with <if-statement>
are allowed in a <statement-list>
. For example, IF ENERGY#Current>10 Power1 0; IF var1==1 Power1 1 ENDIF ENDIF
, is permitted.
<logical-expression>
Examples:
-
VAR1>=10
-
Multiple comparison expressions with logical operator
AND
orOR
between them.AND
has higher priority thanOR
. For example:
UPTIME>100 AND MEM1==1 OR MEM2==1
Parenthesis can be used to change the priority of logical expression. For example:
UPTIME>100 AND (MEM1==1 OR MEM2==1)
-
The following variables can be used in
<condition>
:Symbol Description VAR<x> variable (<x> = 1..MAX_RULE_VARS
, e.g.,VAR2
)MEM<x> persistent variable (<x> = 1..MAX_RULE_MEMS
, e.g.,MEM3
)TIME minutes past midnight UPTIME uptime minutes UTCTIME UTC time, UNIX timestamp, seconds since 01/01/1970 LOCALTIME local time, UNIX timestamp SUNRISE current sunrise time (minutes past midnight) SUNSET current sunset time (minutes past midnight)
<statement-list>
-
A Tasmota command (e.g.,
LedPower on
) -
Another IF statement (
IF ... ENDIF
) -
Multiple Tasmota commands or IF statements separated by
;
. For example:
Power1 off; LedPower on; IF (Mem1==0) Var1 Var1+1; Mem1 1 ENDIF; Delay 10; Power1 on
Backlog
is implied and is not required (saves rule set buffer space).But not like this:
Power1 off; LedPower on; IF (Mem1==0) Var1 Var1+1; Mem1 1 ENDIF; Delay 10; Power1 on
You should split it in two lines like:
on power2#state=1 do Power1 off; LedPower on; endon
on power2#state=1 do IF (Mem1==0) Var1 Var1+1; Mem1 1 ENDIF; Delay 10; Power1 on endon
[!EXAMPLE] Rule used to control pressure cooker with a Sonoff S31. Once it is finished cooking, shut off the power immediately.
Rule1
on system#boot do var1 0 endon
on energy#power>100 do if (var1!=1) ruletimer1 0;var1 1 endif endon
on tele-energy#power<50 do if (var1==1) var1 2;ruletimer1 600 endif endon
on rules#timer=1 do backlog var1 0;power off endon
!> This feature is not included in precompiled binaries.
To use it you must compile your build. Add the following to user_config_override.h
:
#define USE_EXPRESSION // Add support for expression evaluation in rules (+3k2 code, +64 bytes mem)
#define SUPPORT_IF_STATEMENT // Add support for IF statement in rules (+4k2 code, -332 bytes mem)
Beginning with Tasmota version 6.4.1.14, an optional feature for using mathematical expressions in rules was introduced.
Once the feature is enabled, the use of expressions is supported in the following commands:
- Var
- Mem
- RuleTimer
- If conditional statement (requires
#define SUPPORT_IF_STATEMENT
)
Expressions can use of the following operators. They are listed by the order of operations priority, from higher to lower.
( )
(parentheses are used to explicitly control the order of operations)^
(power)%
(modulo, division by zero returns modulo "0")*
and/
(multiplication and division; division by zero returns "0")+
and-
(addition and subtraction)
[!EXAMPLE]
1+2*2
results in 5.0 as the multiplication is done first due to its higher priority
(1+2)*2
results in 6.0
In addition to numeric constants, the following symbolic values can be used:
Symbol | Description |
---|---|
VAR<x> | variable (<x> = 1..MAX_RULE_VARS , e.g., VAR2 ) |
MEM<x> | persistent variable (<x> = 1..MAX_RULE_MEMS , e.g., MEM3 ) |
TIME | minutes past midnight |
UPTIME | uptime minutes |
UTCTIME | UTC time, UNIX timestamp, seconds since 01/01/1970 |
LOCALTIME | local time, UNIX timestamp |
SUNRISE | current sunrise time (minutes past midnight) |
SUNSET | current sunset time (minutes past midnight) |
[!EXAMPLE]
Mem1=((0.5*Var1)+10)*0.7
To use expressions in the Var
, Mem
and RuleTimer
commands, an equal sign (=
) character has to be used after the command. If not, the traditional syntax interpretation is used.
Statement | Var1 Result |
---|---|
Var1=42 |
42 |
Var1 1+1 |
"1+1" (the literal string) |
Var1=1+1 |
2 |
Var1=sunset-sunrise |
duration of daylight in minutes |
Sample rules to use as a starting point to creating your own.