Complex motion/presense rule/s?

It’s not overengineered. Presence detection is hard and reliable presence detection is even harder.
Your idea is basically a variation of the ‘wasp in the box’ algorithm.
Which is one problem. Another main challenge is to get reliable sensor/detector readings.
I’ve held a presentation on that a while back, linked to in the blog to contain a number of issues to watch out for. There’s also a number of threads in the forum.

I have had some good results with the following algorithm.
I divided my living space in rooms and have motion sensors there.
For each rooms I have two counters:
One counts only if the doors to the room are closed meaning I know for sure that somebody is in that room.
The other one counts the amount of movements in the last 15 mins making it possible to use different timeouts for lights, e.g. when there was lots of movement I increase the timeout to keep the lights longer.
This of course only allows to detect that there is somebody, not who it is.

I’m pretty confident I do have reliable sensors (and more will be added over the time)
Question is more about which triggers for rules can be used and how to construct rule/s

eg. changed since would be very handy to have.

I’m not still convinced about Jython that much so I’ll probably go with DSL rules even tho I see some limitations in there, so not sure.
Or node-red is option too just to compute value for current OH item.

Would be nice if somebody have started with something already so we can brainstorm it together :wink:

I have a cat, so I told myself I don’t even start with that. Phone detection didn’t work and so I pushed that away. But looking at your initial post, I thought, I can go with microphones. If the door is closed and it is quit… away-switch is on. I guess that whole discussion comes and goes with good sensors. I just bought a 7,2ghz (true-)presence sensor that also detects me when I sleep - but also that cat :-/ And then, there is that other company that just does not release that sensor that looks like the solution to this problem: https://www.youtube.com/watch?v=VB2fLHVEhjs

it’s there (in persistence)

can you kick me to the direction?
I know graphs can draw based on state timelime so that’s definitely there but … how to access this info from rules?

it’s kind of attribute or?

Read the docs.

You can get this information through Persistence. When you call MyItem.previousState(true) it will return a HistoricState Object which includes a timestamp (.getTimestamp) and the state (.state). By passing true to the call it will return the previous state that is different from the current state. You can then check the timestamp to see how long ago it is. This works great as long as your “since” is greater than half a second or so. It takes time to save the states to the database.

Except when sleeping one would presume. As Markus indicated, this is one of the more difficult problems to solve in home automation.

well I know that, but I don’t feel it is what I would need.
changed since sounds like timebased but in this aplication it is not.
it’s more like this
“state changed since last movement” or “is movement since last changed door to closed”

And since it is returning last different value - which I know what it was (opened or closed) based on which state is now, that will really not help here :slight_smile:
So I don’t really believe time based persistence changed since will help with this

edit: it might be solvable be comparing timestamps of various items, but that seems bit overcomplicated for now, I do like simple algorithms :stuck_out_tongue:

But have to dig it deeper

So you check the lastUpdate time for the movement and the previousState time for the Item. I don’t see how Persistence would be applicable.

Then omit the true and it will return the previous entry regardless of whether or not it’s different from the current state.

You are not going to get away from that. Despite your assertion, it is time based. You need to know how long it’s been since something happened. For that you need to compare timestamps. That’s your only option unless you want to set up Timers which will be even more complex.

The only question is do you get those timestamps from Persistence or do you want to maintain them all yourself?

well I tend to disagree I need timestamps. Since I’m not necessary in need to work with time differencies but state changes after another trigger.

Yes it can be solved by timestamps, but I like challenges so I’m thinking about ruleset without need of one.
Mainly because I’m maintaining motion detectors to keep their time-spans for which motion is ON I do not need (i can) store when it occured.

Al I can say is I’ve gone down the road you are intent on going down more than once. In the end, working with timestamps has always been the far simpler approach than anything else I’ve tried. You asked for advice, that’s mine based on years of experience with OH and similar systems.

this very depends about exact environment, so years of experience might or might not be handy.
I have as well years of experience with programming, yet there is still room for improvements everywhere :slight_smile:

let’s see what I’m now running in production to see if it is solid enough
Short explanation, but code is quite easy to follow.

I have introduced two helpers, one holds ON 15mins after last movement occured.
second one holds if marked entrypoints have changed.
Divided into two simple rules. When marked doors changes their state, helper holds ON
Then in “main” rule I’m checking if there is a motion in a group (±2min value) while doorhelper is ON
if so that means, somebody is home even doors have been opened, so let’s reset door helper and set globalpresence to ON

if 15min motion helper expires (changes it’s state) and door helper is ON that means there were no motion and we can assume nobody is home.

If 15min expires but doors are not changed, nothing happening … just nobody is moving - but as doors have not been changed, we can assume somebody is still home.

I’m running it for couple of days now, seems 100% accurate. But again, this depends how sensors are placed and which are used.
Your results may vary.

if you spot some corner case - speak up
I’m always opened to make rules simplier :slight_smile:

… and there is no single timestamp at all :smiley:

// code is in progress so ignore bits here and there :stuck_out_tongue:

rule "Presense detection / Wasps in the Jar"
when
    //System started  or
    //Item gMotion changed or
    Member of gMotion received update or
    //Item gContactsDoors changed or
    Item holderPresenceMotion changed
then
    val helper  = holderPresenceMotion.state   // this holds movement for 15mins (expire binding)
    val motion  = gMotion.state                // this holds group info about movement +- 2min
    val doors   = holderPresenceDoors.state    // this holds info if doors have been changed since
    //val presence = holderPresence.state

    // lets check if there is a movement after doors helper have been switched ON
    if(motion == ON && doors != OFF){

        logInfo("PRESENCE", "Motion after door changed ==> somebody home")

        // set doors helper to OFF because there is a movement
        holderPresenceDoors.sendCommand(OFF)
        // set global presense to ON (somebody is home)
        holderPresence.sendCommand(ON)
    }

    // 15min helper expired and doors have been changed?, assume nobody home
    if(helper == OFF && doors == ON){

        logInfo("PRESENCE", "No motion after door has changed")

        // set global presence to OFF (door were changed and motion expired)
        holderPresence.sendCommand(OFF)
    }
