Skip to content

Modbus device profiles

A profile describes which registers to read from one device type, their data types, scale, and units. A profile is used by many sources; a node stores only the profiles its installations need, plus the firmware’s built-in profiles.

Profile Device Notes
eastron-sdm120 Eastron SDM120 (single-phase meter) built into the firmware. Factory baud 2400, can be 1200–9600. The device only accepts even register addresses and counts (even_regs); the node rounds requests
peacefair-pzem016 Peacefair PZEM-016 (single-phase meter, 100 A CT; PZEM-014 is the same with a 10 A shunt) built into the firmware. Fixed baud 9600 8N1; low word first. The default address is not stated in the datasheet: find it with a USB-RS485 adapter on a computer before installing

SDM120 metrics: voltage, current, power, apparent, reactive, pf, freq, energy_imp, energy_exp, energy_total (source prefix + suffix). PZEM-016 metrics: voltage, current, power, energy, frequency, power factor, and a power alarm status.

On installations with dozens of devices, install a compact profile that reads only the registers in use (e.g. SDM120: voltage, current, power, energy = 4 metrics, not 10). Messages are smaller and the read cycle faster (Capacity).

One JSON file per device type:

{
"profile_id": "eastron-sdm120", "version": 1, "name": "Eastron SDM120",
"bus": {"baud": 2400, "parity": "N", "stop": 1, "baud_options": [1200, 2400, 4800, 9600]},
"quirks": {"even_regs": true},
"poll": {"interval_s": 5, "timeout_ms": 500, "retries": 1},
"regs": [{"ch": "v", "fn": 4, "reg": 0, "type": "f32", "words": "big", "bytes": "big",
"dec": 1, "unit": "V", "suffix": "voltage", "label": "Tegangan", "delta": 2}],
"tests": [{"ch": "v", "raw": "43663334", "expect": 230.2}]
}
Field Meaning
profile_id, version identity. Increase version on every change; installations pin the version (pv)
bus hints (the device’s default baud and supported options). The effective bus comes from the sources message; the Sources page warns if the baud is not supported by the profile
quirks.even_regs the device only accepts even register addresses and counts
poll default interval_s, timeout_ms, retries
regs[].ch short channel id (v, i, p, …)
regs[].fn Modbus function: 1, 2 (bit), 3 (holding), 4 (input)
regs[].reg zero-based protocol address. Datasheet addresses are often written with another numbering (30001 = 0 for fn 4)
regs[].type u16, s16, u32, s32, f32, bit
regs[].words, bytes word order (big AB CD, little CD AB) and byte order within a word
regs[].scale, offset, dec, unit value = raw × scale + offset; decimals; unit
regs[].suffix metric name suffix (name = <prefix>_<suffix>, max. 24 characters)
regs[].delta change threshold for telemetry groups (here)
tests raw bytes (hex) and the expected value, from examples in the datasheet

At most 16 registers per profile. Metric types: number (num), non-negative integer (count), or boolean (bool).

  1. Write profile_id.json from the datasheet of the device actually used; do not guess register addresses. Include test vectors from the datasheet.
  2. Load it through the Sources tab in the web (the Import profile box: the Choose file… button loads a .json into the text box for review first, the Use example button shows an example with an explanation of each key), or send it with a profiles message:
Terminal window
python3 Tools/celestianctl.py profiles --list # library contents
python3 Tools/celestianctl.py profiles <mac> --files profil.json # send specific profiles (replaces the sent set)
python3 Tools/celestianctl.py profiles <mac> --get # download the set on the node
python3 Tools/celestianctl.py profiles <mac> --clear # delete sent profiles (built-in seed stays)

The profiles message replaces the whole sent profile set and supports confirm_s, profiles_confirm, and profiles_rollback like sources. Profile size on G1 is limited: the full form (with label, tests, description) may not fit together with two profiles; send the compact form.