I need to get MQTT "stateTopic" and "commandTopic" values from a Rule

  • Platform information:
    • Hardware: Raspberry Pi 3b
    • OS: Raspbian
    • Java Runtime Environment: Zulu
    • openHAB version: 2.5.1
  • Issue of the topic:

Hi there,
I need to get the value of channels fields associated to a MQTT thing from inside a Rule.
For instance, in this thing inside a MQTT broker bridge:
Thing topic venti_casa “Ventilador_Co” @ “Cocina”{
Channels:
Type switch : VentiSw “VentiladorSW” [ stateTopic=“gw/SWP/RD-ESP01-EFBB/out”, commandTopic=“gw/all/all/in”, on=“On”, off=“Off” , transformationPattern=“JSONPATH:$.OxS” ]
Type string : VentiEv “Evento” [stateTopic=“gw/SWP/RD-ESP01-EFBB/out”, transformationPattern=“JSONPATH:$.LT”]
}

I want to get “stateTopic” and “commandTopic” values from a Rule everytime the switch item state changes.
My question is: what method is available in the item object to get such fields from my rule?

My expectation is to get it like:
val String myStateTopic = ItemId.bound_fileds.getStateTopic()
val String myCommandTopic = ItemId.bound_fileds.getCommandTopic()
… or similar (below is the intended rule)

Thanks
Juan

  • Please post configurations (if applicable):
    • Items configuration related to the issue
    • Sitemap configuration related to the issue
    • Rules code related to the issue

rule “Publish state change”
when
Item VentiSW received command ON
then
val actions = getActions(“mqtt”,“mqtt:broker:pcmiathing”)
actions.publishMQTT(VentiSW.bound_fileds.getCommandTopic().toString(),“ON”,true)

end

  • Services configuration related to the issue
  • If logs where generated please post these here using code fences:

The whole point of Things and Items is that this sort of detail is something you shouldn’t need to do. The whole point is to have a normalized interface to your devices (i.e. Items) that have the same options and same capabilities no matter what binding they are linked to.

Given your example, you should just VentiSW.sendCommand(ON) and the binding will send the command (perhaps transformed) to the MQTT command topic.

So the short answer is you can’t and you shouldn’t.

However, there is one case where Channels are exposed to Rules directly which is with Channel Event Triggers. You can create a Channel on the MQTT Broker Thing to subscribe to the incoming topic and create a Rule that has a Channel trigger. The triggeringEvent will contain a String that can contain both the topic and message received. See MQTT 2.5 Event Bus for an example.

For another approach … why every time? These don’t change. You could set up a look-up table arrangement for topic strings associated with each Item.

If you’re just trying to log MQTT traffic, it might be more effective to use one of the broker interrogating tools like mqtt.fx

Hi, first thanks for the support.

Since I´m new here with your comments I start to realize the purpose of mqtt bindings variables. I was wrongly trying to group switches and make a rule to listen to which member was manually changed and use the stateTopic to identify the switch, and commandTopic to send a JSON payload with the new state.

But this is a wrong design, I need to make clear mqtt topics design hierarchy and simply use the triggeringItem.name to prepare the commandTopic (yes, I´m using mqtt spy for mqtt sniffing). I´ll go through a redesign and let you know.

You can take it one step further. When you sendCommand to an Item linked to an MQTT Channel, a message gets published to the commandTopic. Only in rate cases where you cannot know the command topic ahead of time is the pyblishMqtt Action required.

These are great news. I´ll check

Hi Rich, I tested your recommendation in this way inside my rule:
if(receivedCommand == ON){
val String sendMsg = “{“SId”:”"+triggeringItem.name+",“DId”:“UE*”,“OxS”:""+receivedCommand.toString+"",“Dn”:""+“Dn”+"",“LT”:""+dtime+"",“CMD”:""+“CHG”+"",“TYP”:""+TYP+"",“DxN”:""+“0”+""}"
triggeringItem.sendCommand(sendMsg)
}

I was thinking that any message was permitted in this case. But this is the warn I get:

