This is a hard problem that gets even harder when you have to synchronize more than two or the Items are a different type.
Because this code needs to be be absolutely clear, let’s address a couple of coding issues. You can address these or not as you see fit.
- What’s the deal with the extra pair of parens? Don’t add stuff that doesn’t need to be there unless it adds clarity. The parens in this context don’t do anything.
if(zwave_device_XXXXXX_node61_switch_binary.state != zwave_device_XXXXXX_node51_switch_dimmer.state)
if (zwave_device_XXXXXX_node51_switch_dimmer.state >=3)
sendCommand(zwave_device_XXXXXX_node61_switch_binary, ON) // Laundry Garage
else
sendCommand(zwave_device_XXXXXX_node61_switch_binary, OFF) // Laundry Garage
If you want to add clarity use curly brackets.
if(zwave_device_XXXXXX_node61_switch_binary.state != zwave_device_XXXXXX_node51_switch_dimmer.state) {
if (zwave_device_XXXXXX_node51_switch_dimmer.state >=3) {
sendCommand(zwave_device_XXXXXX_node61_switch_binary, ON) // Laundry Garage
}
else {
sendCommand(zwave_device_XXXXXX_node61_switch_binary, OFF) // Laundry Garage
}
}
- Where these Items created automatically in OH 2.x? These are, frankly, terrible names for Items. One of the whole points of Items is that it doesn’t matter what type of technology it’s connected to. Laundry_Light and Garage_Dimmer would be much better names for these. Not only are they shorter you can look at them and immediately know what the Item controls. I’m not super big on renaming Items any more (since you basically have to delete the old and create a new one with the new name) but this is one case where I think it’s worth the effort.
OK, with that out of the way let’s address the rule itself.
-
The rule only triggers when the switch changes. What about the dimmer? I would expect the rule to trigger for either Item.
-
if(zwave_device_XXXXXX_node61_switch_binary.state != zwave_device_XXXXXX_node51_switch_dimmer.state)I don’t think that will work. If the second Item is in fact a Dimmer, it will never be the case that a Dimmer’s state (without conversion) will equal the state of a Switch Item. This is another place where using better Item names can help because it’s really hard to tell what’s what here. But basically, since the states of the two Items will always be different, the rule will always send a command to node51, even when they are the same equivalent state.Thankfully we can get the state of a dimmer as an OnOffType.
if(zwave_device_XXXXXX_node61_switch_binary.state != zwave_device_XXXXXX_node51_switch_dimmer.getStateAs(OnOffType)) {
Or, using better Item names:
if(Laundry_Light.state != GarageDimmer.getStateAs(OnOffType)){
That’s a probably the main thing that’s wrong and causing the loop. Unless node51 is in fact a Switch Item instead of a Dimmer in which case
. It’s impossible to really understand this rule without a lot more information.
- I like to use Design Pattern: How to Structure a Rule. It sometimes results in longer rules but those rules are always easier to understand.
// 1. Decide if the rule needs to run
if(Laundry_Light.state == GarageDimmer.getStateAs(OnOffType)) return;
// 2. Calculate what to do
var syncState = Laundry_Light.state
// 3. Do it
Garage_Dimmer.postUpdate(syncState)
Already, that’s much simpler, but remember my question in 1 above, shouldn’t the rule run when the dimmer changes too?
rule "Laundry_2_Garage_Sync"
when
Item Laundry_Light changed or
Item Garage_Dimmer changed
then
// 1. Decide if the rule needs to run
if(Laundry_Light.state == GarageDimmer.getStateAs(OnOffType)) return;
// 2. Calculate what to do
val item2update = if(triggeringItemName == 'Laundry_Light') Garage_Dimmer else Laundry_Light
val syncState = if(triggeringItemName == 'Laundry_Light') Laundry_Light.state else Garage_Dimmer.getStateAs(OnOffType)
// 3. Do it
item2update.postUpdate(syncState)
end
The rule will trigger on either Item changing.
- If the states are already the same the rule simply exits.
- Then we determine which Item to update based on which Item triggered the rule (see Implicit Variables). Also calculate the command to send to the Item that needs to be synchronized.
- Finally post the update to the switch that didn’t change.
If the ternary operator is something you might forget section 2 could be something like this.
// 2. Calculate what to do
var item2update = Laundry_Light
if(triggeringItemName == 'Laundry_Light') {
item2command = Garage_Dimmer
}
var syncState = newState
if(syncState instanceof PercentType) {
syncState = Garage_Dimmer.getStateAs(OnOffType)
}
In this case we assume that the Item that needs to be updated is the Laundry_Light. But if the Laundry_Light triggered the rule change to Garage_Dimmer. We do the same for the syncState. If the type of the newState is from the Dimmer, we get the state from the Dimmer as an OnOffType.
The flow will be something like the following:
- Laundry_Light changes to ON, triggering the rule.
- The Dimmer isn’t on so the Dimmer will be updated to ON.
- The Dimmer will change to 100 (or what ever) triggering the rule again.
- This time Laundry_Light and Garage_Dimmer will be the same so the rule exits without doing anything.
The same happens if the Dimmer changes to ON to the Laundry_Light.
There might be a problem here though. Updating the Item will not in fact change the state of the end device. It only updates OH internally. Later on, when the binding polls the device’s state it will update the Item back to it’s old state which will trigger the rule again and undo the last command. If that’s the case, use sendCommand instead of postUpdate in section 3 of the rule.