Identify the Modbus TCP device's IP address and port (default 502), its Unit ID (also called Slave ID or Server ID), and the register map (holding registers, input registers, coils, discrete inputs) from the device datasheet
Use a Modbus TCP client library (e.g., pymodbus in Python) to connect and read registers: connect to the device IP/port, then call read_holding_registers(address, count, unit=<unit_id>); interpret the raw 16-bit register values using the datasheet's data type and scale factor
Implement a polling loop with a configurable interval (e.g., every 5 seconds); handle connection errors and Modbus exception codes (e.g., 0x02 Illegal Data Address, 0x04 Slave Device Failure) with retry logic and exponential backoff
Normalize the polled values (apply scale factors, convert units) and serialize them to JSON; publish to the MQTT broker on a topic like factory/<site>/device/<id>/telemetry at QoS 1
If multiple Modbus devices share the same gateway, serialize requests to avoid collisions; Modbus TCP supports multiple concurrent TCP connections to different Unit IDs but a single device may not handle concurrent requests gracefully
Log Modbus response times and exception rates; persistent exception code 0x06 (Slave Device Busy) indicates the poll interval is too aggressive for the device's processing speed
Known gotchas
Modbus TCP has no built-in authentication or encryption; the gateway should be on an isolated OT network or VPN and not directly exposed to the internet or shared IT networks
Register addresses in Modbus datasheets often use 1-based addressing (register 40001 = address 0 in the protocol); off-by-one errors from address convention confusion are extremely common and produce wrong data without any error indication
Word order (endianness) for 32-bit values spanning two registers varies by device manufacturer and is not standardized in Modbus; always verify byte order and word order empirically against known reference values from the device display or vendor software
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp