Skip to content

Matter: add Electrical Power Measurement cluster to On/Off Plug-in Unit - #24922

Open
lboue wants to merge 6 commits into
arendst:developmentfrom
lboue:matter-electrical-power-measurement
Open

Matter: add Electrical Power Measurement cluster to On/Off Plug-in Unit#24922
lboue wants to merge 6 commits into
arendst:developmentfrom
lboue:matter-electrical-power-measurement

Conversation

@lboue

@lboue lboue commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Description:

Adds Matter support for live electrical power reporting on relay/plug endpoints:

  • New relay_power plugin (Matter_Plugin_OnOff_Power, Matter_Plugin_3_OnOff_Power.be): extends the existing relay On/Off Plug-in Unit (device type 0x010A) with the Electrical Power Measurement cluster (0x0090, Matter 1.4.1 §2.13). Reads Voltage/Current/Power/ApparentPower/ReactivePower/Factor/Frequency from Tasmota's ENERGY sensor JSON (single-channel energy monitoring chips: HLW8012, BL0937, CSE7766, ADE7953, PZEM, ...) and exposes them as RMSVoltage, RMSCurrent, ActivePower, RMSPower, ApparentPower, ReactivePower, Frequency, PowerFactor, plus the mandatory PowerMode/NumberOfMeasurementTypes/Accuracy attributes. This lets Matter controllers (Apple Home, Google Home, SmartThings, ...) display live power usage for Tasmota smart plugs, the same way many commercial Matter plugs do.
  • New v_relay_power virtual variant (Matter_Plugin_Virt_OnOff_Power, Matter_Plugin_9_Virt_OnOff_Power.be): lets the cluster be exercised without physical hardware, driven entirely through the MtrUpdate command (e.g. MtrUpdate {"Name":"Plug","Voltage":230.5,"Current":0.42,"ActivePower":95.6}). Useful for testing/demoing without an energy-monitoring device.
  • New http_relay_power bridge variant (Matter_Plugin_Bridge_OnOff_Power, Matter_Plugin_8_Bridge_OnOff_Power.be): same cluster, but polling a remote Tasmota device over HTTP (Status 10) instead of local sensors, completing the local/virtual/bridge trio already used by other plugins.
  • Matter_Plugin_0.be: registers FEATURE_MAPS/CLUSTER_REVISIONS entries for cluster 0x0090.
  • Matter_UI.be:
    • adds relay_power, v_relay_power and http_relay_power to the endpoint-type configuration dropdowns.
    • improves the "Add Remote sensor or device" auto-detection: when the probed remote device reports an ENERGY sensor, the first detected relay is now suggested as relay_power instead of plain light0/relay (the type is otherwise not editable for already-detected rows, so without this the cluster was unreachable from that screen). Only the first relay is tagged, since most Tasmota energy-monitoring boards (single CSE7766/HLW8012/etc. chip) have one shared meter for the whole device rather than one per relay — tagging every relay would duplicate the same aggregate reading misleadingly.
  • be_matter_module.c: registers the new solidified plugin headers (this file maintains an explicit include list with no auto-discovery; the initial push was missing the first pair and failed CI, fixed in a follow-up commit).

Design notes:

  • The cluster is added directly on the existing "On/Off Plug-in Unit" endpoint rather than composed as a separate "Electrical Sensor" (0x0510) device type, matching common real-world Matter plug implementations.
  • Single measurement channel only; multi-phase/multi-channel energy (Voltage1/2, Power1/2, ...) is out of scope for this PR.
  • Electrical Energy Measurement (0x0091, cumulative kWh) is not covered by this PR.
  • In the virtual variant, the wattage test key is ActivePower rather than Power, since Power is already the inherited On/Off boolean command.

Related issue (if applicable): N/A

Test results:

Flashed and tested on real hardware: ESP32-S3 (tasmota32s3 env), Tasmota 15.5.0.2(tasmota32), Core 3.3.8.

