Design Pattern: Motion Sensor Timer

motionsensor
motiondetection
designpattern
Tags: #<Tag:0x00007fd32245d600> #<Tag:0x00007fd32245d4c0> #<Tag:0x00007fd32245d380>

(Christer Voreland) #42

Hi Oliver, i feel your pain, ive been scratching my head for a while myself and doing alot of testing to make sure that the rules i use work correctly. i can give you an example here of rules that work in my case:

I use Expire binding with items
My multisensor 6 has a motion timeout of 10sec

Switch Bad1VDTimer	 			{expire="7m,command=OFF"}
Switch Bad1VDTimerNight	 		{expire="3m,command=OFF"}

First rule is to allow me to have an override switch: here i take the zwave device and move it to an virtual device “IF” override is not ON

rule "Bad1MotionON"
	when
	Item Bad1Motion received update ON
	then if(Bad1VDMotionOverride.state==OFF){Bad1VDMotion.sendCommand(ON)}end

rule "Bad1MotionOFF"
	when
	Item Bad1Motion received update OFF
	then if(Bad1VDMotionOverride.state==OFF){Bad1VDMotion.sendCommand(OFF)}end

Here is the rule for motion on Daytime/NightTime

    rule "MotionOn Daytime/NightTime"
	when
    Item Bad1VDMotion received update 
	then if ((Bad1VDMotion.state==ON) &&(GoodnightMode.state==OFF) && (CozyMode.state==OFF)&&(Bad1LightON.state==OFF)) {
	sendCommand(Bad1Dim1,100)
	sendCommand(Bad1VDSonos,ON)
	sendCommand(Bad1LightON,ON)}
	else if ((Bad1VDMotion.state==ON) && (GoodnightMode.state==ON)){
	sendCommand(Bad1Dim1,10)
	sendCommand(Bad1LightON,ON)}
	else if ((Bad1VDMotion.state==ON)&&(CozyMode.state==ON)&&(GoodnightMode.state==OFF)){
	sendCommand(Bad1Dim1,10)
	sendCommand(Bad1VDSonos,ON)
	sendCommand(Bad1LightON,ON)}
	end

When motion off is received from Zwave device (virtual device) i starts the timer

rule "MotionOff"
 	when
 	Item Bad1VDMotion received update OFF
 	then sendCommand(Bad1VDTimer,ON) end

Here the timer runs out but will only turn off the light IF there is no motion

rule "LightOff"
	when
	Item Bad1VDTimer received update OFF
	then if (Bad1VDMotion.state==OFF){
	sendCommand(Bad1Dim1,0)
	sendCommand(Bad1VDSonos,OFF)
	sendCommand(Bad1LightON,OFF)}end
  
rule "LightOff Nighttime"
  when Item Bad1VDTimerNight received update OFF
  	
  then if ((Bad1VDMotion.state==OFF)&&(Bad1VDTimer.state==OFF)){
	sendCommand(Bad1Dim1,0)
	sendCommand(Bad1VDSonos,OFF)
	sendCommand(Bad1LightON,OFF)}end
  	     
  
rule "LightManualOff"
	when
	Item Bad1Dim1 received update 0
	then 
	sendCommand(Bad1VDSonos,OFF)
	sendCommand(Bad1LightON,OFF) end

The Bad1LightON switch is used to allow me to manually dim the light and not having it getting triggered back to the original setpoint the next time i trigger the motion sensor.

Hope this helps alittle :slight_smile:

Regards Chris


(Rich Koshak) #43

Sadly the answer is no. There are over 200 technologies that OH supports each of which can have upwards of a thousand separate devices. There are literally billions of combinations of technologies, devices, and rules. We could start now and stop development on OH entirely and dedicate all of our time compiling just a list of all of these combinations and we wouldn’t finish in our lifetimes.

Home automation is hard and the fragmented nature of the industry makes it even harder. There isn’t a whole lot OH can do about it. But you should be able to find everything you need to make OH work with devices/technologies that OH supports from the OH docs or from this forum.

There are literally two functional complete and working examples at the top of this thread. The comments and discussions are inevitable as the fact that every one’s OH system is completely unique there are enevitable cases that don’t quite work the same as the OP’s example, there are suggestions for changes or improvements, etc. This is a good thing and most of the posters go back and update the top posting with corrections and improvements.

