Modbus to Unified Namespace: Choosing an Edge Gateway for Brownfield Plants
Most of the machines that will feed your Unified Namespace were commissioned before the term existed. They speak Modbus, they expose a flat table of 16-bit registers with no names, no units and no change notification, and they sit on a two-wire RS-485 bus that was sized for a SCADA poll in 2008. The usual advice is to “put a gateway in front of it and publish to MQTT.” That sentence hides every hard problem: who owns the poll schedule, where register 40017 becomes line2/press07/hydraulic_pressure, and what the namespace says when the meter stops answering.
This article treats Modbus to Unified Namespace as an engineering pipeline rather than a product choice. It matters now because retrofit budgets are real, the gateway market has split into open-source and commercial camps, and a badly modeled namespace is expensive to undo once consumers subscribe to it. You will leave with a polling-budget method, a register-map modeling pattern, a topic design, an honest comparison of the gateway families, and the failure modes that bite in month three.
What this covers: the retrofit pipeline, Modbus protocol limits that govern your design, polling arithmetic, data modeling, gateway comparison, a decision matrix, trade-offs and a rollout checklist.
Context and Background
A Unified Namespace (UNS) is a single, hierarchical topic space on an MQTT broker in which every producer publishes the current state of the business and every consumer subscribes to what it needs. If the concept is new, start with our reference piece on Unified Namespace architecture for industrial IoT; for the transport choices around it, see OPC UA FX versus MQTT Sparkplug B for a Unified Namespace. Greenfield equipment increasingly arrives with OPC UA or native MQTT. Brownfield equipment does not, and in most discrete and process plants the long tail of meters, drives, temperature controllers, soft starters, flow computers and small PLCs speaks Modbus.
Modbus is attractive for retrofit precisely because it is primitive. The Modbus Application Protocol specification (version 1.1b3, published at modbus.org) defines a client-server request-response model with a handful of function codes: read coils (01), read discrete inputs (02), read holding registers (03), read input registers (04), and the write counterparts. Addresses run from 0 to 65535 in the protocol data unit, and a device is addressed by a one-byte unit identifier on serial lines. That simplicity is why nearly every instrument vendor implemented it, and why we have a protocol guide on this site: see our complete Modbus protocol guide for framing, CRC and function-code detail. This article assumes you know those basics and focuses on what changes when the consumer is a namespace rather than a SCADA screen.
The retrofit problem has three characteristics that greenfield thinking misses. First, Modbus is poll-only. There is no subscription, no event and no timestamp from the device. Any “publish on change” behaviour in your namespace is manufactured by the gateway comparing successive polls. Second, the register map is the only schema. Meaning lives in a PDF manual: which registers hold a 32-bit float, in which word order, with which scale factor, and whether the address in the manual is one-based. Third, the physical bus is the scarce resource. A serial RS-485 segment carries one transaction at a time, so every consumer that wants data competes for the same few hundred milliseconds of airtime per device.
The incumbent approach is a SCADA or OPC server that polls everything and exposes tags northbound. SCADA platforms handle this well, and if you already run one, the comparison in our Ignition versus Wonderware versus FactoryTalk SCADA guide is relevant to whether the SCADA server should double as your Modbus edge. The newer approach, and the subject here, is to place a small gateway at the edge that owns the polling, applies a model, and publishes into the broker so that SCADA, historian, MES and analytics all become peers subscribing to the same topics. Neither is universally right. The rest of this article gives you the means to choose.
The Modbus-to-UNS Retrofit Pipeline: Reference Architecture
Direct answer: a Modbus-to-UNS retrofit has five stages: physical access (RS-485 or Ethernet), a single polling owner that reads register blocks on a fixed schedule, a decoding and modeling layer that turns raw registers into typed, scaled, named metrics with quality, a publish layer that applies deadband and heartbeat rules, and an MQTT broker whose topic tree follows an ISA-95 style hierarchy. The gateway owns stages two to four.

