The MODBUS_TCP route enables communication with PLCs, RTUs, and industrial devices using the Modbus TCP/IP protocol. It supports reading and writing registers and coils with configurable polling intervals and automatic batch optimization.
Modbus TCP is one of the most widely supported industrial protocols. If your device supports Modbus, this route provides a reliable way to integrate it with MQTT.
DEFINE ROUTE ModbusDevice WITH TYPE MODBUS_TCP ADD MODBUS_CONFIG WITH HOST "192.168.1.100" WITH PORT 502 WITH SLAVE_ID 1 ADD MAPPING SensorReadings WITH EVERY 500 MILLISECONDS ADD TAG Temperature WITH ADDRESS "100" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "modbus/temperature"
ADD MODBUS_CONFIG WITH HOST "192.168.1.100" WITH PORT 502 WITH SLAVE_ID 1 WITH CONNECTION_TIMEOUT 5000 WITH READ_TIMEOUT 1000 WITH WRITE_TIMEOUT 1000 WITH RETRY_COUNT 3 WITH RETRY_DELAY 100
Most Modbus devices use Holding Registers for configuration and Input Registers for measured values. Check your device documentation for the correct address type.
ADD TAG TemperatureSensor WITH ADDRESS "100" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "modbus/sensors/temperature" WITH SCALING 0.1 WITH OFFSET 0 WITH UNIT "°C" WITH DECIMAL_PLACES 2 WITH MIN_VALUE -40 WITH MAX_VALUE 150 WITH DEADBAND 0.5 WITH PUBLISH_MODE "JSON" WITH WRITABLE "true" WITH DESTINATION_TOPIC "modbus/sensors/temperature/set" WITH BYTE_ORDER "BIGENDIAN" WITH WORD_ORDER "BIGENDIAN" WITH DESCRIPTION "Main process temperature sensor"
For on-demand Modbus operations (not polling), use the EVENT syntax. Publish a message to SOURCE_TOPIC to trigger the operation; the route executes it and publishes the result to DESTINATION_TOPIC.
ADD EVENT ReadOnDemand WITH SOURCE_TOPIC "modbus/commands/read" WITH DESTINATION_TOPIC "modbus/responses/read" WITH QUERY "{operation: READ_HOLDING_REGISTERS, start_address: 0, count: 10}"
Read temperature and pressure from a Modbus device:
DEFINE ROUTE ProcessSensors WITH TYPE MODBUS_TCP ADD MODBUS_CONFIG WITH HOST "192.168.1.100" WITH PORT 502 WITH SLAVE_ID 1 ADD MAPPING Sensors WITH EVERY 1 SECOND ADD TAG Temperature WITH ADDRESS "100" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "process/temperature" WITH SCALING 0.1 WITH UNIT "°C" ADD TAG Pressure WITH ADDRESS "102" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "process/pressure" WITH UNIT "bar"
Group TAGs by update frequency:
DEFINE ROUTE PLCConnection WITH TYPE MODBUS_TCP ADD MODBUS_CONFIG WITH HOST "192.168.1.50" WITH PORT 502 WITH SLAVE_ID 1 ADD MAPPING FastLoop WITH EVERY 100 MILLISECONDS ADD TAG MotorSpeed WITH ADDRESS "200" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT16" WITH SOURCE_TOPIC "plc/motor/speed" ADD TAG MotorCurrent WITH ADDRESS "201" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "plc/motor/current" ADD MAPPING SlowLoop WITH EVERY 5 SECONDS ADD TAG TotalRuntime WITH ADDRESS "300" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT32" WITH SOURCE_TOPIC "plc/stats/runtime" ADD TAG FaultCode WITH ADDRESS "400" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT16" WITH SOURCE_TOPIC "plc/status/fault"
Read values and write setpoints:
DEFINE ROUTE ControlSystem WITH TYPE MODBUS_TCP ADD MODBUS_CONFIG WITH HOST "192.168.1.100" WITH PORT 502 WITH SLAVE_ID 1 ADD MAPPING ControlLoop WITH EVERY 500 MILLISECONDS ADD TAG ProcessValue WITH ADDRESS "100" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "control/pv" WITH PUBLISH_MODE "JSON" ADD TAG Setpoint WITH ADDRESS "200" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "control/sp" WITH WRITABLE "true" WITH DESTINATION_TOPIC "control/sp/set" WITH MIN_VALUE 0 WITH MAX_VALUE 100 ADD TAG OutputValue WITH ADDRESS "300" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "control/output"
Read digital inputs and control outputs:
DEFINE ROUTE DigitalIO WITH TYPE MODBUS_TCP ADD MODBUS_CONFIG WITH HOST "192.168.1.75" WITH PORT 502 WITH SLAVE_ID 1 ADD MAPPING DigitalInputs WITH EVERY 100 MILLISECONDS ADD TAG StartButton WITH ADDRESS "0" WITH ADDRESS_TYPE "DISCRETE_INPUT" WITH DATA_TYPE "BOOL" WITH SOURCE_TOPIC "io/inputs/start" ADD TAG StopButton WITH ADDRESS "1" WITH ADDRESS_TYPE "DISCRETE_INPUT" WITH DATA_TYPE "BOOL" WITH SOURCE_TOPIC "io/inputs/stop" ADD TAG RunningLight WITH ADDRESS "0" WITH ADDRESS_TYPE "COIL" WITH DATA_TYPE "BOOL" WITH SOURCE_TOPIC "io/outputs/running" WITH WRITABLE "true" WITH DESTINATION_TOPIC "io/outputs/running/set"
Continuous monitoring with on-demand read and write events in the same route:
DEFINE ROUTE FullModbusSetup WITH TYPE MODBUS_TCP ADD MODBUS_CONFIG WITH HOST "192.168.1.100" WITH PORT 502 WITH SLAVE_ID 1 ADD MAPPING ProcessSensors WITH EVERY 500 MILLISECONDS ADD TAG Temperature WITH ADDRESS "100" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "process/temperature" WITH UNIT "°C" ADD TAG Pressure WITH ADDRESS "102" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "process/pressure" WITH UNIT "bar" ADD EVENT ReadRegisters WITH SOURCE_TOPIC "modbus/commands/read" WITH DESTINATION_TOPIC "modbus/responses/read" WITH QUERY "{operation: READ_HOLDING_REGISTERS, start_address: 0, count: 10}" ADD EVENT WriteSetpoint WITH SOURCE_TOPIC "modbus/commands/write" WITH DESTINATION_TOPIC "modbus/responses/write" WITH QUERY "{operation: WRITE_SINGLE_REGISTER, address: 200, value: 0}"
To trigger the on-demand read, publish any message to modbus/commands/read. The route reads registers 0-9 and publishes the result to modbus/responses/read. To write, publish to modbus/commands/write.