[Matter] Stromverbrauch eines Geräts hinzufügen

Aufgrund der Anfrage von @jmarandet zur Verwaltung seiner Shelly-Geräte (Aide pour connexion Shelly EM avec Gladys en MQTT - #8 par jmarandet) wurde die Verwaltung des Stromverbrauchs und der Matter-Cluster wie folgt hinzugefügt:

"id": "156",
"name": "PowerTopology",
"id": "144",
"name": "ElectricalPowerMeasurement",
"id": "145",
"name": "ElectricalEnergyMeasurement",

Hallo à tous :slight_smile:

Ich habe einen PR zu diesem Thema erstellt, vollständig blind, basierend auf dem, was ich in Matter.js gefunden habe.

@Nagromdark Kannst du dir den PR ansehen und mir sagen, was du davon hältst? Falls du Material zum Testen hast, nehme ich das auch gerne mit :smiley:

@jmarandet Ich bräuchte deine Hilfe. In Matterbridge, bei den Shellys, siehst du welche « supported_feature »?

Normalerweise ist das eine Information, die du in jedem Gerät finden kannst.

Ich wäre für einen Screenshot eines deiner Shellys mit allen angezeigten Werten dankbar!

Andere Frage, die in kWh angezeigten Werte, sind das wirklich ein Index? Also im Sinne von « kumuliertem » Verbrauch, der nur wächst?

Hallo, ich habe es noch nicht angesehen, ich habe im Moment etwas weniger Zeit. Ich habe auf jeden Fall kein Gerät, um das zu testen, sorry.

Ich habe mir eine kleine Testumgebung mit meinem Eve Energy-Stecker eingerichtet, der den Verbrauch meldet, aber ich werde verrückt. Ich habe es geschafft, die Spannung, die Stromstärke und die Leistung zu ermitteln, aber ich bekomme den Index einfach nicht hin:

Da der Index nur alle 10 Minuten gemeldet wird, ist das Testen sehr zeitaufwendig. Ich bin jetzt schon seit 1,5 Stunden dran :joy:

Okay, ich habe viel mit dem Entwickler von Matter.js gesprochen, und es liegt wahrscheinlich an meinem Eve Energy-Stecker, der den kumulierten Verbrauchswert nicht hochladen muss.

Ich habe Matterbridge und matterbridge-example-dynamic-platform getestet, aber es funktioniert trotzdem nicht, der Wert wird nicht gesendet…

Ich bin etwas ratlos, was Testgeräte angeht :sweat_smile:

Hallo zusammen,

Leider konnte ich es nicht testen, aber um voranzukommen, habe ich diese Entwicklung in Gladys Assistant 4.65 bereitgestellt, so ist es einfacher, Feedback zu erhalten.

Ich freue mich über Rückmeldungen, ob es funktioniert oder nicht :slight_smile:

cc @jmarandet

Hallo @pierre-gilles,

Bei mir funktioniert es nicht. Ich habe eine Steckdose Nous A8M https://www.domadoo.fr/fr/devices-matter/7147-nous-prise-connectee-wifi-matter-16a-mesure-consommation-a8m.html mit Verbrauchsmessung, aber ich habe keine Rückmeldung in Gladys.

Hier ist ein Screenshot der App der Steckdose, wo ich hier einen Verbrauch von 25W habe. Also ist die Messung OK

In Gladys habe ich nur die Schalterfunktion

Sind alle verfügbaren Funktionen im JSON enthalten?

Kann ich verstehen, warum ich eine der Funktionen, die du hinzugefügt hast, wiederfinden sollte?

image

Hier das JSON

{
    "node_id": "15556639130473728473",
    "is_connected": true,
    "devices": [
      {
        "name": "MA-onoffpluginunit",
        "number": "1",
        "cluster_clients": [
          {
            "id": "3",
            "name": "Identify",
            "attributes": [
              "0",
              "1",
              "65528",
              "65529",
              "65531",
              "65532",
              "65533",
              "identifyTime",
              "identifyType",
              "clusterRevision",
              "featureMap",
              "attributeList",
              "acceptedCommandList",
              "generatedCommandList"
            ],
            "commands": [
              "0",
              "64",
              "identify",
              "triggerEffect"
            ],
            "all_keys": [
              "id",
              "name",
              "revision",
              "_type",
              "supportedFeatures",
              "isUnknown",
              "endpointId",
              "attributes",
              "events",
              "commands",
              "subscribeAllAttributes",
              "_triggerAttributeUpdate",
              "_triggerEventUpdate",
              "isAttributeSupported",
              "isAttributeSupportedByName",
              "isCommandSupported",
              "isCommandSupportedByName",
              "getIdentifyTimeAttribute",
              "setIdentifyTimeAttribute",
              "subscribeIdentifyTimeAttribute",
              "addIdentifyTimeAttributeListener",
              "removeIdentifyTimeAttributeListener",
              "getIdentifyTypeAttribute",
              "setIdentifyTypeAttribute",
              "subscribeIdentifyTypeAttribute",
              "addIdentifyTypeAttributeListener",
              "removeIdentifyTypeAttributeListener",
              "getClusterRevisionAttribute",
              "setClusterRevisionAttribute",
              "subscribeClusterRevisionAttribute",
              "addClusterRevisionAttributeListener",
              "removeClusterRevisionAttributeListener",
              "getFeatureMapAttribute",
              "setFeatureMapAttribute",
              "subscribeFeatureMapAttribute",
              "addFeatureMapAttributeListener",
              "removeFeatureMapAttributeListener",
              "getAttributeListAttribute",
              "setAttributeListAttribute",
              "subscribeAttributeListAttribute",
              "addAttributeListAttributeListener",
              "removeAttributeListAttributeListener",
              "getAcceptedCommandListAttribute",
              "setAcceptedCommandListAttribute",
              "subscribeAcceptedCommandListAttribute",
              "addAcceptedCommandListAttributeListener",
              "removeAcceptedCommandListAttributeListener",
              "getGeneratedCommandListAttribute",
              "setGeneratedCommandListAttribute",
              "subscribeGeneratedCommandListAttribute",
              "addGeneratedCommandListAttributeListener",
              "removeGeneratedCommandListAttributeListener",
              "identify",
              "triggerEffect"
            ]
          },
          {
            "id": "4",
            "name": "Groups",
            "attributes": [
              "0",
              "65528",
              "65529",
              "65531",
              "65532",
              "65533",
              "nameSupport",
              "clusterRevision",
              "featureMap",
              "attributeList",
              "acceptedCommandList",
              "generatedCommandList"
            ],
            "commands": [
              "0",
              "1",
              "2",
              "3",
              "4",
              "5",
              "addGroup",
              "viewGroup",
              "getGroupMembership",
              "removeGroup",
              "removeAllGroups",
              "addGroupIfIdentifying"
            ],
            "all_keys": [
              "id",
              "name",
              "revision",
              "_type",
              "supportedFeatures",
              "isUnknown",
              "endpointId",
              "attributes",
              "events",
              "commands",
              "subscribeAllAttributes",
              "_triggerAttributeUpdate",
              "_triggerEventUpdate",
              "isAttributeSupported",
              "isAttributeSupportedByName",
              "isCommandSupported",
              "isCommandSupportedByName",
              "getNameSupportAttribute",
              "setNameSupportAttribute",
              "subscribeNameSupportAttribute",
              "addNameSupportAttributeListener",
              "removeNameSupportAttributeListener",
              "getClusterRevisionAttribute",
              "setClusterRevisionAttribute",
              "subscribeClusterRevisionAttribute",
              "addClusterRevisionAttributeListener",
              "removeClusterRevisionAttributeListener",
              "getFeatureMapAttribute",
              "setFeatureMapAttribute",
              "subscribeFeatureMapAttribute",
              "addFeatureMapAttributeListener",
              "removeFeatureMapAttributeListener",
              "getAttributeListAttribute",
              "setAttributeListAttribute",
              "subscribeAttributeListAttribute",
              "addAttributeListAttributeListener",
              "removeAttributeListAttributeListener",
              "getAcceptedCommandListAttribute",
              "setAcceptedCommandListAttribute",
              "subscribeAcceptedCommandListAttribute",
              "addAcceptedCommandListAttributeListener",
              "removeAcceptedCommandListAttributeListener",
              "getGeneratedCommandListAttribute",
              "setGeneratedCommandListAttribute",
              "subscribeGeneratedCommandListAttribute",
              "addGeneratedCommandListAttributeListener",
              "removeGeneratedCommandListAttributeListener",
              "addGroup",
              "viewGroup",
              "getGroupMembership",
              "removeGroup",
              "removeAllGroups",
              "addGroupIfIdentifying"
            ]
          },
          {
            "id": "6",
            "name": "OnOff",
            "attributes": [
              "0",
              "16384",
              "16385",
              "16386",
              "16387",
              "65528",
              "65529",
              "65531",
              "65532",
              "65533",
              "onOff",
              "clusterRevision",
              "featureMap",
              "attributeList",
              "acceptedCommandList",
              "generatedCommandList",
              "globalSceneControl",
              "onTime",
              "offWaitTime",
              "startUpOnOff"
            ],
            "commands": [
              "0",
              "1",
              "2",
              "64",
              "65",
              "66",
              "off",
              "on",
              "toggle",
              "offWithEffect",
              "onWithRecallGlobalScene",
              "onWithTimedOff"
            ],
            "all_keys": [
              "id",
              "name",
              "revision",
              "_type",
              "supportedFeatures",
              "isUnknown",
              "endpointId",
              "attributes",
              "events",
              "commands",
              "subscribeAllAttributes",
              "_triggerAttributeUpdate",
              "_triggerEventUpdate",
              "isAttributeSupported",
              "isAttributeSupportedByName",
              "isCommandSupported",
              "isCommandSupportedByName",
              "getOnOffAttribute",
              "setOnOffAttribute",
              "subscribeOnOffAttribute",
              "addOnOffAttributeListener",
              "removeOnOffAttributeListener",
              "getClusterRevisionAttribute",
              "setClusterRevisionAttribute",
              "subscribeClusterRevisionAttribute",
              "addClusterRevisionAttributeListener"},
              "removeClusterRevisionAttributeListener",
              "getFeatureMapAttribute",
              "setFeatureMapAttribute",
              "subscribeFeatureMapAttribute",
              "addFeatureMapAttributeListener",
              "removeFeatureMapAttributeListener",
              "getAttributeListAttribute",
              "setAttributeListAttribute",
              "subscribeAttributeListAttribute",
              "addAttributeListAttributeListener",
              "removeAttributeListAttributeListener",
              "getAcceptedCommandListAttribute",
              "setAcceptedCommandListAttribute",
              "subscribeAcceptedCommandListAttribute",
              "addAcceptedCommandListAttributeListener",
              "removeAcceptedCommandListAttributeListener",
              "getGeneratedCommandListAttribute",
              "setGeneratedCommandListAttribute",
              "subscribeGeneratedCommandListAttribute",
              "addGeneratedCommandListAttributeListener",
              "removeGeneratedCommandListAttributeListener",
              "getGlobalSceneControlAttribute",
              "setGlobalSceneControlAttribute",
              "subscribeGlobalSceneControlAttribute",
              "addGlobalSceneControlAttributeListener",
              "removeGlobalSceneControlAttributeListener",
              "getOnTimeAttribute",
              "setOnTimeAttribute",
              "subscribeOnTimeAttribute",
              "addOnTimeAttributeListener",
              "removeOnTimeAttributeListener",
              "getOffWaitTimeAttribute",
              "setOffWaitTimeAttribute",
              "subscribeOffWaitTimeAttribute",
              "addOffWaitTimeAttributeListener",
              "removeOffWaitTimeAttributeListener",
              "getStartUpOnOffAttribute",
              "setStartUpOnOffAttribute",
              "subscribeStartUpOnOffAttribute",
              "addStartUpOnOffAttributeListener",
              "removeStartUpOnOffAttributeListener",
              "off",
              "on",
              "toggle",
              "offWithEffect",
              "onWithRecallGlobalScene",
              "onWithTimedOff"
            ]
          },
          {
            "id": "29",
            "name": "Descriptor",
            "attributes": [
              "0",
              "1",
              "2",
              "3",
              "4",
              "65528",
              "65529",
              "65531",
              "65532",
              "65533",
              "deviceTypeList",
              "serverList",
              "clientList",
              "partsList",
              "clusterRevision",
              "featureMap",
              "attributeList",
              "acceptedCommandList",
              "generatedCommandList",
              "tagList"
            ],
            "commands": [],
            "all_keys": [
              "id",
              "name",
              "revision",
              "_type",
              "supportedFeatures",
              "isUnknown",
              "endpointId",
              "attributes",
              "events",
              "commands",
              "subscribeAllAttributes",
              "_triggerAttributeUpdate",
              "_triggerEventUpdate",
              "isAttributeSupported",
              "isAttributeSupportedByName",
              "isCommandSupported",
              "isCommandSupportedByName",
              "getDeviceTypeListAttribute",
              "setDeviceTypeListAttribute",
              "subscribeDeviceTypeListAttribute",
              "addDeviceTypeListAttributeListener",
              "removeDeviceTypeListAttributeListener",
              "getServerListAttribute",
              "setServerListAttribute",
              "subscribeServerListAttribute",
              "addServerListAttributeListener",
              "removeServerListAttributeListener",
              "getClientListAttribute",
              "setClientListAttribute",
              "subscribeClientListAttribute",
              "addClientListAttributeListener",
              "removeClientListAttributeListener",
              "getPartsListAttribute",
              "setPartsListAttribute",
              "subscribePartsListAttribute",
              "addPartsListAttributeListener",
              "removePartsListAttributeListener",
              "getClusterRevisionAttribute",
              "setClusterRevisionAttribute",
              "subscribeClusterRevisionAttribute",
              "addClusterRevisionAttributeListener",
              "removeClusterRevisionAttributeListener",
              "getFeatureMapAttribute",
              "setFeatureMapAttribute",
              "subscribeFeatureMapAttribute",
              "addFeatureMapAttributeListener",
              "removeFeatureMapAttributeListener",
              "getAttributeListAttribute",
              "setAttributeListAttribute",
              "subscribeAttributeListAttribute",
              "addAttributeListAttributeListener",
              "removeAttributeListAttributeListener",
              "getAcceptedCommandListAttribute",
              "setAcceptedCommandListAttribute",
              "subscribeAcceptedCommandListAttribute",
              "addAcceptedCommandListAttributeListener",
              "removeAcceptedCommandListAttributeListener",
              "getGeneratedCommandListAttribute",
              "setGeneratedCommandListAttribute",
              "subscribeGeneratedCommandListAttribute",
              "addGeneratedCommandListAttributeListener",
              "removeGeneratedCommandListAttributeListener",
              "getTagListAttribute",
              "setTagListAttribute",
              "subscribeTagListAttribute",
              "addTagListAttributeListener",
              "removeTagListAttributeListener"
            ]
          }
        ],
        "child_endpoints": []
      }
    ],
    "node_information": {
      "vendor_name": "NOUS TECHNOLOGY",
      "product_name": "A8M",
      "product_id": 2268,
      "vendor_id": 5168
    }
  }

