To control my lights I have 2 switches (Off pulse, On Pulse) connected to a PLC.
When the proxy switch receives an update through the UI I will control the correct pulse.
rule "Lights Pulse"
when Member of Lights received update
then
if (triggeringItem.state==ON) {
var pulseOn = gLights_PLC_Pulse.allMembers.filter[s|s.name == triggeringItem.name + "_Pulse_ON"].head
pulseOn.sendCommand(ON)
} else if(triggeringItem.state==OFF){
var pulseOff = gLights_PLC_Pulse.allMembers.filter[s|s.name == triggeringItem.name + "_Pulse_OFF"].head
pulseOff.sendCommand(ON)
}
end
This works perfect if im controlling the lights one by one.
However if I use a group command the result of the filter can be null randomly.
On the forums I find some threads with a simular issue I think, and it could be a threading issue.
Any idea’s how I can solve this ?
rule "Lights Pulse"
when Member of Lights received update
then
if (triggeringItem.state==ON) {
var pulseOn = gLights_PLC_Pulse.allMembers.filter[s|s.name == triggeringItem.name + "_Pulse_ON"].head
if(pulseOn !== null)
pulseOn.sendCommand(ON)
} else if(triggeringItem.state==OFF){
var pulseOff = gLights_PLC_Pulse.allMembers.filter[s|s.name == triggeringItem.name + "_Pulse_OFF"].head
if(pulseOff !== null)
pulseOff.sendCommand(ON)
}
end
What it boils down to is if you are iterating over the members of a Group while the Group itself is updating because the Items in the Group are changing the iteration will simply fail. A filter is a type of iteration.
I know of no good way to correct this beyond what Udo recommends and just test for null to filter out those failures if using this approach. Of course that also means that that particular event won’t occur.
But there can be other things you can do. For example, why pull the Item out of the Group just to send it a command? While the recommendation is to not use the sendCommand action where you can avoid it, this is one of those places where it makes sense to use it.
In fact, this whole rule could be boiled down to one line of code.
then
sendCommand(triggeringItem.name+"_Pulse_"+newState, "ON")
end
And now, since you are not looping through the changing Group you shouldn’t get the null errors any more.
The rule will only trigger when one of the members receive a command. Updates can happen all the time and they do not always result in a change to the Item.
Usually, when one has a rule triggered to do something, it needs to do so in response to a command or a change. Rarely will you see a rule triggered by an update because a update may just be the binding polling the devices and saying “yep, that light is still OFF”.
Well, if you want to instruct some feature to “do something”, you’d send it a command. That’s not the same as Item state. You already do this for your pulse Items.
Consider a Dimmer type - you can send it ON.OFF,INCREASE command but its state is only ever a % number.
For Switch types,ON/OFF commands resemble ON/OFF states, but it’s still a good habit to get into, being clear about command and state distinctions.
If you do change your rule trigger, be sure to change your if() to look at the receivedCommand implicit variable. The Item state then becomes irrelevant to this rule.
If your PLC provides feedback about the target lighting circuit, you could use that to update the Item state to reflect reality.