Control Tasmota timers via MQTT

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

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 and Sunset

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:

  1. Times for each timer can be set on Tasmota itself, or
  2. 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:

  1. Timer 1: Output 1 ON @ 1845hrs +/-15 minutes, every day
  2. Timer 2: Output 1 OFF @ 1930hrs +/-15 minutes, every day
  3. Timer 3: Output 1 ON @ 2145hrs +/-15 minutes, every day
  4. 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

5 Likes

Thanks so much @hafniumzinc!
Thats a really great guide and works perfectly. Saved me so much time!

Did you already build a configuration GUI for the basic ui and would be so kind to share the items, sitemap und rules?

I’m glad it helped! I use the above together with presence detection - I don’t trigger it from any UI.

In general:

  • IF family members are home THEN dis-arm timers
  • IF family members are not home THEN arm timers

My presence detection is based entirely on this post:

OpenHAB detects whether a family member is home based on if their phone is connected to the home wifi.

Below is how I’ve implemented it.

Prerequisites

  • Network binding installed in OpenHab
    • PaperUI -> Add-ons -> Bindings -> I‚Äôm glad it helped! I use the above together with presence detection - I don‚Äôt trigger it from any UI.

Configuration files
network.things
Change the IP addresses below to those which match those of your phones.

network:pingdevice:dDadAndroid [ hostname="192.168.1.99", retry=1, timeout=5000, refreshInterval=60000 ]
network:pingdevice:dMumAndroid [ hostname="192.168.1.78", retry=1, timeout=5000, refreshInterval=60000 ]

network.items

Switch sPresence "Someone is present"
Group:Switch:AND(OFF,ON) gPresenceSensors
Switch sPresenceTimer { expire="5m,command=OFF" }

Switch sDadAndroid (gPresenceSensors) { channel="network:pingdevice:dDadAndroid:online" }
DateTime dtDadAndroid { channel="network:pingdevice:dDadAndroid:lastseen" }

Switch sMumAndroid (gPresenceSensors) { channel="network:pingdevice:dMumAndroid:online" }
DateTime dtMumAndroid { channel="network:pingdevice:dMumAndroid:lastseen" }

lights.items

Group:Switch:OR(ON,OFF) gAwayLightTimers

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" }

presence.rules
This is almost exactly the same as the Rules DSL in the post I linked above, just with the Items slightly re-named to match the network.items file.

rule "Reset Presence and sensors to OFF on startup"
when
    System started
then
    sPresence.sendCommand(OFF)
    gPresenceSensors.sendCommand(OFF)
end

rule "A presence sensor was updated"
when
        Item gPresenceSensors changed
then

    if(sPresenceTimer.state == ON && gPresenceSensors.state == sPresence.state) {
        //logInfo("presence-rules", "Timer is running but group and proxy are the same, cancelling timer")
        sPresenceTimer.postUpdate(OFF)
    }
    else if(gPresenceSensors.state == sPresence.state) {
        //logInfo("presence-rules", "No timer and both group and proxy are the same, nothing to do")
        return;
    }

    if(gPresenceSensors.state == OFF) {
        //logInfo("presence-rules", "Everyone is away, setting anti-flapping timer")
        sPresenceTimer.sendCommand(ON)
    }
    else if(gPresenceSensors.state == ON) {
        //logInfo("presence-rules", "Someone came home, setting presence to ON")
        sPresence.sendCommand(ON)
    }

end

rule "Presence timer expired, no one is home"
when
    Item sPresenceTimer received command OFF
then
    //logInfo("presence-rules", "Everyone is still away, setting presence to OFF")
    sPresence.sendCommand(OFF)
end

lights.rules

//PRESENCE BASED RULES
//ARM LIGHT TIMERS
rule "Arm light timers group when presence is not detected"
when
	Item sPresence changed
then
	if(sPresence.state==OFF){
		gAwayLightTimers.sendCommand(ON)
	}
	else{
		gAwayLightTimers.sendCommand(OFF)
	}
end

rule "Arm light timers"
when
	Item gAwayLightTimers changed to ON
then
	//ARM sBedroomSideLight TO TURN ON AT 1845 +/-15MINS, TURN OFF AT 1930 +/-15MINS, TURN ON 2145 /-15MINS, TURN OFF 2230+/-15MINS	
	strBedroomSideLightTimer1.sendCommand("{\"Arm\":1,\"Mode\":0,\"Time\":\"18:45\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":1}")
	strBedroomSideLightTimer2.sendCommand("{\"Arm\":1,\"Mode\":0,\"Time\":\"19:30\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":0}")
	strBedroomSideLightTimer3.sendCommand("{\"Arm\":1,\"Mode\":0,\"Time\":\"21:45\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":1}")
	strBedroomSideLightTimer4.sendCommand("{\"Arm\":1,\"Mode\":0,\"Time\":\"22:30\",\"Window\":15,\"Days\":\"1111111\",\"Repeat\":1,\"Output\":1,\"Action\":0}")
end

rule "Disarm light timers"
when
	Item gAwayLightTimers changed to OFF
then
	//DISARM
	var jsonString = "{\"Arm\":0,\"Repeat\":0}"

	strBedroomSideLightTimer1.sendCommand(jsonString)
	strBedroomSideLightTimer2.sendCommand(jsonString)
	strBedroomSideLightTimer3.sendCommand(jsonString)
	strBedroomSideLightTimer4.sendCommand(jsonString)
end

sitemap snippets
I have two sitemaps. The normal one doesn’t show any of the above. I use a debug one to monitor what’s going on. Some snippets below.

Frame label="Upstairs lights"{
	Switch item=sBedroomSideLight label="Bedroom side" icon="light"
}

Frame label="Devices"{
	Text item=sDadAndroid label="Dad's phone [%s]" icon="boy_3"
	Text item=dtDadAndroid label="Last seen [%1$ta %1$tR]" icon="time"
	Text item=sMumAndroid label="Mum's phone [%s]" icon="girl_2"
	Text item=dtMumAndroid label="Last seen [%1$ta %1$tR]" icon="time"
}

Frame label="Debug"{
	Switch item=sPresence label="sPresence [%s]"
	Switch item=sPresenceTimer label="sPresenceTimer [%s]"
	Switch item=gPresenceSensors label="gPresenceSensors [%s]"

	Switch item=gAwayLightTimers label="gAwayLightTimers  [%s]"
}

Hope this helps!

1 Like