I have an ecobee thermostat, which has integrated occupancy sensors. I’ve set up the ecobee binding and some rules to turn off the lights when the ecobee says there’s no one in the room. (The ecobee trips occupancy “ON” for a minimum of 30 minutes, and the ecobee binding sends status updates every minute. So this rule turns off the lights if no one has been in the room for 30 to 31 minutes, when the occupancy status updates to “OFF”)
rule "LivingRoom Lights Auto-OFF"
when
Item LivingRoomOccu received update OFF
then
Living_Room.sendCommand(OFF)
end
It works, but there is a small catch:
Sometimes, when I walk into the room, the occupancy sensor doesn’t trip ON until after then next OFF update goes through. I’m trying to figure out the best way to ignore that false “unoccupied” reading.
I’m considering creating a switch called “OccupancyDelay” and then using the below pair of rules. The goal being to delay the OFF command until two consecutive Occupancy OFF updates have been recieved. Is there a better way to make this happen?
rule "LivingRoom Lights Auto-OFF"
when Item LivingRoomOccu received update OFF
then
if (OccupancyDelay.state == ON) {
Living_Room.sendCommand(OFF)
OccupancyDelay.sendCommand(OFF)
}
else {
OccupancyDelay.sendCommand(ON)
}
end
rule "LivingRoom Lights Occupancy reset"
when
Item LivingRoomOccu received update ON
then
OccupancyDelay.sendCommand(OFF)
end
Also, I’m curious about efficient use of system resources. As it is, the rule sends an “OFF” command to the lights every minute as long as the room is not occupied. To the user, this is invisible and doesn’t pose a problem. But, does it consume system resources or cause any background issue that I may not be aware of?
And, if I put an “if” clause into the rule, so that it only sends the OFF command if the lights are already on, does evaluating that “if” clause every minute cause more or less of a burden on system resources than just letting it send the OFF command every minute?
I think I understand the issue, and I think it’s the result of the very long latency between when the physical sensor trips and the time it’s reported by the API. So you want to avoid OFF commands for the maximum latency since the last ON command:
import org.joda.time.*
var DateTime lastOn = null
rule LivingRoomOccuON
when
Item LivingRoomOccu changed to ON
then
lastOn = now.toDateTime
Living_Room.sendCommand(ON)
end
rule LivingRoomOccuOFF
when
Item LivingRoomOccu received update OFF
then
if (lastOn != null && lastOn.plusMinutes(6).isBeforeNow()) {
Living_Room.sendCommand(OFF)
}
end
Untested! (and updated)
Also, what binding are you using to turn the light off and on? If it’s Z-Wave, for example, I doubt there are any side effects from multiple OFF commands.
Nice. I’ve just installed the new binding JAR and I’ll let you know how it goes.
I realized any issue with the occupancy delay code, so I’ll be trying something else with that, as well: As it is, the code doesn’t set the variable until the occupancy state switches to ON… but at that point, I don’t need the delay anymore.
The lag time between occupancy triggering and the binding hearing about through the API is too long to use for turning lights ON upon entering the room. However, I hope to use this code as a backup for turning the lights OFF if we forget when we leave the room for a while, or leave the house. So, I’ve changed the code to: trigger when any light in the room is turned on, and set the variable to that time. Then, when an “Occupancy OFF” update comes in, it gets ignored if it’s still within 6 minutes of the light getting turned on.
I won’t be home during the day today to check that it works though. Hopefully I’ll have a moment tonight.
One more quick question related to this: Is there a way to access the occupancy settings for the main thermostat? I can see the remote sensor capability settings for occupancy, but I can’t seem to find any way to get the occupancy from the thermostat itself.
I can see the occupancy from the main thermostat in my ecobee portal… is it just not accessible via the API?
They just grouped all the sensors that way in the API. You can also get the relative humidity at the thermostat that way:
Number humidity { ecobee="<[123456789012#remoteSensors(Dining Room).capability(humidity).value]" }
and you can get the ambient temperature at the thermostat itself, instead of the temperature averaged across all active sensors that runtime.actualTemperature returns, like this:
Number temperature { ecobee="<[123456789012#remoteSensors(Dining Room).capability(temperature).value]" }
Here’s what ended up working, in the kitchen. I’m using the light getting turned on (or updated, in case it’s set to a dimmer level instead of ON) as a trigger, since the whole point of this rule is that the occupancy trigger of the ecobee sensor doesn’t report quickly enough.
rule "KitchenOccuON"
when
Item Kitchen_Table received update
then
if (Kitchen_Table.state != OFF){
lastOn = now.toDateTime
}
end
rule "KitchenOccuOFF"
when
Item KitchenOccu received update OFF
then
if (lastOn != null && lastOn.plusMinutes(7).isBeforeNow()) {
Kitchen_Table.sendCommand(OFF)
}
end
Now I intend to do the same thing in the LIving Room, using a group of lights instead of a single light. So I’ve set the rule up like this:
rule "LivingRoomOccuON"
when
Item Living_Room received update
then
if (Living_Room.state != OFF){
LRlastOn = now.toDateTime
LRRuleFired.sendCommand(ON)
}
end
rule "LivingRoomOFF"
when
Item LivingRoomOccu received update OFF
then
if (LRlastOn != null && LRlastOn.plusMinutes(7).isBeforeNow()) {
Living_Room.sendCommand(OFF)
}
end
I added the virtual switch in there (LRRuleFired) so that I could easily see if the trigger fired. I wasn’t sure if it would work using a group instead of a single light.
The good news is that updating the status of any of the lights in the group does serve to trigger the rule. It seems to trigger four times, though. In the events.log, “LRRuleFired” gets set to “ON” four times in a row, in under one second, every time a light in the group “Living_Room” gets its status updated.
At first I thought it must be related to the number fo lights in the group, but there are actually more than 4 lights in the Living_Room group.
I suspect that this is fine for the operation of the rule, but is there a better way to trigger a rule when any one of a group of lights is updated?
Group items seem to receive lots of updates, but if you just want to know if any of the contained items was updated, it should be OK to do it that way.