This post summarises my experience with having a wireless appliance switched on and off at certain parts of a day. This is a nice example of using Drools timers and internal facts.
Wireless suffers the problem of unreliable communication in a noisy, long distance environment. Even in the same room sometimes the transmission fails, this is my experience with EnOcean, Z-wave and WeMo. Luckily, this problem can be solved in Openremote in a smart way by sensing back the switch state and deciding if retransmission is necessary. This is an unique characteristics of Openremote architecture not commonly found in other home automation controllers. The algorithm presented below addresses this problem and is in my humble opinion a must have for everyone who has a need of reliable wireless switching.
First I’ve declared a fact which will be used by the switching algorithm state machine.
declare SocketState
@role(event)
on : int
// -1: idle
// 0: switching off
// 1: switching on
end
rule "Init SocketState"
when
then
insert(new SocketState(-1));
end
Next, the rule for initiating switching on the appliance every Friday at 6:10 AM:
rule "Lamp on"
timer(cron: 0 10 6 ? * fri)
when
Event(source=="SocketSwitching1.STATE", value=="off")
$s: SocketState(on!=1)
then
$s.setOn(1);
update($s);
end
Note that the rule is executed only when socket is not yet turned on and not in switching StcketState. All it does is setting the SocketState fact into switching on state and pass it to other rules with update() statement.
Now, we will be sending wireless telegrams to the switching socket every 5 seconds as long as its state is off. Usually the light go on immediately, however when it is noisy few retransmissions are necessary.
rule "Lamp on execute"
timer(int: 0s 5s) // repeat every 5 seconds
when
$s: SocketState(on==1)
Event(source=="SocketSwitching1.STATE", value=="off")
then
execute.command("SocketSwitching1.ON"); // Light ON
end
Finally when the socket state is changed to on it is marked by SocketState fact:
rule "Lamp on executed"
when
$s: SocketState(on==1)
Event(source=="SocketSwitching1.STATE", value=="on")
then
$s.setOn(-1);
update($s);
end
The same algorithm is used for switching the socket off on 6:25 AM.
rule "Lamp off"
timer(cron: 0 25 6 ? * fri)
when
Event(source=="SocketSwitching1.STATE", value=="on")
$s: SocketState(on!=0)
then
$s.setOn(0);
update($s);
end
rule "Lamp off execute"
timer(int: 0s 5s)
when
$s: SocketState(on==0)
Event(source=="SocketSwitching1.STATE", value=="on")
then
execute.command("SocketSwitching1.OFF"); // Light OFF
end
rule "Lamp off executed"
when
$s: SocketState(on==0)
Event(source=="SocketSwitching1.STATE", value=="off")
then
$s.setOn(-1);
update($s);
end
Because ON and OFF states sent by socket can easily be missed in noisy environment an extra bit of robustness is achieved by declaring the ON state in case when non-zero power measurement message arrives:
rule "SocketSwitching1 state ON through power"
// Set state ON when power is not 0
when
Event(source=="SocketSwitching1.POWER", value!="0")
Event(source=="SocketSwitching1.STATE", value!="on")
then
execute.command("SocketSwitching1.ON");
end
The last touch is to retract the last power measurement fact so the repeating same values are processed by the rules engine. Without this rule when power measurement value stays the same the “SocketSwitching1 state ON through power” rule will be triggered only once (this is due to implementation of Drools engine within Openremote).
rule "SocketSwitching1 retract last power measurement"
salience -100 // Because of retracting of the event
when
$s : Event(source=="SocketSwitching1.POWER",$v:value)
then
retract($s);
end
Michal,
Intriguing post again. I was intrigued by your statement: “Even in the same room sometimes the transmission fails, this is my experience with EnOcean, Z-wave and WeMo”. Do you have data on failure rate of each of these protocols in your mixed environment?
Pieter
Hi Pieter,
I don’t have statistics about failure rate of each protocols because for me one fail is already too much ;).
I was curious which one of the three was failing least. I understand that hard statistics is impossible at this scale. Thanks.
In my experiments, the most fragile are WeMo’s. Although they use IP/TCP/UPnP based protocol, which should be very reliable, they are bit ‘over-engineered’ and devices are frequently lost. You should also be very careful which wireless protection are you using with them as not every one is stable.
EnOcean and Z-wave are in the same league. The only problem with Z-wave is when I move devices around. Frequently they don’t work in a new place where EnOcean has no problems. Probably I would need to re-mesh but this is quite cumbersome, therefore my choice are EnOcean removable sockets. Different story would be for stationary devices for sure. However, during my experiments, when things are regularly moved around, EnOcean is the best.
Thanks for the update.
As my main goal for HA is energy conservation, my sympathy is with Enocean, At present I focus on Z-wave on RaZberry. It is easy to do a “re-mesh” there. I do new inclusions close to the zwave controller, than move to the final place, followed by the re-establishment of the routes. Works like a charm. As I said at other occasions the stability of Z-Wave does increase with the number of devices.
Recently I learned that the Razberry people are working on the addition of the Enocean protocol.
hi michal ,
i got your rule how you writing but i am not getting one thing how i need to write class for that rule .
rule “Lamp off”
timer(cron: 0 25 6 ? * fri)
when
Event(source==”SocketSwitching1.STATE”, value==”on”)
$s: SocketState(on!=0)
then
$s.setOn(0);
update($s);
end
rule “Lamp off execute”
timer(int: 0s 5s)
when
$s: SocketState(on==0)
Event(source==”SocketSwitching1.STATE”, value==”on”)
then
execute.command(“SocketSwitching1.OFF”); // Light OFF
end
rule “Lamp off executed”
when
$s: SocketState(on==0)
Event(source==”SocketSwitching1.STATE”, value==”off”)
then
$s.setOn(-1);
update($s);
end
because i create simple hello drools program i am not able to satisfied this condition
I don’t quite understand what the problem is.