Motion detection -> lights on - if it's dark and within time period, with timer - Help needed

Hello,

I’m using OH2 beta 3 and

  • milight rgb bulbs with the milight binding for OH2
  • Fibaro FGMS001 z-wave multisensor

Now I need some help with the rule.

What I want:
when there is motion detected (by the FGMS001)
then
lights on.

  • if there is no motion for a specific period of time then switch off
  • just lights on if luminosity (by the FGMS001) is lower then specific value
  • just lights on/of if light’s aren’t always on by manual setting
  • if it’s evening then lights on at high brightness, and if it’s deep night then just 20% brightness so that I won’t get blind

Except of the last line all the rest is already working (mainly becaus of this thread: Design Pattern: Motion Sensor Timer),
but the I think I have a “knot” within my “if-the-else” terms.

var Timer Flur_MotionTimer = null
var Number Flur_Status = 1
var Number Flur_Lux = Flur_Auge_Lux.state as DecimalType
var Number hour = now.getHourOfDay	



	/* Auge Bewegung*/
	rule "Flur Licht an"
	when
    Item Flur_Auge_Burglar changed from OFF to ON			// wenn Bewegung registriert wird
	then											// dann
		if((Flur_Status == 1) && (Flur_Lux <= 20)) {			// nur wenn Licht vorher ausgeschaltet ist && dunkel (Flur_Status == number of lights scene, 1==OFF)
    	if ((hour >= 1)  || (hour <= 5)) {						// nur wenn zwischen 1 und 5 Uhr morgens
    	Scene_Flur.sendCommand(11)}						// Licht an mit 20% Helligkeit
    	else {
    	Scene_Flur.sendCommand(10)}						// Licht an mit 70% Helligkeit
    	if(Flur_MotionTimer != null) {
        Flur_MotionTimer.reschedule
    	}
    	else {
    	Flur_MotionTimer = createTimer(now.plusMinutes(1)) [ |	                   // Licht bleibt (X) Minuten an solange keine weitere Bewegung
    	    if(Flur_Status != 1){								           // nur wenn inzwischen nicht manuell Licht angeschaltet wurde
    	    Scene_ColorSelect_Flur_Deckenlampe.sendCommand(OFF)	   // Licht aus
    	    Flur_MotionTimer = null}
    	]
    	}
    	}
    }
	end 

One thing is, you have to write to the vars in the rule, not outside the rule. Without setting the vars in the rule, I doubt the rule is working as expected :wink:
The second thing is, to get the time from 1 to 5 o’clock, you have to && the statements, not ||.

if ((hour >= 1) || (hour <= 5)) // boolean OR

6 >=1, 0 <= 5 so this if clause would always be true.

if ((hour >= 1) && (hour <= 5)) // boolean AND

6 >= 1 but not <= 5 -> false
0 <= 5 but not >= 1 -> false
4 <= 5 and >= 1 -> true

How do you get information about manually switched light? I guess this is done through Flur_Status ?

1 Like

You can simplify the the rule a little by using the Time if Day design pattern. Move the calculation for evening and night to its own rule and it is a simple if statement everywhere else.

1 Like

I’d like to initiate the status var with a “1” to be sure that, after a power loss / system restart, the motion detection is working because the first check in my rule is if status ==1
So you mean: initiating the vars outside of the rules, just "var Number Flur_Status"
and then the value at the beginning of the rule “Flur_Status = 1”?

Aaaah, a little but important thing and, for sure, wrong at this point.

Yes. At the scene selection rules the Flur_Status gets a number between 1 and 11 comparing to the active scene. 1 stands for lights off, 10 stands for lights on @ 70% brightness.
If another scene is manually choosen I don’t want to automatically lights on and off by motion detection (the same rule is working in the the living room and the dining room where a permanent on/off by motion is annoying)

I think I got it and will try this.
edit:
I looked at your design pattern and I think it’s not the right thing for me because I don’t need a dynamical time periode but always the same time between 1 and 5.That’s the time when we (my wife and me) are sleeping and the lights should be at a low brightness when activated by motion detection because at this time that’s the case if someone is on the way to the rest room…