end

rule "Presense detection: Doors in/out"
when
    Item gContactsDoors changed
then
    // doors opened/closed
    holderPresenceDoors.sendCommand(ON)
    
    logInfo("PRESENCE", "Door opened/closed ==> setting helper to ON ")
end

value of holderPresence (based on doors and motions) I can further combine with mobile phones, running Kodi or specific lights … to make it even more accurate. But for now, let’s keep it simple.

you may want to check out this tutorial by Scott

here is a further reading on the idea Markus mention
Rule Example Wasp in Box

Area Actions are nice, thanks -> using something very similar actually.

But Wasp in the Box based on timestamps is no go for me, as it is unnecessarily complicated.
Logic issue with wasp in the box does not depends on time at all, but about knowing changes of the specific entries which might (and should) be timeless.
That’s why I wanted to start over, with states instead of timestamps.

I’m interested to see how you solve this problem - please keep this thread updated.

I’m using a variation of Andrew”s Wasp in Box algorithm, and I find it reliable. I found it was important to tune the algorithm to my specific context (which sounds obvious in retrospect.)

well those two rules above works very accurate, there are some cases which might be corners - somebody is sleeping and somebody else left house -> house will be marked as empty, but … not sure if worth the hassle of overcomplicating it.

anyway my sensors are placed on several places one of which is entrance hall. That makes things a lot of easier as my latest motion will be always entrance hall when leaving home therefore whole group will become off after grace period which will be always after doors are triggered.

Have a look at https://github.com/mjcumming/Occupancy-Manager/blob/master/README.md

This does essentially what you are doing and built so that you do not need to do anything but define your items with the appropriate metadata and tags.

looks pretty much similar yeah.
Anyway I do believe that those ruleset/logics can’t be really generalized as everyone has got very different setup and usecases.

My two rules with no timestamps works flawlessly so far, which makes this area of interest for now satisfied :slight_smile:

So after a month I’ve captured some minor corner cases and as well splitted one rule to two (as in one it sometimes happened that one part used older data from postupdate)

so actual and 99.9% accurate solution is this (0.1% is when somebody is sleeping eg. not moving and somebody else triggers doors)

/* motion detectors activity */
rule "Motion activity"
when
    Member of gMotion received update
then
    var now = new DateTimeType()
    
    postUpdate(triggeringItem.name+"_t", now.toString)
    postUpdate(gMotion_t, now)

    // global 15min coundown reset (expire binding)
    holderPresenceMotion.sendCommand(ON)
end

rule "Presense detection / somebody home"
when
    //Item gMotion changed to ON or
    Member of gMotion changed to ON
then
    // set doors helper to OFF because there is a movement
    if(holderPresenceDoors.state != OFF){
        holderPresenceDoors.sendCommand(OFF)
        logInfo(logName, "Doors => helper OFF")
    } 

    // set global presense to ON (somebody is home)
    if(holderPresence.state != ON){
        holderPresence.sendCommand(ON)
        logInfo(logName, "Motion => somebody home")
    }
end

rule "Presence detection / nobody home"
when
    Item holderPresenceMotion changed to OFF
then
    // 15min helper expired and doors helper is not OFF?, assume nobody home, set presence helper to OFF
    if(holderPresenceDoors.state == ON){
        holderPresence.sendCommand(OFF)
        logInfo(logName, "15min + Doors => empty house")
    }
end

rule "Presence detection / Doors in-out"
when
    Member of gContactsDoors received update
then
    // set in-out helper to ON as doors have been oppened/closed
    if(holderPresenceDoors.state != ON){
        holderPresenceDoors.sendCommand(ON)
        logInfo(logName, "Doors => helper ON")
    }
end

some relevant items

Switch      holderPresenceMotion    "Motion sensors [MAP(motion.map):%s]"    <motion> (gPresence) { expire="15m,command=OFF" }
Switch      holderPresenceDoors
Switch      holderPresence          "Is anybody home? [MAP(presense.map):%s]"   <motion>    (gPresence)

Group:Switch:OR(ON, OFF)        gPresence       "Presence [(%d)]"
Group:Switch:OR(ON, OFF)        gMotion         "Motion [(%d)]"             <motion>
Group:Contact:OR(OPEN, CLOSED)  gContacts       "Doors & Windows [(%d)]"    <contact>
Group:Contact:OR(OPEN, CLOSED)  gContactsDoors

and as sensors
I have currently 6 PIR sensors (AM312) and indeed Contacts on entrance doors.
All PIRs have 2min cooldown, in which another movement retriggers 2min grace period.
Then I’m using one 15min expire binding holderMotion to be sure there is enough time after no movement to safely say there is nobody home when doors have been triggered.

Currently I’m not combining these informations with anything else like Kodi or mobiles or something else, as in my setup this is accurate in basically any normal life situation happening at my house.

What I’m using it for? mainly for turning down heating - so I don’t need to have programmed timespans when it should maintain temperatures, simply when somebody is home heating is set to comfort level, otherwise powersafe. Then I’m using it for some additional ambilighting here and there as well as garden lights/pond etc.

Might or might not help somebody.
It’s quite simple yet very precise solution of presence detection
(and it’s not using any timestamp at all - as I originaly wanted to avoid them :slight_smile: )

Cheers

2 Likes