home-assistant / android

:iphone: Home Assistant Companion for Android
https://companion.home-assistant.io/
Apache License 2.0
2.23k stars 623 forks source link

Matter commissioning potentially uses link-local addresses #4528

Open agners opened 1 month ago

agners commented 1 month ago

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:

jpelgrom commented 1 month ago

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?

agners commented 1 month ago

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:

agners commented 1 month ago

@jpelgrom what I was wondering, we currently have multiple ways to commission a device:

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...

jpelgrom commented 1 month ago

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.