After involuntarily taking a couple of cold showers recently I thought I get back to this subject. A have built myself a little test rig (luckily I have a spare UniPi). I can confirm now that there is a reproducible behavior in my pimatic / UniPi combination that leads to a state in which a relay is not switched as desired. The condition is a) that at least 2 relays are switched at the same time plus b) a race condition. Although reproducible, b) results in this effect showing or not. The condition a) can be met by switching 2 relays in the same rule as well as 2 relays switching in 2 different rules, where one rule triggers the other. For example, the following set of rules will produce the behavior:
{
"id": "switchback-tester",
"name": "switchback_tester",
"rule": "when brenner is turned on then turn relay-5 off and turn relay-6 off",
"active": true,
"logging": true
},
{
"id": "switchback-tester-2",
"name": "switchback_tester-2",
"rule": "when brenner is turned off then turn relay-5 on and turn relay-6 on",
"active": true,
"logging": true
},
{
"id": "switchback-tester-brenner",
"name": "switchback_tester_brenner",
"rule": "when every 30s then turn brenner on",
"active": true,
"logging": true
},
{
"id": "switchback-tester-brenner-2",
"name": "switchback_tester_brenner-2",
"rule": "when every 30s then after 15s turn brenner off",
"active": true,
"logging": true
}
These rules should set both relay 5 and 6 to the same state but rarely do. I have found a workaround for no more cold showers, which involves avoiding the situation that more than one relay is switched at a time. This workaround is not very good, as many rules depend on sensors are hence are non-deterministic, so I can’t really be sure they prevent the undesireful behavior.
Since relays are a lot slower than anything else that is happening in the processor or memory, I wonder if it is possible to modify rule execution in such a way that it is blocking. I assume that this effect could be prevented, if the switching of a relay is waited for until the new state is confirmed and only then further rules are evaluated. I would like to contribute but am not expert enough neither in Pimatic nor in Coffee for giving it a try.
Could somebody let me know if such blocking behavior is even possible and if so, what would be the right way to go about it? Blocking would mean that rule execution needs to be queued, so that no events are lost. I wonder if this compatible with the current architecture of the rule engine.
BTW, the workaround is as follows: For rules that involve no relay state in the condition, but switch several relays in their action, switch the first relay with no delay, but the second with 4s, the third with 8s and so on. For rules with a relay state in their condition, switch the first relay with a delay of 4s, the second with 8s etc. Hope it works, just only changed my rules.