Modbus and Industrial IoT Gateways

IoTProtocolsEmbedded

Walk into almost any factory, water treatment plant, or building automation closet and you'll find Modbus — a protocol older than most of the engineers maintaining it, still faithfully shuttling register values between PLCs, meters, and drives. The job of an industrial IoT gateway is to stand at the boundary between that world and the modern IP stack: it polls those Modbus devices, turns raw registers into meaningful telemetry, and forwards it to a message broker or cloud where the rest of your system can use it. That translation layer is unglamorous and absolutely critical, because it's where the plant floor meets everything else.

I've written gateway firmware and the edge software that runs on it, and the recurring lesson is that Modbus is easy to read about and full of small, device-specific gotchas in practice. Let me lay out how it works and where it bites.

The Modbus data model in one screen

Modbus exposes four tables, and understanding them removes most of the confusion:

Table Access Type Typical use
Coils Read/Write 1 bit Digital outputs, on/off
Discrete Inputs Read 1 bit Digital inputs, status flags
Input Registers Read 16-bit Sensor readings
Holding Registers Read/Write 16-bit Setpoints, config, most data

Everything is 16 bits. That's the first trap: a temperature, a power reading, or a 32-bit counter doesn't fit in one register, so vendors split values across two (or four) registers — and they don't agree on byte and word order. You'll read a "float" that comes out as garbage until you swap the word order. Every gateway I've built ends up with a per-device configuration for endianness, because there is no universal answer.

RTU vs TCP, and why it matters operationally

Modbus RTU is the serial variant: an RS-485 bus, one master, several slaves addressed by a unit ID, compact binary frames with a CRC. Modbus TCP wraps the same protocol data unit in a TCP packet with an MBAP header and drops the CRC because TCP already guarantees integrity. Functionally they carry the same requests; operationally they behave differently.

On RTU you're managing a shared serial bus — timing, termination resistors, baud rates, and the fact that only one conversation happens at a time. On TCP you get concurrency and standard networking tooling, but you also inherit TCP's connection semantics, which surprise people used to serial. Here's a minimal TCP read in Python to show how little code it takes:

from pymodbus.client import ModbusTcpClient

client = ModbusTcpClient("10.4.2.17", port=502)
client.connect()

# Read 2 holding registers starting at 40001 (address 0), unit/slave 1
rr = client.read_holding_registers(address=0, count=2, slave=1)
raw = rr.registers  # e.g. [17282, 4661]

# Reassemble a 32-bit float; word order is DEVICE-SPECIFIC
import struct
value = struct.unpack(">f", struct.pack(">HH", raw[0], raw[1]))[0]
client.close()

The >HH versus <HH decision in that snippet is where most "wrong readings" bugs live. Read the vendor's register map carefully; when it's ambiguous, brute-force all four orderings against a known value.

Polling strategy is the whole game

Modbus is request-response with no push. The gateway decides what to read, how often, and in what batches, and that polling plan determines both data freshness and bus health. A few hard-won rules:

Once the data is polled and normalized, the gateway's second job is publishing it. I almost always land on MQTT for the northbound side because it fits the intermittent, many-device shape of field telemetry — the reasoning is the same as in MQTT for IoT at scale, where the broker decouples flaky field links from backend consumers. The gateway becomes a Modbus-to-MQTT translator, and suddenly plant-floor data is available to any modern subscriber.

Where the gateway earns its keep

Protocol translation is the headline, but the parts that matter at 3 a.m. are the resilience features:

That last point deserves emphasis. Modbus has zero built-in security: any device on the bus can read or write any register. Treat the fieldbus as fully trusted-internal and let the gateway be the only thing that crosses into the IP world. If you're building the edge stack on top of this — say a Flutter-based HMI or commissioning tool — the same isolation principle carries over, and I've written about that edge tooling in Flutter for embedded and IoT.

The senior take

Modbus is not elegant, and it's not going away. The winning move is to stop wishing it were something better and instead build a gateway that's boringly reliable: careful register maps checked against real devices, a tiered polling plan that respects each bus, store-and-forward that never drops a reading, and hard isolation from the rest of the network. Do that, and a protocol from 1979 becomes a dependable data source feeding a thoroughly modern system — which is exactly the kind of unglamorous engineering that keeps plants running.

Resources

Frequently asked questions

What is Modbus and why is it still everywhere?

Modbus is a simple request-response serial and TCP protocol from 1979 for reading and writing registers on industrial devices like PLCs, meters, and sensors. It persists because it is trivially simple, royalty-free, well-documented, and implemented in virtually every piece of industrial equipment made in the last four decades, which makes it the default lingua franca of the plant floor.

What does an industrial IoT gateway actually do?

An industrial IoT gateway sits between legacy field devices and modern systems, translating protocols like Modbus, BACnet, or Profibus into IP-based transports such as MQTT or HTTP. It polls devices, normalizes their raw registers into meaningful values, buffers data during network outages, and enforces security so field equipment is never exposed directly to the network.

What is the difference between Modbus RTU and Modbus TCP?

Modbus RTU runs over serial lines (RS-485/RS-232) using a compact binary frame with a CRC, typically in a multi-drop bus with one master. Modbus TCP wraps the same data model in TCP/IP packets, dropping the CRC because TCP handles integrity and using an MBAP header instead. RTU is common on older field buses; TCP is common for Ethernet-connected equipment.

Hiring a senior Android / Flutter engineer?

I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.

Get in touch →