Generic Presence Detection

In the end, you could use Present as the timer so long as ON keeps getting sent to it while you are present every <n minutes where n is the timer length.

I did just that. My presence detection is based on the Fritz!Box (router) TR065 binding. The binding updates presence items (MAC addresses of iPhones) once per minute. So there is my “every x minutes” trigger to keep the timers running.

The Fritz!Box presence detection is generally very reliable. However, there are two catches: Sometimes a MAC will be falsely reported as being absent for a short period of time. Especially at night, when the phones are on standby. I have learned from experience that this generally happens within a timeframe of less than five minutes. Secondly, the moment a MAC becomes (really) absent, it sometimes gets reported as being present again directly after the absence and then (finally) absent again within seconds. It then stays absent reliably.

The solution is what you proposed, and it is beautifully elegant. I cannot use the presence Items controlled by the binding directly for the reasons mentioned above. So they serve as the triggers for the “real” presence items I then use in other rules. The “real” presence items expire after 5 minutes if not updated. In other words, presence is detected immediately and absence is detected with a 5min delay. (Actually, just for completeness’ sake: Absence is detected with a 20mind delay because the Fritz!Box reports absence with a delay of 15min. This seems to be built into the firmware and cannot be helped.)

Note that I also use “arrival” items. I have defined a timeframe of 5min in which someone is in the state of arriving. E.g. the front door light would be switched on during that time (if it is dark, etc.). Those are just “sugar” items that are not really necessary. The advantage being that the arrival timeframe can be defined in the items definition file as well.

Items:

// Fritz!Box presence items

// iPhone A
Switch PresenceFritzA "A (Fritz) [MAP(presence.map):%d]" <present> {fritzboxtr064="maconline:xx-xx-xx-xx-xx-xx"}
// iPhone B
Switch PresenceFritzB "B (Fritz) [MAP(presence.map):%d]" <present> {fritzboxtr064="maconline:xx-xx-xx-xx-xx-xx"}

// if at least one person is present (ON), the group is present (ON), else absent (OFF)
Group:Switch:OR(ON, OFF) PresenceAnyone "Anyone [MAP(presence.map):%d]" <present>
// be present immediately but be absent after (not receiving presence update for) five minutes
Switch PresenceA "A [MAP(presence.map):%d]" <present> (PresenceAnyone) {expire="5m,command=OFF"}
Switch PresenceB "B [MAP(presence.map):%d]" <present> (PresenceAnyone) {expire="5m,command=OFF"}

// if at least one person is arriving (ON), anyone is arriving (ON) else not (OFF)
Group:Switch:OR(ON, OFF) ArrivalAnyone "Anyone [MAP(arrival.map):%d]"
// status "arriving" is kept for five minutes
Switch ArrivalA "A [MAP(arrival.map):%d]" (ArrivalAnyone) {expire="5m,command=OFF"}
Switch ArrivalB "B [MAP(arrival.map):%d]" (ArrivalAnyone) {expire="5m,command=OFF"}

// There is no XOR for groups so we need to use an Item and a rule
Switch ArrivalFirst "First [MAP(arrival.map):%d]" {expire="5m,command=OFF"}

Rules:

rule "A (Fritz) present or absent"
when
	Item PresenceFritzA received update ON
then
	PresenceA.sendCommand(ON);	
end

rule "B (Fritz) present or absent"
when
	Item PresenceFritzB received update ON
then
	PresenceB.sendCommand(ON);	
end

rule "A arriving"
when
	Item PresenceA changed to ON
then
	ArrivalA.sendCommand(ON)
end

rule "B arriving"
when
	Item PresenceB changed to ON
then
	ArrivalB.sendCommand(ON)
end

rule "First arrival"
when
	Item PresenceAnyone changed to ON
then
	ArrivalFirst.sendCommand(ON)
end

Thank you very much for that elegant solution. It helped me do away with tons of lines of cumbersome timer code as well.

4 Likes