Would you rather just have examples with no corrections or alternative suggestions? You want to just hope it works for you and if not you are out of luck? Or would you rather have the opportunity to ask for help from the very person who posted the example?

I understand your frustration and am not belittling it. But what you are asking for has been brought up multiple times and no one has been willing to work on it, largely because it is an impossible task. It is hard enough for the Zwave devs and users to keep up with just that one technology.


(Kim Skatun) #44

Thanks for the great design pattern @rlkoshak

It seems like several people here on the forum uses xiamo or hue motion sensor, all of these reports strings back(MOTION, true or similar). The disadvantages with these sensor(as far as I know) is that you need to poll them to get the status, I tried setting the polling interval to 0.5s but this made my rpi crash… so I ended up with 1.0s which is to slow for bathroom but might be OK for garage etc… I am still searching for MQTT motion sensors or similar, so please tip me if you know any devices like that.

If you still want to use hue motion sensor, then you could use map function to get it to work:

(function(i) {
    var json = JSON.parse(i);
    return ((json['state']['presence'])) == true ? "ON" : "OFF";
})(input)

Then the switch item will use both the http and expire binding:

Switch HallwayMotion "Hallway Motion" (Group_Presence,Group_Hallway) { http="<[http://192.168.0.??????/api/?????????????????????????r/sensors/3:1000:JS(getHueMotion.js)]" , expire="3m,command=OFF" }

Then in your rule use as @rlkoshak suggested:

when
Item HallwayMotion received command ON
then
// Do ur stuff
end

(Oliver) #45

Hi Rich,
thanks for the detailed answer… i think you are right and i will try to find out my problems here…
i am not a totally dummy… and i think i will solute my problems… at the moment i am trying and testing as much as i can to install oh2 in my new house in the middle of next year… so enough time.
but i have to find out which devices i will use…
i was thinking about to use the zwave uzb1 and the zigbee raspbee module from dresden-elektronik to be able to use both technologies. I want to use ikea lights and leds from the german company Paulman … which are working with zigbee too… (Paulmann is in the “smart-friends” alliance). I dont know if this is a good idea… but i will try and no i am waiting if the zigbee device will be working… to test light action combined with the sensor…
maybe i have to change my compnents… i want to use aeotec multisensor 6 and also “Door / Window Sensor 6” from them…and lots of zigbee controled lights for not having to use knx with a dali-device which is much more expensive.
Every advice is welcome…

kind regards,

oliver


(Oliver) #46

Hi Chris,

great example. Big thanks… i will try to adapt it for my usage… think it will work.
where do you define CozyMode and GoodnightMode?
You also implemented Sonos? I also want to do… when entering the room you play music?
how you do?
i would like to see more of your rules and configs… i think i can adapt a lot…
At the moment my mane problem is, i am waiting on the integration of raspbee device to controk my test ligt via zigbee, but i also ordered an cheap zigbee usb with ti chip…
kind regards,

Oliver


(Marcel Becker) #47

Hi Chris,

thanks for your rule example.

On my try i got:
[ERROR] [ntime.internal.engine.RuleEngineImpl] - Rule ‘EGFlurMotionOFF’: The name ‘EGFlurVDMotionOverride’ cannot be resolved to an item or type; line 12, column 10, length 22

Is xVDMotionOverride to set as an item?

GoodnightMode and CozyMode too?


(Christer Voreland) #48

Hi Marcello

I have all my items stated in the example above as an item.
This way you can link them to your sitemap page and turn the motion detection on or off.

As of now the GoodnightMode and CozyMode are separate switches but would probably be better to put as a Number item and then just define them in a MAP file.

Chris


(Christer Voreland) #49

Hi Oliver,

I have currently defined the items CozyMode and GoodnightMode as a switch item and trigger GoodnightMode with a switch by the masterbedroom. CozyMode is currently set to trigger at 9PM with a cron rule if AwayMode (a switch by the frontdoor) is not activated.

The sonos are implemented for both bathrooms and the kitchen. The bathrooms detect motion, turns off the fan, dim the light up and turn on the selected radio channel and volume defined in my sitemap.

