Overview
When the house is unoccupied, I want some of the lights attached to Sonoff Basic R2 switches to turn on and off at believable times in the evening. Tasmota firmware includes timers which allow an action to be performed at a set time. Additionally, the Tasmota timer command can randomly vary the actual time that the action occurs by up to 15 minutes (early and late).
Prerequisites
Hardware
- Sonoff Basic R2, flashed with Tasmota
Software
- MQTT broker - I use Mosquitto, setup as per its defaults
- On my setup, Mosquitto and OpenHab are running on the same device, at 192.168.1.92
- MQTT Binding installed via PaperUI
- JSONPath transform installed via PaperUI
Tasmota setup
MQTT parameters
( http://sonoff-ip-address/mq , or device home -> Configuration -> Configure MQTT )
Timezone
Ensure Tasmota knows what timezone the Sonoff Basic is in, and when (if) there are any daylight saving dates it must know about. Configuration details can be found on the Tasmota website. The example Sonoff device is in the UK, so the following commands where sent via the console (http://sonoff-ip-address/cs or device home -> Console). Copy/paste each line below, one-by-one into the ‘Enter command’ field of the Tasmota console, and hit Enter:
TimeZone 99
TimeDST 0,0,3,1,1,60
TimeSTD 0,0,10,1,2,0
Location
Timers can trigger based on sunrise and sunset, as long as a location has been set. Enter the following commands via the console (http://sonoff-ip-address/cs or device home -> Console), substituting xx.xxxx and yy.yyyy for the real coordinates of the Sonoff.
latitude xx.xxxx
longitude yy.yyyy
OpenHab setup
Shown by default is the initial setup I originally posted. Over time my setup has evolved. I am now able to, from within openHAB:
- Enable/Disable all timers
- Enable/Disable individual timers
- Adjust the
window
, or time randomiser - Adjust the action ON or OFF
- Adjust the mode between
Time
,Sunrise
andSunset
If you want to take advantage of these features click on the Click here for a more advanced version where available.
Things
mqttbridge.things
I have a separate file which just contains the bridge Thing to my Mosquitto MQTT broker:
Bridge mqtt:broker:MosquittoMqttBroker "Mosquitto MQTT Broker" [
host="192.168.1.92",
secure=false,
port=1883,
clientID="OpenHAB2"
]
lights.things
// Switch Bedroom Side Light
Thing mqtt:topic:swBedroomSideLight "Switch Bedroom Side Light" (mqtt:broker:MosquittoMqttBroker) {
Channels:
Type switch : switch "Power Switch" [
stateTopic="stat/swBedroomSideLight/POWER",
commandTopic="cmnd/swBedroomSideLight/POWER",
on="ON",
off="OFF"
]
Type string : timer1 "String Timer 1" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer1"
]
Type string : timer2 "String Timer 2" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer2"
]
Type string : timer3 "String Timer 3" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer3"
]
Type string : timer4 "String Timer 4" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer4"
]
}
Click here for a more advanced version
// Switch Bedroom Side Light
Thing mqtt:topic:swBedroomSideLight "Switch Bedroom Side Light" (mqtt:broker:MosquittoMqttBroker) {
Channels:
Type switch : switch "Power Switch" [
stateTopic="stat/swBedroomSideLight/POWER",
commandTopic="cmnd/swBedroomSideLight/POWER",
on="ON",
off="OFF"
]
Type switch : timers_enable "Switch Timer Enable" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timers",
transformationPattern="REGEX:(.*\"Timers\".*)∩JSONPATH:$.Timers",
on="ON",
off="OFF"
]
Type string : timer1 "String Timer 1" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer1"
]
Type switch : timer1_armed "Switch Timer 1 armed" [
commandTopic="cmnd/swBedroomSideLight/Timer1",
formatBeforePublish="{\"Enable\":%s,\"Repeat\":1}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer1\".*)∩JSONPATH:$.Timer1.Enable",
on="1",
off="0"
]
Type string : timer1_time "Switch Timer 1 time" [
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer1\".*)∩JSONPATH:$.Timer1.Time"
]
Type number : timer1_window "Switch Timer 1 window" [
commandTopic="cmnd/swBedroomSideLight/Timer1",
formatBeforePublish="{\"Window\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer1\".*)∩JSONPATH:$.Timer1.Window"
]
Type number : timer1_mode "Switch Timer 1 mode" [
commandTopic="cmnd/swBedroomSideLight/Timer1",
formatBeforePublish="{\"Mode\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer1\".*)∩JSONPATH:$.Timer1.Mode"
]
Type switch : timer1_action "Switch Timer 1 action" [
commandTopic="cmnd/swBedroomSideLight/Timer1",
formatBeforePublish="{\"Action\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer1\".*)∩JSONPATH:$.Timer1.Action",
on="1",
off="0"
]
Type string : timer2 "String Timer 2" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer2"
]
Type switch : timer2_armed "Switch Timer 2 armed" [
commandTopic="cmnd/swBedroomSideLight/Timer2",
formatBeforePublish="{\"Enable\":%s,\"Repeat\":1}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer2\".*)∩JSONPATH:$.Timer2.Enable",
on="1",
off="0"
]
Type string : timer2_time "Switch Timer 2 time" [
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer2\".*)∩JSONPATH:$.Timer2.Time"
]
Type number : timer2_window "Switch Timer 2 window" [
commandTopic="cmnd/swBedroomSideLight/Timer2",
formatBeforePublish="{\"Window\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer2\".*)∩JSONPATH:$.Timer2.Window"
]
Type number : timer2_mode "Switch Timer 2 mode" [
commandTopic="cmnd/swBedroomSideLight/Timer2",
formatBeforePublish="{\"Mode\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer2\".*)∩JSONPATH:$.Timer2.Mode"
]
Type switch : timer2_action "Switch Timer 2 action" [
commandTopic="cmnd/swBedroomSideLight/Timer2",
formatBeforePublish="{\"Action\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer2\".*)∩JSONPATH:$.Timer2.Action",
on="1",
off="0"
]
Type string : timer3 "String Timer 3" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer3"
]
Type switch : timer3_armed "Switch Timer 3 armed" [
commandTopic="cmnd/swBedroomSideLight/Timer3",
formatBeforePublish="{\"Enable\":%s,\"Repeat\":1}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer3\".*)∩JSONPATH:$.Timer3.Enable",
on="1",
off="0"
]
Type string : timer3_time "Switch Timer 3 time" [
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer3\".*)∩JSONPATH:$.Timer3.Time"
]
Type number : timer3_window "Switch Timer 3 window" [
commandTopic="cmnd/swBedroomSideLight/Timer3",
formatBeforePublish="{\"Window\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer3\".*)∩JSONPATH:$.Timer3.Window"
]
Type number : timer3_mode "Switch Timer 3 mode" [
commandTopic="cmnd/swBedroomSideLight/Timer3",
formatBeforePublish="{\"Mode\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer3\".*)∩JSONPATH:$.Timer3.Mode"
]
Type switch : timer3_action "Switch Timer 3 action" [
commandTopic="cmnd/swBedroomSideLight/Timer3",
formatBeforePublish="{\"Action\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer3\".*)∩JSONPATH:$.Timer3.Action",
on="1",
off="0"
]
Type string : timer4 "String Timer 4" [
stateTopic="stat/swBedroomSideLight/RESULT",
commandTopic="cmnd/swBedroomSideLight/Timer4"
]
Type switch : timer4_armed "Switch Timer 4 armed" [
commandTopic="cmnd/swBedroomSideLight/Timer4",
formatBeforePublish="{\"Enable\":%s,\"Repeat\":1}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer4\".*)∩JSONPATH:$.Timer4.Enable",
on="1",
off="0"
]
Type string : timer4_time "Switch Timer 4 time" [
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer4\".*)∩JSONPATH:$.Timer4.Time"
]
Type number : timer4_window "Switch Timer 4 window" [
commandTopic="cmnd/swBedroomSideLight/Timer4",
formatBeforePublish="{\"Window\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer4\".*)∩JSONPATH:$.Timer4.Window"
]
Type number : timer4_mode "Switch Timer 4 mode" [
commandTopic="cmnd/swBedroomSideLight/Timer4",
formatBeforePublish="{\"Mode\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer4\".*)∩JSONPATH:$.Timer4.Mode"
]
Type switch : timer4_action "Switch Timer 4 action" [
commandTopic="cmnd/swBedroomSideLight/Timer4",
formatBeforePublish="{\"Action\":%s}",
stateTopic="stat/swBedroomSideLight/RESULT",
transformationPattern="REGEX:(^\\{\"Timer4\".*)∩JSONPATH:$.Timer4.Action",
on="1",
off="0"
]
}
Items
Switch sBedroomSideLight "Bedroom Side Light" { channel="mqtt:topic:swBedroomSideLight:switch" }
String strBedroomSideLightTimer1 "Bedroom Side Light" { channel="mqtt:topic:swBedroomSideLight:timer1" }
String strBedroomSideLightTimer2 "Bedroom Side Light" { channel="mqtt:topic:swBedroomSideLight:timer2" }
String strBedroomSideLightTimer3 "Bedroom Side Light" { channel="mqtt:topic:swBedroomSideLight:timer3" }
String strBedroomSideLightTimer4 "Bedroom Side Light" { channel="mqtt:topic:swBedroomSideLight:timer4" }
Click here for a more advanced version
Switch sBedroomSideLight "Bedroom Side Light" { channel="mqtt:topic:swBedroomSideLight:switch" }
Switch sBedroomSideLightTimersEnable "Bedroom Side Light" (gTimersEnable) { channel="mqtt:topic:swBedroomSideLight:timers_enable" }
Switch sBedroomSideLightTimer1Armed "Bedroom Side Light Timer1" (gTimersArm) { channel="mqtt:topic:swBedroomSideLight:timer1_armed" }
String strBedroomSideLightTimer1Time "Bedroom Side Light Timer1 Time" { channel="mqtt:topic:swBedroomSideLight:timer1_time" }
Number strBedroomSideLightTimer1Window "Living Room Short Light Timer1 Window" { channel="mqtt:topic:swBedroomSideLight:timer1_window" }
Number strBedroomSideLightTimer1Mode "Bedroom Side Light Timer1 Mode" { channel="mqtt:topic:swBedroomSideLight:timer1_mode" }
Switch strBedroomSideLightTimer1Action "Bedroom Side Light Timer1 Action" { channel="mqtt:topic:swBedroomSideLight:timer1_action" }
Switch sBedroomSideLightTimer2Armed "Bedroom Side Light Timer2" (gTimersArm) { channel="mqtt:topic:swBedroomSideLight:timer2_armed" }
String strBedroomSideLightTimer2Time "Bedroom Side Light Timer2 Time" { channel="mqtt:topic:swBedroomSideLight:timer2_time" }
Number strBedroomSideLightTimer2Window "Living Room Short Light Timer2 Window" { channel="mqtt:topic:swBedroomSideLight:timer2_window" }
Number strBedroomSideLightTimer2Mode "Bedroom Side Light Timer2 Mode" { channel="mqtt:topic:swBedroomSideLight:timer2_mode" }
Switch strBedroomSideLightTimer2Action "Bedroom Side Light Timer2 Action" { channel="mqtt:topic:swBedroomSideLight:timer2_action" }
Switch sBedroomSideLightTimer3Armed "Bedroom Side Light Timer3" (gTimersArm) { channel="mqtt:topic:swBedroomSideLight:timer3_armed" }
String strBedroomSideLightTimer3Time "Bedroom Side Light Timer3 Time" { channel="mqtt:topic:swBedroomSideLight:timer3_time" }
Number strBedroomSideLightTimer3Window "Living Room Short Light Timer3 Window" { channel="mqtt:topic:swBedroomSideLight:timer3_window" }
Number strBedroomSideLightTimer3Mode "Bedroom Side Light Timer3 Mode" { channel="mqtt:topic:swBedroomSideLight:timer3_mode" }
Switch strBedroomSideLightTimer3Action "Bedroom Side Light Timer3 Action" { channel="mqtt:topic:swBedroomSideLight:timer3_action" }
Switch sBedroomSideLightTimer4Armed "Bedroom Side Light Timer4" (gTimersArm) { channel="mqtt:topic:swBedroomSideLight:timer4_armed" }
String strBedroomSideLightTimer4Time "Bedroom Side Light Timer4 Time" { channel="mqtt:topic:swBedroomSideLight:timer4_time" }
Number strBedroomSideLightTimer4Window "Living Room Short Light Timer4 Window" { channel="mqtt:topic:swBedroomSideLight:timer4_window" }
Number strBedroomSideLightTimer4Mode "Bedroom Side Light Timer4 Mode" { channel="mqtt:topic:swBedroomSideLight:timer4_mode" }
Switch strBedroomSideLightTimer4Action "Bedroom Side Light Timer4 Action" { channel="mqtt:topic:swBedroomSideLight:timer4_action" }
Sitemap
Click here for a more advanced version
This is only valid if using the advanced versions of the Things and Items. The image below only shows the controls for the first two timers.
Frame label="Enable"{
Switch item=sBedroomSideLightTimersEnable label="Enable []" mappings=[OFF="Disable", ON="Enable"]
}
Frame label="Timer1" {
Switch item=sBedroomSideLightTimer1Armed label="Activate []" mappings=[OFF="Disable", ON="Enable"]
Text item=strBedroomSideLightTimer1Time label="Time"
Slider item=strBedroomSideLightTimer1Window icon="time" label="+/- minutes" minValue=0 maxValue=15 step=1
Selection item=strBedroomSideLightTimer1Mode icon="time" label="Mode" mappings=[0='Time', 1='Sunrise', 2='Sunset']
Switch item=strBedroomSideLightTimer1Action label="Action []" mappings=[OFF="OFF", ON="ON"]
}
Frame label="Timer2" {
Switch item=sBedroomSideLightTimer2Armed label="Activate []" mappings=[OFF="Disable", ON="Enable"]
Text item=strBedroomSideLightTimer2Time label="Time"
Slider item=strBedroomSideLightTimer2Window icon="time" label="+/- minutes" minValue=0 maxValue=15 step=1
Selection item=strBedroomSideLightTimer2Mode icon="time" label="Mode" mappings=[0='Time', 1='Sunrise', 2='Sunset']
Switch item=strBedroomSideLightTimer2Action label="Action []" mappings=[OFF="OFF", ON="ON"]
}
Frame label="Timer3" {
Switch item=sBedroomSideLightTimer3Armed label="Activate []" mappings=[OFF="Disable", ON="Enable"]
Text item=strBedroomSideLightTimer3Time label="Time"
Slider item=strBedroomSideLightTimer3Window icon="time" label="+/- minutes" minValue=0 maxValue=15 step=1
Selection item=strBedroomSideLightTimer3Mode icon="time" label="Mode" mappings=[0='Time', 1='Sunrise', 2='Sunset']
Switch item=strBedroomSideLightTimer3Action label="Action []" mappings=[OFF="OFF", ON="ON"]
}
Frame label="Timer4" {
Switch item=sBedroomSideLightTimer4Armed label="Activate []" mappings=[OFF="Disable", ON="Enable"]
Text item=strBedroomSideLightTimer4Time label="Time"
Slider item=strBedroomSideLightTimer4Window icon="time" label="+/- minutes" minValue=0 maxValue=15 step=1
Selection item=strBedroomSideLightTimer4Mode icon="time" label="Mode" mappings=[0='Time', 1='Sunrise', 2='Sunset']
Switch item=strBedroomSideLightTimer4Action label="Action []" mappings=[OFF="OFF", ON="ON"]
}
Rule snippets
//Arm all the timers
//Set Repeat to TRUE so that it continues to function after the first time
var jsonString = "{\"Enable\":1,\"Repeat\":1}"
strBedroomSideLightTimer1.sendCommand(jsonString)
strBedroomSideLightTimer2.sendCommand(jsonString)
strBedroomSideLightTimer3.sendCommand(jsonString)
strBedroomSideLightTimer4.sendCommand(jsonString)
//Dis-arm all the timers
var jsonString = "{\"Enable\":0,\"Repeat\":0}"
strBedroomSideLightTimer1.sendCommand(jsonString)
strBedroomSideLightTimer2.sendCommand(jsonString)
strBedroomSideLightTimer3.sendCommand(jsonString)
strBedroomSideLightTimer4.sendCommand(jsonString)
Click here for a more advanced version
Because Tasmota doesn’t send updates when Timer settings are changed within Tasmota, we need to periodically poll the device to see what the current settings are. The following is a Jython rule which polls the settings every hour:
'''
TASMOTA MAINTENANCE
Check Tasmota timer settings every hour
'''
@rule("Tasmota maintenance", description="Check Tasmota timer settings every hour")
@when("Time cron 0 0 0/1 ? * * *")
@when("System started")
def action_tasmota_maintenance(event):
#Get MQTT actions
mqttActions = actions.get("mqtt","mqtt:broker:MosquittoMqttBroker")
#Check timer settings
for timer_item in ir.getItem("gTasmotaTimer").members:
timer_item_name = str(timer_item.name)[3:]
timer_item_topic = str(timer_item_name)[:-6]
timer_item_number = str(timer_item_name)[-1:]
mqttActions.publishMQTT("cmnd/sw{}/timer{}".format(timer_item_topic,timer_item_number),"")
Timer setup
There are two options:
- Times for each timer can be set on Tasmota itself, or
- Times for each timer can be transferred via MQTT to Tasmota from OpenHab
Setup Timer via Tasmota
To set the times on Tasmota itself, navigate to the Timers page (http://sonoff-ip-address/tm or device home -> Configuration -> Configure Timer).
Ensure Enable Timers is checked.
Below is an example where Timer 1 is set to turn Output 1 of the device (on a Sonoff Basic this is the relay) to On at 1845hrs +/-15 minutes, every day of the week.
Three other timers have been set, which means the Sonoff has the following four timers:
- Timer 1: Output 1 ON @ 1845hrs +/-15 minutes, every day
- Timer 2: Output 1 OFF @ 1930hrs +/-15 minutes, every day
- Timer 3: Output 1 ON @ 2145hrs +/-15 minutes, every day
- Timer 4: Output 1 OFF @ 2230hrs +/-15 minutes, every day
Setup Timer via OpenHab
You can send any compatible JSON payload via sendCommand.
Instead of setting up the timer via Tasmota, OpenHab can send all the relevant information via MQTT.
Rule snippets
//ARM sBedroomSideLight TO TURN ON AT 1845 +/-15MINS, TURN OFF AT 1930 +/-15MINS, TURN ON 2145 /-15MINS, TURN OFF 2230+/-15MINS
strBedroomSideLightTimer1.sendCommand("{\"Enable\":1,\"Mode\":0,\"Time\":\"18:45\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":1}")
strBedroomSideLightTimer2.sendCommand("{\"Enable\":1,\"Mode\":0,\"Time\":\"19:30\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":0}")
strBedroomSideLightTimer3.sendCommand("{\"Enable\":1,\"Mode\":0,\"Time\":\"21:45\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":1}")
strBedroomSideLightTimer4.sendCommand("{\"Enable\":1,\"Mode\":0,\"Time\":\"22:30\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":0}")
//ARM sBedroomSideLight TO TURN ON 1 HOUR BEFORE DUSK AND TURN OFF AT 2200 +/-15MINS
//MODE:2 = DUSK; MODE:1 = DAWN; TIME:-1:00 = activate 1 hour earlier than the mode
strBedroomSideLightTimer1.sendCommand("{\"Enable\":1,\"Mode\":2,\"Time\":\"-01:00\",\"Window\":0,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":1}")
strBedroomSideLightTimer2.sendCommand("{\"Enable\":1,\"Mode\":0,\"Time\":\"22:00\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":0}")
Edit 23/12/2020: Updated to conform to latest Tasmota syntax.
Edit 12/09/2020: Updated to add advanced options
Edit 18/05/2020: Updated to use default Tasmota MQTT settings for FullTopic