Local + virtual (relay_power / v_relay_power)

  • Built and flashed via PlatformIO (pio run -e tasmota32s3 --target upload) — build succeeds (Flash 70.7%, RAM 21.9%).
  • Configured endpoint 2 as v_relay_power via the Matter web UI; commissioned the device with chip-tool (manual pairing code) onto a test fabric — commissioning completed successfully.
  • chip-tool descriptor read device-type-list confirms endpoint 2 reports device type 266 (On/Off Plug-in Unit) alongside 19 (Bridged Node).
  • Read the ElectricalPowerMeasurement cluster (0x0090) on endpoint 2 via chip-tool:
    • PowerMode = 2 (AC), NumberOfMeasurementTypes = 8.
    • Accuracy: 8 MeasurementAccuracyStruct entries returned with correct MeasurementType enums, min/max ranges and AccuracyRanges — matches the declarative table in the plugin.
    • Before any update, ActivePower/ReactivePower/ApparentPower/Frequency/PowerFactor correctly read back null (nullable/X quality, as specified).
  • Sent MtrUpdate {"Ep":2,"Power":1,"Voltage":230.5,"Current":0.42,"ActivePower":95.6,"ApparentPower":98.1,"ReactivePower":12.0,"Factor":0.97,"Frequency":50.0} via the console — accepted (RESULT = {"MtrUpdate":{"Ep":2,"Power":1}}).
  • Re-read via chip-tool after the update:
    • ActivePower = 95600 (mW) ✓ matches 95.6 W × 1000.
    • RMSVoltage = 230500 (mV) ✓ matches 230.5 V × 1000.
  • Serial console confirmed no crash/exception around commissioning or the virtual update (Status 0 reports healthy heap ~190KB free, stable uptime, Wifi connected throughout).

Bridge (http_relay_power) against a real remote device

  • Bridged a real NOUS A5T 4-outlet power strip (single shared CSE7766 meter, ENERGY in its Status 10) at a separate IP on the LAN.
  • Before the auto-detect fix: all 4 relays were suggested (and had been added) as http_light0 ("Light 0 OnOff") — the shared power meter was invisible from Matter, and the type wasn't editable for already-probed rows.
  • After the fix: re-probing via "Add Remote Tasmota or OpenBK" now returns [{"relay":1,"type":"http_relay_power"},{"relay":2,"type":"http_light0"},{"relay":3,"type":"http_light0"},{"relay":4,"type":"http_light0"}] — only relay 1 is tagged with the power cluster.
  • Deleted the old relay-1 http_light0 endpoint, re-ran the probe, added the new http_relay_power endpoint for relay 1 — the existing relay 2/3/4 endpoints were correctly recognized as duplicates and skipped (no double endpoints).
  • Tasmota's own status list now shows Power1 Off 2.0W (bridge-polled ActivePower displayed next to the On/Off state via web_values()) while Power2/Power3/Power4 remain plain on/off — matching the physical reality of one shared meter across four sockets.

Not yet tested: ESP8266 build, and the physical (non-virtual, non-bridge) relay_power path against a locally-attached energy-monitoring chip.

Checklist:

  • The pull request is done against the latest development branch
  • Only relevant files were touched
  • Only one feature/fix was added per PR and the code change compiles without warnings
  • The code change is tested and works with Tasmota core ESP8266 V.2.7.8
  • The code change is tested and works with Tasmota core ESP32 V.3.3.8 from Platform 2026.05.50
  • I accept the CLA.

NOTE: The code change must pass CI tests. Your PR cannot be merged unless tests pass

lboue and others added 5 commits July 31, 2026 07:54
Adds a new "relay_power" plugin type (Matter_Plugin_OnOff_Power) that extends
the existing relay/OnOff Plug-in Unit (0x010A) with the Electrical Power
Measurement cluster (0x0090), reporting Voltage, Current, ActivePower,
ApparentPower, ReactivePower, Frequency and PowerFactor from Tasmota's ENERGY
sensor JSON, so Matter controllers can display live power usage for smart
plugs with energy monitoring.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ement

