Configuration

Modbus configure file

To communicate with Modbus devices, a CSV configure file describes device addresses, poll ranges, and reference mappings. See also Basic Usage for coil/register bit semantics and MQTT write constraints.

CSV structure

Each non-empty row is one of three types:

  • devicedevice,<name>,<slave_id>

  • pollpoll,<object_type>,<start>,<size>,<endian>

  • refref,<name>,<address>,<dtype>,<rw>,<unit>,<scale> (<unit> and <scale> optional)

  • device<name> is unique per file (used in MQTT topics). <slave_id> is the Modbus unit ID (1–254). Multiple devices may share the same slave ID when they are logical views of one physical slave; poll ranges must not overlap.

  • poll<object_type> is coil, discrete_input, holding_register, or input_register. <start> and <size> define the address range. <endian> must be BE_BE, LE_BE, LE_LE, or BE_LE.

  • ref<address> may be decimal or hexadecimal (0x10). For register bit reads, use <address>:<bit> (0–15) with dtype bool. <rw> is r, w, or rw. <unit> and <scale> are optional; scale multiplies read values and divides write values.

Supported dtypes

uint16, int16, uint32, int32, uint64, int64, float16, float32, float64, bool, bool8, bool16, stringNNN (where NNN is the string byte length).

Poll size limits

  • Coils and discrete inputs: maximum 2000 points per poll.

  • Holding and input registers: maximum 123 registers per poll.

Validation rules

  • Duplicate device names or reference names on the same device abort config loading.

  • Duplicate pollers (same function code, start, size, endian on one device) are ignored with a warning.

  • Overlapping poll ranges on the same slave ID and function code produce a warning.

  • References outside the poller range or with invalid endian/dtype are ignored with a warning.

  • References marked w or rw on discrete_input or input_register pollers log a warning at load time (Modbus inputs are read-only; MQTT writes are rejected).

Here is the annotated template:

 1# Modbus Configuration File
 2# --------------------------
 3# This configuration file is to describe the Modbus registers of target device(s) and defines poller(s) to help polling data.
 4# The file format uses "csv" instead of json or yaml because many vendor's modbus registers are described in a table so it is easier to edit the information in excel and export to csv format.
 5#
 6# Configuration Types
 7# --------------------------
 8# device,<device_name>,<device_id>
 9# poll,<object_type>,<start_address>,<size>,<endian>
10# ref,<ref_name>,<address>,<dtype>,<rw>,<unit>,<scale>
11#
12# Configuration Objects
13# --------------------------
14# <device_name>: any string without spaces to describe the device (must be unique in the file)
15# <device_id>: integer 1 to 254; Modbus slave address used on the bus
16# Multiple device rows may share the same <device_id> when they are logical views of one
17# physical slave (distinct MQTT topics via {{device_name}}); poll ranges must not overlap
18# <object_type>: coil/discrete_input/holding_register/input_register
19# <start_address>: integer 0 to 65535 (The start address of Modbus registers to poll)
20# <size>: integer 0 to 65535 (No. of registers to poll and value must not exceed the limits of Modbus)
21# <endian>: byte_order and word_order e.g. BE_BE/BE_LE/LE_LE/LE_BE
22# <ref_name>: any string without spaces to describe the reference
23# <address>: integer 0 to 65535 (the modbus address and should match the poller range)
24# <dtype>: uint16/int16/uint32/int32/uint64/int64/float16/float32/float64/bool/bool8/bool16/stringXXX (required)
25# <rw>: read/write setting e.g. r/w/rw
26# <unit> (optional): the measurement unit of reference
27# <scale> (Optional): a float value to be multiplied with actual register reading; leave empty to disable scaling (0 is not supported as a multiplier)
28# <endian> must be one of BE_BE, LE_BE, LE_LE, BE_LE (typos give unpredictable results)
29# bool on coil/discrete_input: absolute Modbus coil address, publishes one boolean
30# bool8/bool16 on coil/discrete_input: legacy grouped reads; address is group index (0=coils 0-7, 1=coils 8-15 / "09-16" in tables)
31# if the poll ends mid-group, missing bits are padded with false (bool8 and bool16)
32# bool with address:bit (0-15): use on holding_register or input_register pollers only (not coils)
33#
34# Typical Structure
35# -----------------------------
36# device,dev001,1   <- the first device (dev001)
37# poll,...          <- the first poller of dev001
38# ref,...           <- the references in poller
39# ref,...
40# poll,...          <- the second poller of dev001
41# ref,...
42# ref,...
43# device,dev002,2   <- a second physical slave (dev002)
44# poll,...          <- the first poller of dev002
45# ref,...
46# device,dev001b,1  <- optional: another logical device on slave 1 (unique name, non-overlapping polls)
47# poll,...
48# ref,...
49#
50# Configuration Example
51# !!! Please remove all comments for your config file !!!
52# -----------------------------
53device,modsim01,1,,
54poll,coil,0,12,BE_BE
55ref,coil01,0,bool,rw
56ref,coil02,1,bool,rw
57ref,coil09-12,1,bool8,rw
58poll,holding_register,40000,20,BE_BE
59ref,holding_reg01,40000,uint16,rw
60ref,holding_reg02,40001,uint16,rw
61ref,holding_reg03,40002,uint16,rw
62ref,holding_reg04,40003,uint16,rw
63ref,holding_reg05,40004,int16,rw
64ref,holding_reg06,40005,int16,rw
65ref,holding_reg07,40006,int16,rw
66ref,holding_reg08,40007,int16,rw
67ref,holding_reg09,40008,uint32,rw
68ref,holding_reg10,40010,uint32,rw
69ref,holding_reg11,40012,int32,rw
70ref,holding_reg12,40014,int32,rw
71ref,holding_reg13,40016,float32,rw
72ref,holding_reg14,40018,float32,rw
73# Example of reading a single bit from a register
74# The format is address:bit (0-15), and is only for dtype=bool on registers.
75ref,alarm_bit_15,40019:15,bool,r,