I made some changes and code cleanup (notepad++ helped me because it shows related brackets), but now nothing is working and I don’t know where to search the error.
The Log shows me that the motion sensor sends an event, but no reaction of the rule.
The declaration of variables isn’t really clear to me (and the rules section at the OH doku isn’t complete) and I think the error is something about this.

/* Auge Bewegung*/   
    rule "Flur Licht an"  
    when
    Item Flur_Auge_Burglar changed from OFF to ON                 			// wenn Bewegung registriert wird
    then                                                            		
        hour = now.getHourOfDay									// hole aktuelle Uhrzeit
    	Flur_Lux = Flur_Auge_Lux.state as DecimalType					// hole aktuellen Lux-Wert
        if((Flur_Status == 1) && (Flur_Lux <= 20)) {                      	                // nur wenn Licht ausgeschaltet ist && dunkel
            if ((hour >= 1) && (hour <= 5)) {                              	                        // wenn zwischen 1 und 5 Uhr morgens...
                Scene_Flur.sendCommand(11)                                	                // ...Licht an mit 20% Helligkeit
            }
            else {										               // ansonsten...	
            Scene_Flur.sendCommand(10)                                    	               // ...Licht an mit 70% Helligkeit
            }
            
            if(Flur_MotionTimer != null) {
            Flur_MotionTimer.reschedule
            }
        }    
      	else {
            Flur_MotionTimer = createTimer(now.plusMinutes(1)) [ |                     // Licht bleibt (X) Minuten an solange keine weitere Bewegung
            if((Flur_Status == 10) || (Flur_Status == 11)){                                    // nur wenn Licht inzwischen nicht manuell angeschaltet wurde
            	Scene_ColorSelect_Flur_Deckenlampe.sendCommand(OFF)       	// Licht aus
                Flur_MotionTimer = null
			}
            ]
        } 
	end 

At the beginning of the .rules file the variables are declared like:

var Timer Flur_MotionTimer
var Number Flur_Status
var Number hour

I cannot recommend highly enough to use Designer. It will find most syntax errors as you type and using <crtl><space> you can discover all of the correct ways to complete a line. Very useful for figuring out which methods are available on a class. This will make writing and debugging your rules SOOO much easier.

That design pattern is not necessarily intended only for dynamic times. It is for cases where you may have other rules that care about night time. If you look you will see that the start of Morning and the end of Evening are static.

What it does is let you centralize the calculation of such states so that in the future, as things change and/or you want to add or remove states you only have to change it in one place.

Believe me, organizing your rules in this way will pay dividends in the long run.

As a case in point, I use a related design pattern to determine when it is cloudy to help control some of my lights. Because I’ve separated it out I can easily change to use a different weather service or a lighting sensor and I never have to adjust the lighting, roller shade, or alerting rules which all care about cloudy conditions. I’ve been debating with myself whether the Time of Day and Separation of Behaviors design patterns are actually the same thing for a while now.

So does the events.log actually show the Item changing from OFF to ON or just receiving an ON update? For the rule to trigger as is it must be in the OFF state and then change to ON.

Add a logInfo statement as the first line of the rule to see if it is triggering at all.

Are there any errors in openhab.log? In particular look for errors when OH loads the rules files. If there is a problem parsing the file (e.g. mismatched { } or ( ) ) it will fail to parse the file and as far as OH is concerned all the rules after the error simply do not exist.

Again, this is where Designer comes in handy as it will highlight pretty much the entire file after the error in red.

Thanks for your time and answers,

I found two errors.
1.: at my light-scene rules there were two options for the “10 - command” instead of 10 and 11.
2.: “Flur_MotionTimer.reschedule” caused an error, must be “Flur_MotionTimer.reschedule(now.plusMinutes(1))”

