Marketplace MQTT Event Bus

@rlkoshak, I’ve been trying to implement the eventbus in openhab 2.5
The publishing part works fine but when I try to add the channel in PaperUI (almost idendically to your example), I always get ERROR: 409 - Conflict. nothing in Karaf or any of the logs.
The added channel is nowhere to be found in PaperUI.

How can I debug the creation of the channel ?
Can you provide an example of how the channel can be configured in the mqtt.things config file ?

409 means there is something about the state of the server preventing the creation of the Channel.

There should be something in the logs about that. I’m not sure how to debug this. Perhaps restart openHAB and see if it persists. If so look in the REST API Docs at the Channel creation endpoint and see if the docs provide any additional information about what the 409 means.

No, nothing in the logs.
I had tried to restart openhab. the problem persists.
What Karaf command can I use to view the created MQTT channels ?
Any chance you can hint to the correct syntax to create the channel in the things config fil e ?

After increasing the debug level on the MQTT binding I get this in the Karaf interface

20:22:13.176 [INFO ] [est.core.internal.thing.ThingResource] - Received HTTP PUT request for update at 'things/mqtt:broker:local' for an unmanaged thing 'mqtt:broker:local'.

In the end. I found the solution here

Bridge mqtt:broker:myUnsecureBroker [ host="192.168.0.42", secure=false ]
{
    Channels:
        Type publishTrigger : myTriggerChannel "Receive everything" [ stateTopic="allItems/#", separator="#" ]
}

Sorry to hijack this topic. I have a scenario that a master OH3 is sitting in a cloud with openhabcloud. All the remote servers will connect to openhabcloud via cloud connector, and could be behind firewall or proxy servers. In such a case, master OH3 will not able to communicate with remote servers unless it punches through openhabcloud. Any thoughts on how to resolve this scenario? Thanks

I don’t think it can be done. But you should open a new thread so people who use (and perhaps the developer) the remote binding can answer.

Hi Rich

Im trying to set this up , on the local instance I can see the command sent, and received on the remote instance. The remote instance has a Zwave light, and its console log shows it being switched on but it doesnt actually switch on. Instead, the remote instance log fills with this:


16:01:08.710 [INFO ] [smarthome.event.ChannelTriggeredEvent] - mqtt:broker:2eee62e3:House-updates triggered Garage/out/BedRoom1Sw1/state#OFF
16:01:08.722 [INFO ] [smarthome.event.ChannelTriggeredEvent] - mqtt:broker:2eee62e3:House-updates triggered Garage/out/BedRoom1Sw1/state#OFF
16:01:08.769 [INFO ] [smarthome.event.ChannelTriggeredEvent] - mqtt:broker:2eee62e3:House-updates triggered Garage/out/BedRoom1Sw1/state#OFF
16:01:08.770 [INFO ] [smarthome.event.ChannelTriggeredEvent] - mqtt:broker:2eee62e3:House-updates triggered Garage/out/BedRoom1Sw1/state#OFF

I have two instances

Garage (Main instance, with mosquitto running locally)
House (remote instance, with Zwave and local devices)

Here is the Broker on the Garage (Main) instance:

Here is the Broker on the House (client) instance that has the ZWave light

When the real light switch is removed from the two groups, I dont get the infinite logs but the light also doesnt switch on (despite it showing an update)

Its really not clear from your tutorial what is done to what device, ie whats done to the Local and Remote instances. In ’ Setting up the Subscriptions’ your screenshot doesnt really align with what your talking about so to me, I’ve no idea what channels go on what device.

ie: is there a broker per machine? then is there a channel per broker, per machine? are the rules required on both. Sorry, but its really really confusing.

Thanks

One of the OH instances needs to be the main one. This instance only publishes commands and only subscribes to updates. The remote instance is the one that is actually connected to the device. This instance only publishes updates and only subscribes to commands.

If both instances subscribe to both commands and updates and both instances publish both commands and updates you’ll end up with an infinite loop. So you should never have an Item that is a member of both PubItems_CMD and PubItems_UPD on the same OH instance.

The entire first few hundred lines of the tutorial is intended to make this point.

The “owner” of the device subscribes for commands and publishes updates. The other instance of OH subscribes to updates and publishes commands.

Pay attention to the tables. Pay particular attention to to the topics in the tables.

I’m not sure how to correct this. That section has a screen shot for the subscription Trigger Channel and then spends the whole section describing what each of the parameters mean and what should go in there.

But the discussion about what subscription goes on what device happened earlier. But this is really complicated. It’s not just a simple one-to-one configuration. If you want that you are better off using the Remote openHAB add-on.

There is some additional discussion about the various topologies that is possible with the event bud (one-way, one-to-one, hub and star, etc) at the links to the github repo. Looking at those might be helpful.

