MQTT publish configuration

Using openhab 3.3.0, and installed MQTT binding, Generic MQTT thing and MQTT broker. Connection to broker (mosquitto) seems to work fine, but if I add a channel to Generic MQTT thing and link an item to it, I’ll only see subscribe messages in the (mosquitto) broker. In this case I would only need to publish values to broker and subscribe is not needed.

Manual wasn’t so clear on this, but for publish to work, do I need to use configuration files or can this be done via UI?

Please show your Thing and Item configurations.

You channel will publish messages to the command Topic that you set, when you send commands to the linked openHAB Item.

Just to answer your specific question, yes, this can be done via the UI. You can even have one Channel that both publishes and subscribes. So, you’ve done something wrong with your config. If @rossko57’s suggestion doesn’t fix it, please do as @hafniumzinc asked and post your config. When doing so, click on the “Code” tab and paste the YAML you find there into a reply using code fences.

```
code goes here
```

ok, here’s my config:

MQTT Broker:

UID: mqtt:broker:1e12072f13
label: MQTT Broker
thingTypeUID: mqtt:broker
configuration:
  lwtQos: 0
  publickeypin: true
  clientid: 74a70906-4f44-43f2-8511-35e53e410edf
  keepAlive: 60
  birthRetain: true
  secure: false
  certificatepin: true
  shutdownRetain: false
  qos: 0
  reconnectTime: 60000
  port: 1883
  host: eclipse-mosquitto
  lwtRetain: true
  enableDiscovery: true
channels:
  - id: Nibe_uplink
    channelTypeUID: mqtt:publishTrigger
    label: MQTT Nibe uplink
    description: ""
    configuration:
      stateTopic: nibe-uplink/frequency

and Generic MQTT thing:

UID: mqtt:topic:1e12072f13:529695a186
label: Generic MQTT Thing
thingTypeUID: mqtt:topic
configuration: {}
bridgeUID: mqtt:broker:1e12072f13
channels:
  - id: MQTT_freq
    channelTypeUID: mqtt:number
    label: MQTT uplink frequency
    description: ""
    configuration:
      retained: true
      min: 1
      qos: 0
      stateTopic: nibe-uplink/frequency
      max: 120

Command topic is deliberately empty, as this is just (read only) sensor value

screenshot of the linked item:

So what are you trying to publish from openHAB, that isn’t working?

Just added one screenshot to that earlier post (so trying to publish a frequency value).

Logs from mosquitto show there’s only subscribe event:

2022-10-07T13:37:49: Received SUBSCRIBE from 74a70906-4f44-43f2-8511-35e53e410edf                                        
2022-10-07T13:37:49:    nibe-uplink/frequency (QoS 0)                                                                    
2022-10-07T13:37:49: 74a70906-4f44-43f2-8511-35e53e410edf 0 nibe-uplink/frequency                                        
2022-10-07T13:37:49: Sending SUBACK to 74a70906-4f44-43f2-8511-35e53e410edf  

Nowhere in your configuration is anything setup to publish the frequency value from openHAB. To publish from openHAB you need to use the command topic, as @rossko57 pointed out.

But isn’t command topic used when you need to change something?

A commandTopic is used to publish. I’m not sure what else we can say.

Ok, if it’s so then I’ll try that. For read-only sensors a bit misleading though…

Werll, openHAB has no idea who or what is subscribed to the topic that it publishes on.

If a channel has no commandTopic, then to openHAB it is read-only channel, since there is no way to publish anything (“write”).

Why are you wanting to publish something to a read-only sensor, are we misunderstanding what you mean by “publish”?

I’m trying to publish a sensor reading (here frequency) from openhab to mosquitto broker, so that other (mqtt) clients can use that value. Not trying to publish to a sensor, if my configuration implies that, then it’s wrong.

Alright, it’s a bit confusing.

Have you got data arriving on one topic and you want to re-publish it on some other topic?
It’s probably sanest to configure separate read and write channels for that, possibly separate Things if the expected sender and recipient are different boxes.

To publish to MQTT, you’ll need to set a commandTopic, and send a command to a linked Item.

You may still have to work out how to turn this frequency sensor reading into an Item command, that rather depends on its its source.

Frequency (and many other values) are actually sourced with using another binding, using a REST API:

What I’m trying here is to “MQTT:fy” all values got from the API.

Okay, so let’s guess that your values end up as Item state updates.

And now, you want to re-transmit that data onto MQTT.
There’s more than one way to do this, but let’s follow one through.

It’s vital that you understand the difference between Item state and Item command.

The MQTT binding won’t publish anything unless you set up a channel with commandTopic.
If you are just publishing, and not reading anything back, that’s all it needs (stateTopic is about receiving MQTT messages). That would be a write-only channel.

So once you have set up that channel, in the ordinary way you would link it to an Item. When you send commands to that linked Item, it triggers the channel to publish.

but

Okay, so let’s guess that your values end up as Item state updates.