Adds Matter_Plugin_Virt_OnOff_Power ("v_relay_power") so the new
ElectricalPowerMeasurement-enabled plug can be exercised without physical
hardware, driven entirely via `MtrUpdate` (e.g. Voltage/Current/ActivePower/
ApparentPower/ReactivePower/Factor/Frequency).

Also guards Matter_Plugin_OnOff_Power.parse_sensors() against VIRTUAL
instances (it must not read the local ENERGY sensor) and declares
UPDATE_COMMANDS so MtrUpdate accepts the new measurement keys. The wattage
key is named `ActivePower` rather than `Power` since `Power` is already the
inherited On/Off boolean command.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
be_matter_module.c maintains an explicit, hand-written list of solidified
Berry header includes (no auto-discovery). The new OnOff_Power and
Virt_OnOff_Power plugin files were missing from that list, so their classes
were never defined, causing the "undeclared" build failures reported by CI
(be_class_Matter_Plugin_OnOff_Power / be_class_Matter_Plugin_Virt_OnOff_Power)
even though matter.plugins_classes referenced them by name.
…urement

Adds Matter_Plugin_Bridge_OnOff_Power ("http_relay_power") so the
ElectricalPowerMeasurement-enabled plug can also be bridged from a remote
Tasmota device over HTTP (polling `Status 10`), completing the local/virtual/
bridge trio already used by other plugins (relay, relay_power now included).

Refactors the ENERGY-object parsing in Matter_Plugin_OnOff_Power into a
shared `_parse_energy()` helper used by both `parse_sensors()` (local device)
and the new `parse_status()` override (bridge, index 10 / Status 10), and
guards `parse_sensors()` against BRIDGE instances so a bridge endpoint never
reads the local gateway's own ENERGY sensor by mistake.

Registers the new solidified header in be_matter_module.c (missed this for
the previous two plugin files, which broke CI) and adds http_relay_power to
the bridge type dropdown in Matter_UI.be.

Verified with a full PlatformIO build for tasmota32s3 (SUCCESS).
…GY sensor

The "Add Remote sensor or device" auto-detection always suggested plain
light0/relay for every detected relay channel, even when the remote device
reports an ENERGY sensor (e.g. a NOUS A5T 4-outlet power strip with a single
shared CSE7766 meter) - so relay+power devices showed up as plain "Light 0
OnOff" with no way to pick relay_power from that screen (the type column is
static text for already-detected rows, only editable for a brand new blank
row).

generate_config_from_status() now tags the first detected relay as
relay_power when ENERGY is present, leaving the rest as plain relays: most
Tasmota energy-monitoring boards have a single meter for the whole device,
not one per relay, so duplicating the cluster across every channel would
misleadingly show the same aggregate reading on each endpoint.
@lboue
lboue marked this pull request as ready for review July 31, 2026 07:18
…ng plug

Adds device type 0x0510 (Electrical Sensor) alongside 0x010A (On/Off
Plug-in Unit) on the same endpoint for relay_power/v_relay_power/
http_relay_power, plus the mandatory Power Topology cluster (0x009C) with
the NODE feature (this single ENERGY sensor meters the whole device, not a
subset of endpoints - matches Tasmota's non-indexed ENERGY object).

Matches the Matter 1.4.1 Device Library requirement that Electrical Power
Measurement lives on an Electrical Sensor device type, while keeping the
cluster on the plug's own endpoint (composed DeviceTypeList) rather than a
separate endpoint, since controllers only recognize the measurement
capability when the Electrical Sensor device type is actually declared.

Verified on real ESP32-S3 hardware via chip-tool: endpoint 2 now reports
DeviceTypeList = [266 (On/Off Plug-in Unit), 1296/0x0510 (Electrical
Sensor), 19 (Bridged Node)], and Power Topology FeatureMap = 1 (NODE).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant