Matter Binding

So I’m trying this, and was able to pair the OTBR from the openHAB UI. After this it said that the device had been added to the inbox, however it does not appear there or anywhere else.

In the logs I can regularly see openHAB talking to the OTBR:


2025-08-03 16:19:52.285 [TRACE] [ternal.client.MatterWebsocketService] - MessageExchange: New exchange channel: udp://[fe80::de1e:d5ff:feae:fda0%enp0s25]:5540 on session secure/59092 protocol: 1 exId: 25173 sess: secure/59092 peerSess: 59092 SAT: 4000 SAI: 800 SII: 800 maxTrans: 5 MRP
2025-08-03 16:19:52.285 [TRACE] [ternal.client.MatterWebsocketService] - MessageExchange: Message « for: I/ReportData msgId: 59092/25173/134628030 type: 0x1/0x5 reqAck size: 11 payload: 152600932cc32d24ff0c18
2025-08-03 16:19:52.286 [TRACE] [ternal.client.MatterWebsocketService] - MessageChannel: Message » for: I/StatusResponse status: Success(0x0) subId: 767765651 empty msgId: 59092/25173/250935005 type: 0x1/0x1 acked: 134628030 reqAck size: 8 payload: 1524000024ff0c18
2025-08-03 16:19:52.305 [TRACE] [ternal.client.MatterWebsocketService] - MessageExchange: Message « for: SC/StandaloneAck msgId: 59092/25173/134628031 type: 0x0/0x10 acked: 250935005

And I see corresponding logs on the OTBR device, so it looks like they are talking to each other. I also see in the openHAB logs that commissioning seems to have succeeded, and I have a node ID. It’s just that the node isn’t showing up anywhere.

Some more logs from commissioning:

2025-08-03 15:47:36.450 [TRACE] [ternal.client.MatterWebsocketService] - CommissioningController: Connecting to node 17164787669940316652...
2025-08-03 15:47:36.452 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Created paired node with device data undefined
2025-08-03 15:47:36.454 [TRACE] [ternal.client.MatterWebsocketService] - InteractionClient: Sending read request: attributes: 0x0/BasicInformation(0x28)/*, 0x0/Descriptor(0x1d)/serverList(0x1), */NetworkCommissioning(0x31)/0xfffc, */NetworkCommissioning(0x31)/0x1, */NetworkCommissioning(0x31)/0x4, */PowerSource(0x2f)/0xfffc, */PowerSource(0x2f)/0x0, 0x0/ThreadNetworkDiagnostics(0x35)/routingRole(0x1) and events: undefined

2025-08-03 15:47:37.130 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Creating device 0 {"29":{"deviceTypeList":[{"deviceType":22,"revision":3},{"deviceType":18,"revision":1}],"serverList":[29,31,40,48,49,51,60,62,63,42],"clientList":[41],"partsList":[1],"generatedCommandList":[],"acceptedCommandList":[],"attributeList":[0,1,2,3,65532,65533,65528,65529,65531],"featureMap":{"tagList":false},"clusterRevision":3},"31":{"acl":[{"privilege":5,"authMode":2,"subjects":["13045821003508705553"],"targets":null,"fabricIndex":1}],"subjectsPerAccessControlEntry":4,"targetsPerAccessControlEntry":3,"accessControlEntriesPerFabric":4,"generatedCommandList":[],"acceptedCommandList":[],"attributeList":[0,2,4,3,65532,65533,65528,65529,65531],"featureMap":{"extension":false,"managedDevice":false},"clusterRevision":2},"40":{"dataModelRevision":19,"vendorName":"TEST_VENDOR","vendorId":65521,"productName":"TEST_PRODUCT","productId":32768,"nodeLabel":"","location":"XX","hardwareVersion":0,"hardwareVersionString":"TEST_VERSION","softwareVersion":0,"softwareVersionString":"ec9699b","uniqueId":"581DC7E9E25B308F","capabilityMinima":{"caseSessionsPerFabric":3,"subscriptionsPerFabric":3},"specificationVersion":17104896,"maxPathsPerInvoke":1,"generatedCommandList":[],"acceptedCommandList":[],"attributeList":[65532,0,6,1,2,3,4,7,8,9,10,18,19,21,22,65533,5,65528,65 ...

025-08-03 15:47:37.143 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: NodeId 17164787669940316652: Device type with code 145 not known, use 
generic replacement.
2025-08-03 15:47:37.145 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Endpoints from PartsLists [[0,[1]],[1,[]]]
2025-08-03 15:47:37.146 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Endpoint usages {"1":[0]}
2025-08-03 15:47:37.146 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Processing Endpoint [["1",[0]]]
2025-08-03 15:47:37.146 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Endpoint structure: Child: 1 -> Parent: 0
2025-08-03 15:47:37.147 [TRACE] [ternal.client.MatterWebsocketService] - PairedNode: Node 17164787669940316652: Endpoint data Cleanup {"0":true}

2025-08-03 15:47:37.193 [TRACE] [ternal.client.MatterWebsocketService] - Commissioned Node: 17164787669940316652
2025-08-03 15:47:37.194 [TRACE] [ternal.client.MatterWebsocketService] - matter: Sending response: {"type":"response","message":{"type":"resultSuccess","id
":"b47f61e0-ca91-4e0b-a711-3e60307aba27","result":"17164787669940316652","error":"undefined","errorId":"undefined"}}
2025-08-03 15:47:37.194 [DEBUG] [al.controller.MatterControllerClient] - onWebSocketText {"type":"response","message":{"type":"resultSuccess","id":"b47f61e
0-ca91-4e0b-a711-3e60307aba27","result":"17164787669940316652","error":"undefined","errorId":"undefined"}}
2025-08-03 15:47:37.195 [DEBUG] [al.controller.MatterControllerClient] - result type: resultSuccess 
2025-08-03 15:47:37.195 [DEBUG] [r.internal.handler.ControllerHandler] - updateNode BEGIN 17164787669940316652

Here is perhaps something suspicious, after openHAB restart:

2025-08-03 17:32:38.213 [TRACE] [ternal.client.MatterWebsocketService] - MessageExchange: New exchange channel: udp://[fe80::de1e:d5ff:feae:fda0%enp0s25]:5540 on session secure/37537 protocol: 1 exId: 28974 sess: secure/37537 peerSess: 37537 SAT: 4000 SAI: 800 SII: 800 maxTrans: 5 MRP
2025-08-03 17:32:38.214 [TRACE] [ternal.client.MatterWebsocketService] - MessageExchange: Message « for: I/ReportData msgId: 37537/28974/199714383 type: 0x1/0x5 reqAck size: 1174 payload: 15260095dc88cd360115350126001d508f81370124020024031d2404001836021524001624010318152400122401011818181815350126001d508f81370124020024031d240401183602041d041f0428043004310433043c043e043f042a18181815350126001d508f81370124020024031d240402183602042918181815350126001d508f81370124020024031d240403183602040118181815350126001d508f81370124020024031d2504fcff18240200181815350126001d508f81370124020024031d2504fdff18240203181815350126001d508f81370124020024031d2504f8ff18360218181815350126001d508f81370124020024031d2504f9ff18360218181815350126001d508f81370124020024031d2504fbff183602040004010402040305fcff05fdff05f8ff05f9ff05fbff1818181535012600f9e27e67370124020024031f240400183602152401052402023603071169773d15110cb518340424fe01181818181535012600f9e27e67370124020024031f2404021824020418181535012600f9e27e67370124020024031f2404041824020418181535012600f9e27e67370124020024031f2404031824020318181535012600f9e27e67370124020024031f2504fcff1824020018181535012600f9e27e67370124020024031f2504fdff1824020218181535012600f9e27e67370124020024031f2504f8ff1836021818181535012600f9e27e67370124020024031f2504f9ff1836021818181535012600f9e27e67370124020024031f2504fbff183602040004020404040305fcff05fdff05f8ff05f9ff05fbff181818153501260031bdd44a37012402002403282504fcff182402001818153501260031bdd44a3701240200240328240400182402131818153501260031bdd44a3701240200240328240406182c020258581818153501260031bdd44a3701240200240328240401182c020b544553545f56454e444f521818153501260031bdd44a3701240200240328240402182502f1ff1818153501260031bdd44a3701240200240328240403182c020c544553545f50524f445543541818153501260031bdd44a370124020024032824040418250200801818153501260031bdd44a3701240200240328240407182402001818153501260031bdd44a3701240200240328240408182c020c544553545f56455253494f4e1818153501260031bdd44a3701240200240328240409182402001818153501260031bdd44a370124020024032824040a182c0207656339363939621818153501260031bdd44a3701240200240328240412182c0210353932374430463730434635373545451818153501260031bdd44a3701240200240328240413183502240003240103181818153501260031bdd44a3701240200240328240415182602000005011818153501260031bdd44a3701240200240328240416182402011818153501260031bdd44a37012402002403282504fdff182402051818153501260031bdd44a3701240200240328240405182c02001818153501260031bdd44a37012402002403282504f8ff183602181818153501260031bdd44a37012402002403282504f9ff18360218181818290324ff0c18
2025-08-03 17:32:38.219 [TRACE] [ternal.client.MatterWebsocketService] - MessageChannel: Message » for: I/StatusResponse status: InvalidSubscription(0x7d) subId: 3448298645 msgId: 37537/28974/166256473 type: 0x1/0x1 acked: 199714383 reqAck size: 8 payload: 1524007d24ff0c18
2025-08-03 17:32:38.282 [TRACE] [ternal.client.MatterWebsocketService] - MessageExchange: Message « for: SC/StandaloneAck msgId: 37537/28974/199714384 type: 0x0/0x10 acked: 166256473
2025-08-03 17:32:38.284 [TRACE] [ternal.client.MatterWebsocketService] - ExchangeManager: Error on channel udp://[fe80::de1e:d5ff:feae:fda0%enp0s25]:5540: Invalid Data report with unexpected subscription ID 3448298645

Hi @marcusb are you adding the OTBR as an IP matter device itself ? or are you adding a thread device to openHAB through the OTBR? If you are pairing as an IP matter device, how did you provision it on your network ?

Also it would be helpful to have all the logs, the snippets you pasted don’t have enough information for me to help. Can you pause your controller thing, then unpause it, and send me all the TRACE logs after that (for the next few mins or until it calms down)?

Yes. No Thread devices involved yet.

And as I was collecting the logs, I figured I would factory reset the OTBR and pair again. And this time it worked! (I’ve already tried this before so no idea why it only worked the second time.)

I now have the thing configured, and can see the “Thread Border Router Operational Dataset” settings in openHAB. So I can go ahead and configure the Thread network now.

Thats great. Couple things.

Just to state the obvious, a Thread Operational Dataset is the record used by the OTBR to manage its thread network

A “Pending” dataset is one that is “staged” to become active after X amount of milliseconds, the OTBR handles pushing this to all its thread devices during this window, so when it does become active after X millseconds, they all migrate to the new config (otherwise they would become disconnected and need pairing again). Typically if you have battery thread devices, you would make this longer as they need to “wake up” to get it before the set goes live.

You can generate a new data set (the defaults are fine), an optionally save it to the thing (so not yet pushed), see screenshot. When ready, you can use the “Push Local Operational Dataset” action, which allows you to adjust how long the devices waits until it make it active. (if no thread devices yet, you can make this short)

Many of these actions are for debugging and testing, again i don’t know of any ecosystem that yet support the Matter TBR clusters yet like we do, so this is uncharted waters……

Good Luck!

image

Hi Dan, the firmware of the Tapo P110M was updated probably very recently to support power management through Matter. After restarting OH, a power management group with 7 channels appeared. The “active power” channel works well. Bravo.

The 4 energy channels are not very clear to me and there is no channel description. What is imported vs exported? What is the applicable period?

Firmware of lightbulb L535E should also be updated (not yet), I will then report.

I’m guessing from the 7 channels total that there are 2 different clusters here? One for ElectricalEnergyMeasurement(3 channels) and one for ElectricalPowerMeasurement(4 channels) ? I don’t have any devices myself that support these, so i’m not super familiar with real world usage, just some feedback from the beta testing period.

Until i can update the docs, you can take a look at the cluster generated classes for an explanation of the channels, i purposely included the docs from the spec as javadoc comments to help with stuff like this. You’ll see the channel names use the clusterName-attrbuteName format, like electricalpowermeasurement-activepower

Here are the relevant generated spec classes:

ElectricalEnergyMeasurementCluster

ElectricalPowerMeasurementCluster

Hopefully a restart is not necessary, when the device comes online (from offline) it should update its channel and channel groups to reflect the current device capabilities. If that didn’t work, i need to take a look why.

@digitaldan

My matter controller didn’t start today. Status: “Handler Missing.” The error message in the log was: “could not download node.js”.
After some searching, I was able to trace this to a internal IPv6 network issue. Unfortunately, even after resolving the problem, the matter controller remained offline because the handle doesn’t retry starting cyclically. The problem could only be resolved by restarting openHAB.

Wouldn’t it make sense to implement a retry here ?

The problem can be easily reproduced by starting openHAB without an IPv6 internet connection.

i don’t think thats really the issue, if it could not download node, it had issues with internet access in general (DNS, no routes, etc…) , it only uses iPV6 when the matter network is brought by the nodejs app (so that has to be running already) , and afaik, the binding can be used with just IPV4, but obviously will only work with matter devices that also support ipv4 (which is very few, and not officially supported by matter).

There probably could use some hardening of the osgi service that provides the runtime and ultimately downloads a nodejs verison, its not something i have had to look at in a while, but i’ll put it on my list.

The log file does not look like.

Level was ERROR, log is from start of openHAB with IPv4 internet connection but without IPv6 internet connection. Local IPv6 was OK.

matter.log (36.2 KB)

Could not connect to nodejs.org/[2606:4700:10:0:0:0:ac42:8046]:443

Download of nodej.s is over IPv6.

This sounds like a local issue to your specific setup, java is resolving a IPV6 address for the domain so something in your environment is resolving that , but since you don’t have ipv6 working it fails. this has nothing to do with the binding, there is absolutely nothing in the java code that deals with IPV6, thats entirely handled within the nodejs Typescript app . Something there sounds like it was half configured for IPV6 at the OS level (it should never resolve an IPV6 address if there is no IPV6 support, but yet it was).

1 Like

Thanks for the tip, you’re absolutely right. After restarting my DNS server, I can no longer reproduce the problem.

2 Likes

Excellent, and i did move some code around to ensure the download function gets included in the general retry mechanism that already exists in the node runtime service, not sure why i did not have it there in the first place since thats probably the thing that is most likely to fail

2 Likes

Dan,

Would like your opinion on something. I plan on purchasing some roller shades soon. These have the option of using z-wave (Which I already use extensively) or Matter.

Is using Matter a preferred choice since it is the latest, and presumable greatest, technology?

Scott

If it were me, then yes i am primarily only buying Matter devices if a choice is available, IMHO, its momentum is quickly building and its what nearly all the big players are focusing on (Apple, Google, Ikea, TP-Link, etc….) Plus the Matter binding supports almost everything out there, and is easy to add new device features too (although take that with some salt coming from me)

The question i would ask is if the blinds are Wifi or Thread? And what Vendor? If its Wifi, then its pretty plug and play. If its Thread, you need a Thread router within range of the device (similar to zigbee or z-wave range), so recent Apple TVs/Home Pods, Certain Gen6 Echos, Recent Google Home Hubs, ikea dirigera hub or Aqara Hub to name a few.

Thread works great, and is an important part of the matter ecosystem (especially for battery devices) , but requires a little extra work (which frustrates the reddit crowd apparently).

1 Like

When the firmware of the Tapo lightbulb will be updated, I will try to just disable/reenable the corresponding thing.

I’m guessing from the 7 channels total that there are 2 different clusters here? One for ElectricalEnergyMeasurement(3 channels) and one for ElectricalPowerMeasurement(4 channels) ? I don’t have any devices myself that support these, so i’m not super familiar with real world usage, just some feedback from the beta testing period.

Here is what I get:

image

I would expect a different label for the four “Energy” channels.

Until i can update the docs, you can take a look at the cluster generated classes for an explanation of the channels, i purposely included the docs from the spec as javadoc comments to help with stuff like this

To be honest with you, it is no more clear after reading that…

The two “exported” channels remain to 0 in my case. Maybe “exported” is for energy production while “imported” is for energy consumption ?

In the Tapo app, you can get energy consumption for different periods, like day by day for example. The values provided by Matter do not match obviously values provided by the Tapo app.

Could it mean energy imported into the Tapo socket and energy exported from the socket to the connected device? The difference would be the energy consumed by the electronics within the plug itself? Just a guess on my part, I assume the plug doesn’t measure energy fed back into the home wiring from a battery or solar panel.

I imagine the data exported via Matter is simple total power consumed and instantaneous energy conumption, The day by day consumption in the Tapo app would be calculated by rules on the plug itself and presented in the Tapo app. Unless there are Matter clusters/fields that export that sort of info?

I have one of these plugs and an Amazon Echo that supports Matter. I’ll spin up an OH5 VM and try and add the plug as a thing when I get home.

In fact, the value in cumulative imported is consistent with Tapo consumption when I sum up 2024 + 2025. So yes it is the total consumed since ever.

And yes the other is certainly the instantaneous consumption as it switches to 0 when I switch off the socket.

Mayb the 2 exported channels should be advanced channels until we understand what they are for ?