Design Pattern: Motion Sensor Timer

motionsensor
motiondetection
designpattern
Tags: #<Tag:0x00007fe05430ee40> #<Tag:0x00007fe05430ecd8> #<Tag:0x00007fe05430eb48>

(Karen Mitchell) #68

Correct, the KitchenArmedTripped doesn’t fire again when it detects motion. The issue is that ‘nothing’ is updated until after it changes to a 0 and then detects motion again.

How do I get the ‘wait’ time between the sensor setting the KitchenArmedTripped to a 1 and then being reset to a 0. I think if it goes back to a 0, it may be ‘looking’ for motion again. Right now, it triggers and then stops looking for about 11 minutes (which is probably some kind of delay since the last trigger).


(Rich Koshak) #69

You will have to look in the manual for the sensor. Your rule will never work until you get updates faster than your Expire timer.


(Boris) #70

Rich, thank you so much,
but please give me some time to understand.
It looks at first view already really promising even I see some of the commands first time (no surprise:-)

I think I will go without this additional binding because it doesn’t increase my poor understanding.

Maybe a few questions already now
What is this import Java.util.List stands for and does this require always internet access?
What is this var List … stands for and what is this ArreyList I don’t see it used further?
Not so important but what happens when I would have a power loss during the timer runs, can I influence this?
There is not one timer for each device Target one for all, what gets restarted, right?

Please let me come back when I am able to apply that rule and see if it is working as required.

Thanks a lot


(Rich Koshak) #71

It tells the rules engine you want to use the List class. You can’t create and use a List without that import. It does not user the internet.

It stores the Timers for the first two ON events.

You see timers used again, several times. var List timers crates a variable of type List named timers.

Not without making the rule at least twice more complex. If you lose power the minute starts over.

You didn’t say anything about the events on one device. You said three events per minute from any device.


(Boris) #72

Hi Rich and others which may help here

Now I am trying to implement the rule you provided me, but there is something not correct I asume, can you check please and help me to resolve it?
Thanks in advance!

This is the rule I have created now:

import java.util.List
var List timers = createArrayList
var Timer shutoffTimer = null
var lastRun = now

rule “Sonbas Motion changed from OFF to ON 3 times in a minute”
when
Item Sonbas10b changed from OFF to ON or
Item Sonoff3 changed from OFF to ON
then
if(shutoffTimer !== null || Alarm.state == OFF || lastRun.isAfter(now.minusMinutes(2))) return;
if(timers.size < 2) {
val t = createTimer(now.plusMinutes(1), [ | timers.remove(t) ])
timers.add(t)
}

if(timers.size == 2) {
sendMail("xxx@gmail.com", “Sonbas10b”, “Sonbas10b motion”)
TH03.sendCommand(ON)
lastRun = now
logInfo(“RuleInfo”, “Siren START”)
shutoffTimer = createTimer(now.plusSeconds(30)) [|
TH03.sendCommand(OFF)
logInfo(“RuleInfo”, “Siren STOP”)
shutoffTimer = null
]
}
end

and this is stated in openhab.log:

2018-06-26 22:39:36.825 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model ‘MQTT.rules’
2018-06-26 22:39:51.397 [WARN ] [me.internal.engine.RuleContextHelper] - Variable ‘timers’ on rule file ‘MQTT.rules’ cannot be initialized with value ‘createArrayList’: The name ‘createArrayList’ cannot be resolved to an item or type; line 3, column 26, length 15
2018-06-26 22:39:51.587 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5
2018-06-26 22:39:56.065 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5
2018-06-26 22:40:00.583 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5


(Rich Koshak) #73
newArrayList

I recommend using Maps though so you can associated the Timer with the Item that caused its creation.

Also, in the future How to use code fences.


(Boris) #74

You mean newArrayList instead createArrayList, that´s all?
Just one other thing. This command:
val t = createTimer(now.plusMinutes(1), [ | timers.remove(t) ])
timers.add(t)
how does this work, e.g. what means “timers.remove(t)”
Do I need to enter for “t” a value or does it just count it to “val t”


(Boris) #75

Ok now with code fences:-)

You mean newArrayList instead createArrayList ?