Figure 1: The five-stage Modbus to Unified Namespace retrofit pipeline. The gateway is the only component that talks Modbus; everything northbound consumes the namespace.
Figure 1 shows the shape. Field devices sit on one or more serial segments or on the plant Ethernet. A protocol converter or the gateway’s own serial port exposes them. The gateway runs a poll scheduler, a decoder, a publisher and a local buffer. Northbound, a broker holds the namespace, and consumers such as SCADA, historian, MES and dashboards subscribe. The critical architectural rule is one polling owner per device. If the SCADA server and the gateway both poll the same drive over the same RS-485 bus, you have doubled the traffic and created timing interference that neither side can see.
Stage 1: Physical access
On serial, you have RS-485 two-wire multidrop running RTU framing. On Ethernet, you have Modbus TCP, or RTU over TCP when a serial-to-Ethernet converter tunnels raw RTU frames. These are not the same. Modbus TCP wraps the PDU in a seven-byte MBAP header and drops the CRC because TCP provides integrity; the specification’s maximum TCP ADU is 260 bytes (253-byte PDU plus the header). RTU over TCP keeps the serial frame, address and CRC intact inside a TCP stream. Gateways and drivers treat them as distinct transports. Ignition’s Modbus drivers, for example, list “Modbus TCP,” “Modbus RTU over TCP” and “Modbus RTU” as separate driver types, and Telegraf’s Modbus input likewise supports TCP, RTU over TCP, ASCII over TCP and serial RTU or ASCII. Picking the wrong one is the single most common reason a retrofit “connects but returns garbage.”
Stage 2: The polling owner and scheduler
The scheduler converts a list of desired metrics into a set of read requests. Good schedulers coalesce adjacent registers into blocks, respect the protocol maximums, and stagger devices so one slow responder does not stall the whole cycle. The protocol limits are fixed by the specification: a single read of holding registers (function 03) returns 1 to 125 registers, and a single read of coils or discrete inputs returns up to 2000 bits. These numbers appear as defaults in real products: Ignition documents 125 as its default maximum holding registers per read and 2000 for coils and discrete inputs, and Telegraf exposes max_word_registers_per_request style workarounds for devices that do not honour the full limit. Many field devices support fewer than 125 per request, so the safe design treats 125 as a ceiling and the device manual as the truth.
Stage 3: Decoding and modeling
Raw registers become metrics here. A metric definition carries a register address, a register type, a data type, a byte and word order, a scale factor and offset, an engineering unit and a name. This is the most valuable artifact in the whole project, and it should live in version control as data, not be buried in a GUI. We return to it in depth below.
Stage 4: Publish rules
The publisher decides what goes onto the broker and when. Because Modbus gives no change events, the gateway implements report by exception itself: it compares the new decoded value against the last published value, publishes if the difference exceeds a deadband, and additionally publishes a heartbeat at a slow interval so that a silent topic can be distinguished from a stable value. We treat this as the “publish clock,” separate from the “poll clock.”
Stage 5: The namespace
The broker holds the namespace. Topics follow an ISA-95 style path of enterprise, site, area, line and cell, with device and metric leaves beneath. Retained messages give late-joining consumers the current state. A device-level status topic, backed by the MQTT last will and testament mechanism for gateway death and by explicit quality fields for device death, tells consumers whether the value they are reading is alive.
Three clocks, one thesis
The perspective we want you to leave with is that a retrofit has three independent clocks that are routinely conflated. The poll clock is how often the gateway reads the device, bounded by bus physics. The publish clock is how often a value is emitted to the namespace, governed by deadband and heartbeat. The quality clock is how long a value may go without confirmation before it is declared stale. Most failed retrofits set one number, “1 second,” and assume it governs all three. It does not, and the consequences of that confusion are the bulk of the failure modes later in this article.

