Marketplace MQTT Event Bus

First, this is far and away the best OpenHAB-related tutorial I’ve seen. It’s clear. It’s detailed. It shows lots of UI screenshots. Good job. We beginners need more like these.

It does seem to be self-contradictory however, probably as a result of changing circumstances over time. At the top it says:

However there may be use cases where MQTT is preferred, such as integration with a non-openHAB service.

That’s my situation, so I thought I was in the perfect place.

Later however, it says

[I’ve elipsed out some portions of that quote that were specific to that user’s needs.]

As I spent some time going down a blind alley and would like to prevent others from doing so in the future, I respectfully suggest that the first quote be deleted or altered to remove the reference to non-openHAB services.

Again, thank you for the great writing, and for all your work on openHAB.

I see this tutorial needs to be updated for OH 4 so thanks for reminding me that it’s here.

The two statements are not contradictory but perhaps need explanation.

What is missing from both statements is the direction of the integration.

OH → The World

If OH is simply exposing itself to some other service, MQTT and the MQTT Event Bus is a good choice. OH, as the source, gets to dictate what and how the messages get published.

So if you were wanting to use MQTT to integrate OH with Home Assistant, Node Red (if for some reason the plugin doesn’t work for you) or some custom GUI, MQTT and the MQTT Event Bus is a good choice.

Device → OH
However, if one is trying to expose something else to OH, a Generic MQTT Thing is the better choice. The reason is that MQTT Event Bus requires the MQTT topics to fit a very specific structure/hierarchy, a structure that is almost certainly not something that a third party service is going to know and follow. OH needs to adapt to the structure/hierarchy and messages published by the device, not the other way around.

That’s what those two statements are supposed to mean.

Thank you. I actually need bi-directional integration. A few current devices and all future devices will be managed by OH, but about 30 legacy devices are currently managed by another system, so I need these two to talk. Now I know that the Generic MQTT Thing is the right answer for me. Any text that will help guide folks to the right solution for them would be great.

Assuming your legacy system can not/should not adjust to the OH MQTT Event Bus.

The advice above is a rule of thumb, not a hard and fast rule. MQTT can be pretty flexible but some systems and devices sometimes are not flexible at all.

Updated from OH v3.3.0 to OH v4.0.4 and tried to get this new event bus implementation to work, but definitely would use some additional advice.

There used to be two rules (publisher, subscription), but now that I create a new rule that supposedly has both functions, what should be put to “Then” section?

Install the rule template. Make sure you get the 4.0+ template. MQTT Event Bus [4.0.0.0;4.9.9.9]

Configure your MQTT broker with an event channel and the Groups as described in that link.

Create a new rule and choose that as the template. Fill in the properties.

That’s it. The whole point of rule templates is they are installed and configured. You don’t need to edit the rule.

1 Like

