SunSpec discovery
Most register maps are static: a point lives at a fixed offset. SunSpec devices are different: their models are laid out as a chain whose position varies by device, so the address of a point is discovered at runtime.
The model chain
A SunSpec device begins with the marker "SunS" at one of a few well-known
anchor registers (commonly 40000 or 50000). After the marker comes a chain of
models, each a (model_id, length) header followed by its data, terminated by
0xFFFF.
To find model 103 (a three-phase inverter), a runtime probes the anchors for
"SunS", then walks header to header (offset += 2 + length) until it
matches 103.
Declaring discovery
A block marks itself discovered instead of giving fixed offsets:
blocks:
- block_id: inverter
space: HOLDING_REGISTER
discovery:
kind: SUNSPEC
anchor_candidates: [0, 40000, 50000]
model_id: 103
points:
- point_id: ac_power
storage_type: S16
value_type: { primitive: DECIMAL }
mapping: { model_relative_offset: 14 }
transform: { scale_ref: { point_id: ac_power_sf, mode: POW10 } }
Points inside use model_relative_offset, an offset relative to the model's
ID register (offset 0 is the model id, 1 is the length, data begins at 2).
This ID-relative convention is identical across every ModDef runtime.
Caching
Discovery costs a few reads. The runtime resolves each discovered block's base address once and caches it, so subsequent reads of any point in that block go straight to the register without re-probing the anchor. The SunSpec scale factors those points reference are read live per decode.