But in general, this tutorial is an advanced tutorial and not something to be taken on lightly unless there is no other option. The code is deceptively simple but understanding the message flows is vital.

I should add that if you have any suggestions to make the tutorial more clear I’m open to them. I’ve rewritten that thing three times now and plan on another rewrite at some point.

Also, if it’s still not clear I’ll try to draw another diagram to help.

2 Likes

Thanks Rich, it makes more sense after your first few sentences. Best to break it up like so:

Main Instance (Publishes only)

  • insert rules
  • insert broker
  • etc etc

Also, setting the groups as string gave me errors with OnOff Types FYI.

Question, so this would not work if the remote instance was sending commands? Lets say the remote instance has a ZWave scene controller physically in the house - you push buttons etc so it sends commands back to the Main instance which runs rules from those commands. So not only On/Off commands but numbers such as power metering readings and scene numbers etc, even OPEN/Closed from Contacts

Effectively, totally bi-directional. This bidirectional works just fine with MQTT 1.x event bus using all item types

Cheers

There is no basic rule. It all depends on which openHAB instance is actually connected to the device, how many openHAB instances are connected to each other, and the nature of the device. That’s why it’s important to make sure to understand the data flows.

The thing you need to avoid are infinite loops. Infinite loops occur when you subscribe to both the update and the command channel for a given Item on both OH instances.

But you wouldn’t need to publish updates from that scene controller right? All you care about are publishing the Commands. And you wouldn’t be commanding this Item from the openHAB that isn’t connected to the controller. All you care about is subscribing to the commands.

So those Items are members of PubItems_CMD only on the machine connected to the controller. The other openHAB instance subscribes to the commands only and publishes nothing for that Item. You don’t care about the updates at all for that Item. It’s only the command that are generated by physically pressing the buttons on the controller.

These are sensors. So for these Items you don’t care about commands. In the case of Contacts you can’t command them if you wanted to. So the instance of openHAB actually connected to the device puts those Items into PubItems_UPD. The other openHAB instance only subscribes. It doesn’t own the device and the device is a sensor. You wouldn’t be updating that device in the other openHAB instance anyway so don’t publish anything at all for those Items.

Even in the MQTT 1.x event bus if you didn’t get these settings right an infinite loop occurred. I fought against many such loops in the past with MQTT 1.x.

But, the above is by design more flexible and more capable than the MQTT 1.x event bus. It was never intended to be a mere reimplementation. I had plans to create a simpler version that more closely mimicked the old event bus only even simpler but that became redundant when the Remote openHAB add-on was released. So this tutorial is mainly kept around to handle those cases that are too complicated to be implemented by the Remote openHAB add-on.

If you want simple mirroring that’s the tool to use. If you are on OH 2 and want simple mirroring of everything, the MQTT 1.x event bus is what you want to use. If you want to have control over how the Items are mirrored on an Item by Item basis then this tutorial is for you. But that means you have to understand the data flows on an Item by Item basis.

The only real difference here from the 1.x EventBus is that in order to allow the control and flexibility I can’t just hide these details like the 1.x binding did. But make no mistake, it worked pretty much the same way to avoid infinite loops.

Which openHAB instance “owns” the Item (i.e. is connected to the actual device)? That will usually be the one that publishes the state updates, unless the Item is commanded from the binding (e.g. a motion sensor, remote controller, etc) in which case only the commands are published.

The openHAB instance that has a proxy for the Item usually wants to know what state the device actually is in. So in that case it will subscribe to updates. But for actuators it also wants to remotely control them so it will publish commands.

You never want a case where you both publish and subscribe to commands on the same OH instance at the same time. When that happens:

  1. OH 1 publishes a command
  2. OH 2 receives the command and sendCommand on the Item
  3. OH 2 publishes the command
  4. OH 1 receives the command and sendCommand on the Item
  5. return to 1.

The same occurs if you both publish and subscribe for updates on the same OH instance at the same time.

  1. OH 1 publishes an update
  2. OH 2 receives the update and postUpdate on the Item
  3. OH 2 publishes the update
  4. OH 1 receives the update and postUpdate on the Item
  5. return to 1.

It’s still two way.

1 Like

Thanks Rich, I’m going to have another stab today at doing this - all makes sense. I had used MQTT1.x successfully for some time to do what I needed but the implementation confused me using MQTT2

Very detailed response, thank you! I cant use the Remote OpenHab binding because I’m not using OH3 - have no desire to do that yet. For now, it’s about getting off the legacy 1.x bindings which I’ve all but done except for MQTT

Thank you!

Hi Rich, I still can’t get it to work.