Now it seems to be working. I will going on with testing the time-part.
Eclipse showed me the second error and errors with missing “(”, but no “{” errors, therefore I used notepad.

This is a new and helpful information for me, thanks.

A logfile isn’t created, although the log config seems to be OK. I will look at this problem.

When the rule is working I would prefer to “outsource” it and call it just with the room-token. Because I’ll use this motion rule in 5 rooms.
But step by step, next is testing. Time-part and the Lux value isn’t exact the right.

If you installed via apt-get you should have /var/logs/openhab2/openhab.log. By default all errors go to this file as well. If installed manually logs are in <root oh folder>/userdata/logs.openhab.log I beleive.

1 Like

happy new year :slight_smile:

While christmas time I did no progress with OH and lambda, but now it will go on.

But first I need some help to locate a failure inside my light code.

already working:

  • lights on/off, light scenes via buttons
  • motion detection -> lights on
  • nightmode: brightness reduced when lights on by motion
  • motion detection override when manually switch lights on/off/changes lightscenes

not working correctly:

  1. when lights ar switched on via motion detection - they won’t go off again besides there is a second motion trigger after a few minutes
  2. this second trigger switches lights off even when there is some continous motion in the room

example:
When I walk shortly into the kitchen (to the recycle bin) lights go on, but not off after 1 minute as it should. Then, when I’m walking a second time into the kitchen -> lights go off.
Also: when I enter the kitchen (lights go on) and I’m starting cooking lights go off after some minutes (code should prevent that)

	/* Auge Bewegung*/   
    rule "Kueche Licht an"  
    when
    Item Kueche_Auge_Burglar changed from OFF to ON                 			// wenn Bewegung registriert wird
    then                                                            			// dann
        hour = now.getHourOfDay													// hole aktuelle Uhrzeit
    	Kueche_Lux = Kueche_Auge_Lux.state as DecimalType						// hole aktuellen Lux-Wert
        if((Kueche_Status == 1) && (Kueche_Lux <= 5)) {                      	// nur wenn Licht ausgeschaltet ist && dunkel
            if ((hour >= 1) && (hour <= 5)) {                              		// wenn zwischen 1 und 5 Uhr morgens...
                Scene_Kueche.sendCommand(11)                                	// ...Licht an mit 20% Helligkeit
            }
            else {																// ansonsten...
            Scene_Kueche.sendCommand(10)                                    	// ...Licht an mit 70% Helligkeit
            }
            
            if(Kueche_MotionTimer != null) {
            Kueche_MotionTimer.reschedule(now.plusMinutes(1))
            }
        }    
      	else {
            Kueche_MotionTimer = createTimer(now.plusMinutes(1)) [ |          	// Licht bleibt (X) Minuten an solange keine weitere Bewegung
            if((Kueche_Status == 10) || (Kueche_Status == 11)){                 // nur wenn Licht inzwischen nicht manuell angeschaltet wurde
            	Scene_Kueche.sendCommand(1)       								// Licht aus
                Kueche_MotionTimer = null
			}
            ]
        } 
	end   

Kueche_Auge_Burglar -> motion detection
Kueche_Lux -> brightness sensor
Kueche_Status -> indicates the number of the light scenes. 1 = lights off, 2 = normal on, 10 = motion on, 70% brightness, 11= nightmode, green, 20% brightness

Does anybody see the failure?

I have a similar setup, but it’s working as far as I can tell.
At first I started setting my dimlevels and turning on / off 100% with openhab, but found out that the delay is too long in my opinion. I have solved this by using associations with z-wave, i.e the motion sensor sends motions directly to the switch to turn it on.

  1. You can solve this by setting the parameter 12 to BASIC ON instead of BASIC ON and OFF.
    It will make the motion sensor only send on commands and not any off commands
  2. I’ve solved this with a timer with reschedule, like this:
 val Number currentDimLevel = ZwaveBathDimmerDim.state as DecimalType
    if (currentDimLevel == 0) {
          ZwaveBathDimmerDim.sendCommand(dimLevel)
    } else {
        logInfo("DimmerBath", "Not turning on light is already on")
    }
    if (mBathLightsTimer == null) {
        logInfo("DimmerBath", "No timer running creating a timer and setting light on time: " + minutes)
        mBathLightsTimer = createTimer(now.plusMinutes(minutes)) [|
             mBathLightsTimer = null
             ZwaveBathDimmerDim.sendCommand(OFF)
       ]
       logInfo("DimmerBath", " Current DimLevel: " + currentDimLevel + " turning on lights")
    } else { //Timer is running
            //Timer is running renew time
            logInfo("DimmerBath", "Timer is running renewing time: " + minutes)
            
            //If dimLevel is off for some reason set it to on.
            mBathLightsTimer.reschedule(now.plusMinutes(minutes))
    }

Regards S

What is Kueche_Status? If it is an Item you need to compare its state and you may need to cast it to a DecimalType. Same with Kueche_Lux.

if(((Kueche_Status.state as DecimalType) == 1) && ((Kueche_Lux.state as DecimalType) <= 5)) {

both are “var Number”. The “Kueche_status” indicates the different light-scenes, and at the 6th code-line “Kueche_Lux” gets the decimal value of the lux sensor

No more ideas what’s wrong with this?

Putting logInfo into key places in your rule allows you to follow how it works in action.

Meantime, lets unroll the logic a bit …

The rule will only trigger when motion sensor changes from OFF to ON. It will not trigger if there is continuous ON from the motion sensor e.g. the timer will not be rescheduled. Explains one of your problems?

What you might consider is triggering lights on from motion ON, and starting the off-timer in another triggered from motion OFF.

This is the entry to rescheduling an already running timer, note that Kueche_Status must be 1. Is that supposed to be the case, doesn’t 1 mean lights-off for you?

If Kueche_Status is not 1, then we set up a timer. It’d be really, really smart to see if that timer already exists first.

Yes, sure - thanks a lot.
I will try to modify the triggers as you proposed.

You’re right, but yesterday I found a little mistake at this part: the ending “}” of the

if((Kueche_Status == 1) && (Kueche_Lux <= 5)) {

is at the wrong position, should be 2 lines above, after

Scene_Kueche.sendCommand(10) 

This "if((Kueche_Status == 1) " -comparison should prevent triggering when lights are setting on manually and, the more important thing, then switch off automatically after some time.

So, got some free time for modifying and testing.

Actually: just one thing isn’t working
-> the timer-reschedule when continuous motion

	/* Auge Bewegung  */ 
    rule "Flur Licht an"  
    when
    	Item Flur_Auge_Burglar changed from OFF to ON                			// wenn Bewegung aufhört
    then                 													// solange Bewegung registriert wird
        hour = now.getHourOfDay												// hole aktuelle Uhrzeit
    	Flur_Lux = Flur_Auge_Lux.state as DecimalType						// hole aktuellen Lux-Wert
        if((Flur_Status == 1) && (Flur_Lux <= 3)) {                      	// nur wenn Licht ausgeschaltet ist && dunkel
            if ((hour >= 1) && (hour <= 5)) {                              	// wenn zwischen 1 und 5 Uhr morgens...
                Scene_Flur.sendCommand(11)                                	// ...Licht an mit 20% Helligkeit
            }
          
            else{
            	Scene_Flur.sendCommand(10) 
            }
        }
                
        if(Flur_MotionTimer != null) {
        	Flur_MotionTimer.reschedule(now.plusMinutes(1))
        }
        
	
    when
    	Item Flur_Auge_Burglar changed from ON to OFF                		// wenn Bewegung aufhört
    then  
            Flur_MotionTimer = createTimer(now.plusMinutes(1)) [ |          // Licht bleibt (X) Minuten an solange keine weitere Bewegung
            if((Flur_Status == 10) || (Flur_Status == 11)){                 // nur wenn Licht per Bewegung angeschaltet wurde
          		Scene_Flur.sendCommand(1)       							// Licht aus
                Flur_MotionTimer = null		
			}
            ]

If the motion is continually ON, the timer never will be rescheduled. Perhaps that isn’t what you want? Perhaps when motion is continually on, have lights continuously on. When motion stops, then you want to begin your timer. You’ll have to change or cancel the timer if motion restarts again before timeout.

I think my description above was wrong but the coding goes the right way.

Timer will be set when there is no more motion

when
    	Item Flur_Auge_Burglar changed from ON to OFF                		// wenn Bewegung aufhört
    then
Flur_MotionTimer = createTimer(now.plusMinutes(1)) [ |

But I think the reschedule part is wrong or at the wrong place.

        if(Flur_MotionTimer != null) {
        	Flur_MotionTimer.reschedule(now.plusMinutes(1))
        }

This should be checked at every motion detection.

My point was, that if you have continuous motion detection the timer reschedule will never be carried out (well strictly, once only). The rule only triggers on a change. If a timer is left over from before the continuous state, it will eventually turn the lights OFF (while motion is still active).

When motion-on is detected, cancel any existing timer. (lights will remain on for duration of motion.) When motion-off is detected, start a new timer.