Wenn das nicht vorhanden ist, bedeutet das, dass die Steckdose keine Matter-Informationen meldet?

Ich habe die Information auf einem anderen Forum gefunden

‚Die Energieverbrauchserfassung ist nur in Version 1.3 von Matter implementiert.

Solange es kein Firmware-Update gibt, wird der Energieverbrauch nicht über das Matter-Protokoll übertragen.‘

Tatsächlich müssen wir warten, bis NOUS seine Buchse aktualisiert!

Es ist kompliziert zu wissen, was mit Matter verfügbar ist.

Diese Marke unter Zigbee konnte ich direkt mit Zigbee2MQTT paarweise verbinden.

Hier musste ich ein Konto bei Nous erstellen, die Steckdose mit der Nous-App paarweise verbinden und dann die Steckdose mit Matter teilen. Eine echte Schinderei……

Erstes Matter-Komponente für mich und schlechte Erfahrung……

Heißt das, ein WLAN+Matter-Gerät ist viel komplizierter in die Integration als ein Thread+Matter-Gerät? Ich dachte, das wäre Plug’n’Play :frowning:
Es ist klar, dass es lästig wird, wenn man für jede Marke ein Konto erstellen muss.

Das hängt tatsächlich von den Marken ab.

Einige Marken spielen mit bei Matter, andere bevorzugen es, ihre eigene Anwendung durchzusetzen.

Bei Eve zum Beispiel kannst du alle ihre Produkte von A bis Z ohne Anwendung nutzen:

Aber wir sind noch am Anfang mit Matter, die Marken testen noch.

Als Verbraucher ist es auch unsere Aufgabe, uns bei den Marken zu beschweren und nach lokalen Lösungen ohne Anwendungen zu fragen :slightly_smiling_face:

Aber das hat nicht viel mit Matter zu tun, das ist schließlich ein rein lokales Protokoll.

Eve => Thread => kein Konto erstellen
Wir => Wifi => Konto erstellen

Nur weil eine Steckdose WLAN-fähig ist, muss sie nicht zwangsläufig die Erstellung eines Kontos erfordern. Man könnte denselben Prozess wie bei der Eve-Thread-Steckdose für eine WLAN-Matter-Steckdose haben… das ist eine Entscheidung des Herstellers.

@pierre-gilles, ich komme auf meine NOUS A8M Matter WiFi-Anbindung zurück, die ich in Gladys gepairt habe.

Der Schalter wird korrekt erkannt, aber ich habe nicht alle Daten zur Verbrauchsaufzeichnung, Stromstärke und Spannung.

Zum Test habe ich die Matter-Integration in Home Assistant hinzugefügt. Dort werden alle Daten korrekt erkannt. Warum nicht in Gladys?
Ich wäre nach deiner Rückkehr aus dem Urlaub daran interessiert, den Grund zu verstehen.