Main instance (Called, Garage, runs the UI, Habpanel) - has a proxy item for StudySw1 which is a light switch. I also want it to receive updates to the Power channels

Switch BedRoom1Sw1  "Study"    Switch BedRoom1Sw1  "Study"    (Group_HabPanel_Dashboard,gLights_Random,gAllLights,gInsideLights,PubItems_CMD)            { alexa="PowerController.powerState" }
Number BedRoom1Num1 "Study - Current Consumption [%.1f W]"  (gAllLightsUsage,gEnergyRealTime,PubItems_UPD)
Number BedRoom1Num2 "Study - Usage [%.1f kW]"               (gPowerUsage,PubItems_UPD)



Remote Instance (called House)- has the real item with Zwave binding for StudySw1 which is a light switch
I want it to send the power channel updates to the Main instance

/*ZWave Switch Bedroom Lights*/
Switch BedRoom1Sw1  "Study"                                   (Group_HabPanel_Dashboard,gLights_Random,gAllLights,gInsideLights,PubItems_CMD)               { channel="zwave:device:12c97eda:node30:switch_binary1"}
Number BedRoom1Num1 "Study - Current Consumption [%.1f W]"    (gAllLightsUsage,gEnergyRealTime,PubItems_UPD)                                                { channel="zwave:device:12c97eda:node30:meter_watts1"}
Number BedRoom1Num2 "Study - Usage [%.1f kW]"                 (gPowerUsage,PubItems_UPD)                                                                    { channel="zwave:device:12c97eda:node30:meter_kwh1"}

Main Instance rules:


val eb_br = "mqtt:broker:broker" // Thing ID of the broker connection
val eb_name = "Garage"              // <client ID>

rule "Publish commands to the event bus"
when
    Member of PubItems_CMD received command // eb_cmd_gr
then
    val mqttActions = getActions("mqtt",eb_br)
    mqttActions.publishMQTT(eb_name+"/out/"+triggeringItem.name+"/command",receivedCommand.toString)
end

rule "Publish updates to the event bus"
when
    Member of PubItems_UPD received update // eb_upd_gr
then
    val mqttActions = getActions("mqtt",eb_br)
    mqttActions.publishMQTT(eb_name+"/out/"+triggeringItem.name+"/state",triggeringItem.state.toString)
end


rule "Subscribe for commands and updates from the event bus"
when
    Channel "mqtt:broker:broker:remote-updates" triggered
then
    var topic = receivedEvent.toString.split("#").get(0)
    var state = receivedEvent.toString.split("#").get(1)
    val itemName = topic.split("/").get(2)
    val type = topic.split("/").get(3)

    if(type == "command") sendCommand(itemName, state)
    else postUpdate(itemName, state)
end

And the channel

Remote Instance

Rules:


val eb_br = "mqtt:broker:broker" // Thing ID of the broker connection
val eb_name = "House"              // <client ID>

rule "Publish commands to the event bus"
when
    Member of PubItems_CMD received command // eb_cmd_gr
then
    val mqttActions = getActions("mqtt",eb_br)
    mqttActions.publishMQTT(eb_name+"/out/"+triggeringItem.name+"/command",receivedCommand.toString)
end

rule "Publish updates to the event bus"
when
    Member of PubItems_UPD received update // eb_upd_gr
then
    val mqttActions = getActions("mqtt",eb_br)
    mqttActions.publishMQTT(eb_name+"/out/"+triggeringItem.name+"/state",triggeringItem.state.toString)
end


rule "Subscribe for commands and updates from the event bus"
when
    Channel "mqtt:broker:broker:remote-updates" triggered
then
    var topic = receivedEvent.toString.split("#").get(0)
    var state = receivedEvent.toString.split("#").get(1)
    val itemName = topic.split("/").get(2)
    val type = topic.split("/").get(3)

    if(type == "command") sendCommand(itemName, state)
    else postUpdate(itemName, state)
end

Remote Channel configuration

Problem:

  1. I can see the switch updates coming from the Main/Proxy/UI instance to the Remote instance, but the light wont switch on/off

  2. I can’t see the power updates coming from the Remote instance to the Main instance

OK, let’s take this one Item at a time.

First of all, your Items are called BedRoom1Sw1 but they are labeled “Study” which is a little confusing. Make sure you are looking at the right Items.

One requirement is that the Items have to have the same name in both Garage and House. That seems to be the case here which is good.

Based on the two sets of Item definitions BedRoom1Sw1 is “owned” by House and Garage has the proxy.

BedRoom1Sw1 is a switch that controls a light. So we need the following data flows.

Direction Type Purpose
House to Garage Updates When the light changes state we need to represent that change in the proxy Item at Garage
Garage to House Commands The rules and HABPanel and such needs to be able to control this light which means it needs to be able to send commands.