(Boris) #76

So I changed to newArrayList, but there is another error upcoming for the following line 12, column 32 this is the Alarmˋcommand
if(shutoffTimer !== null || Alarm.state == OFF || lastRun.isAfter(now.minusMinutes(2))) return;ˋ

What do I need to change here, any idea?
Thank you

2018-06-27 11:32:51.612 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5
2018-06-27 11:32:57.599 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5
2018-06-27 11:33:04.961 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5
2018-06-27 11:33:12.747 [ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘Sonbas Motion changed from OFF to ON 3 times in a minute’: The name ‘Alarm’ cannot be resolved to an item or type; line 12, column 32, length 5ˋ


(Boris) #77

Hi Rich, ok solved by my own -ˋAlarm.Stateˋ belongs to an item.

So the rule works, the only remaining thing is that I can see now in openhab.log tons of stupid comments - what can I do against that?
even that the rule works it raises so much issues?

And one of the comments refers to
val t = createTimer(now.plusMinutes(1), [ | timers.remove(t) ])
timers.add(t)ˋ

The ˋtˋ at position 65 is not recognized, do I need to adjust?

Thanks a lot

2018-06-27 13:21:31.828 [ERROR] [org.quartz.core.JobRunShell ] - Job DEFAULT.2018-06-27T13:21:31.823+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
.remove()
} ] threw an unhandled Exception:
java.lang.reflect.UndeclaredThrowableException: null
at com.sun.proxy.$Proxy145.apply(Unknown Source) [?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:49) [137:org.eclipse.smarthome.model.script:0.10.0.oh230]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) [107:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [107:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
Caused by: org.eclipse.smarthome.model.script.engine.ScriptExecutionException: The name ‘t’ cannot be resolved to an item or type; line 14, column 65, length 1
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:133) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:223) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1115) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1045) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:143) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:763) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:219) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:446) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:227) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
… 4 more
2018-06-27 13:21:31.923 [ERROR] [org.quartz.core.ErrorLogger ] - Job (DEFAULT.2018-06-27T13:21:31.823+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
.remove()
} ] threw an exception.
org.quartz.SchedulerException: Job threw an unhandled exception.
at org.quartz.core.JobRunShell.run(JobRunShell.java:213) [107:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573) [107:org.eclipse.smarthome.core.scheduler:0.10.0.oh230]
Caused by: java.lang.reflect.UndeclaredThrowableException
at com.sun.proxy.$Proxy145.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:49) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[?:?]
… 1 more
Caused by: org.eclipse.smarthome.model.script.engine.ScriptExecutionException: The name ‘t’ cannot be resolved to an item or type; line 14, column 65, length 1
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:133) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:901) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:864) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:223) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluateArgumentExpressions(XbaseInterpreter.java:1115) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._invokeFeature(XbaseInterpreter.java:1045) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.invokeFeature(XbaseInterpreter.java:991) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.invokeFeature(ScriptInterpreter.java:143) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:763) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:219) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter._doEvaluate(XbaseInterpreter.java:446) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.doEvaluate(XbaseInterpreter.java:227) ~[?:?]
at org.eclipse.smarthome.model.script.interpreter.ScriptInterpreter.doEvaluate(ScriptInterpreter.java:219) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.internalEvaluate(XbaseInterpreter.java:203) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter.evaluate(XbaseInterpreter.java:189) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.ClosureInvocationHandler.doInvoke(ClosureInvocationHandler.java:46) ~[?:?]
at org.eclipse.xtext.xbase.interpreter.impl.AbstractClosureInvocationHandler.invoke(AbstractClosureInvocationHandler.java:29) ~[?:?]
at com.sun.proxy.$Proxy145.apply(Unknown Source) ~[?:?]
at org.eclipse.smarthome.model.script.internal.actions.TimerExecutionJob.execute(TimerExecutionJob.java:49) ~[?:?]
at org.quartz.core.JobRunShell.run(JobRunShell.java:202) ~[?:?]
… 1 more


(Boris) #78