In the kitchen i sense the watt usage on the cooking top and turn on the Radio and fan. Fan turns off if the wattage is below a certain value for more than 30seconds. Wattage is definded in my sitemap.

I’ll try to upload some of my codes this weekend.

Regards

Chris


(Rich Koshak) #50

Or a String Item and skip the MAP and just make the String Item use the values you would have put into the MAP in the first place.


(Christer Voreland) #51

Here is what i use for Sonos, I use the same code for all Sonos and change the radio channel/channel string on top.

   val String Channel0 = "P4 Radio Norge"
    val String Channel1 = "Korean Pop"	
    val String Channel2 = "Liberdade"
    val String Channel3 = "Jazz"
    val String Channel4 = "P5"
    val String Channel5 = "Radio Sørlandet"
    val String Channel6 = "Nrk MP3"
    val String Channel7 = "BuddaBar"
    val String Channel8 = "Something "
    val String Channel9 = "Something else"

    rule "Sonos Bad1"
when
	Item Bad1VDSonos received update ON
	then if ((Bad1VDSonosOverride.state==OFF)&&(Bad1_Sonos_State.state!="PLAYING")){
		
		val volumebad1 = (Bad1VDSonosVolume.state as Number).intValue
		
		sendCommand(Bad1_Sonos_Volume,volumebad1){
		Thread::sleep(100)
		if 
		(Bad1SonosSelector.state==0){
		sendCommand(Bad1_Sonos_Favorite, Channel0)}
		else if 
		(Bad1SonosSelector.state==1){
		sendCommand(Bad1_Sonos_Favorite, Channel1)}
		else if
		(Bad1SonosSelector.state==2){
		sendCommand(Bad1_Sonos_PlayPlaylist, Channel2)} 
		else if
		(Bad1SonosSelector.state==3){
		sendCommand(Bad1_Sonos_PlayPlaylist, Channel3)}
		else if
		(Bad1SonosSelector.state==4){
		sendCommand(Bad1_Sonos_Favorite, Channel4)} 
		else if
		(Bad1SonosSelector.state==5){
		sendCommand(Bad1_Sonos_Favorite, Channel5)} 
		else if
		(Bad1SonosSelector.state==6){
		sendCommand(Bad1_Sonos_Favorite, Channel6)} 
		else if
		(Bad1SonosSelector.state==7){
		sendCommand(Bad1_Sonos_Favorite, Channel7)} 
		else if
		(Bad1SonosSelector.state==8){
		sendCommand(Bad1_Sonos_Favorite, Channel8)}
		else if
		(Bad1SonosSelector.state==9){
		sendCommand(Bad1_Sonos_Favorite, Channel9)}}}
		end
	
		

rule"Sonos OFF"
when
	Item Bad1VDSonos received update OFF
	then if (Bad1_Sonos_State.state!="STOPPED"){
	sendCommand(Bad1_Sonos_Stop,ON)} end

(Rich Koshak) #52

Some ideas:

If you use a lambda you can avoid duplicating the same code for each Sonos (if I understand your comment correctly).

If you use a Map you can drastically reduce the code in your rule. You can populate it using a HashMap but I prefer to use the MAP transform:

sonos.map

0=P4 Radio Norge
1=Korean Pop
2=Liberdade
3=Jazz
4=P5
5=Radio Sørlandet
6=Nrk MP3
7=BuddaBar
8=Something
9=Something else
rule "Sonos Bad1"
when
    Item Bad1VDSonos received update ON
then
    if(Bad1VDSonosOverride.state == OFF && Bad1_Sonos_State.state != "PLAYING"){
        Bad1_Sonos_Volume.sendCommand(Bad1VDSonosVolume.state as Number)
        Thread::sleep(100)
        Bad1_Sonos_PlayPlaylist.sendCommand(transform("MAP", sonos.map, Bad1SonosSelector.state.toString))
    }
end

rule"Sonos OFF"
when
    Item Bad1VDSonos received update OFF
then 
    if (Bad1_Sonos_State.state!="STOPPED"){
        Bad1_Sonos_Stop.sendCommand(ON)
    } 
end