Hi there, I am trying to following your tutorial but I am still struggling :(. I am trying to publish a number to a another system (SAE) but keep on getting this error.


So its triggering but its not sending anything to MQTT. What can I be missing? Thanks in advance, Erik

That’s not what this is for. Just use a Generic MQTT Thing configured to publish the number to the topic you want. Using the EB to publish one number is like using a blowtorch to light a candle.

Please don’t post screen shots of errors.

What version of OH? You installed the rule template (templates is on OH 3)? How did you configure them? What are the Groups and Item memberships?

Thanks Rich, that was indeed quite straightforward to use a Generic MQTT thing, defining a command topic and using the follow option. Thanks again for your quick response, Erik

Hello Rich,

I, too, don’t really need to link two openhab instances, but rather only want to do the same as Erik, publish state changes of OH items to MQTT. I could go the route of a Generic MQTT thing, but since I have quite a few items to publish, adding them to a group is a lot easier than creating MQTT channels and linking them. So basically using 1/4 of the function of the Event Bus.

I’m very sure that I have the configuration correct (I created the Publish-Channel on the MQTT bridge thing), even tried switching out the groups, but also run into the same error:
MQTT Event Bus rule triggered without an event we can process.

Any idea on this?

Put the rule into debug level logging by setting the logger level for org.openhab.automation.rules_tools.MQTTEventBus to DEBUG in any of the usual ways. There is also a line you can uncomment at the top of the Script Action to put the rule into debug logging.

It might be the template needs to be updated for a change in OH 4. A new Item event was added.

I’ve added some updates to the logging also so please remove the old template and add the new one and reinstantiate the rule.

That might be better handled using a rule with the publish Action. You’ll have a lot more control over how it works.

Thanks, Rich!

I got it working, mostly.
Incoming (updates) is working, and outgoing (commands) is working if I explicitly send a command (openhab:send) to the item in the command group.

I’ve added one of my sensor items to the command group, but updates there don’t trigger the rule, even though I changed the command condition of the rule to “when a member of a group is updated”.

Debug log only says this:

2024-01-19 09:21:13.692 [WARN ] [.automation.rules_tools.MQTTEventBus] - MQTT Event Bus rule triggered without an event we can process, ignoring
2024-01-19 09:21:42.837 [DEBUG] [.automation.rules_tools.MQTTEventBus] - Processing an MQTT Event Bus event: ItemStateUpdatedEvent

So it’s getting the event, but doesn’t know to react to it.
Same is true if I issue “openhab:update” to the item in karaf.

The new version of the template does handle that event. And I changed that first log statement so you need to update the template and regenerate the rule.

Thanks.
I thought I had the latest version (from the addon-store)
MQTT Event Bus [4.0.0.0;4.9.9.9]
Created At February 8, 2023 10:28 AM
Updated At September 13, 2023 8:35 AM

Isn’t that what I need?
I did notice that the rule only considers “ItemStateEvent” and not “ItemStateUpdateEvent”:

var pubEvent = () => {
          console.debug('Publishing an event bus event');
          var retained = (event.type == 'ItemStateEvent');

I’ve updated the code at GitHub but I didn’t update the marketplace post. It should still pick up the new code from GitHub though. The last few lines of the rule script action should look like the following:

        if(this.event !== undefined) {
          console.debug('Processing an MQTT Event Bus event: ' + event.type);
          switch(event.type) {
            // Process an incoming message on the MQTT Channel Trigger, updating/commanding the corresponding Item
            case 'ChannelTriggeredEvent':
              procEvent();
              break;
            // Publish state updates and commands on local Items
            case 'ItemStateEvent':
            case 'ItemStateUpdatedEvent':
            case 'ItemCommandEvent':
              pubEvent();
              break;
            // Warn if we received an unknown event.
            default:
              console.warn('MQTT Event Bus rule triggered without an event we can process: ' + event.type + ', ignoring');
          }
        }

        else {
          console.warn('MQTT Event Bus rule triggered without event, ignoring');
        }

They do.
I’ve updated openhab (was a version behind) and re-installed the rule template and the rule.
Same thing, works on “openhab:send” but not on “openhab:update”.

Seems the logging has changed with the update, too, since I do get debug messages on the “send”, but no longer on the “update”.

The big thing I changed was that first log statement from above. Previously is would log:

MQTT Event Bus rule triggered without an event we can process, ignoring

Now it should log

MQTT Event Bus rule triggered without an event we can process: <NameOfSomeEvent>, ignoring

where <NameOfSomeEvent> is the name of the event that is being ignored.

The only other change was adding ItemStateUpdatedEvent to the list of publish triggers six lines above the log statement.

I didn’t change anything else, unless you had an even older version of the rule template.

I meant that the logging may have changed with the OH update.

But it’s really strange, it seems like the whole section isn’t processed.
For an “openhab:send” I get a command-event:

2024-01-19 11:14:09.817 [DEBUG] [.automation.rules_tools.MQTTEventBus] - Processing an MQTT Event Bus event: ChannelTriggeredEvent
2024-01-19 11:14:09.817 [DEBUG] [.automation.rules_tools.MQTTEventBus] - Processing an event bus event
2024-01-19 11:14:09.817 [DEBUG] [.automation.rules_tools.MQTTEventBus] - Received MQTT EB message: type = command item = testnumber3 state/cmd = 55

But nothing in the logs for a StateEvent or StateUpdateEvent.

Same is for incoming, that works, but no debug log entry.

If there is nothing at all, your rule trigger is messed up. You should at least get Processing an MQTT Event Bus event: log every time the rule is triggered with any sort of event. Otherwise you get
MQTT Event Bus rule triggered without event, ignoring. But either way, you get at least one of those logs when the rule triggers.

No logs at all means the rule isn’t triggering.

I agree, I wondered about that.
The default trigger is “When a member of a group receives a command”, which explains it.
An update is not a command, therefore it does not trigger.
When I change it to “When a member of a group was updated”, something bigger gets messed up.

2024-01-19 11:47:56.538 [ERROR] [b.automation.script.javascript.stack] - Failed to execute script:
org.graalvm.polyglot.PolyglotException: TypeError: undefined has no such function "toString"
        at <js>.pubEvent(<eval>:42) ~[?:?]
        at <js>.:program(<eval>:58) ~[?:?]
        at org.graalvm.polyglot.Context.eval(Context.java:399) ~[?:?]
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:458) ~[?:?]
        at com.oracle.truffle.js.scriptengine.GraalJSScriptEngine.eval(GraalJSScriptEngine.java:426) ~[?:?]
        at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:262) ~[java.scripting:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.DelegatingScriptEngineWithInvocableAndAutocloseable.eval(DelegatingScriptEngineWithInvocableAndAutocloseable.java:53) ~[?:?]
        at org.openhab.automation.jsscripting.internal.scriptengine.InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.eval(InvocationInterceptingScriptEngineWithInvocableAndAutoCloseable.java:78) ~[?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.lambda$0(ScriptActionHandler.java:71) ~[?:?]
        at java.util.Optional.ifPresent(Optional.java:178) [?:?]
        at org.openhab.core.automation.module.script.internal.handler.ScriptActionHandler.execute(ScriptActionHandler.java:68) [bundleFile:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.executeActions(RuleEngineImpl.java:1188) [bundleFile:?]
        at org.openhab.core.automation.internal.RuleEngineImpl.runRule(RuleEngineImpl.java:997) [bundleFile:?]
        at org.openhab.core.automation.internal.TriggerHandlerCallbackImpl$TriggerData.run(TriggerHandlerCallbackImpl.java:87) [bundleFile:?]
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539) [?:?]
        at java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) [?:?]
        at java.lang.Thread.run(Thread.java:833) [?:?]
2024-01-19 11:47:56.539 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'mqtt_event_bus' failed: org.graalvm.polyglot.PolyglotException: TypeError: undefined has no such function "toString"