you haven’t got commands to your ‘data source’ Items, only state updates. It’s not going to work in the ordinary way.

That’s okay, openHAB provides a special tool called follow profile.
This modifies the channel-to-Item link. In the follow profile case, it modifies it so that Item state changes are sent to the channel as though they were commands. (real commands are ignored for that channel)

So -

Make your ‘write only’ MQTT channel.

You have an Item already linked to the whatever-binding as a data source. now add another link of the same Item to the MQTT channel - but apply the follow profile.

2 Likes

It might be easier to use the MQTT Event Bus.

  1. Create two Groups, one for publishing commands and another for publishing updates
  2. Add all the Items you want to have their updates to that Group
  3. Install and configure the MQTT Event Bus Publisher (I hope it’s clear now that OH is publishing values) rule template (Settings → Automation → Rule Templates).
  4. Instantiate a rule based on that template, selecting your Groups.

That’s it. No MQTT configuration required (beyond setting up the Broker Thing). Which Item’s are publishes and whether commands, updates, or both are published is controlled based on the Group membership.

2 Likes

Thanks! Using commandTopic together with follow profile did the trick, at least now seeing publish events in mosquitto.

I tried this approach as well, but got stuck in rule creation, as after broker thing selection I could not set update/command groups


(nothing is cropped out, last setting is MQTT Broker Thing)

There should be more if you scroll down.

If there isn’t try uninstalling and reinstalling the template or restarting OH or your browser or something. The properties are there and should be rendered. You can double check by going to Developer Tools → API Explorer. Scroll down to the "templates"line and select the /templates/{template_id}, click “try it out” an use rules_tools:mqtt_eb_pubor the UID. The result should match the following.

{
  "label": "MQTT Event Bus Publish",
  "uid": "rules_tools:mqtt_eb_pub",
  "tags": [
    "marketplace:127997"
  ],
  "description": "Publishes all update and command events for members of the configure Group to the event bus.",
  "visibility": "VISIBLE",
  "configDescriptions": [
    {
      "context": "thing",
      "description": "Select the MQTT Broker Thing used for the MQTT Event Bus",
      "label": "MQTT Broker Thing",
      "name": "broker",
      "required": true,
      "type": "TEXT",
      "readOnly": false,
      "multiple": false,
      "advanced": false,
      "verify": false,
      "limitToOptions": true,
      "options": [],
      "filterCriteria": []
    },
    {
      "description": "Name of this openHAB instance, used as the root fo the topic structure.",
      "label": "openHAB Instance Name",
      "name": "topicRoot",
      "required": true,
      "type": "TEXT",
      "readOnly": false,
      "multiple": false,
      "advanced": false,
      "verify": false,
      "limitToOptions": true,
      "options": [],
      "filterCriteria": []
    },
    {
      "context": "item",
      "description": "Group Item whose member's commands are to be published.",
      "label": "Command Group",
      "name": "cmd",
      "required": true,
      "type": "TEXT",
      "readOnly": false,
      "multiple": false,
      "advanced": false,
      "verify": false,
      "limitToOptions": true,
      "options": [],
      "filterCriteria": [
        {
          "value": "Group",
          "name": "type"
        }
      ]
    },
    {
      "context": "item",
      "description": "Group Item whose member's updates are to be published.",
      "label": "Update Group",
      "name": "upd",
      "required": true,
      "type": "TEXT",
      "readOnly": false,
      "multiple": false,
      "advanced": false,
      "verify": false,
      "limitToOptions": true,
      "options": [],
      "filterCriteria": [
        {
          "value": "Group",
          "name": "type"
        }
      ]
    }
  ],
  "triggers": [
    {
      "id": "1",
      "configuration": {
        "groupName": "${cmd}"
      },
      "type": "core.GroupCommandTrigger"
    },
    {
      "id": "2",
      "configuration": {
        "groupName": "${upd}"
      },
      "type": "core.GroupStateUpdateTrigger"
    }
  ],
  "conditions": [],
  "actions": [
    {
      "inputs": {},
      "id": "3",
      "configuration": {
        "type": "application/javascript",
        "script": "if(typeof(require) === \"function\") Object.assign(this, require('@runtime'));\nvar logger = Java.type(\"org.slf4j.LoggerFactory\").getLogger(\"org.openhab.model.script.rules_tools.MQTT_EB\");\n\nvar isState = (event.itemState !== undefined);\nvar topic = \"${topicRoot}/out/\" + event.itemName + ((isState) ? \"/state\" : \"/command\");\nvar msg = ((isState) ? event.itemState : event.itemCommand).toString();\n\nlogger.debug(\"Topic: \" + topic + \" Message: \" + msg + \" Retained: \" + isState);\nvar mqtt = actions.get(\"mqtt\", \"${broker}\");\nmqtt.publishMQTT(topic, msg, isState); // retained true for updates\n"
      },
      "type": "script.ScriptAction"
    }
  ]
}

Pay particular attention to the first section where the properties are defined.