Figure 2: One poll cycle. The poll clock runs unconditionally; the publish clock is derived from deadband and heartbeat rules; the quality clock flags a value as stale when polls fail.
Figure 2 traces a single device through a cycle. The gateway sends a block read, receives registers, decodes and scales them, evaluates the deadband against the last published value, and publishes only when warranted. If the read times out, nothing new is decoded, but the quality state must still change: the gateway publishes a bad-quality marker after a configured number of consecutive failures. That last step is the one most home-grown flows omit.
Deeper Analysis: Polling Budgets, Register-Map Modeling and Gateway Families
Polling budget arithmetic (illustrative)
The numbers below are illustrative arithmetic from first principles, not measurements from any specific device. Real devices add turnaround latency that varies from a few milliseconds to over a hundred. Use the method, then replace the assumptions with a capture from your own bus.
On RTU, each character is transmitted as 11 bits when using 8 data bits, an even parity bit, one start and one stop bit. A function 03 request is 8 bytes: unit address, function code, start address (2), quantity (2) and CRC (2). The response is 5 bytes of overhead (address, function, byte count, CRC) plus 2 bytes per register. Reading 40 registers therefore costs 8 bytes out and 85 bytes back, or 93 bytes on the wire.
At 9600 baud, 93 bytes times 11 bits is 1,023 bits, which takes about 106.6 ms. The RTU framing rule requires a silent interval of at least 3.5 character times between frames; at 9600 baud that is roughly 4 ms, and you pay it at least twice per transaction, so call it 8 ms. Assume, as an illustrative figure, 15 ms of device turnaround. A single 40-register read is then about 130 ms.
Now put 12 identical drives on one bus, each polled for 40 registers. A full scan is 12 times 130 ms, roughly 1.56 seconds. That is the floor for your poll clock at 9600 baud with this register count, and it is a floor, not a target: retries, a single slow device, or a consumer that adds its own reads all push it up. At 19200 baud the transmission portion halves; at 115200 baud, the same transaction transmits in about 9 ms, and the specification fixes the silent interval at 1.75 ms above 19200 baud, so a transaction is nearer 28 ms and the 12-device scan lands near a third of a second. Slave devices often cap their supported baud rate, and a bus runs at the speed of its slowest member, so verify before promising anything.
Modbus TCP changes the arithmetic. The request is 12 bytes (7-byte MBAP header plus 5 bytes of PDU) and the response 9 plus 2 bytes per register, so the same 40-register read is about 101 bytes, trivial on Ethernet. The limit moves from airtime to the device itself: embedded Modbus TCP servers commonly accept only a small number of simultaneous connections, and their register-service loop may run at the PLC scan rate. This matters for brownfield politics: if the SCADA server already holds the device’s only connection, your gateway may be refused. Check the device manual for its maximum connection count rather than assuming.
Two design consequences follow. Block reads beat single-register reads because the per-transaction overhead of 8 request bytes, 5 response bytes, two silent intervals and the turnaround dwarfs the cost of extra registers. Reading 40 registers costs only about 3.3 times what reading 1 register costs in this model (about 130 ms against about 40 ms), so a contiguous block, even with some unused registers in it, is cheaper than ten scattered reads. Telegraf’s Modbus plugin makes the same trade explicit with its request-optimization options (shrink, rearrange, max_insert), where max_insert fills holes between wanted registers up to a limit so that fewer requests are issued. Second, tier your metrics: put the 5 registers that matter at 250 ms into one fast group and the 60 registers that matter at 10 seconds into a slow group, instead of polling everything at the fastest required rate.
Report by exception does not reduce bus load
A persistent misunderstanding in UNS retrofit proposals is that report-by-exception (RBE) saves bandwidth on the field bus. It does not. The gateway still polls at the poll clock; RBE only reduces what travels to the broker. On a plant LAN, MQTT traffic is rarely the constraint, but broker fan-out, cloud bridge egress and historian write volume are. RBE earns its keep northbound.
Deadband design deserves care. An absolute deadband of 0.5 on a temperature in degrees Celsius is sensible; the same absolute deadband on a power reading that spans 0 to 400 kW is meaningless. Use per-metric deadbands in the model, add a time-based heartbeat so a flat signal is distinguishable from a dead one, and consider publishing on state transitions (run, stop, fault) unconditionally. Counters and totals, such as energy in kilowatt-hours, should usually be published on a time basis rather than a change basis, because their value is monotonic and every poll “changes.”
Register-map modeling
A register map entry should capture everything needed to turn two bytes into a trustworthy number. Consider this illustrative entry in YAML, which any of the gateways below can be generated from or configured with equivalent fields:
device: press07_meter
transport: rtu # rtu | tcp | rtu_over_tcp
unit_id: 17
base_topic: acme/pune/pressshop/line2/press07
metrics:
- name: voltage_l1
register_type: holding # holding | input | coil | discrete
address: 4096 # PDU address, zero-based
data_type: uint16
scale: 0.1
unit: V
poll_group: fast # 250 ms
deadband: 0.5
- name: active_power
register_type: holding
address: 4112
data_type: float32
word_order: CDAB
unit: kW
poll_group: fast
deadband: 0.2
- name: energy_total
register_type: holding
address: 4200
data_type: uint32
scale: 0.01
unit: kWh
poll_group: slow # 10 s
publish: interval # time-based, not change-based
Four traps live in this table. Addressing base: the Modbus data model numbers items from 1, mapping to PDU addresses from 0, and manuals mix conventions; “register 40017” in a manual is usually PDU address 16 for holding registers under the traditional 4xxxx notation, but some vendors list PDU addresses directly. Ignition exposes a zero-based addressing option precisely because “some Modbus implementations” require it, and Telegraf has a read_coils_starting_at_zero workaround. Word and byte order: a 32-bit value spans two 16-bit registers and the protocol does not say which word is first. Telegraf documents four orders, ABCD, DCBA, BADC and CDAB. As a worked example, the IEEE 754 single-precision value 25.0 is the 32-bit pattern 0x41C80000. A device that sends registers 0x41C8 then 0x0000 is big-endian ABCD. A device that sends 0x0000 then 0x41C8 is word-swapped CDAB, and decoding it as ABCD yields the 32-bit pattern 0x000041C8, which is a denormal number near 2.4e-41, effectively zero, and the bug looks like a dead sensor rather than a decoding fault. Scaling: many instruments transmit integers with an implied decimal (2315 meaning 231.5 V); the scale lives only in the manual. Signedness and sentinel values: some devices return 0x7FFF or 0xFFFF for “sensor fault,” which will faithfully become a 65535 degree reading if the model has no sentinel rule.
Treat every register map as code: review it, test it against a recorded capture, and keep the vendor manual page reference in a comment. A commissioning test that compares the gateway’s decoded value to the device’s front-panel display, for at least three distinct values per metric, catches almost every word-order and scaling error.
Topic and payload design
The topic tree should follow the plant’s ISA-95 style equipment hierarchy rather than the network topology or the gateway vendor’s default. A workable pattern is enterprise/site/area/line/cell/device/metric, with the retained messages for current values and a sibling status subtopic for health. Keep levels lowercase, avoid spaces and wildcard characters, and avoid encoding units or data types in topic names. Payloads should be small JSON documents with a value, a UTC timestamp assigned by the gateway at poll time, and a quality flag. Because Modbus provides no source timestamp, the timestamp is the time the gateway read the register, and the namespace should say so, preferably in a documented payload field rather than leaving consumers to assume device time.

