How to connect Modbus to MQTT

Turning polled registers into MQTT messages: topic design, payload shape, publish rate, quality and what to do when the broker is unreachable.

7 min read · Updated

Modbus is a polled, register-based protocol with no notion of a name or a unit. MQTT is a publish/subscribe transport that carries whatever bytes you give it. Connecting them is less about the plumbing than about the decisions in between.

The pieces

Topic design

Topics are how subscribers find data, and they are hard to change once systems depend on them. A hierarchy from general to specific works best:

A topic per tag
factory/line-1/main-meter/voltage_l1
factory/line-1/main-meter/current_l1
site/{area}/{device}/{tag}
  • Put the fixed parts on the left so a subscriber can use a wildcard: factory/line-1/+/voltage_l1.
  • Avoid spaces, # and + inside a topic segment.
  • Decide early between one topic per tag and one topic per device. A topic per tag suits alerting on a single value; a device payload suits storing a consistent snapshot.

Payload shape

A bare number is tempting and almost always regretted: the subscriber has no idea what unit it is in, when it was read, or whether it is trustworthy.

A payload that survives contact with a consumer
{
  "device": "Main Meter",
  "tag": "Voltage_L1",
  "value": 230.5,
  "unit": "V",
  "quality": "GOOD",
  "timestamp": "2026-03-04T09:21:14.250Z"
}

The timestamp should be when the value was read, not when it was published — they differ after a buffered outage, and a historian that uses the publish time will draw the recovery as a vertical line.

How often to publish

Polling rate and publish rate are different decisions. Poll as fast as the process and the device allow; publish only when there is something to say.

  • On change with a deadband — publish when the value moves by more than a threshold. Best for most analogue values.
  • Periodic — a fixed interval regardless of change. Predictable volume, suits totals and slow values.
  • On change with a heartbeat — publish on change, and at least every N seconds so a subscriber can tell a quiet tag from a dead one.
A deadband suppresses publishing, not polling. The gateway still reads the register at full rate, so a trend or an alarm evaluated locally still sees every sample.

Quality, and not lying about it

When a read fails, the wrong thing to do is publish the last value again, and the second wrong thing is to publish zero. Both are indistinguishable from a real reading. Publish the failure — a null value with a quality of BAD or TIMEOUT — and let the subscriber decide.

When the broker is unreachable

Site links fail. Without buffering, everything measured during the outage is gone. With Store & Forward, messages go to a bounded on-disk queue and replay in order when the broker returns. Bounded matters: an unbounded buffer eventually fills the disk and takes the gateway down with it.

Security

  • Use mqtts:// with TLS. Credentials on a plant network are not private.
  • The connection to the broker is outbound, so the PLC never needs to be reachable from outside.
  • Keep credentials out of configuration files that get copied around; a gateway should hold them in an encrypted store on the machine that runs it.
Edge Gateway

Do this without writing the poller

Topic design, payload shape, publish rate, quality handling and buffering are all configuration in the Edge Logic Editor rather than code you have to own.

How to connect Modbus to MQTT | Modbus Logic