Design Pattern: Motion Sensor Timer

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

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.

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
1 Like

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

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

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?

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

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

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.

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

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.

1 Like

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

1 Like

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.

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
1 Like
var Timer Patio_Motion_Timer = null

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)

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.

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

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.

1 Like

So I am trying to get a motion sensor rule running what activates a siren (just a switch) when the detector has changed from OFF to ON, 3 times in a minute. This should avoid not necessary activations.
Can you help me here?
Please keep it simple because when I am reading your examples I am quite often lost - maybe your coding is too good for me :slight_smile:

The rule I am running (without this logic) so far is:

var Timer shutoffTimer = null

rule ā€œSonoffMotion changed from OFF to ON 3 times in a minuteā€

when
	Item Sonoff1 changed from OFF to ON or  //Question: how to say 3 activations in a minute?
	Item Sonoff3 changed from OFF to ON		//Question: how to say 3 activations in a minute?
then
	if (shutoffTimer === null && Alarm.state == ON && lastRun.isBefore(now.minusMinutes(5))) {
		sendMail("xxx@gmail.com", "Sonoff1", "Sonoff1 motion")
		Sonoff2.sendCommand(ON)
		lastRun = now
		logInfo("RuleInfo", "Siren START")
		shutoffTimer = createTimer(now.plusSeconds(240)) [|
		Sonoff2.sendCommand(OFF)
		logInfo("RuleInfo", "Siren STOP")
		shutoffTimer = null
		]
	}

end