I’ve installed a recessed Z Wave sensor into my down stairs toilet door. The aim is to control the Hue light in my down stairs toilet. The easy part is getting the light to switch on and off when the sensor reports as open and then closed again.
What I need help with is how I put some logic into the rule so that the light doesn’t turn off straight away. Such as, you open the door to enter the toilet and then close the door after you the light needs to stay on until to open and then close the door again.
I’ve made some progress on getting my rule working. This is what I have so far. As I’m sure you can see, I need to close the door twice to turn the light off. Generally this works fine, however we use the toilet as a cloak room. This means that when getting a coat or putting one away we only open and close the door once. How can I add a calculation to work out the difference between opening and close, my idea is to switch the light off if the difference is 60 seconds or less.
rule "Toilet Door Open"
when
Item Hallway_Toilet_Door_Sensor received update OPEN
then
if (Hallway_Toilet_Occupied.state != "Yes") {
Hallway_Toilet_Light.sendCommand(100)
postUpdate(Hallway_Toilet_Occupied, "Yes")
} else {
postUpdate(Hallway_Toilet_Occupied, "No")
}
end
rule "Toilet Door Closed"
when
Item Hallway_Toilet_Door_Sensor received update CLOSED
then
if(Hallway_Toilet_Occupied.state == "No") {
Hallway_Toilet_Light.sendCommand(0)
}
end
Keep a timestamp as a global var. Set the timestamp to now when the door opens. When the door closes check the timestamp with if(timestamp.isBefore(now.minusMinutes(1))
What have I got wrong with this? It’s trowing an exception and not working.
import org.openhab.core.library.types.*
import org.eclipse.xtext.xbase.lib.*
import org.openhab.core.library.types.DateTimeType
var DateTime timestamp = null
rule "Hallway Motion Sensor Activation"
when
Item Hallway_Motion_Sensor changed from CLOSED to OPEN
then
postUpdate(Hallway_Motion_Sensor_Last_Activation, new DateTimeType())
if(TimeOfDay.state == "Evening") {
Dining_Area_Bloom_Light.sendCommand(0)
} else if (TimeOfDay.state == "Night") {
Dining_Area_Bloom_Light.sendCommand(0)
}
end
rule "Toilet Door Open"
when
Item Hallway_Toilet_Door_Sensor received update OPEN
then
var DateTime timestamp = now
if (Hallway_Toilet_Occupied.state != "Yes") {
Hallway_Toilet_Light.sendCommand(100)
postUpdate(Hallway_Toilet_Occupied, "Yes")
} else {
postUpdate(Hallway_Toilet_Occupied, "No")
}
end
rule "Toilet Door Closed"
when
Item Hallway_Toilet_Door_Sensor received update CLOSED
then
if(Hallway_Toilet_Occupied.state == "No") {
Hallway_Toilet_Light.sendCommand(0)
} else if(timestamp.isBefore(now.minusMinutes(1)) {
postUpdate(Hallway_Toilet_Occupied, "No")
Hallway_Toilet_Light.sendCommand(0)
}
end
Here’s the error;
2016-11-28 20:54:46.295 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule ‘Toilet Door Closed’: The name ‘.isBefore()’ cannot be resolved to an item or type.
Now getting this error; 2016-11-28 21:11:14.445 [ERROR] [o.o.c.s.ScriptExecutionThread ] - Error during the execution of rule ‘Toilet Door Closed’: cannot invoke method public boolean org.joda.time.base.AbstractInstant.isBefore(org.joda.time.ReadableInstant) on null
Well, that is actually a complicated if/else/if statement. It isn’t ignoring the timestamp if, it is simply evaluating to true, or false (you haven’t actually said in what ways it isn’t working).
Add some logging statements so you can see the states of Hallway_Toilet_Occupied.state, timestamp, now, and now.minusMinutes(1) to see what state everything is in when you run.
As written, the else if clause will on run if Hallway_Toilet_Occupied.state equals something other than “No” and timestamp was taken more than a minute ago. The entire Rule only runs when Hallway_Toilet_Door_Sensor receives a CLOSED.
Make sure you are not receiving any extraneous OPEN updates on Hallway_Toilet_Occupied which would mess up your timestamp. If you are you can fix that by changing your rule trigger to Item Hallway_Toilet_Door_Sensor changed to OPEN