MQTT: isCommand loop and single topic for states/commands

Use case: i want items to report their state to a single MQTT topic, and update their state when receiving commands from other clients. For example, a bulb which sends its current state every 60 seconds, but with 4 people who are able to send commands to that topic to change the color.

Let’s say the topic is: bulbs/01/color and i have CLIENT_A, CLIENT_B, CLIENT_C, and CLIENT_D. OpenHAB is CLIENT_A.

In the MQTT binding, i have a generic MQTT thing (“MQTT Transmitter”) which connects to a remote Mosquitto MQTT broker. Inside that there is a channel (“Bulb 01 Color Signal”) which follows a linked Item bulb_01_color.

MQTT State Topic: bulbs/01/color/state
MQTT Command Topic: bulbs/01/color/command

In the overview, it says:

Let’s assume there is an MQTT capable light bulb.

It has a unique id amongst all light bulbs, say “device123”. The manufacturer decided to accept new brightness values on “device123/brightness/set”. In openHAB we call that a command topic.

And now assume that we have a mobile phone (or openHAB itself) and we register with the MQTT broker, and want to retrieve the current brightness value. The manufacturer specified that this value can be found on “device123/brightness”. In openHAB we call that a state topic."

Easy enough. The device subscribe to new brightness values on /set and publishes values on /brightness.

The State topic guidance says

“An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.”

So the State topic is being subscribed to, i.e. receives INBOUND messages.

The Command topic guidance says

“An MQTT topic that this thing will send a command to. If not set, this will be a read-only switch.”

The Command topic is a publisher, i.e. sends OUTBOUND messages.

This seems to be the opposite of the way it’s set up in the MQTT thing.

When OpenHAB (CLIENT_A) makes a change through a command (e.g. ON/OFF), it will publish ON to the Command topic (i.e. “here is a command received through PaperUI”). I need the bulb to report ON to the State topic immediately afterwards.

Then, CLIENT_B, (or C, or D) a totally different command line client (say mosquitto_pub) wants to send a change. If you send it to the Command topic, it doesn’t update. If you send it to the State topic, it doesn’t update either.

So following on from that, if you tick isCommand and publish the update to the State topic, it will change the bulb’s state. It acts on messages it subscribes to (i.e. treats them as a “write” command).

The guidance says:

“If the received MQTT value should not only update the state of linked items, but command them, enable this option.”

What’s the difference between updating a linked item, and commanding it? Does updating the OpenHAB item’s state send a command to the physical device?

Here’s the problem: i don’t want to use 2 topics. I’d like one single sync topic: bulbs/01/color . Ticking isCommand places the entire thing into an infinite loop. When the item is given a command (e.g. changing it in PaperUI), it will publish it to the topic, and the MQTT subscriber binding (state topic) will interpret it as a command, thereby generating another publish message as a command, which the State topic will treat as a command, which then generates another command, and so on. You have an infinite loop where subscribing and publishing gets messed up. It doesn’t seem to differentiate between clients.

The terminology is incredibly confusing here.

I need OpenHAB to:

  • subscribe to incoming commands on an MQTT topic (e.g. from external clients)
  • publish all internal commands received on an MQTT topic (e.g. from PaperUI)
  • publish all outgoing state changes to a topic, regardless of how they were triggered.

How is this supposed to work with isCommand? Is there a way to do this without duplicating channels in the MQTT Thing?

Use different topics for state and command.

So if you want to set the colour from any device use one topic then the bulb will set the state to a different one.

Yeh, i think the terminology here isn’t too helpful. For anyone else encountering this problem, this is how i solved it after a few hours of banging my head against the desk.

The context here is in remote controlling OpenHAB, and isCommand is ON.

State Topic - this is the incoming topic the MQTT Thing SUBSCRIBES to, and receives state UPDATE requests on. Other clients publish commands into this channel and the binding will treat them as a “todo” list. The binding LISTENS to this topic and processes the message it receives as “commands”.

Command Topic - this is the outgoing topic where the MQTT Thing PUBLISHES changes to which have happened on a device or been requested through PaperUI or the API.

So it gets a bit odd. For the example above:

State Topic: (Should be named “Subscription Topic”)

bulb/01/power/command - other clients publish what they want to happen here. Could also be called “todo”, “commands”, “todo”, “receive” etc.

Command Topic (Should be named “Publish Topic”)

bulb/01/power/state - OpenHAB publishes state changes and commands processed/sent here. Could also be called “done”, “sent”, “processed” etc/

Ideally we would all use the one convention or standard.

I like this one

With MQTT you subscribe to a topic this tells the MQTT Broker “Hey I interested in this send me everything when anything is published to this topic”

You topic can be anything and you can call it Geoff for all I care.

Now to help combat the two generals problem of programming.

The MQTT binding designed by smarter people than I use the 2 topics state and command.

The device that is being controlled publishes its state to the state topic.

If anything wants to control that device it publishes to the command topic.

If openHAB subscribes to a state topic “Geoff” and wants to tell your device that the state has changed of an item it would publish to that state topic. If openHAB wants to change the state of your device it would publish to the command topic. Either way it could be confusing in different contexts.

The device that is being controlled publishes its state to the state topic.
If anything wants to control that device it publishes to the command topic.

That’s definitely what i was trying to achieve, but after a day of testing it, it works the opposite. Quick method to reproduce is to attach a device, let’s say a speaker (in my example). Set up 2 topics (command, and state). Move the volume up and down: the changes go into the “command” topic, and if you want to do it via MQTT, you have to send values to the “state” topic with the isCommand switch ticked.

Yes in openHAB you send a command to the speaker on the command topic to the device.

The device/speaker reports that its state has changed to openHAB on the state topic.

You are not commanding openHAB as it is not the device.

You could use another client to sent a command then the speaker will change the state topic reporting back to openHAB “Hey someone else set my volume to 32”

Right. So the device changes and the device publishes that new state on the state topic. openHAB subscribes to that state topic so it knows the state of the device. This is the state topic in the Thing configuration.

For this openHAB wants to send a command to the device. openHAB is publishing a message to the device in response to this command. This is the command topic in the thing configuration.

I assume by “move the volume up and down” you are talking about changing the state of an openHAB Item. So the Item receives a command to change the volume. That command goes to the binding and gets published on the command topic as configured in the Thing. The command topic is used when openHAB is commanding a device to do something.

Now you change the volume outside of openHAB. openHAB needs to keep track of that change i state. So when the device changes state, it publishes it’s new state to the state topic. openHAB sees that message and updates the Item to reflect the new state of the device.

Sometimes, you want openHAB to be the device that is being commanded. That’s rare but not unheard of. In those rare cases you would toggle on the “is command” toggle. When that happens, instead of updating the Item the binding will send a command to the Item.

It’s not working the opposite. I think you are understanding it backwards. The two topics configured on the Channel are from openHAB’s perspective with openHAB controlling some other device. openHAB is told of the current state of that external device through messages published the state topic from the external device. openHAB tells the device to do something by publishing messages on the command topic. openHAB is commanding the device to do something.

Yep, i’m talking in the context of isCommand being set, so the HAB is being commanded by the remote MQTT broker. I’ve tested it relentlessly (i had to in order to get it working), and i’m not seeing the state updating on the State Topic, only on the Command Topic. I’ve tried to publish commands to the Command Topic, and they are only actioning anything when being received by the State Topic. That makes sense as OpenHAB needs to “listen” to the subscription to know what to do.

I think my point here is that MQTT is a Pub/Sub pattern broker, and the docs need to be a bit clearer in referring to it that way. Commands are published to the broker channel, and States are subscribed to.

Tested how? openHAB subscribes to the state topic. End of story. How are you running your tests?

In order to test commanding openHAB as the “thing being commanded” you would:

  1. configure your Thing channel to subscribe to the topic that the command messages will be sent as the State topic.
  2. Toggle the treat state updates as commands toggle
  3. From something outside of openHAB (e.g. MQTTExplorer) publish a message to that command topic.

The names and descriptions shown in the UI for “State Topic” and “Command Topic” cover the most common use case. But the description should make it clear. openHAB can only receive messages on the State Topic as configured in the Channel. I can only publish messages on the Command Topic as configured in the Channel.

More clear than what’s already there?

For the state topic is says (copied from your original post):

An MQTT topic that this thing will subscribe to, to receive the state. This can be left empty, the channel will be state-less command-only channel.

For the command topic is says:

An MQTT topic that this thing will send a command to. If not set, this will be a read-only switch.

The state topic subscrbes, the command topic sends (i.e. publishes).

Perhaps change “send a command to” to “publishes a message to” might be a little bit clearer, but over all the openHAB docs will present the information and description of things using the openHAB perspective and the openHAB terminology where possible. And from OH’s perspective and in it’s terminology, what it’s doing is commanding the device.

You are free to file an issue (even better a PR with the changes made).

That’s exactly what i’ve been doing, but i just don’t think it’s helpful to do this with terminology when it comes to standard patterns. MQTT is Pub/Sub, and then we have another layer of State/Command which really isn’t too related to what’s actually going on. The language in OpenHAB is so absurdly bland and generic it’s hard to follow it as it is (“Thing”, “Item” etc).

I use MQTT Explorer for my testing and debugging, so i’m manually sending raw input to a topic and watching for changes in PaperUI as well as physically. I’ve got Hue lights and 50 other things set to report their status via MQTT, but it’s important for me to be able to send messages via MQTT - predominantly because a) it’s faster than REST even on a VPN, and b) NAT and firewall issues for incoming comms.

In my context, OH is acting as a “server” by subscribing to commands it is being given by a remote client (i.e. as you correctly say, the “thing being commanded”), and reporting what it has done to other clients. So it’s technically reversed - it subscribes to a “commands” topic, and publishes to a “state” topic.

This is my point about the abstract terminology: i now have “command” in my state topic, and “state” in my command topic - working fine, but it’s a nightmare to explain and debug (particularly when you’re tired). In that configuration, it’s actually subscribing to commands, and publishing states. The use case is easy to imagine: all you need is more than 1 room.

I agree we should change it to TX and RX

That’s because openHAB’s terminology has to work with all sorts of different technologies. Not just MQTT. Every technology has it’s own way of working and it’s own terminology and OH has to provide a way to abstract them all to a coherent layer of abstraction and meaning. It’s really hard to get more specific when that’s the case.

Which is in the minority of uses for Generic MQTT Things. As already mentioned, openHAB being a hub, the vast majority of the time is interacting with and controlling external devices, not being controlled by external devices. We can switch the names around if you want but then those who use the majority of use case for Generic MQTT Things will complain that it doesn’t make sense.

But my point is that in the text that describes what the field is for, already states that the the state topic is subscription and the command topic is publication. Given that text is already there, what would you change to make it more clear that this is what those two fields represent?

If you have any ideas that do not break the understanding of the binding for those who follow the majority use case, an issue or even a PR would I’m sure be welcomed.

1 Like