Motion and Alarm Timer Help

Hi,

I’m coming to the end of my presence detection rules and am pretty happy with the whole process but I’m getting confused on the last bit. I keep making it far to complicated and I’m sure there is an easier way…that’s where I hope you lovely people can come in…

So, my code:

rule "vMotion is ON - Intruder!"
when
    Item vMotion changed
then
    if(vMotion.state == ON)
        {
        logInfo(logName, "vMotion Alert - Double Check for Presence")	
        *** do some stuff to check for my / wife presence in the house and set vPresent to ON if there is
            if(vPresent.state == ON) // vPresent is ON - someone is actually home
                {
                logInfo(logName, "vMotion Alert - Phew - Someone was actually present - nothing to do")
                vMotion.sendCommand(OFF) // set vMotion OFF again as it was me / wife that set the motion sensor off
                }
            else
                {
                logInfo(logName, "vMotion Alert - INTRUDER - No one is home")
                sendBroadcastNotification("vMotion Alert - INTRUDER - No one is home")
                *** turn on camera to log who set of motion
                logInfo(logName, "vMotion Alert - INTRUDER - Turning on cameras") 
                sendBroadcastNotification("vMotion Alert - INTRUDER - Turning on cameras")               
                }
        }
    else
        {
            logInfo(logName, "vMotion set to OFF")
            sendBroadcastNotification("vMotion Alert - INTRUDER - No more motion detected after 5 minutes - vMotion OFF")
        }
end

So a quick summary of the rule, I have a few motion sensors, all grouped into a vMotion group switch. When motion is detected this rule fires.

If vMotion is set to ON, it first checks to see if a family member is present, if they are it turns vMotion OFF and adds a logfile.

If we aren’t present then it takes it to the next stage where it assumes an intruder, (simple logic of no one home but there is movement so someone must be in the house), so it sends me as message and turns on the camera if they aren’t already on.

The vMotion item has an expire binding of 5 minutes, so obviously if there is no more motion it turns vMotion to OFF after 5 minutes and the final part of the else rule runs, informing me that it was a one off motion so either postman, spider, ghost, whatever but leaves the cameras on just in case, (and to be honest I’ll have checked them by then anyway).

All good, and the rule runs perfectly. The issue I have is at the moment other than turning the cameras on when first motion is detected, I have nothing to say what happens if more motion is detected within the 5 minute expire.

Ideally I’d like it to turn on another proxy variable called vAlarm from within this rule which then runs another ‘when vAlarm changes’ rule to sound the alarm, flash the lights etc. However, I am struggling to see the best way for the rule to check that more motion has been detected.

My thought is that I might need to remove the expire binding and add an ‘in rule’ timer in its place or incorporate a counter which increments for each motion and if after 5 minutes it is more than 1 set vAlarm but I’m getting into knots as to the best way to do it really.

Ideally there would be some way in the expire binding to pull out how many timer resets the 5m expire timer has had but I don’t think that is possible…

Any ideas gratefully welcomed!

Perhaps create a unbound number item and use it as a counter

Thanks, but how would / could I use it to count the number of times the expire binding has reset…is that possible?

I wonder if I should make my vMotion proxy a number rather than a switch and then have 0 for OFF, 1 for ON and then have a timer set to 2 or something if a timer reaches x minutes and then run a case statement to determine what to do…hummm…

Another thing to think about. Arrgghh!

OR

could I just set a timer in the rule that counts to 5 minutes 10 seconds and then test to see if vMotion is still ON, if it is then I guess the expire binding has been reset so it can turn on vAlarm, if its not then it can disarm???

Well you have a section of rule that runs when vMotion goes to OFF, so you could increment a count from there. You could even put an expire on the counter so that it self-clears after an hour or two idle.
I’m not sure how such a counter helps with this though -

Seems a reasonable thing to look at. For myself, I probably would not start messaging at the first “knock” but wait for another, whether that comes from same or another sensor.

I do something like this. If you set up your sensor rules to send vMotion a command (rather than update) and disable autoupdate for vMotion - you can trigger a rule from the command, use it to increment your counter (until some limit) and take different actions at each stage.

Thanks, interesting notion of incrementing a counter on OFF, my thought process is always to increase when something is switched ON, but I like the alternative take…I like it when something so simple can be taken and adapted with just a little twist.

I agree on the first knock part, i only put the message in there to check the rule worked through the logic, the idea is to replace it with this vAlarm concept but I’ve not quite got the logic yet.

I’m going to go and have a play with the counter ideas…

Just a thought, I got influx going so I could look at what my motion sensors actually are doing. Motion sensors can be a little flaky. Some take quite a long time to reset also.
The motion sensor I use for presence is pointed at a stairwell where there are no windows or anything other then the front (only) door to reduce false alarms. The one in the living room goes off occasionally when I am not there.

Hi,

Right, reworked it a little but it’s erroring, sure it’s nothing major but I’m getting code blind now…

Item

Number vMotionC     "vMotionC [%d]"     <motion>     { expire="5m,state=0" }

Command in separate rule updating vMotionC

vMotionC.sendCommand(vMotionCCount + 1)

Top of the rule

var vMotionCCount = vMotionC.state as DecimalType

Rule

rule "vMotionC is > 0 - Intruder!"
when
    Item vMotionC changed