To achieve that:

There are multiple ways to do this but in a one-to-one topology like this I find it easiest to have only one of the OH instances “own” the MQTT topics but that will require more changes to the rules. So instead let’s let each OH instance use it’s own out topics and they each subscribe to each others.

OH Instance Subscription topic
Garage House/out/*
House Garage/out/*

This will set up the two way traffic and it handles both commands and updates.

Now for the Items:

OH Instance Configuration for BedRoom1Sw1
House BedRoom1Sw1 is a member of PubItems_UPD
Garage BedRoom1Sw1 is a member of PubItems_CMD

Updates to the Items on House will be published and Garage will receive that message and update the proxy Item, keeping them in sync. Commands on the proxy Item from Rules or the UI will be published and House will receive them and command the Item linked to the actual device.

A nice additional thing you can do is for the proxy Item on Garage set autoupdate to false. That means the Item itself won’t change state on Garage until it also does so on House, giving you a confirmation that the light actually turned on or off as commanded.

The configuration for the other two Items is even easier because the data flow is actually just one way and all we care about are the updates.

Garage is already subscribed to the right topics so the only thing you need to do on House is add BedRoom1Num1 and BedRoom1Num2 to PubItems_UPD. That’s all there is to it. When the Zwave binding updates the Item that update will be published and Garage will receive the update and postUpdate to the proxy Item, keeping them in sync.

For the rules you probably already have everything configured as they need to be. You need all three rules in both instances. eb_name on the House set of rules need to be “House” and eb-name on the Garage set of rules need to be “Garage”. Other than that they will be the same (unless the Broker Thing is different on the two instances in which case set eb_br as appropriate for each instance).

Looking at your config as posted:

  • the Switch is a member of the wrong Group on House; it should be a member of PubItem_UPD
  • the Number Items should not be a member of PubItem_UPD on Garage, only on House; there is nothing to publish from Garage for these sensor Items
  • the broker Trigger Channels on both OH instances should subscribe to everything under out, not just the state or the command subtopics.

Thanks Rich, I was pretty close . After making those fixes it still does not work.

Ive checked it all and updated as required. For the channel in MQTT, with those topics you’ve listed do I need a separator character?

Also, using autoupdate=“false” on the proxy, wont allow the light to switch on in the UI at all - so I’ve removed it for now.

Once changing the MQTT Channel configuration to Garage/out/* & House/out/* I no longer get any log events :frowning:

Yes, put in “#”. Otherwise the topic name is not passed along with the message in the event from the subscription channel. Without the topic name we have no idea which Item and whether it’s an update or a command. There should be errors in the log when the subscription rule runs if the separation character is missing.

It won’t work right until the event bus works. When it’s false, House will have to publish the state update before HABPanel on Garage will show the light has switched.

OK cool. Unforunately, no joy still.

Proxy/House receives nothing at all - log shows nothing. Topics have * at the end in the channel configuration (different to your how to post at the top)

FIXED!!!

You had given me the wrong channel configuration rich :wink:

This is what it needed, it needed the + and the #, not the * you had mentioned…

Thanks so much - Light going on/off now, ill wait a bit and see if the energy figures are sent from House to Garage…

Hi Rich

It seems something isnt quite right with regards to Scene Controllers.

The house has quite alot of them, but now they are throwing these errors. As you suggested, I put the PubItems_CMD as they send commands only, but the rules for those commands are actually on the Garage instance.

Would this be I receive this error?

17:56:33.869 [WARN ] [verter.ZWaveMultiLevelSwitchConverter] - No conversion in ZWaveMultiLevelSwitchConverter to StringType
17:56:39.661 [INFO ] [smarthome.event.ItemStateChangedEvent] - Kitchen_AeoButton_Scene changed from 2.0 to 1.0
17:56:40.758 [INFO ] [smarthome.event.ItemStateChangedEvent] - Kitchen_AeoButton_Scene changed from 1.0 to 2.0
17:56:40.846 [WARN ] [verter.ZWaveMultiLevelSwitchConverter] - No conversion in ZWaveMultiLevelSwitchConverter to StringType

That was a typo on my part. Getting old sucks and I didn’t have my glasses on. * and # are completely indistinguishable without my glasses.

You need to use #. I’ll update my reply above as well to correct that. In the mean time:

OH Instance Subscription Topic
Garage House/out/#
House Garage/out/#

You will want to use # instead of + though. + only works at one level and # covers the whole subtree.

The rules need to be on both instances.

The warning is coming from the Zwave binding. I don’t really know what it means. It’s complaining about a StringType. Maybe add some logging to the subscription rule on House to see if you can figure out which Item it’s complaining about. Since it’s co