Sorry to bother you with so many questions but now I am playing a bit around with that rule and notice, that it isn’t working correct.
The delay for the next timer activation is working, but counting the single PIR movements doesn´t.
It means when alarm was triggered after the 3rd PIR signal, it takes two minutes until next activation can be triggered, that´s OK,
but now only one PIR movement re-activates the alarm, and the rule should always wait for 3 PIR movements.


(Rich Koshak) #79

You’ve applied code fences in the area they are needed the least.

Use code fences for ALL code and logs posted.

ReadingcodewithoutcodefencesislikereadingEnglishwithoutspacesbetweenwords.

As to your problem, you cannot refer to a call on the same line that it is declared on. You can declare it first then assign on the next line, or take my suggestion and use a Map instead of a List.


(Boris) #80

Hi, but the code originally came from you:grinning:
Sorry, I wouldn´t know how to use maps instead of lists.
But for the beginning can I somehow correct the rule so that
it would reset the counter of the PIR activations after a minute or after Alarm was activated?
So in all cases it would need to have the three PIR movements again


(Rich Koshak) #81

It’s not in this thread and not from the DP from what I can tell with a search. Without context I can’t tell you why List was used.

Look at the first posting in the thread which uses Maps. To get the number of timers use timers.values.size.

Beyond that, I’m on my phone. It is almost impossible to read code when it isn’t in code fences.


(Boris) #82

This is the whole rule again,
I don´t know why these fences don´t work properly.

The rule is working generally, but when the alarm was activated once,
it activates the alarm immediately with each PIR movements instead
waiting for the 3rd signal.

Thanks a lot

import java.util.List
var List timers = newArrayList
var Timer shutoffTimer = null
var lastRun = now

rule “Sonbas Motion changed from OFF to ON 3 times in a minute”
when
Item Sonbas10b changed from OFF to ON or
Item Sonoff3 changed from OFF to ON
then
if(shutoffTimer !== null || Alarm.state == OFF || lastRun.isAfter(now.minusMinutes(2))) return;
if(timers.size < 2) {
val t = createTimer(now.plusMinutes(1), [ | timers.remove(t) ])
timers.add(t)
}

if(timers.size == 2) {
sendMail("xxx@gmail.com", “Sonbas10b”, “Sonbas10b motion”)
TH03.sendCommand(ON)
lastRun = now
logInfo(“RuleInfo”, “Siren START”)
shutoffTimer = createTimer(now.plusSeconds(30)) [|
TH03.sendCommand(OFF)
logInfo(“RuleInfo”, “Siren STOP”)
shutoffTimer = null
]
}
end`


(Rich Koshak) #83
```php
Code goes here
```

(Boris) #84

Next try, slowly I feel …

``
import java.util.List
var List timers = newArrayList
var Timer shutoffTimer = null
var lastRun = now

rule “Sonbas Motion changed from OFF to ON 3 times in a minute”
when
Item Sonbas10b changed from OFF to ON or
Item Sonoff3 changed from OFF to ON
then
if(shutoffTimer !== null || Alarm.state == OFF || lastRun.isAfter(now.minusMinutes(2))) return;
if(timers.size < 2) {
val t = createTimer(now.plusMinutes(1), [ | timers.remove(t) ])
timers.add(t)
}

if(timers.size == 2) {
sendMail("xxx@gmail.com", “Sonbas10b”, “Sonbas10b motion”)
TH03.sendCommand(ON)
lastRun = now
logInfo(“RuleInfo”, “Siren START”)
shutoffTimer = createTimer(now.plusSeconds(30)) [|
TH03.sendCommand(OFF)
logInfo(“RuleInfo”, “Siren STOP”)
shutoffTimer = null
]
}
end``


(Rich Koshak) #85

I can’t tell what is going wrong.

You must have three back ticks. The “php” part is optional.

```

Then later in your code on a new line. There the back ticks must be on their own line.

Then close with three back ticks on their own line.


(Boris) #86

Ok will try it next time.

But more important would be how to reset the counter, when alarm was activated.
Now it counts the first time correctly to 3 but after that each new pir movement is triggering the alarm.
I would like to have the counter to 3 again.
Can you help please?


(Rich Koshak) #87
count = count +1
if(count > 3) count = 3