With this approach not only is your Rule shorter, you can add and remove channels by simply editing the map file and you don’t have to touch your Rules. Note, it is better to call the method on the Item than to call the sendCommand Actions.


(Christer Voreland) #53

Wow Rikoshak, this was a really good code upgrade, thank you very much :smile:


(Rich Koshak) #54

One last little bit that can further simplify the rule is if you make Bad1SonosSelector become a String Item and have it populated with the values in sonos.map instead of a number, you can get rid of the MAP and just:

Bad1_Sonos_PlayPlaylist.sendCommand(Bad1SonosSelector.state.toString)

That is what I meant by “Or a String Item and skip the MAP and just make the String Item use the values you would have put into the MAP in the first place” in my posting above.


Getting a rule to fire on Motion
(shrek) #55

Thank for your help. Now it works.Here is my setting.
My Patio light is triggered on by a Patio motion sensor. The motion sensor turns itself off automatically after 3 Min. I want to keep the light on for 10 Min if no new motion detected.

Switch Patio_Motion             "Patio Motion Sensor[%s]" <motion> { channel="zwave:device:12345678:node1:sensor_binary,respond_to_basic=true" }
Switch Patio_Light              "Patio Light[%s]" <light> { channel="zwave:device:12345678:node2:switch_binary" }
var Timer Patio_Motion_Timer = null
val int timeoutMinutes = 10
rule "Patio_Motion_Light OFF by Timer"
when
    Item Patio_Motion changed from ON to OFF
then
    if(Patio_Motion_Timer == null)
     {
     Patio_Motion_Timer = createTimer(now.plusMinutes(timeoutMinutes)) [|
     Patio_Light.sendCommand(OFF)
     Patio_Motion_Timer = null]
     }
    else 
    {
    Patio_Motion_Timer.reschedule(now.plusMinutes(timeoutMinutes))
    }
end

(Rich Koshak) #56
var Timer Patio_Motion_Timer = null

(Ganesh) #57

If it helps, my guidelines around motion sensor design:

Motion timeout maybe set at hardware level via a potentiometer but it is better to be able to control it from server.

It is also wise to ACTIVATE a motion sensor based on light level or a user specified weekly schedule.

A motion sensor could be used as an intrusion detection device or simply to turn lights on and off to save energy or both!

If a motion sensor is being used as intrusion detection device then it must have a tamper protection. Typical techniques are LDR light dependent resistor, push button or two push buttons - one in pressed position and other in unpressed position. If here is impact on the sensor, one of the switch will change its position and hence tamper detection. But if the impact completly collapses the circuit and battery, then you need some kind of monitoring algorithm at server that detects when sensor has gone unusually offline.

If it helps here is how we handle a motion sensor from server (this is tested with a modified Arduino and modified HC-SR501 hardware and OH 2.1.0. The HW mods were basically for voltage and battery life) :

Code in next post.


(controlc) #58

I think there is a problem with this rule. If MotionDetector1 changed first from OFF to ON a timer will be started. If then MotionDetector2 will triggered (a new timer will be started) and MotionDetector1 will now changed from ON to OFF and the timer will count down and after then the Light will go off - but the timer for MotionDetector2 is already counting … - so the rule should only work if the first triggered motion sensor will triggered again to reschedule the timer …

Is that right? And how could I avoid that?

And another question: Why send after counting down the timer the timer to OFF?

sw.sendCommand(OFF)


(Rich Koshak) #59

For one the code above doesn’t actually do anything except control the motion detectors. There is no code there to actually turn on or off any lights. The DP assumes you will have a rule (not shown) that triggers when MotionDetector1 received command OFF that implements the turning ON or OFF the light. Put another way, this DP covers the automatic turning off the MotionDetector Item, what you do with those events is an exercise left to the student.

If you are trying to control the same light using multiple motion detectors indeed, you would need to add some logic to the code that turns on/off the light (i.e. the code that is out of scope of this article) to check if there is a Timer running for the other MotionDetectors before actually turning off the light.


(Mathias Knop) #60

Does someone also have an idea to implement a dynamic expire interval?


(Rich Koshak) #61

Follow the first example in the OP only instead of using timeoutMinutes use a dynamically calculated number.

You cannot use a dynamic timeout with the Expire binding.