Also habe ich ein bisschen auf meiner Seite gesucht, da Home Assistant auch das Herunterladen einer JSON-Datei ermöglicht. Ich könnte sie dir geben, falls nötig.
Ich habe diese JSON-Datei einer KI gegeben und hier ist ihre Schlussfolgerung: Hier wird ein herstellerspezifisches Cluster verwendet:

Basierend auf der von Ihnen bereitgestellten JSON-Datei handelt es sich um eine sehr interessante Analyse. Sie verwenden Home Assistant 2025.12 und das betreffende Gerät ist ein Produkt der Marke NOUS TECHNOLOGY.

Hier sind die Funktionen, die ich aus der Analyse der Cluster und Attribute des "Node 2" ableiten konnte:

1. Geräteidentifikation
Hersteller: NOUS TECHNOLOGY (Attribut 0/40/1)

Modell: A8M (Attribut 0/40/3)

Gerätetyp: Steckdose (On/Off Plug-in Unit).

Der Code 266 (also 0x010A), der im Descriptor-Cluster des Endpunkts 1 gefunden wurde, bestätigt, dass es sich um eine Leistungsschalteinheit handelt.

2. Steuerfunktionen (Endpoint 1)
Der Endpunkt 1 ist derjenige, der den "Smart-Home"-Aspekt der Steckdose verwaltet:

Schalten (Cluster 0x0006 - On/Off):

Das Gerät kann ein- und ausgeschaltet werden.

Aktueller Zustand: Die Steckdose ist derzeit ausgeschaltet ("1/6/0": false).

Zustandsspeicher: Sie unterstützt die Konfiguration des Zustands nach einem Stromausfall (Attribute 16384 und folgende).

Identifikation (Cluster 0x0003):

Sie können die LED der Steckdose zum Blinken bringen, um sie physisch von anderen zu identifizieren.

Gruppenverwaltung (Cluster 0x0004):

Sie kann Gruppen zugewiesen werden, um gleichzeitig mit anderen Steckdosen gesteuert zu werden.

3. Verbrauchsmessung (Hersteller-Cluster)
Hier wird es interessant. Man sieht einen Cluster mit einer sehr hohen ID: 308149265 (0x125B0011).

Im aktuellen Matter-Ökosystem (Version 1.0 bis 1.3) war die Energiemessung noch nicht für alle gleich standardisiert. NOUS verwendet hier ein herstellerspezifisches Cluster, um die elektrischen Informationen zu übertragen. Basierend auf den Rohwerten in der JSON-Datei (1/308149265/...) meldet die Steckdose:

Spannung: Wahrscheinlich das Attribut 308084772 (Wert 2249, also 224,9V).

