Marketplace MQTT Event Bus

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"

There is one more change required to handle ItemStateUpdatedEvent.

Line 42 in the Script Action needs to be changed to

          var retained = (event.type == 'ItemStateEvent' || event.type == 'ItemStateUpdatedEvent');

There are two Groups: an update Group and a command Group. You shouldn’t change the trigger for the command Group, you should put the Items into the update Group.

That makes sense.
However, it doesn’t matter since var pubEvent isn’t called in the first place.
Were that the case, console.debug('Publishing an event bus event'); would be executed and place a line in the log. That is not happening.

Regarding update/command group: it was my understanding that the update group is the incoming channel (updates from remote instances) and the command channel the outgoing one (issuing commands to remote instances).
Is that not correct?

Since “updates” is a one-way street coming into the system, triggered by the MQTT topic, I don’t see how that can work with outgoing data.

You don’t show the full set of logs, but the stack trace clearly shows it’s coming from pubEvent.

I think you will find that line 42 of the Script Action is the changed line.

No, that’s not correct.

Incoming messages use the topic to match the message to an Item. There is no Group for incoming messages. Both the command Group and the update Group publish messages, the first publishes commands and the latter publishes the updates. Updates are published with the retained flag set to true and to the state topic and commands are published without the retained flag set to the command topic.

That’s the whole reason the rule exists in the first place and why you don’t need to create any separate MQTT Things, just the one Event Channel on the Broker. The Rule does the publishing and a Rule can publish under any circumstances.

Incoming Messages

  1. The MQTT Event Channel on the broker receives the message
  2. The Item name and whether the message is a command or state is parsed out of the MQTT Topic
  3. The message is sent as an update or a command to the Item based on the info parsed out of the comment; a message is logged if the Item doesn’t exist.

Outgoing Commands

  1. A member of ItemCommand Group triggers the rule with the command
  2. The topic to publish the command to is calculated based on the Item name and the rule properties
  3. The command (as a String) is published to that command topic with the retained flag set to false using the MQTT binding’s publishMQTT Action

Outgoing Updates

  1. A member of the ItemUpdate Group triggers the rule with the update
  2. The topic to publish the update to is calculated based on the Item name and the rule properties
  3. The update (as a String) is published to that update topic with the retained flag set to true using the MQTT binding’s publishMQTT Action

I see, thanks for the clarification, I did not find that in the documentation I found.
Sadly, even if I send an update to a local item in the “update” group, it does not trigger the rule.

But as you said, using the Event Bus is probably overkill for my use case, so I defined MQTT things for the items I want published, and linked the channels to the items via follow-channels. That works well.