The MODBUS_SERIAL route enables communication with industrial devices using Modbus RTU protocol over serial connections (RS-232 or RS-485). It supports the same TAG-based configuration as Modbus TCP but adds serial-specific parameters for baud rate, parity, and data bits.
Modbus Serial (RTU) is commonly used for legacy equipment, long-distance communication, and multi-drop RS-485 networks where multiple devices share a single bus.
DEFINE ROUTE SerialDevice WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM1" WITH BAUD_RATE 9600 WITH PARITY "NONE" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1 ADD MAPPING SensorReadings WITH EVERY 1 SECOND ADD TAG Temperature WITH ADDRESS "100" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "serial/temperature"
Different devices use different serial settings. Here are common configurations:
Standard (Most Common)
Even Parity
High Speed
Linux USB Adapter
ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM1" WITH BAUD_RATE 9600 WITH PARITY "NONE" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1
ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM1" WITH BAUD_RATE 9600 WITH PARITY "EVEN" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1
ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "/dev/ttyUSB0" WITH BAUD_RATE 115200 WITH PARITY "NONE" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1
ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "/dev/ttyUSB0" WITH BAUD_RATE 9600 WITH PARITY "NONE" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1
On Linux, USB-to-serial adapters typically appear as /dev/ttyUSB0, /dev/ttyUSB1, etc.
Create separate routes or use different slave IDs:
DEFINE ROUTE TemperatureController WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM1" WITH BAUD_RATE 9600 WITH SLAVE_ID 1 ADD MAPPING TempController WITH EVERY 1 SECOND ADD TAG Temperature WITH ADDRESS "0" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "modbus/device1/temperature"DEFINE ROUTE FlowMeter WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM1" WITH BAUD_RATE 9600 WITH SLAVE_ID 2 ADD MAPPING FlowMeter WITH EVERY 1 SECOND ADD TAG FlowRate WITH ADDRESS "0" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "modbus/device2/flow"
When sharing a serial port between multiple slave IDs, ensure polling intervals are set to avoid bus collisions. The route handles sequencing automatically, but very fast polling across many devices may cause timeouts.
ADD TAG SensorValue WITH ADDRESS "100" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "serial/sensor" WITH SCALING 0.1 WITH OFFSET 0 WITH UNIT "°C" WITH DEADBAND 0.5 WITH PUBLISH_MODE "JSON" WITH WRITABLE "true" WITH DESTINATION_TOPIC "serial/sensor/set" WITH BYTE_ORDER "BIGENDIAN" WITH WORD_ORDER "BIGENDIAN"
For on-demand Modbus Serial 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.Modbus Serial supports the same EVENT operations as Modbus TCP. See the Modbus TCP Event-Based Operations for the full supported operations table and query parameter details.
DEFINE ROUTE EnergyMeter WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM3" WITH BAUD_RATE 9600 WITH PARITY "EVEN" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1 WITH READ_TIMEOUT 1000 WITH RETRY_COUNT 3 ADD MAPPING Readings WITH EVERY 1 SECOND ADD TAG Voltage WITH ADDRESS "0" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "meter/voltage" WITH UNIT "V" ADD TAG Current WITH ADDRESS "2" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "meter/current" WITH UNIT "A" ADD TAG Power WITH ADDRESS "4" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "meter/power" WITH UNIT "kW"
Read process value and write setpoint:
DEFINE ROUTE TempController WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "/dev/ttyUSB0" WITH BAUD_RATE 9600 WITH PARITY "NONE" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1 ADD MAPPING Control WITH EVERY 500 MILLISECONDS ADD TAG ProcessValue WITH ADDRESS "0" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "INT16" WITH SOURCE_TOPIC "tempctrl/pv" WITH SCALING 0.1 WITH UNIT "°C" ADD TAG Setpoint WITH ADDRESS "1" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "INT16" WITH SOURCE_TOPIC "tempctrl/sp" WITH SCALING 0.1 WITH UNIT "°C" WITH WRITABLE "true" WITH DESTINATION_TOPIC "tempctrl/sp/set" ADD TAG Output WITH ADDRESS "2" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "INT16" WITH SOURCE_TOPIC "tempctrl/output" WITH SCALING 0.1 WITH UNIT "%"
Control a motor drive:
DEFINE ROUTE VFDControl WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM2" WITH BAUD_RATE 19200 WITH PARITY "EVEN" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1 ADD MAPPING DriveStatus WITH EVERY 200 MILLISECONDS ADD TAG ActualSpeed WITH ADDRESS "8451" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT16" WITH SOURCE_TOPIC "vfd/speed/actual" WITH SCALING 0.1 WITH UNIT "Hz" ADD TAG MotorCurrent WITH ADDRESS "8448" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT16" WITH SOURCE_TOPIC "vfd/current" WITH SCALING 0.01 WITH UNIT "A" ADD TAG SpeedReference WITH ADDRESS "8502" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT16" WITH SOURCE_TOPIC "vfd/speed/reference" WITH SCALING 0.1 WITH UNIT "Hz" WITH WRITABLE "true" WITH DESTINATION_TOPIC "vfd/speed/set" ADD TAG ControlWord WITH ADDRESS "8501" WITH ADDRESS_TYPE "HOLDING_REGISTER" WITH DATA_TYPE "UINT16" WITH SOURCE_TOPIC "vfd/control" WITH WRITABLE "true" WITH DESTINATION_TOPIC "vfd/control/set"
Continuous monitoring with on-demand read and write events in the same route:
DEFINE ROUTE FullSerialSetup WITH TYPE MODBUS_SERIAL ADD MODBUS_CONFIG WITH CONNECTION_TYPE "SERIAL" WITH COM_PORT "COM3" WITH BAUD_RATE 9600 WITH PARITY "EVEN" WITH DATA_BITS 8 WITH STOP_BITS "ONE" WITH SLAVE_ID 1 ADD MAPPING ProcessReadings WITH EVERY 1 SECOND ADD TAG Voltage WITH ADDRESS "0" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "meter/voltage" WITH UNIT "V" ADD TAG Current WITH ADDRESS "2" WITH ADDRESS_TYPE "INPUT_REGISTER" WITH DATA_TYPE "FLOAT" WITH SOURCE_TOPIC "meter/current" WITH UNIT "A" ADD EVENT ReadRegisters WITH SOURCE_TOPIC "serial/commands/read" WITH DESTINATION_TOPIC "serial/responses/read" WITH QUERY "{operation: READ_HOLDING_REGISTERS, start_address: 0, count: 10}" ADD EVENT WriteRegister WITH SOURCE_TOPIC "serial/commands/write" WITH DESTINATION_TOPIC "serial/responses/write" WITH QUERY "{operation: WRITE_SINGLE_REGISTER, address: 100, value: 0}"
The MAPPING continuously reads voltage and current. To trigger an on-demand register read, publish any message to serial/commands/read. To write, publish to serial/commands/write.