[SOLVED] Merging two items

Hello

I need your help in using a “double switch” item.
I have a Item connected to the ModBus Binding that I can control from a push button. Pressing this push button changes the value off the item.
Now I added a Sonoff T2, that I can control thru mqtt. I want the Sonoff to change the item’s value, I could do this by a simple rule on T2 change, but I don’t know hot to make this bidirectional. If I touch the T2, the modbus item changes and the T2 led and relay change. If I change the ModBus value by pressing the push button or on the sitemap, nothing happens on the Sonoff T2 (as there is no rule updating the T2’s value).
I didn’t try any “inverse” rule as I think I will end with an infinite loop.

Is there any better option? Any way of merging one item to react to two Bindings and update the values to modbus and mqtt?

João

Yes of course

Can you post your item definition?
What is the behaviour that you want to achieve?
What topic and payload are to be published/received on mqtt?

After a few tries I ended with this:

Switch LampadaSotao "Lâmpada do sótão" (Sotao, Lampadas) {modbus="slave4:46", mqtt=">[mosquitto:cmnd/sonoff_int/POWER1:command:*:default], <[mosquitto:stat/sonoff_int/POWER1:state:default]" }

I want to turn on and of from the push button or the Sonoff and have information on the Sonoff of the actual state of the lamp (conected to the modbus equipment).

João

The difficulty is that an incoming change event from the Sonoff will update the Item. The modbus binding passes out commands (not updates). And vice-versa when the modbus side initiates a change.

So you’re going to need rules. I would think the least brain-exploding approach would be to separate your Items.

rule "modbus leading"
   when Item modbus changed   // ignores commands
then
   if (mqtt.state != modbus.state) {  // avoids looping
      mqtt.sendCommand(modbus.state)
   }
end

rule "mqtt leading"
   when Item mqtt changed
then
   if (mqtt.state != modbus.state) {
      modbus.sendCommand(mqtt.state)
   }
end

Needs some work to deal with e.g. NULL states etc., but devices should track each other when one is commanded by other rules, UI, local buttons etc.

Yes

Not necessarily.
I think this is a very good case of using the MQTT Action…
Install the MQTT Action in the paperUI

Remove the command part of the mqtt binding in the item:

Switch LampadaSotao "Lâmpada do sótão" (Sotao, Lampadas) {modbus="slave4:46", mqtt="<[mosquitto:stat/sonoff_int/POWER1:state:default]" }

The rule:

rule "LampadaSotao Updated via Sonoff"
when
    Switch LampadaSotao changed
then
    if (LampadaSotao.state != NULL) {
        LampadaSotao.sendCommand(LampadaSotao.state.toString) // Send command to modbus
        publish("mosquitto", "cmnd/sonoff_int/POWER1", LampadaSotao.state.toString) // Send command to MQTT
    }
end

I’m not even sure you need to do that, a command sent from rule will go to all (configured) bindings. Triggering the rule on change is the important part, looking at it again. So long as neither device is upset by e.g. command ON when already ON.

One factor deciding approach might be how you want it all to behave under fault conditions i.e. one of the tracked devices goes offline. I think all the suggestions cope reasonably here.

Actually, thinking still more … the modbus binding is a polling binding. That’s to say, it updates Items regularly with current state. That sets a little race condition trap … You could send a command and openHAB could autoupdate your Item before the command takes effect at the device. A read poll can update the Item again with the old state in that tiny instant. Potential misbehaviour.

Strongly recommend autoupdate=“false” so that Item(s) reflect actual device changes (always a good idea for modbus anyway).

You can configure the mqtt binding to only receive state updates

Very tiny. A few millis

Yes that will only apply to the modbus binding because we are forcing mqtt updates
So it becomes:

Switch LampadaSotao "Lâmpada do sótão" (Sotao, Lampadas) { modbus="slave4:46", mqtt="<[mosquitto:stat/sonoff_int/POWER1:state:default], autoupdate="false" }

Thank you. I will test tonight.

João

Yup, my point was that you can configure the Item binding to handle commands to mqtt as well, and not need to use the separate mqtt action in the change-rule.
That’s assuming the OP wants commands from other rules or UI to always switch both devices :slight_smile:

This depends very much on the modbus setup performance and device behaviour. It is a real effect and has been seen in other people’s modbus configurations, but easily avoided once understood.

In this case you can’t because the OP wan’t to send a command from a state update and we’ll end up with a binding loop, that’s why we need a rule and a separate command sent

That’s what the rule triggered from changed achieves, it does not respond to a simple update but only to a change.

Other rule or UI command ON to Item, both devices get commanded ON by outbound bindings.
The Item state will change to ON and trigger this rule, which will send another command ON to both - but its redundant. End, no loop, as state does not change further.

One or other device gets changed to ON by pushbutton, Item gets updated and changed to ON by inbound bindings, that triggers rule which sends ON to both devices. One is redundant, the other makes the second device track. An update comes back, but does not change the state, so no loop.

I’ve seen this on another thread. It is more than potential for polling type bindings. I think it will mainly show up if by chance the polling period of the binding lines up with a polling Rule or a periodic event.

I only had the time to make one simple test:

My items:

Switch LampadaSotao “Lâmpada do sótão” (Sotao, Lampadas) {modbus=“slave4:46”}
Switch Sonoff_sotao (sonoff) { mqtt=">[mosquitto:cmnd/sonoff_int/POWER1:command:*:default], <[mosquitto:stat/sonoff_int/POWER1:state:default]" }

The rules:

rule “modbus leading”
when
Item LampadaSotao changed // ignores commands
then
if (Sonoff_sotao.state != LampadaSotao.state) { // avoids looping
Sonoff_sotao.sendCommand(LampadaSotao.state.toString)
}
end

rule “mqtt leading”
when
Item Sonoff_sotao changed
then
if (Sonoff_sotao.state != LampadaSotao.state) {
LampadaSotao.sendCommand(Sonoff_sotao.state.toString)
}
end

The logs:

2018-10-18 23:53:41.109 [vent.ItemStateChangedEvent] - Sonoff_sotao changed from OFF to ON

2018-10-18 23:53:41.121 [ome.event.ItemCommandEvent] - Item ‘LampadaSotao’ received command ON

2018-10-18 23:53:41.133 [vent.ItemStateChangedEvent] - LampadaSotao changed from OFF to ON

and

2018-10-19 00:01:25.455 [vent.ItemStateChangedEvent] - LampadaSotao changed from OFF to ON

2018-10-19 00:01:25.478 [ome.event.ItemCommandEvent] - Item ‘Sonoff_sotao’ received command ON

2018-10-19 00:01:25.500 [vent.ItemStateChangedEvent] - Sonoff_sotao changed from OFF to ON

I will play with this a bit the weekend, but the main goal is achieved.

Thank you.

João