Presence Detection Rule

It is a side effect of how the state of a Group Item gets calculated. The short of it is that your rule will triggered n times per item update where n is the number of items they are a member of the group.

You are not doing anything wrong. I should have had the lock there in the first place.

I am trying to use your code. However, i noticed that the “gPresent changed” is never trigged. Any idea?

openhab.log does not show the logInfo “Here”

2017-08-22 19:10:07.074 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'default.items'

events.log shows

2017-08-22 19:10:39.364 [ItemStateChangedEvent     ] - S_V_JohnPhoneIP changed from OFF to ON

Item file

Group gPresent     "Present group" <present>
Group gJohnPresent "John Present" <present>

Switch Present "Someone is Present" <present> // turns off 5 minutes after everyone leaves
Switch  S_V_JohnPhoneIP <network>  (gJohnPresent,gPresent) {channel="network:device:d12435eb:online"}


import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import java.util.concurrent.locks.ReentrantLock
val ReentrantLock lock = new ReentrantLock ()

var Timer presenceTimer = null

rule "gPresent changed"
        Item gPresent received update
                logInfo("mydata", "HERE") // log variable
try {

                // your code goes here
                val isPresent = gPresent.allMembers.filter(s | s.state == ON).size > 0
                logInfo("mydata", "#" + isPresent + "#") // log variable

                // Someone came home
                if(isPresent && Present.state != ON) {
                        logInfo("Presence", "Someone is home")
                                if(presenceTimer != null) {
                                                presenceTimer = null

        // Everyone is gone
                else if(!isPresent && Present.state != OFF) {
                        logInfo("Presence", "No one is home, setting timer")
                                if(presenceTimer != null) {
                        presenceTimer = createTimer(now.plusMinutes(5), [|
                                        logInfo("Presence", "No one is home after five minutes")
                                        if(Present.state != OFF) Present.sendCommand(OFF)

       catch(Throwable t){
                logError("Presence", "Error processing BTPresence update: " + t)
        finally {

I think that this is due to the new way that Groups work now:

Try to use a type (and optionally a function) for your Group definition.
Something like:

Group:Switch gPresent     "Present group" <present>

Group:Switch gPresent     "Present group" <present>

is also not triggering the rule. I wonder if the following is required

Group:Switch:OR(ON,OFF)  gPresent     "Present group" <present>

I have updated the above code that I payed above which you can find here:

My understanding is adding a type to the group should be sufficient to get update events on the Group but since I use gPresent’s state elsewhere I’ve always had a function.

I noticed that there is no ReentrantLock in the new code. Is that not required anymore?

That is correct. The ReentrantLock is no longer needed. I’ve been running this code for many months now and I honestly don’t remember why there ReentrantLock lock was in there in the first place.

I have a DateTime associated to each Sensor as Rich Koshak as explained in another post.

i want to display the max of all those dates

How can i proceed ?

Group:DateTime:MAX SensorUpdates

Something like that should work.

If not you will need a Rule and a Proxy Item.

@rlkoshak Thanks i will try but i have seen another issue

The Sensor_lastUpdate is update at each reboot or restart service


rule "ZWaveNode2_DoorWindowSensor"
    Item ZWaveNode2_DoorWindowSensor changed 
     ZWaveNode2_DoorWindowSensor_LastUpdate.postUpdate(new DateTimeType()) 

log at the boot

018-06-06 10:06:42.821 [vent.ItemStateChangedEvent] - ZWaveNode2_DoorWindowSensor_LastUpdate changed from NULL to 2018-06-06T09:41:32.001+0300


        everyMinute     :       "0 * * * * ?"
        every5Minutes   :       "0 */5 * * * ?"
        everyHour       :       "0 0 * * * ?"
        everyDay        :       "0 0 0 * * ?"

        default = everyChange

    * : strategy = everyChange, everyDay, restoreOnStartup

i have tried to check if the value is not NULL in my rule (boot time) but it do not work

rule "ZWaveNode2_DoorWindowSensor"
    Item ZWaveNode2_DoorWindowSensor changed 
        if (ZWaveNode2_DoorWindowSensor.previousState().state.toString!==NULL){
        ZWaveNode2_DoorWindowSensor_LastUpdate.postUpdate(new DateTimeType()) 


it do not work
Could you advise?

Try that.
Don’t forget the ; after return

rule "ZWaveNode2_DoorWindowSensor"
    Item ZWaveNode2_DoorWindowSensor changed
    if (previousState === null) return; # Don't run the rule if the previous state is null
    ZWaveNode2_DoorWindowSensor_LastUpdate.postUpdate(new DateTimeType()) 


if(previousState != NULL) {

.previousState will give you the most recent value in the database. So what is probably happening is the changed state (i.e. the change that triggered the Rule) is already saved in the DB before the Rule executes giving you the current state of the Item when you call previousState. This is why the implicit variable previousState exists.

Also, only use !== or === when on of the operands is null which is not the same thing as NULL.

1 Like

THanks a lot


The return is like an "Exit rule " or “exit if”?

Exit rule

1 Like

Hi Rich

In your pattern you have an item Garage_status_LastUpdate which shows when the garage was opened, it records a value like so:

smarthome:status Garage_status_LastUpdate

Am I right in saying a Transform map could somehow conver this rather unusable string to something more like minutes or seconds that the door has been open for use in an TTS Alexa rule?


No. That item is a DateTime so it records an instant in time, not a duration.

You need a Number Item and a Rule to periodically increment the value while the door is open. Then you need a JS transform to convert the number, let’s say minutes, to hh:mm

1 Like


Where can I learn how to have my openHab raspberry PI home hub detect when a remote raspberry PI that detects my cell phone via Bluetooth for presence detection?

Mike Reporter is one way.

Integrating reelyActive on a Raspberry Pi 3 with openHAB over MQTT is another.

Thank you, I’ll dig in!