Example 1: Modsim device (Modbus TCP device)

This example configuration is included for local testing with a Modbus TCP simulator or device.

 1device,modsim01,1,,
 2poll,coil,0,16,BE_BE
 3ref,coil01-08,0,bool8,rw
 4ref,coil09-16,1,bool8,rw
 5poll,discrete_input,10000,16,BE_BE
 6ref,di01-08,10000,bool8,rw
 7ref,di09-16,10001,bool8,rw
 8poll,input_register,30000,20,BE_BE
 9ref,input_reg01,30000,uint16,rw
10ref,input_reg02,30001,uint16,rw
11ref,input_reg03,30002,uint16,rw
12ref,input_reg04,30003,uint16,rw
13ref,input_reg05,30004,int16,rw
14ref,input_reg06,30005,int16,rw
15ref,input_reg07,30006,int16,rw
16ref,input_reg08,30007,int16,rw
17ref,input_reg09,30008,uint32,rw
18ref,input_reg10,30010,uint32,rw,,0.001
19ref,input_reg11,30012,int32,rw
20ref,input_reg12,30014,int32,rw,,1000
21ref,input_reg13,30016,float32,rw
22ref,input_reg14,30018,float32,rw
23poll,holding_register,40000,44,BE_BE
24ref,holding_reg01,40000,uint16,rw
25ref,holding_reg02,40001,uint16,rw
26ref,holding_reg03,40002,uint16,rw
27ref,holding_reg04,40003,uint16,rw
28ref,holding_reg05,40004,int16,rw
29ref,holding_reg06,40005,int16,rw
30ref,holding_reg07,40006,int16,rw
31ref,holding_reg08,40007,int16,rw
32ref,holding_reg09,40008,uint32,rw
33ref,holding_reg10,40010,uint32,rw,,0.001
34ref,holding_reg11,40012,int32,rw
35ref,holding_reg12,40014,int32,rw,,1000
36ref,holding_reg13,40016,float32,rw
37ref,holding_reg14,40018,float32,rw
38ref,holding_reg15,40020,uint64,rw
39ref,holding_reg16,40024,int64,rw
40ref,holding_reg17,40028,float64,rw
41ref,holding_reg18,40032,float64,rw
42ref,holding_reg19,40036,string16,rw

Example 2: SCPM-S6 Power Meter (Modbus RTU device)