[WARN ] [rthome.model.script.actions.BusEvent] - Cannot convert ‘{“SId”:"VentiSw,“DId”:“UE*”,“OxS”:“ON”,“Dn”:“Dn”,“LT”:“2020-02-09T21:11:44”,“CMD”:“CHG”,“TYP”:“SW”,“DxN”:“0”}’ to a command type which item ‘VentiSw’ accepts: [OnOffType, RefreshType].

Can you help on any way to send this json string I´m preparing above? Or should I use publishMqtt Action ?

Thanks
Juan

It’s surprisingly difficult to read arbitrary MQTT payloads especially for a rule like
‘if topic payload x/y/z > 80 then do this’
MQTT has no synchronous get data payload content. You need subscriptions with values stored within OH really.

This whole rule is crackers.
Let’s guess the triggering Item is a Switch type,since you’re expecting an ON command.
Sending it some arbitrary string isn’t going to work … it likes ON/OFF commands.
Plus it’s then going to trigger your rule again …

Is there some reason you are trying to avoid the publish action?
Is there some reason you are not just setting up a conventional MQTT Thing?
What are you actually trying to achieve?

Hello. Thanks. Yes , this is a switch. I explained when opening this thread.

Regarding your question, probably was my missinterpretation about Rich’s words above “When you sendCommand to an Item linked to an MQTT Channel, a message gets published to the commandTopic” above. I thought the “message” published was the string in the sendCommand payload. Probably Rich can clarify which is the message published.

Meanwhile I will go back to publishMQTT method. Thanks

What are you trying to achieve?

Maybe a run through of ordinary MQTT sending will help.

You can set up an MQTT Thing with channel, and define a commandTopic.
You can link that channel to an Item.

Now, when you send a command to the openHAB Item, the binding will get it and will publish a message to the MQTT topic you defined.
It uses the command as the basis of the payload.
So for a switch Item, the binding might publish
blah/bleh/rhubarb ON

That would be pretty limited, so the binding allows you to use transformations in various ways.
That allows you to do things like convert ON to {"banana"=22} and use that as the payload instead.

I´m trying to do exactly what you mention " … convert ON to {"banana"=22} and use that as the payload instead."

…before let me tell you the whole story , first I tried to do this with Transformations inside the binding channel but I cannot manage more than ‘state’ variable to prepare de JSON string so that I needed to use Rules to modify several fields and then use publishMQTT.
In the meantime (a few answers above) I was suggested to use sendCommand instead publishMQTT seizing the fact that the message is sent automatically via MQTT.

So my question is, can I use sendCommand to convert the following ==> command ON converted to {“SId”:"VentiSw,“DId”:“UE*”,“OxS”:“ON”,“Dn”:“Dn”,“LT”:“2020-02-09T21:11:44”,“CMD”:“CHG”,“TYP”:“SW”,“DxN”:“0”}
where json field SId=item name, OxS=OHab command, LT=datetime taken from now function, and the rest is fixed or taken from other items ?

Or the only way is using publishMQTT instead?

Thanks

The message is what ever you configure the commandTopic part of the Channel to publish when it receives an ON command.

The whole point of Items and Rules is you shouldn’t have to do anything different for a Switch Item linked to a Zwave switch and another Switch Item linked to MQTT. You send ON and let the binding handle the rest.

It seems like you are trying to have just one Generic MQTT Thing to represent lots of different devices. That isn’t how Things are supposed to work. You should create one Generic MQTT Thing per device, so you wouldn’t need to send the SId as part of the command. Failing that, your only real option is to use the publishMQTT Action in which case you are not using the commandTopic part of the MQTT Thing at all.

You can of course use a String type Item with MQTT channel/Thing.
An Item only has one state, to be sent as payload.
But a string can happen to be a string of JSON or CSV or whatever.

Still don’t know what you’re trying to achieve. Why would the other end care what your openHAB Item name is? Why send a timestamp - the other end knows when it gets the message? It all seemsan unusual approach.

Hi. Every handshake is being logged to a DB for further analysis. That´s why every command and ack needs to be complete. Openhab in this case acts as a dashboard.
Thanks for the support.

Ah, you’re writing your own persistence or logging service.

That´s right!