Basic Usage

modpoll2mqtt v2.1.1 - Modbus to MQTT gateway

usage: modpoll [-h] [-v] -f CONFIG [CONFIG ...] [--csv-delimiter {comma,tab}]
               [--no-output] [-r RATE] [-1] [--interval INTERVAL] [--tcp TCP]
               [--tcp-port TCP_PORT] [--udp UDP] [--udp-port UDP_PORT]
               [--serial SERIAL] [--serial-baud SERIAL_BAUD]
               [--serial-parity {none,odd,even}] [--timeout TIMEOUT]
               [-o EXPORT] [--mqtt-version {3.1.1,5.0}]
               [--mqtt-host MQTT_HOST] [--mqtt-port MQTT_PORT]
               [--mqtt-clientid MQTT_CLIENTID]
               [--mqtt-publish-topic-pattern MQTT_PUBLISH_TOPIC_PATTERN]
               [--mqtt-subscribe-topic-pattern MQTT_SUBSCRIBE_TOPIC_PATTERN]
               [--mqtt-diagnostics-topic-pattern MQTT_DIAGNOSTICS_TOPIC_PATTERN]
               [--mqtt-qos {0,1,2}] [--mqtt-rx-queue-size N]
               [--mqtt-user MQTT_USER] [--mqtt-pass MQTT_PASS]
               [--mqtt-use-tls] [--mqtt-insecure]
               [--mqtt-cacerts MQTT_CACERTS]
               [--mqtt-tls-version {tlsv1.2,tlsv1.1,tlsv1}] [--mqtt-single]
               [--mqtt-keys {name-with-unit,name-only}] [--mqtt-retain]
               [--diagnostics-rate DIAGNOSTICS_RATE] [--autoremove]
               [--loglevel {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--timestamp]
               [--delay DELAY] [--framer {default,ascii,rtu,socket}]

Named Arguments

-v, --version

show program’s version number and exit

-f, --config

A local path or URL of Modbus configuration file. Required!

--csv-delimiter

Possible choices: comma, tab

Column delimiter code for Modbus config files (comma, tab). Defaults to comma

Default: “comma”

--no-output

Do not print poll results to stdout (useful under systemd)

Default: False

-r, --rate

The sampling rate (s) to poll modbus device, Defaults to 10.0

Default: 10.0

-1, --once

Only run polling at one time

Default: False

--interval

The time interval in seconds between two polling, Defaults to 0.5

Default: 0.5

--tcp

Act as a Modbus TCP master, connecting to host TCP

--tcp-port

Port for MODBUS TCP. Defaults to 502

Default: 502

--udp

Act as a Modbus UDP master, connecting to host UDP

--udp-port

Port for MODBUS UDP. Defaults to 502

Default: 502

--serial, --rtu

pyserial URL (or port name) for serial transport (alias: –rtu)

--serial-baud, --rtu-baud

Baud rate for serial port. Defaults to 9600

Default: 9600

--serial-parity, --rtu-parity

Possible choices: none, odd, even

Parity for serial port. Defaults to none

Default: “none”

--timeout

Response time-out seconds for MODBUS devices, Defaults to 3.0

Default: 3.0

-o, --export

The file name to export references/registers

--mqtt-version

Possible choices: 3.1.1, 5.0

MQTT version. Defaults to MQTT v3.1.1

Default: “3.1.1”

--mqtt-host

MQTT server address. Skip MQTT setup if not specified

--mqtt-port

1883 for non-TLS or 8883 for TLS, Defaults to 1883

Default: 1883

--mqtt-clientid

MQTT client name, If qos > 0, set unique name for multiple clients

--mqtt-publish-topic-pattern

Topic pattern for MQTT publish. Use {{device_name}} as placeholder for the device names in Modbus config. Defaults to “modpoll/{{device_name}}/data”

Default: “modpoll/{{device_name}}/data”

--mqtt-subscribe-topic-pattern

Topic pattern for MQTT write commands. Use + as placeholder for device name. Defaults to “modpoll/+/set”

Default: “modpoll/+/set”

--mqtt-diagnostics-topic-pattern

Topic pattern for MQTT diagnostics. Use {{device_name}} as placeholder for the device names in Modbus config. Defaults to modpoll/{{device_name}}/diagnostics

Default: “modpoll/{{device_name}}/diagnostics”

--mqtt-qos

Possible choices: 0, 1, 2

MQTT QoS value. Defaults to 0

Default: 0

--mqtt-rx-queue-size

Max MQTT subscribe messages buffered between polls (default: 1000)

Default: 1000

--mqtt-user

Username for authentication (optional)

--mqtt-pass

Password for authentication (optional)

--mqtt-use-tls

Use TLS

Default: False

--mqtt-insecure

Use TLS without providing certificates

Default: False

--mqtt-cacerts

Path to ca keychain

--mqtt-tls-version

Possible choices: tlsv1.2, tlsv1.1, tlsv1

TLS protocol version, can be one of tlsv1.2 tlsv1.1 or tlsv1

Default: “tlsv1.2”

--mqtt-single

Publish each value in a single topic. If not specified, groups all values in one topic.

Default: False

--mqtt-keys

Possible choices: name-with-unit, name-only

MQTT JSON payload key format. “name-with-unit” appends “|unit” when configured (default). “name-only” uses reference names only.

Default: “name-with-unit”

--mqtt-retain

Set the MQTT retain flag on published data messages.

Default: False

--diagnostics-rate

Time in seconds as publishing period for each device diagnostics

Default: 0

--autoremove

Automatically remove poller if modbus communication has failed 3 times.

Default: False

--loglevel

Possible choices: DEBUG, INFO, WARNING, ERROR, CRITICAL

Set log level, Defaults to INFO

Default: “INFO”

--timestamp

Add timestamp to the result

Default: False

--delay

Time to delay sending first request in seconds after connecting. Default to 0

Default: 0

--framer

Possible choices: default, ascii, rtu, socket

The type of framer for Modbus messages. Serial supports ascii/rtu; TCP/UDP use socket.

Default: “default”

The config option is required.

Commandline Usage

  • Connect to Modbus TCP device

    modpoll --tcp 192.168.1.10 --config examples/modsim.csv
    
  • Connect to Modbus serial device

    modpoll --serial /dev/ttyUSB0 --serial-baud 9600 --config contrib/eniwise/scpms6.csv
    
  • Connect to Modbus TCP device and publish data to remote MQTT broker

    modpoll --tcp 192.168.1.10 --config examples/modsim.csv --mqtt-host broker.emqx.io
    
  • Connect to Modbus TCP device and export data to local csv file

    modpoll --tcp 192.168.1.10 --config examples/modsim.csv --export data.csv
    

Configuration File

The configuration file (–config) is a CSV file that defines the devices, pollers, and references to be read.

Coil and discrete input references

On coil or discrete_input pollers:

  • 5,bool reads a single coil/discrete input at Modbus address 5 and publishes one boolean value.

  • 0,bool8 / 0,bool16 read a legacy bit group (8 or 16 booleans). With poll,coil,0,16, group address 1 returns Modbus coil addresses 8–15 (often labeled coils 9–16 in vendor tables). If the poll ends before the full group is read, missing bits are padded with false.

  • address:bit syntax is not supported on coil/discrete_input pollers.

Register bit references

For register references (i.e., Holding or Input registers) with a dtype of bool, you can specify a single bit to be extracted from the 16-bit register. This is done by appending :bit to the address, where bit is an integer from 0 to 15.

  • 40110: Reads the entire 16-bit register at address 40110.

  • 40110:15: Reads the 16-bit register at address 40110, extracts bit 15, and returns a boolean value.

The bit is extracted from the final 16-bit value after byte/word swapping based on the poller’s endianness configuration.

Framers and transports

  • Serial (–serial, alias –rtu) supports framers rtu and ascii (e.g., –serial … –framer ascii). Binary framer was removed in pymodbus 3.9+. If –framer default is used, pymodbus defaults to RTU framer.

  • TCP/UDP (–tcp/–udp) use the socket framer; other framers are rejected. If –framer default is used, pymodbus defaults to socket framer.

MQTT retain

By default, published data messages are not retained by the broker. Use --mqtt-retain to set the MQTT retain flag on data publishes (publish_data only; diagnostics are never retained).

This is useful when subscribers (dashboards, automations) connect after modpoll has already started: they receive the last known values immediately instead of waiting for the next poll cycle.

modpoll --tcp 192.168.1.10 --mqtt-host localhost --mqtt-retain --config examples/modsim.csv

Caveats:

  • If a Modbus device becomes unreachable, modpoll stops publishing for that device but the broker may still serve the last retained message, which can look like a live value.

  • Retain is not a last-will/offline signal; it only stores the last successful publish per topic.

MQTT payload keys

By default, grouped MQTT publish payloads use reference names as JSON keys, appending |unit when a unit is configured in the CSV (e.g. "temp|°C"). Use --mqtt-keys name-only to publish keys without the unit suffix:

modpoll --tcp 192.168.1.10 --mqtt-host localhost --mqtt-keys name-only --config examples/modsim.csv

MQTT write commands

Subscribe pattern (default): modpoll/+/set. Publish to modpoll/<device>/set with a JSON object mapping reference names to values:

{
  "PID_V3V_EC_Consigne_reprise": 21.5,
  "BP_MA_CTA": true
}
  • The device is taken from the MQTT topic, not from the JSON payload.

  • Reference names in the payload must match the CSV configuration; unknown keys are skipped with a warning.

  • Values use the same decoded engineering units as MQTT publish (scale and dtype from the CSV are handled by modpoll).

  • Only references marked rw or w in the CSV can be written.

  • Multiple references can be written in a single message.

Duplicate reference names on the same device are rejected when loading the config file.

Breaking change (2.1.0+): the ref/value object format is no longer supported; use a reference map instead.

Breaking change (2.0.0+): the previous low-level format (object_type, address, value) is no longer supported.