📝 Document stream→device mapping in README #51

Merged
mat merged 2 commits from docs-stream-mapping into main 2026-07-14 14:55:09 +00:00
Owner

Extends the Realtime streaming (optional) section of the README with a new ### Mapping streamed measurements to devices subsection, capturing findings confirmed by a live 3-minute stream_measurements spike against a gen4 account plus a raw get_devices() dump.

Findings added

  • capacityIdget_devices(): Measurement.capacity_id is the capacityId string at feature.capacities[].capacity.capacityId; the same capacity object carries deviceId, nature, measureKind, phase, and production (bool) — route + sign with no separate map.
  • Multi-instance / polyphase: a device can expose several SENSOR capacities (3-phase inverter → instances.0/1/2); instantaneous power is the sum of its FLOW capacities, not one instance. Each capacity has a phase (POSITIVE_1/2/3).
  • Typed value fields: value_float (FLOW, watts), value_bool (STATE, on/off); Measurement.value is the raw string — prefer the typed field.
  • Cadence: bursts roughly every ~15 s grouped per connected object (co.{N} segment), not a fixed per-device poll.
  • Unmappable measurements: grid (...sensor.N.withdrawal.data / .injection.data) and battery (...battery_charge.data / .battery_discharge.data) capacityIds have no match in get_devices(); GRID_METER and BATTERY return empty capacity lists — route via get_site_time_series or ignore on the stream.
  • Switch state: arrives as STATE on ...switch.N.data (parallel to ...sensor.N.data FLOW); CapacityChanged is also yielded for switch changes, keyed by the numeric capacity id (not the capacityId string) — don't match it against the string route. Not observed during the spike (no manual toggle).

Snippet

Adds a minimal, comment-free capacityId → (deviceId, nature, production) route built from get_devices(), reusing the nested-loop idiom already in the usage examples.

Docs only — no code or behavior change.

Extends the **Realtime streaming (optional)** section of the README with a new `### Mapping streamed measurements to devices` subsection, capturing findings confirmed by a live 3-minute `stream_measurements` spike against a gen4 account plus a raw `get_devices()` dump. ## Findings added - **`capacityId` ↔ `get_devices()`**: `Measurement.capacity_id` is the `capacityId` string at `feature.capacities[].capacity.capacityId`; the same capacity object carries `deviceId`, `nature`, `measureKind`, `phase`, and `production` (bool) — route + sign with no separate map. - **Multi-instance / polyphase**: a device can expose several `SENSOR` capacities (3-phase inverter → `instances.0/1/2`); instantaneous power is the **sum** of its `FLOW` capacities, not one instance. Each capacity has a `phase` (`POSITIVE_1/2/3`). - **Typed value fields**: `value_float` (FLOW, watts), `value_bool` (STATE, on/off); `Measurement.value` is the raw string — prefer the typed field. - **Cadence**: bursts roughly every ~15 s grouped per connected object (`co.{N}` segment), not a fixed per-device poll. - **Unmappable measurements**: grid (`...sensor.N.withdrawal.data` / `.injection.data`) and battery (`...battery_charge.data` / `.battery_discharge.data`) `capacityId`s have no match in `get_devices()`; `GRID_METER` and `BATTERY` return empty capacity lists — route via `get_site_time_series` or ignore on the stream. - **Switch state**: arrives as `STATE` on `...switch.N.data` (parallel to `...sensor.N.data` `FLOW`); `CapacityChanged` is also yielded for switch changes, keyed by the **numeric** capacity `id` (not the `capacityId` string) — don't match it against the string route. Not observed during the spike (no manual toggle). ## Snippet Adds a minimal, comment-free `capacityId → (deviceId, nature, production)` route built from `get_devices()`, reusing the nested-loop idiom already in the usage examples. Docs only — no code or behavior change.
📝 Document stream→device mapping in README
All checks were successful
Tests / forgejo-pytest (push) Successful in 42s
Tests / forgejo-pytest (pull_request) Successful in 42s
b7f63bcd88
Extend the 'Realtime streaming (optional)' section with a new
'Mapping streamed measurements to devices' subsection capturing
findings from a live 3-minute stream_measurements spike + raw
get_devices() dump:

- capacityId ↔ get_devices(): Measurement.capacity_id is the
  capacity.capacityId string; the same object carries deviceId,
  nature, measureKind, phase, production (bool) for routing + sign.
- Multi-instance/polyphase devices expose several SENSOR capacities;
  instantaneous power is the sum of FLOW capacities, not one instance.
- Typed value fields: value_float (FLOW watts), value_bool (STATE);
  Measurement.value is the raw string — prefer the typed field.
- Cadence: bursts roughly every ~15s grouped per connected object
  (the co.{N} segment), not a fixed per-device poll.
- Unmappable capacityIds (grid withdrawal/injection, battery
  charge/discharge) have no get_devices() capacity; GRID_METER and
  BATTERY return empty capacity lists — route via get_site_time_series
  or ignore on the stream.
- Switch state arrives as STATE on ...switch.N.data (parallel to
  ...sensor.N.data FLOW); CapacityChanged is also yielded for switch
  changes, keyed by the numeric capacity id (not the capacityId string).

Adds a minimal capacityId → (deviceId, nature, production) route
snippet built from get_devices().
mat force-pushed docs-stream-mapping from b7f63bcd88
All checks were successful
Tests / forgejo-pytest (push) Successful in 42s
Tests / forgejo-pytest (pull_request) Successful in 42s
to 642e374eb2
All checks were successful
Tests / forgejo-pytest (push) Successful in 42s
Tests / forgejo-pytest (pull_request) Successful in 42s
2026-07-14 13:22:15 +00:00
Compare
mat changed title from Document stream→device mapping in README to 📝 Document stream→device mapping in README 2026-07-14 14:38:18 +00:00
✏️ Fix stream→device mapping accuracy and prose in README
All checks were successful
Tests / forgejo-pytest (push) Successful in 43s
Tests / forgejo-pytest (pull_request) Successful in 42s
fa1e51b396
Corrections verified against a live Comwatt account:

- capacityId format: grid/battery capacities keep the 'sensor.{j}' segment
  (…sensor.{j}.withdrawal.data etc.), not the bare '…instances.{i}.withdrawal.data'
  form the original parenthetical implied. These are ~24% of stream measurements.
- get_devices() hides grid/battery: parents return empty 'features' AND 'capacities'
  (devices have no 'natures' list — identity is on 'deviceKind.code'); part-children
  WITHDRAWAL/INJECTION/BATTERY_CHARGE/BATTERY_DISCHARGE route via get_connected_objects().
- 'phase' is only on polyphase capacities, not every capacity.
- value_float/value_bool are parsed from the raw string by value shape, not gated on
  measure_kind (in practice FLOW→value_float, STATE→value_bool, verified with zero
  overlap across 328 samples).
- Split the two run-on bullets; drop 'the spike' internal jargon.
- Finish the route snippet with a usage/print line.
mat merged commit 8a65ddb10c into main 2026-07-14 14:55:09 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
mat/python-comwatt-client!51
No description provided.