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:
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.
{
"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.
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.
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.