SCPM-S6 is designed as a sub-circuit power meter to monitor multiple electrical circuit power consumptions.

 1device,scpm001,1,,,
 2poll,holding_register,46001,6,BE_BE,
 3ref,CT_TYPE,46001,uint16,rw,
 4ref,CT_RATING,46002,uint16,rw,
 5ref,DATA_SCALAR,46003,uint16,rw,
 6ref,ReservedA,46004,uint16,rw,
 7ref,ReservedB,46005,uint16,rw,
 8ref,SIGNED_MODE,46006,uint16,rw,
 9poll,holding_register,46011,92,BE_BE,
10ref,Hz,46011,int16,r,Hz,1
11ref,V,46012,int16,r,V,1
12ref,CH1_A,46013,int16,r,A,1
13ref,CH2_A,46014,int16,r,A,1
14ref,CH3_A,46015,int16,r,A,1
15ref,CH4_A,46016,int16,r,A,1
16ref,CH5_A,46017,int16,r,A,1
17ref,CH6_A,46018,int16,r,A,1
18ref,CH1_kWh,46019,uint32,r,kWh,1
19ref,CH2_kWh,46021,uint32,r,kWh,1
20ref,CH3_kWh,46023,uint32,r,kWh,1
21ref,CH4_kWh,46025,uint32,r,kWh,1
22ref,CH5_kWh,46027,uint32,r,kWh,1
23ref,CH6_kWh,46029,uint32,r,kWh,1
24ref,CH1_kWh_P,46031,uint32,r,kWh,1
25ref,CH2_kWh_P,46033,uint32,r,kWh,1
26ref,CH3_kWh_P,46035,uint32,r,kWh,1
27ref,CH4_kWh_P,46037,uint32,r,kWh,1
28ref,CH5_kWh_P,46039,uint32,r,kWh,1
29ref,CH6_kWh_P,46041,uint32,r,kWh,1
30ref,CH1_kWh_N,46043,uint32,r,kWh,1
31ref,CH2_kWh_N,46045,uint32,r,kWh,1
32ref,CH3_kWh_N,46047,uint32,r,kWh,1
33ref,CH4_kWh_N,46049,uint32,r,kWh,1
34ref,CH5_kWh_N,46051,uint32,r,kWh,1
35ref,CH6_kWh_N,46053,uint32,r,kWh,1
36ref,CH1_kVARh,46055,uint32,r,kVARh,1
37ref,CH2_kVARh,46057,uint32,r,kVARh,1
38ref,CH3_kVARh,46059,uint32,r,kVARh,1
39ref,CH4_kVARh,46061,uint32,r,kVARh,1
40ref,CH5_kVARh,46063,uint32,r,kVARh,1
41ref,CH6_kVARh,46065,uint32,r,kVARh,1
42ref,CH1_kVARh_P,46067,uint32,r,kVARh,1
43ref,CH2_kVARh_P,46069,uint32,r,kVARh,1
44ref,CH3_kVARh_P,46071,uint32,r,kVARh,1
45ref,CH4_kVARh_P,46073,uint32,r,kVARh,1
46ref,CH5_kVARh_P,46075,uint32,r,kVARh,1
47ref,CH6_kVARh_P,46077,uint32,r,kVARh,1
48ref,CH1_kVARh_N,46079,uint32,r,kVARh,1
49ref,CH2_kVARh_N,46081,uint32,r,kVARh,1
50ref,CH3_kVARh_N,46083,uint32,r,kVARh,1
51ref,CH4_kVARh_N,46085,uint32,r,kVARh,1
52ref,CH5_kVARh_N,46087,uint32,r,kVARh,1
53ref,CH6_kVARh_N,46089,uint32,r,kVARh,1
54ref,CH1_kVA,46091,int16,r,kVA,1
55ref,CH2_kVA,46092,int16,r,kVA,1
56ref,CH3_kVA,46093,int16,r,kVA,1
57ref,CH4_kVA,46094,int16,r,kVA,1
58ref,CH5_kVA,46095,int16,r,kVA,1
59ref,CH6_kVA,46096,int16,r,kVA,1
60ref,CH1_PF,46097,int16,r,,1
61ref,CH2_PF,46098,int16,r,,1
62ref,CH3_PF,46099,int16,r,,1
63ref,Reserved1,46100,int16,r,
64ref,Reserved2,46101,int16,r,
65ref,Reserved3,46102,int16,r,