Figure 3: An ISA-95 style topic tree for a retrofitted press line. Each device has a status branch and a metrics branch; modeled names replace raw register addresses.
Figure 3 shows the shape. Notice that raw register addresses never appear in topics. The whole point of the modeling layer is that consumers see hydraulic_pressure, not HR4112, so that replacing the meter with a different model changes only the gateway’s register map, not any subscriber. If your organisation intends to use Sparkplug B rather than plain MQTT topics, our comparison Sparkplug B versus plain MQTT topics covers the state-management and birth-certificate trade-offs; the key retrofit point is that Sparkplug gives you device birth and death semantics for free, while plain topics make you build the status branch yourself.
Gateway families compared
Six families cover almost every brownfield deployment. The facts below come from vendor and project documentation read for this article; where we could not verify a claim we say so.
Node-RED with the community Modbus package. The node-red-contrib-modbus package (BSD-3-Clause, version 5.60.2 on its repository when we checked, requiring Node.js 22 or newer and Node-RED 4 or newer) offers read, getter, flex-getter, write, flex-write, queue-info and flex-connector nodes covering function codes 1 to 4 for reads and 5, 6, 15 and 16 for writes, over TCP and serial. Its strengths are speed of prototyping and visibility. Its weakness for production is that polling logic, modeling and deadband become hand-built flows, which do not diff or review well, and unreliable-connection threads recur in the Node-RED community forum. Use it for pilots and small, well-understood sites, and monitor the queue-info node.
Ignition with MQTT modules (Cirrus Link) or Ignition Edge. Ignition’s OPC UA module ships Modbus TCP, RTU over TCP and RTU drivers with documented defaults (125 holding registers per read, 123 per write, 2000 coils), a reverse-word-order switch and a retry count. Modbus devices do not support browsing, so tags are defined by address. Publishing to MQTT is done through the separately licensed Cirrus Link modules; we did not re-verify current module names and licensing for this article, so check with the vendor. This is the natural choice when Ignition is already the plant’s SCADA, because the Modbus owner, tag model and UI are one system. The cost is a heavier runtime at the edge and platform licensing.
Kepware KEPServerEX. PTC’s Kepware offers a Modbus Ethernet driver and a wider suite for serial and device-specific variants, with an MQTT agent and an IoT gateway option for publishing northbound. We could only confirm the driver’s existence from the vendor listing in this research pass; function-code coverage, block-size controls and the current packaging of the MQTT interface should be confirmed against the current manual. Kepware is common in plants that already standardised on it for many protocols, and its strength is breadth and long track record with oddball devices. It is commercial and typically licensed by tag count or driver.
EMQX Neuron. Neuron is positioned as an industrial connectivity server supporting, per the vendor, more than 70 industrial protocols including Modbus, with outputs to MQTT, Sparkplug B, OPC UA, Kafka or HTTP, a sub-50 MB footprint and 100 ms collection frequency as marketing figures. A free version is available with enterprise options for production; the specific boundary between them should be read from the licence terms. Neuron fits the retrofit shape well because it is a purpose-built poll-to-MQTT bridge with a configuration UI and no SCADA dependency.
HiveMQ Edge. HiveMQ Edge is a software MQTT gateway with pre-built adapters including Modbus, OPC UA, Siemens S7, BACnet and EtherNet/IP, available as an open-source edition and a commercial edition activated by licence key. Per HiveMQ’s product page, offline buffering and the data policy engine are commercial features, while local filtering and combining happen at the edge. It is attractive if your broker is already HiveMQ and you want gateway and broker managed together.
Telegraf (and similar open-source pipeline tools). Telegraf’s Modbus input is the most thoroughly documented in this list: TCP, RTU over TCP, ASCII over TCP and serial; four register types; four byte orders; many data types including FLOAT32-IEEE, INT64 and STRING; request optimisation; pause_between_requests and pause_after_connect for slow devices; and three configuration styles (register, request, metric). It publishes to MQTT through its MQTT output, and the entire configuration is a text file under version control, which suits infrastructure-as-code teams. It lacks a built-in deadband and quality model, so you add processors or a downstream stage. Other pipeline tools can fill the same slot, but we could not confirm a Modbus input in Redpanda Connect (formerly Benthos) documentation during this run and do not claim one. Apache PLC4X is another route, covered in our PLC4X PLC-to-MQTT tutorial.
Decision matrix
| Criterion | Node-RED | Ignition plus MQTT modules | Kepware | EMQX Neuron | HiveMQ Edge | Telegraf |
|---|---|---|---|---|---|---|
| Best fit | Pilot, small site | Plant already on Ignition | Mixed legacy protocols | Dedicated poll-to-MQTT bridge | HiveMQ broker shops | Config-as-code teams |
| Modbus transports | TCP and serial | TCP, RTU over TCP, RTU | Ethernet driver confirmed; serial variants unverified here | Modbus supported; variants not verified here | Modbus adapter | TCP, RTU over TCP, ASCII over TCP, serial |
| Modeling and deadband | Hand-built in flows | Tag model, UI | Tag model | Built-in functions per vendor | Data policy engine is commercial | Manual via processors |
| Licence posture | BSD-3-Clause package | Commercial | Commercial | Free plus enterprise | Open source plus commercial | Open source |
| Edge footprint | Moderate | Heavy | Moderate to heavy | Light per vendor | Moderate | Light |
| Main risk | Maintainability | Licence and weight | Cost and lock-in | Edition boundaries | Commercial feature gating | No built-in quality model |
Read the matrix as a starting filter, not a verdict. The biggest differentiator is not any protocol feature, since all of them can read a holding register. It is who maintains the model and the poll schedule after the integrator leaves. A GUI-driven product with a tag model suits a controls team; a text-configured pipeline suits a platform team. Pick the one your actual maintainers will keep alive.

