Skip to content

Modbus sources

Sentinel can be a Modbus RTU master over RS-485 and read up to 40 devices (power meters, temperature and humidity transmitters, and the like). Every register read becomes an ordinary metric in telemetry, events, and rules.

Matter Contents
SNT-G1 pins TX GPIO43, RX GPIO44, DE/RE GPIO40 (direction via RTS). The built-in PZEM-004T uses a different UART, so no clash
Transceiver an isolated RS-485 module. An auto-direction module without a DE pin also works (DE not connected). The board has no RS-485 isolation of its own
Wiring A, B, and GND to the device. Do not connect a device module’s +5V pin (e.g. PZEM-016) to Sentinel’s supply; connect only A, B, and GND
Bus 120 Ω termination at both ends; bias at one point for long buses
DE at boot add a 10 kΩ pull-down on DE so the boot log does not enter the bus

An installation uses two things:

  1. Device profile: the register map of one device type (e.g. Eastron SDM120). See Modbus profiles. Sentinel ships built-in profiles for the Eastron SDM120 and Peacefair PZEM-016.
  2. Source: one installation of a device (address, name prefix) that references a profile.

The metric name in telemetry = <prefix>_<suffix>, e.g. prefix rak1 with suffix voltage becomes rak1_voltage.

Topic m/<workspace>/c/<channel>/<mac>/sources (retained, QoS 1). The message replaces the whole set.

{
"sources_ver": 1,
"buses": [{"id": "uart1", "type": "modbus_rtu", "baud": 9600, "parity": "N", "stop": 1}],
"sources": [
{"id": "grid", "driver": "modbus", "profile": "eastron-sdm120", "pv": 1, "addr": 1, "prefix": "grid", "label": "Meter utama"},
{"id": "rak1", "driver": "modbus", "profile": "eastron-sdm120", "pv": 1, "addr": 2, "prefix": "rak1_pdu", "label": "Meter rak 1"}
]
}
Source field Meaning
id fixed for life, [a-z][a-z0-9_]{0,11}, unique. Changing the id = a new source
driver modbus
profile, pv profile id and its version (the installation pins the version, so updating a profile does not change a running node without a new sources message)
addr Modbus slave address 1…247, unique on the bus
prefix metric name prefix (default id). Use short names (2–6 characters); see Capacity
label max. 12 characters, for display
interval_s, timeout_ms, retries override the profile’s poll values
en false = not read
group, group_ch, deltas telemetry group and thresholds (Telemetry groups)
names rename metrics per channel

buses holds the uart1 bus settings: baud 1200…115200, parity N/E/O, stop 1/2. One bus, one setting: devices with different baud rates cannot share a bus. The bus is always named uart1 in the message (a logical name).

A source may also use inline regs (without a profile) for one-off devices, with ch, fn (1–4), reg (zero-based), type (u16, s16, u32, s32, f32, bit), words/bytes (order), scale, offset, name, unit, dec.

Limit Value
Sources 40
Source metrics 400
Registers per source 16
sources message size G1 6144 B

A source that exceeds a limit is rejected (melebihi batas metrik); other sources are still loaded. A message that is wholly invalid is rejected and the old set keeps running.

The Sources tab in the web interface: choose a profile, fill in the address and prefix, and the page shows the metric names that will be created along with their units and kinds. The page rejects up front source names, prefixes, addresses, or metric names the node would certainly reject. The Devices tab monitors the status of each source.

Sources tab of the web interface.
Sources tab: RS-485 bus and add a source from a profile.

From a terminal:

Terminal window
python3 Tools/celestianctl.py sources <mac> --file Tools/sources-contoh-profil.json
python3 Tools/celestianctl.py profiles <mac> --sources Tools/sources-contoh-profil.json

The second command sends the node the profiles referenced by the sources file, from the library.

Status Meaning and checks
ok answers and its data is fresh
no_response A/B wires swapped → slave address → baud/parity → 120 Ω termination → register address 0- or 1-based
crc_error usually noise or parity
bad_data response does not match the profile
bus_fault bus problem
disabled en = false
bad_config invalid source configuration

Repeated failures back off progressively (interval × 2ⁿ, max. 60 seconds) and do not hold up other sources. A metric whose value is stale (older than three times the interval) is not sent. Per-source diagnostics: sources/reported (not periodic; published on connect and when the set changes).

A wrong bus parameter (baud) makes all sources silent without a clear sign, so sources (and profiles) support confirm_s like rules: the set runs temporarily, cmd sources_confirm with the hash makes it permanent, and without confirmation the node returns to the old set. cmd sources_rollback cancels the pending set or returns to the previous set; cmd get_sources downloads the effective set (…/sources/current).

Terminal window
python3 Tools/celestianctl.py sources <mac> --file sources.json --confirm-s 120
python3 Tools/celestianctl.py sources <mac> --confirm 8a3030f6
python3 Tools/celestianctl.py sources <mac> --rollback

Metric name: lowercase letters, digits, _; starts with a letter; max. 24 characters; unique among all node metrics including built-in sensors; must not start with alarm_, rule_, src_, flag_ or be a fixed name like voltage. The source prefix makes Modbus metrics different from the built-in PZEM-004T voltage, power_draw, ….