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?
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.
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
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.
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.
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”.
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.
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"