I’m working on some Light automation for my hallway and landing. Basically if the Lux is below a certain level and there is movement the lights will come on. I’ve included a time element so that between 9am and 9pm the brightness is 80% and any other time the brightness is 50%.
When I did this with Domoticz I hade to have and elseif using OR instead of and but I’m not sure if I need to here.
Does this code look ok?
rule "lightsAutoH_ON"
when
Item Security_Motion_H changed to ON
then
if(Environment_Lux_H.state <= 15 && Light_Hue_White_H.state == 0 && now.getHourOfDay > 9 && now.getHourOfDay <= 21) {
Light_Hue_White_H.sendCommand(80)
}
else if(Environment_Lux_H.state <=15 && Light_Hue_White.H.state == 0) {
Light_Hue_White_H.sendCommand(50)
}
end
rule "lightsAutoH_OFF"
when
Item Security_Motion_H changed to OFF or
Item Environment_Lux_H received update
then
if (gSafetyAlarms.state == OFF && Light_Hue_White_H.state > 0 && Environment_Lux_H.state > 20) {
Light_Hue_White_H.sendCommand(0)
}
end
Note you have a typo in your first Rule. Light_Hue_White**_**H.state
Often the quickest way to answer a question like this is to run it and see what happens. It looks OK to me but honestly I find these really long if clauses are hard to follow and understand.
So let’s apply some minor restructuring to maybe make it a little easier to understand.
rule "lightsAutoH_ON"
when
Item Security_Motion_H changed to ON
then
if(Environment_Lux_H.state > 15) return; // do nothing if lux is more than 15
if(Light_Hue_White_H.state != 0) return; // do nothing if light's state is not 0
val newState = if(now.getHourOfDay >= 9 && now.getHourOfDay < 21) 80 else 50 // If the hour is between 09:00 and 21:00 use a dimming value of 80 else use 50
Light_Hue_White_H.sendCommand(newState)
end
rule "lightsAutoH_OFF"
when
Item Security_Motion_H changed to OFF or
Item Environment_Lux_H changed
then
if(gSafteyAlarms.state != OFF) return; // do nothing if the safety alarms are off
if(Light_Hue_White_H.state == 0) return; // do nothing if the light is at 0
if(Environment_Lux_H.state <= 20) return; // do nothing if the lux is below 20
Light_Hue_White_H.sendCommand(0)
end
By splitting up the big if clauses into short single if clauses that exit out of the Rule it makes what is going on a bit easier to understand. You don’t have to keep a complicated set of discrete math formulas in your brain to figure out what that one line does. Instead you can just march down the lines and look at them one at a time.
I really appreciate you taking the time to re-write my script in a more concise manner. Having wrote mine and compared it to yours I can see how the change in logic and style make so much more sense.
The ON rule is working exactly as I wanted but the OFF rule is not working.
The lights failed to turn off automatically but unfortunately I wasn’t able to look at the logs at the time.
Checking the logs today to ensure the indevidule items are functioning and they are
018-08-09 09:51:10.884 [DEBUG] [dclass.ZWaveBinarySensorCommandClass] - Sensor Type is MOTION
2018-08-09 09:51:10.887 [DEBUG] [dclass.ZWaveBinarySensorCommandClass] - NODE 6: Sensor Binary report, type=Motion, value=0
2018-08-09 09:51:10.907 [vent.ItemStateChangedEvent] - Security_Motion_H changed from ON to OFF
2018-08-09 09:55:51.287 [vent.ItemStateChangedEvent] - Environment_Lux_H changed from 34 to 31
2018-08-09 09:56:19.787 [vent.ItemStateChangedEvent] - Environment_Lux_H changed from 31 to 33
The only other item that affects the switching off is the group containing my smoke, heat and CO alarms. I grepped all the logs and this was returned;
./events.log:2018-08-05 02:06:58.644 [GroupItemStateChangedEvent] - gSafetyAlarms changed from NULL to OFF through gHeatAlarms
./events.log:2018-08-09 02:32:45.408 [GroupItemStateChangedEvent] - gSafetyAlarms changed from NULL to OFF through gHeatAlarms
So I reckon the rule is exiting because the group has a start up of NULL rather than OFF
It depends on how you want the NULL case to be handled. As written the NULL case is treated as ON. In other words, unless the states is explicitly OFF, assume the alarm is ON.
If you came the test as you indicate, the NULL case we’ll be treated as OFF. In other words, unless the states is explicitly ON, assume the alarm is OFF.
You will have to decide which is the more appropriate behavior.
That depends on the timing. At some point the alarm states changed to OFF at which point the rule should run.
It was still failing to turn the lights off even after the change so I reverted. I think the problem with the off script is that it can’t test for for motion or Lux in the one test.
The logic should be if not motion turn the lights off or if Lux is greater than 20 (regardless of movement) turn the lights off.
The current tests for no motion but because the lights dimmed and therefore lower than 20 Lux the lights stay on.
I’ve tried to split the motion and Lux into two but its failing.
Any advice?
rule "lightsAutoL_ON"
when
Item Security_Motion_L changed to ON
then
if(Environment_Lux_L.state > 15) return; // do nothing if lux is more than 15
if(Light_Hue_White_L.state != 0) return; // do nothing if light's state is not 0
val newState = if(now.getHourOfDay >= 9 && now.getHourOfDay < 21) 80 else 1 // If the hour is between 09:00 and 21:00 use a dimming value of 80 else use 50
Light_Hue_White_L.sendCommand(newState)
end
rule "lightsAutoL_OFF"
when
Item Security_Motion_L changed to OFF
then
if(gSafetyAlarms.state != OFF) return; // Do nothing if Alarms active
if(Light_Hue_White_L.state == 0) // Do nothing if lights already off
Light_Hue_White_L.sendCommand(0)
else if
Item Environment_Lux_L changed
then
if(gSafetyAlarms.state != OFF) return; // do nothing if the safety alarms are on
if(Light_Hue_White_L.state == 0) return; // do nothing if the light is at 0
if(Environment_Lux_L.state <= 20) return; // do nothing if the lux is below 20
Light_Hue_White_L.sendCommand(0)
end
What you have written makes no sense syntactically. You should be seeing errors in your log file when you save this file and OH tries (and fails) to load it.
If you want to trigger a Rule based on more than one event you just list them all with or
when
Item Security_Motion_L changed to OFF or
Item Environment_Lux_L changed
then
If you want to have two different Rules, then you need to fully define two different Rules. the rule "Rule name" part is not options.
There is no such thing as an else if without a leading if statement and there is no such thing as an if or else if statement that doesn’t have an expression that evaluates to either true or false.