Figure 4: A decision flow for picking a Modbus edge gateway. Existing SCADA estate and maintainer skills decide more than protocol coverage does.
Figure 4 encodes the same reasoning as a flow: start from whether a SCADA platform already owns the plant, then from who will maintain the configuration, then from licence tolerance. The terminal nodes are families, not products, because the facts that separate products change faster than this article can.
Trade-offs, Gotchas, and What Goes Wrong
Stale retained values are the namespace’s worst lie. MQTT retained messages persist after the publisher stops. If a meter dies and the gateway simply stops publishing, every consumer that subscribes sees the last good value, forever, with no indication of age. The fix is a quality field in the payload, a per-device status topic updated on consecutive poll failures, and consumer-side age checks against the gateway timestamp. The gateway’s MQTT last will and testament message covers the case where the gateway itself dies, but it says nothing about a single dead device behind a live gateway. You need both layers.
Two pollers, one bus. Brownfield sites accumulate readers: a SCADA server, a vendor’s monitoring laptop, a power-quality tool. On RTU there is one master by design; a second master collides and produces CRC errors and timeouts that look like cabling faults. Establish single ownership and, if SCADA must keep its link, have the gateway become the only poller and give SCADA the data from the namespace, or use a Modbus TCP converter that explicitly multiplexes clients and measure the added latency.
Silent timeouts shift the schedule. A scheduler that waits for a full timeout on a missing device (say 1 second, times a retry count) can consume more of the cycle than all healthy devices together. In the 12-device example, one absent drive with a 1-second timeout and one retry adds about 2 seconds to a cycle that was 1.56 seconds. Use per-device timeouts, mark a failing device as offline and probe it at a slower back-off interval. Telegraf’s pause_between_requests and Ignition’s retry-count setting exist because slow or flaky devices need breathing room, but they lengthen the cycle in return.
Write-safety is not free. Modbus supports writes (functions 05, 06, 15, 16), and a bidirectional namespace invites someone to publish a setpoint. Writing to a drive or controller from an MQTT topic needs authorisation, range limits, an audit trail and an interlock check that no consumer in your namespace provides by default. For a first retrofit, keep it read-only and say so in the design.
Exception responses are information, not noise. A device that returns an illegal data address exception to a block read is telling you the block spans an undefined register. Gateways that collapse every failure into a generic “bad quality” hide the fix. Log the exception code, and prefer gateways that surface it. Aggressive request optimisation options, such as filling holes between registers, can trigger exactly this on devices with sparse maps, which is why Telegraf offers one_request_per_field and per-request size caps as workarounds.
The model drifts from the device. Firmware updates change register maps. A gateway happily decodes the new layout with the old map and publishes plausible nonsense. Record firmware version in the model, read a device identification register at connect time if the device offers one, and add plausibility bounds (a voltage outside its physical range should flag bad quality, not publish).
Security is thin by default. Modbus has no authentication or encryption in the base protocol; a Modbus TCP device trusts anyone who can reach port 502. The gateway belongs on a segmented OT network, with the broker connection secured by TLS and credentials, and the Modbus segment never routed to the IT network. A Modbus/TCP security specification exists, but support in field devices is rare, so assume your devices cannot use it.
Cost of the “unified” in Unified Namespace. A gateway per cell scales well technically and badly operationally if each has a hand-edited config. Fifty gateways with fifty unversioned flows is not a namespace, it is fifty snowflakes. If your plant is large, the argument for a central, templated configuration generated from a register-map repository is stronger than any feature on the matrix.
Practical Recommendations
Start from ownership, not from product. Inventory every Modbus device with its transport, unit ID, baud rate, supported register ranges, firmware version and maximum simultaneous connections. Decide, per segment, who the single polling owner is. Only then shortlist a gateway family using Figure 4 and the matrix.
For the first site, pick one line or cell with a few dozen metrics and finish the whole pipeline: poll schedule, register map in version control, deadbands, status topics, and a consumer that is actually subscribed. Resist connecting every device first. A complete thin slice teaches you your real turnaround times, the true cost of your word-order mistakes, and whether your payload shape works for the historian and the dashboard team before it is frozen across 500 devices.
Separate the three clocks in configuration and in conversation. Write down the poll interval per group, the deadband and heartbeat per metric, and the stale threshold per device, ideally as a small multiple of the poll interval so that two or three consecutive failures declare a value bad. If someone says “we poll every second,” ask which clock they mean.
Prefer a gateway whose configuration is text or exportable, or generate it from your own register-map repository. Keep the namespace contract (topic pattern, payload fields, quality semantics) in a short document that every integrator signs up to, because the gateway will change and the contract must not. If you use Sparkplug B, decide up front how plain-MQTT consumers will see the data.
Measure before you promise. Capture a few minutes of real bus traffic with a serial analyser or packet capture and compare against the arithmetic in this article. Commission with a front-panel comparison for three values per metric.
Rollout checklist
- Every device has a documented transport, unit ID, baud rate and connection limit.
- One polling owner per device; no second master on any RTU segment.
- Register maps are in version control, reference the manual page, and record firmware version.
- Address base, word order, scale and sentinel values were verified against the device display.
- Poll groups, deadbands and heartbeats are defined per metric; counters publish on a time basis.
- Each device has a status topic and each payload carries quality and gateway timestamp.
- The broker connection uses TLS and credentials; the Modbus segment is isolated.
- The gateway publishes a last will message, and a consumer-side stale check exists.
- The first release is read-only; any write path has authorisation and range limits.
- The namespace contract is written down and reviewed by consumers.
Frequently Asked Questions
Can Modbus publish directly to MQTT without a gateway?
Not in practice. Modbus is a poll-based client-server protocol, and field devices do not implement an MQTT client. Something must act as the Modbus client, read registers on a schedule, decode them and publish. That something can be a SCADA platform with an MQTT module, a purpose-built connectivity server, a software gateway such as HiveMQ Edge or EMQX Neuron, a Telegraf pipeline or a Node-RED flow. A few modern devices embed an MQTT client, but they are exceptions rather than brownfield reality.
Does report by exception reduce load on the Modbus bus?
No. Report by exception is implemented in the gateway by comparing consecutive polls, so the gateway still reads the device at the full poll rate. The saving appears northbound: fewer MQTT messages, less broker fan-out and less historian write volume. To reduce bus load you must reduce the poll rate, merge reads into larger blocks, or move rarely needed registers into a slower poll group. Treat the poll clock and the publish clock as separate settings.
How many registers can I read in one Modbus request?
The Modbus Application Protocol specification allows 1 to 125 registers per Read Holding Registers request and up to 2000 coils or discrete inputs per read. Writing multiple registers is limited to 123 per request. Many devices support less than the protocol maximum, so use 125 as a ceiling and the device manual as the truth. Larger blocks reduce per-transaction overhead, but an undefined register inside a block can make the whole request fail with an exception.
Should I use Sparkplug B or plain MQTT topics for a Modbus retrofit?
It depends on your consumers. Sparkplug B gives you birth and death certificates, a defined payload and state management, which helps the stale-data problem and suits Ignition-centred estates. Plain topics with JSON payloads are easier for generic tools and custom applications but require you to design status and quality yourself. Either works with Modbus because the gateway sits in between. Decide once, document the contract, and avoid running both without a bridging plan.
How do I handle 32-bit and floating-point values across two registers?
A 32-bit value spans two 16-bit registers, and the protocol does not define word order. Devices use big-endian, word-swapped or byte-swapped layouts, usually described as ABCD, CDAB, BADC or DCBA. Check the manual, then verify against the device display. For example, 25.0 as an IEEE 754 float is 0x41C80000; decoding a word-swapped device with the wrong order produces a near-zero number. Capture at least three known values per metric during commissioning.
Is Modbus secure enough to expose to the Unified Namespace?
The base Modbus protocol has no authentication or encryption, so devices should never be reachable from the IT network or the internet. Keep the Modbus segment on an isolated OT network and let only the gateway talk to it. Secure the gateway-to-broker link with TLS and credentials, and use topic-level access control on the broker. A security-enhanced Modbus/TCP specification exists, but few field devices implement it, so plan around network segmentation instead.
Further Reading
- Unified Namespace architecture for industrial IoT: the reference architecture this retrofit feeds.
- OPC UA FX versus MQTT Sparkplug B for a Unified Namespace: choosing the transport semantics north of the gateway.
- Complete Modbus protocol guide: framing, CRC and function codes.
- Ignition versus Wonderware versus FactoryTalk SCADA: whether the SCADA server should be your Modbus owner.
- Ignition 8.1 versus 8.3 migration guide: relevant if you retrofit through Ignition drivers.
- Sparkplug B versus plain MQTT topics: payload and state design choices.
- Apache PLC4X PLC-to-MQTT tutorial: an alternative open-source route.
- Modbus Organization specifications: the primary source for the application protocol.
References
- Modbus Organization, MODBUS Application Protocol Specification V1.1b3, https://modbus.org/docs/Modbus_Application_Protocol_V1_1b3.pdf (PDU and ADU sizes, register and coil read limits, function codes).
- Telegraf Modbus input plugin README, https://github.com/influxdata/telegraf/tree/master/plugins/inputs/modbus (transports, byte orders, optimisation and workaround settings).
- Inductive Automation, Connecting to Modbus Device, Ignition 8.3 documentation, https://docs.inductiveautomation.com/docs/8.3/ignition-modules/opc-ua/opc-ua-drivers/modbus/connecting-to-modbus-device (driver types, default request limits, word order and addressing options).
- EMQX, Neuron industrial connectivity server, https://www.emqx.com/en/products/neuron (protocol coverage, outputs, vendor-stated figures).
- HiveMQ, HiveMQ Edge, https://www.hivemq.com/products/hivemq-edge/ (adapters, open-source and commercial editions).
- BiancoRoyal, node-red-contrib-modbus, https://github.com/BiancoRoyal/node-red-contrib-modbus (node list, licence, version, requirements).
- PTC, Kepware Modbus Ethernet driver, https://www.ptc.com/en/store/kepware/drivers/modbus-ethernet (driver listing only).
By Riju – about
