Matter commissioning potentially uses link-local addresses
Home Assistant Android app version(s):
Android version(s): Android 14
Device model(s): Pixel 8 Pro
Home Assistant version: 2024.8.0.dev202407190220
Last working Home Assistant release (if known):
Description of problem, include YAML if issue is related to notifications:
The current Matter commissioning flow simply returns a pin and IP address. The first implementation passed just the pin, which was problematic as it contains no Matter discriminator. This mean, if two devices were commissionable on the network, the Matter Server potentially picked the wrong device, which made the commissioning to fail (see https://github.com/home-assistant-libs/python-matter-server/issues/463).
Since #4069 we pass also the IPv6 address, which makes this work better. However, if the Android Matter commissioning flow returns a link-local IPv6 address, the Server can't reliably determine which network to use. A work around which scopes the link-local IPv6 addresses server side (see https://github.com/home-assistant-libs/python-matter-server/pull/501) makes it work for the common case (single network interface). However, this means that Matter devices can only be reliably commissioned using Android if they are on the primary network. This is tricky for advanced use cases (e.g. dual-home installation with a separate IoT VLAN, which is not the primary network).
Transporting IPv6 link-local addresses to the Server is really a hack. The underlying Matter SDK API to commission a Matter device through an IP address (ConnectIP) is also deprecated.
The Android App should really communicate a setup code/QR code or a pin code with discriminator to the backend. We should check if there are alternative APIs available, or if we can determine the discriminator somehow using the current API.
Companion App Logs:
Screenshot or video of problem:
Additional information:
While I understand this being logged as a bug, the Play Services Matter SDK hasn't changed since release and doesn't return the discriminator. Alternative APIs would be implementing the entire Matter SDK (not Google's Android interfaces) in the app then?
Yeah so my hope is that the Play Services Matter SDK eventually gains that feature. I think what would be good is if we can log that as an official bug/feature request. I can also reach out to some folks and reference that issue so we can get this going.
An alternative could be to implement a simple mDNS reverse lookup in the App. Essentially just look up all commissionable devices, compare IP addresses, and then extract the Discriminator from there. It feels very hacky though :cry:
Implementing the entire Matter SDK ourselfs would be cool, but is really a rather big undertaking. We'd need to make it compile/work with Android, test/validate and certify it. This is no easy feat :cry:
@jpelgrom what I was wondering, we currently have multiple ways to commission a device:
- Half-screen pop-up (if devices are advertising a commissionable device via Bluetooth nearby)
- QR code scanner (at least on Pixel that works)
- In App
The problem is only in-App. So the first two methods use a different flow. From what I understand, for that flow we just get a callback. But maybe that flow can be triggered somehow? :thinking: At least the QR code scanner seems to be able to do that...
we currently have multiple ways to commission a device: (...) * QR code scanner (at least on Pixel that works)
I wasn't aware of that, nice find!
But maybe that flow can be triggered somehow? 🤔 At least the QR code scanner seems to be able to do that...
After testing it, yes it seems like we can trigger it. The camera sends an intent to view a scanned MT:xxxxxxxxxxxxxxxxxxx code, Google Play Services will respond and trigger the commissioning flow.
To test I used: adb shell am start -a "android.intent.action.VIEW" -d "MT:xxxxxxxxxxxxxxxxxxx" which works and suggests using it isn't limited to Google apps.
From the Play Services manifest:
<activity-alias
android:name="com.google.android.gms.home.SetupDeviceActivityQrCode"
android:enabled="true"
android:exported="true"
android:targetActivity="com.google.android.gms.home.SetupDeviceActivity">
<intent-filter>
<data
android:scheme="MT"
android:pathPattern="[A-Z0-9-.]{19,}"/>
<category
android:name="android.intent.category.DEFAULT"/>
<action
android:name="android.intent.action.VIEW"/>
</intent-filter>
</activity-alias>
I guess it would be worth it, now that the app has a native QR code scanner, to see if using this flow improves the commissioning reliability for users? It is undocumented, but if it works reliably that might also be nice so that commissioning with HA Android always works the same.
I seem to have that issue. I have a matter device I'd like to pair and I do see in the matter server logs that the commissioning fails since it cannot connect to the devices link-local address. I would prefer all matter devices to use non-link local addresses (all my others do, this one apparently doesn't) but I understand this must be tolerated.
So I did give homeassistant an additional interface in my IoT Vlan with only IPv6 configured statically. That by itself was harder than neccessary since it seems even though static method is used HA happily accepts gateways and dns info from autoconfiguration. This is a bug itself, I guess.
But in the end I did manage to get the IoT interface enp6s19 to only have a link-local address for HA to reach matter devices that only support that.
My problem: HA still tries the first (other) interface enp6s18 which I can see in the log:
2025-03-06 13:27:54.213 (MainThread) INFO [matter_server.server.device_controller] Starting Matter commissioning using Node ID 11 and IP fe80::8e87:affe:affe:1726%enp6s18.
In Settings -> Network I do have both interfaces selected for multicast traffic, in case that info is used by matter.
Actually I'd suggest that matter would use that info and try to reach link-local IPs on all interfaces which are configured to for integrations to be used in the network settings like that: