My presence detection in combination with time of day

Like many of the Openhab users I was searching a presence detection rule. In my last topic I try to solve a timer issue and got nice and smart help from @shutterfreak.
Solution you can find here: Switching light by daytime and presence

For me as newbee/advanced many rules for presence detection/ coming home seemed very complex. So I tried my way. And I think I was successfull. Time will show it.

What I want:

  • A solution for not switching the light, if network connection from my devices got lost and connected again
  • A solution for having other lights switched by the time of day
  • Switching light of after leaving

What I use:

ITEMS

Network-Items:

Group:Switch:OR(ON,OFF) gPresence "Anwesenheit"

Switch     PingS10PlusOnline     "Online"            {channel="network:pingdevice:s10plus:online"}
Number     PingS10PlusLatency    "Pingzeit"          {channel="network:pingdevice:s10plus:latency"}
DateTime   PingS10PlusLastseen   "Zuletzt gesehen"   {channel="network:pingdevice:s10plus:lastseen"}

Switch     PingS8PlusOnline     "Online"            {channel="network:pingdevice:s8plus:online"}
Number     PingS8PlusLatency    "Pingzeit"          {channel="network:pingdevice:s8plus:latency"}
DateTime   PingS8PlusLastseen   "Zuletzt gesehen"   {channel="network:pingdevice:s8plus:lastseen"}

Light-Items:

Group:Switch:OR(ON, OFF)    gHMFlurLights    "Alle Lichter Flur [(%d)]"
Switch HM_SwitchLight1 "HM Flur 1" <light> (gHMFlurLights) {channel="..."}
Switch HM_SwitchLight2 "HM Flur 2" <light> (gHMFlurLights) {channel="..."}
Switch HM_SwitchLight3 "HM Flur 3" <light> (gHMFlurLights) {channel="..."}

RULES

import org.openhab.model.script.actions.Timer
// This timer will take care of turning off presence:
var Timer timer_presence = null


rule "gPresence schalten"

when
    Item PingS10PlusOnline changed or
    Item PingS8PlusOnline changed
then
    if(PingS10PlusOnline.state == ON || PingS8PlusOnline.state == ON){
        // Cancel timer_presence if it was running
                timer_presence?.cancel()
                gPresence.sendCommand(ON)
    }

    else
                timer_presence = createTimer(now.plusSeconds(30), [ |
                    sendCommand(gPresence, OFF)
                    timer_presence = null
                ])
end
    



rule "Flurlicht schalten bei Anwesenheit"

when 
    Item gPresence changed

then
    switch (gPresence.state) {
        case ON:
            {
                // Process time of day
                switch (vTimeOfDay.state) {
                    case "MORNING",
                    case "DAY",
                    case "AFTERNOON":
                        {
                            gHMFlurLights.sendCommand(ON)
                        }
                    case "EVENING",
                    case "NIGHT",
                    case "BED":
                        {
                            HM_SwitchLight2.sendCommand(ON)
                        }
                }
            }
        case OFF:
            {
                    sendCommand(gHMFlurLights, OFF)
            }
    }
end

At the end I created a small Basic UI Sitemap for checking the function.

sitemap presence label="Anwesenheit"
{
	Frame label="Geräte Präsenz"{
		Switch item=PingS10PlusOnline label="Galaxy S10 [%s]"
		Switch item=PingS8PlusOnline label="Galaxy S8 [%s]"
	}
    Frame label="gPresence ON/OFF"
    {
		Switch item=gPresence label="Anwesenheit [%s]"
        Switch item=gHMFlurLights
        Switch item=HM_SwitchLight1
        Switch item=HM_SwitchLight2
        Switch item=HM_SwitchLight3
	}
}

Hi, instead of timers I suggest using the expire binding. This way you just update a switch when one of your devices received a ping. And if your switch wasn’t updated (turned on) for let’s say 30 seconds, your switch will automatically turn off. So another rules could be attached to the “Switch turned off” event. You will find a lot of examples in the community

1 Like

Hi,

I agree with @Partone. Using the expire binding is much easier than dealing with timers and need to take care about start, cancel and fire them.

One more thing I noticed: Your item gPresence is a group. Any reason for this, since I can’t see any items that belong to it. It seems to be a proxy item.

Here is my implementation that I found working really well for me. It has groups for every person which can be present and the real items evaluating presence are added to this group. This allows me to just add another item (e.g. bluetooth ping, face recognition, etc) if needed.

If every sensor is off I start a 5 minutes timer and after that I set the Presence item with the state of all sensors:

Items:

Switch				Presence		"Anwesenheit [MAP(presence_de.map):%s]"		<presence>

Group:Switch:OR(ON,OFF)		Presence_Sensors

Switch				Presence_Timer															{expire="5m,command=OFF"}

/********************		Person 2	********************/
Group:Switch		Person1_Presence		"Person 1 [MAP(presence_de.map):%s]"		<man_3>		(Presence_Sensors)
Switch 			Person1_Mobile										(Christian_Presence)

/********************		Person 2	********************/

Group:Switch		Person2_Presence		"Person 2 [MAP(presence_de.map):%s]"		<woman_3>	(Presence_Sensors)
Switch 			Person2_Mobile

Rules

/*
 * Somebody came home or everybody left
 * If all sensors to check presence are OFF
 * --> Setup time to check again to avoid flapping
 */
rule "Presence changed"
when
	Item Presence_Sensors changed
then
	if (Presence_Sensors.state == ON)
		Presence.postUpdate(ON)
	else
		Presence_Timer.sendCommand(ON)
end


rule "Check if everybody is still away"
when
	Item Presence_Timer received command OFF
then
	Presence.postUpdate(Presence_Sensors.state)
end

This approach has only some little lines of code and allows me to enhance it by just changing the items.

2 Likes

Thank you!

Keeping it simple and as allrounder for several applications.
I adapted it to my rule and it works too. I will keep that!

1 Like