then
    logInfo(logName, "vMotionC Alert - Double Check for Presence")	
    *** do some presence detection stuff
    createTimer(now.plusSeconds(5),
        [
        if(vPresent.state == ON) // vPresent is ON - someone is actually home
            {
            logInfo(logName, "vMotionC Alert - Phew - Someone was actually present - nothing to do")
            }
        else
            if(vMotionCCount > 0)
                {
                switch vMotionCCount 
                    {
                    case 1:
                        logInfo(logName, "vMotionC Alert - INTRUDER - No one is home Count 1 - Awaiting further count")
                    case 2:
                        sendBroadcastNotification("vMotionC Alert - INTRUDER - No one is home Count 2")
                        sendBroadcastNotification("vMotionC Alert - INTRUDER - Turning on cameras")
                        logInfo(logName, "vMotionC Alert - INTRUDER - Turning on cameras")
                        *** do some stuff - set cameras to turn on etc
                    case 3:
                        sendBroadcastNotification("vMotionC Alert - INTRUDER - No one is home Count 3")
                        *** do some stuff - set cameras to turn on etc fire alarm etc
                    }
                }
            else
                {
                    logInfo(logName, "vMotionC Alert - INTRUDER - 5 minutes with no motion - vMotionC 0")
                    sendBroadcastNotification("vMotionC Alert - INTRUDER - 5 minutes with no motion - vMotionC 0")
                }
        ])
end

So now, I have an number proxy item called vMotionC, which every time there is motion detected will increase the value by 1.

So the rule now runs on a change in the vMotionC, it first checks to see if someone is home
If there is it writes to a log and ends
If there isn;t it checks to see if the count is > 0, if not then vMotionC is 0 and nothing to do.
If it is then it drops into a case statement
case 1 - 1 motion detection - doesn’t do much other than log
case 2 - send me a message and turns the cameras on
case 3 - does a load more stuff including turning on the alarn etc

However, it errors and the log file is:

2019-06-04 22:39:03.216 [WARN ] [el.core.internal.ModelRepositoryImpl] - Configuration model 'motion.rules' has errors, therefore ignoring it: [100,50]: no viable alternative at input '('
[100,51]: extraneous input '"vMotionC Alert - INTRUDER - Turning on cameras"' expecting ')'
[101,32]: no viable alternative at input '('
[101,42]: no viable alternative at input '"vMotionC Alert - INTRUDER - Turning on cameras"'
[103,25]: mismatched input 'if' expecting '=>'
[103,51]: mismatched input '!=' expecting ')'
[103,56]: no viable alternative at input ')'
[104,21]: mismatched input 'case' expecting '}'
[104,27]: mismatched input ':' expecting ']'
[105,25]: missing ')' at 'sendBroadcastNotification'
[106,21]: mismatched input '}' expecting 'end'

So it looks ok except for a few character errors, but I just can’t see them…any help please…

Right, I’ve realised I’ve gone a bit crazy mixing up all sorts of things - I can only put it down to watching the last episode of Chernobel at the same time.

So, new rule:

rule "vMotionC is > 0 - Intruder!"
when
    Item vMotionC changed
then
    if(vMotionC.state > 0)
        {
        switch vMotionC 
            {
            case "1":
                {
                logInfo(logName, "vMotionC Alert - INTRUDER - No one is home Count 1 - Awaiting further count")
                }
            case "2":
                {
                sendBroadcastNotification("vMotionC Alert - INTRUDER - No one is home Count = 2")
                //sendBroadcastNotification("vMotionC Alert - INTRUDER - Turning on cameras")
                logInfo(logName, "vMotionC Alert - INTRUDER - Turning on cameras")
                // set vIFTTTArlo_ONOFF to ON if it isn't already
                if(vIFTTTArlo_ONOFF.state != ON)  vIFTTTArlo_ONOFF.sendCommand(ON)   
                } 
            case "3":
                {
                sendBroadcastNotification("vMotionC Alert - INTRUDER - No one is home Count = 3")
                }
            }
        }
    else
        {
        logInfo(logName, "vMotionC Alert - INTRUDER - 5 minutes with no motion - vMotionC = 0")
        sendBroadcastNotification("vMotionC Alert - INTRUDER - 5 minutes with no motion - vMotionC = 0")
        }
end

I've got a mapping on the sitemap at the moment changing vMotionC, which it does...

I get no errors in the logs but now nothing happens so I'm guessing I've got an issue with the vMotionC.state not relating to the 0, do I need to convert to vMotionC.state.tostring and then modify the 0 to a "0" or something???

Why not change your switch-case to work on numbers instead of strings? But yes it will be the state that you are switching on.

Numbers can be a bit funny about coming out as 1 or 1.0; that shouldn’t happen if you only do integer things to them - but belt and braces, because it will affect a switch-case
(vMotionC.state as Number).intValue
will avoid surprises.

You could also do away with if-else and have case 0 instead

just… ok wow

Hi,

Thanks all, after a nights sleep I can see what I’ve done and it’s a classic case of ‘not having a clear idea of what I want to achieve or how to achieve it’

I’ve mixed numbers, strings and switches and then done some looping that isn’t necessary.

I’m going to have another play with it and go from there, thanks for your help so far, if anyone has any more input in the meantime I’m all ears.

Well, it’s weird, but Numbers aren’t typed as decimal or integer. They behave predictably really, but the user can get surprises.
1 + 1 = 2 tada.
but 1 + 1.0 = ?? 2 or 2.0 ?? Both cases are arguable but it has to go one way or the other.

Most often it doesn’t matter, but switch-case for an example is picky and does not consider 1 to be identical to 1.0

1 Like