Stromstärke: Wahrscheinlich das Attribut 308084774 (Wert 542, also 54,2 mA).

Leistung (Watt): Die anderen Attribute entsprechen der aktiven Leistung und dem kumulierten Verbrauch (kWh).

4. Konnektivität und Gesundheit
Protokoll: Es handelt sich um eine Matter-over-WiFi-Steckdose. Das sieht man daran, dass der Network-Commissioning-Cluster (0/49) vorhanden und für Wi-Fi konfiguriert ist, im Gegensatz zu Thread, das hier nicht als aktiv erscheint.

Signal: Die Steckdose meldet einen RSSI von -34 (0/54/4), was eine ausgezeichnete Wi-Fi-Verbindung anzeigt (sehr nah am Access Point).

In der JSON-Datei Ihrer NOUS A8M-Steckdose:

Das Gerät wurde entworfen oder zertifiziert, bevor Matter 1.3 allgemein verbreitet war, oder der Hersteller hat sich entschieden, sein eigenes Cluster zu verwenden, um die Kompatibilität mit seinen alten Systemen zu gewährleisten.

Deshalb sehen Sie IDs wie 308084772 (die eine proprietäre ID ist) anstelle der Standard-ID 2 für die Spannung.

Wie geht Home Assistant damit um?
Home Assistant verfügt über "Übersetzer" (die als Discovery Schemas bezeichnet werden).

Wenn die ID 0x0090 ist, erstellt Home Assistant automatisch die Leistungssensoren.

Für proprietäre IDs (wie Ihre) muss die Matter-Integration von Home Assistant eine spezifische Regel enthalten, die besagt: "Wenn es sich um eine NOUS-Steckdose handelt, dann entspricht das Attribut X der Spannung".

Hallo @Will_71,

Vielen Dank für deine Untersuchung, es ist sehr klar, was passiert :+1:

NOUS hat die Energienachverfolgung vor der offiziellen Integration in Matter 1.3 implementiert. Es handelt sich also um eine eigene NOUS-Implementierung und nicht um eine Standard-Matter-Funktion.

Home Assistant kann diesen Wert abrufen, weil sie eine spezifische Schicht für NOUS entwickelt haben, um diesen besonderen Fall außerhalb der Matter-Spezifikation zu verwalten.

Auf unserer Seite arbeitet Gladys nicht direkt mit Matter: Wir stützen uns auf die offizielle JavaScript-Abhängigkeit matter-js

:backhand_index_pointing_right: GitHub - matter-js/matter.js: A complete typescript implementation of the Matter protocol specification (https://buildwithmatter.com). Includes full support for controller, device, commissioning, secure communications, device types, and cluster definitions. · GitHub

Ich weiß nicht, ob diese Bibliothek den Zugriff auf nicht offizielle / nicht standardmäßige Attribute erleichtert.

Persönlich frage ich mich auch, ob es sinnvoll ist, Zeit in solche Spezifika zu investieren. Für mich ist das ein bisschen das Gegenteil von Matter: Das Ziel ist es, die Verhaltensweisen zwischen den Herstellern zu vereinheitlichen. Wenn wir nicht offizielle Matter-Implementierungen fördern, könnte dies dazu führen, dass diese Praktiken fortbestehen und die Initiative diskreditieren.

Ich bin übrigens ziemlich überrascht von der Position von Home Assistant in dieser Angelegenheit: Als ein wichtiger Akteur im Ökosystem könnten sie auch ein Beispiel für die strikte Einhaltung der Spezifikationen geben.

Könntest du zunächst NOUS kontaktieren und sie fragen, ob ein Firmware-Update geplant ist, das mit Matter 1.3 konform ist?

Nochmals vielen Dank für dein sehr detailliertes Feedback :slightly_smiling_face:

@Will_71 Ich werde diesen Feature-Request schließen, da wir den Stromverbrauch von Matter-Native-Geräten bereits gut verwalten, der PR Matter: Add electricity consumption features by Pierre-Gilles · Pull Request #2365 · GladysAssistant/Gladys · GitHub wurde im November letzten Jahres gemerged.

Können wir die Diskussion für dein Gerät in einem separaten Thema fortsetzen? :slight_smile: