aiohomekit
aiohomekit copied to clipboard
Examine Thread provisioning for Apple networks
I've got a HomePod Mini on order. I'm going to see how the Home app provisions Nanoleaf Essentials bulbs onto Apple Thread networks.
Finally, some progress... I just needed a BLE "fake bulb" app, no biggie π With the HomePod Mini paired to the Home app, a newly-paired BLE bulb gets sent this tlv8:
HAPThreadControlPoint write: 000262770008000103010103090101
PDU: control=0x0 opcode=0x2 tid=0x62 iid=119 datalen=8 data=0103010103090101
hap_write new_val=0103010103090101
_set_value format=0x1B value.bytes=0103010103090101
Response PDU: 0262000000
HAPThreadControlPoint read
Now, to repeat that to a real bulb & we'll see what we get. Rinse & repeat.
Repeating those bytes to a bulb gave me identical tlv8 to the already-discovered Nanoleaf th/tc
control, just wrapped in a HAP Param Value rather than the Nanoleaf command/response TLVs. Interesting.
[
<1, [
<2, [
<1, b'NanoleafThread56'>,
<2, b'... channel, 2 bytes ...']>,
<3, b'... PAN ID, 2 bytes ...'>,
<4, b'... ext PAN ID, 8 bytes ...'>,
]>,
]>,
]
Good stuff! As soon i saw the TLVs you found for th/tc
I was sure they were going to rock up on this endpoint.
Even more hopeful that we can fully provision a thread mesh purely with aiohomekit. Will start thinking about how this should look in Home Assistant.
We might ultimately want some top level feature in HA for managing Thread networks so that e.g. people wanting to run an open source thread router as a HA add on can then drop their Nanoleaf accessories onto it.
But in the short term, i think it's either going to have to be on the CLI or via custom service calls. It's not like we can have a "move to thread" button or switch because we need to know the details of the mesh.
(https://twitter.com/falstaff_ch/status/1494755206566924289 for someone working on OTBR for HA)
Nice! I've still got to figure out what tags 1 and 3 are but it looks pretty straight-forward to send network credentials. A custom service call might make sense, I've seen that for other integrations. I know you were working on having pairings be multi-protocol, is there work left to do there?
Yes, unfortuantely.
The old code just routed the load operation to the right code based on the connect type string in the config entry.
The new idea was to instead give each backend the chance to provide a Pairing object for a given device id, and that Thread would have priority over BLE if it was available. I think that sort of happens now, but the backends will only consider the connection type string in the config entry. So it would need to look in the discovery data instead or we'd have to mark it as capable of Thread and BLE or something.
Right now its difficult to consider the thread enabled characteristic without layer violations. I'm hoping we can fix that and then respect the characteristic setting.
A more advanced version of that would be that a new multiprotocol class could be returned that would be able to switch protocol at runtime.
I'm doing some πΊπ¦ stuff thats eating all my time right now, so i've not been able to get any of the tests written I wanted to. Not even had chance to try and set up my Nanoleaf gear with my first thread network yet either.
Responding to the initial TLV
[
<1, b'\x01\x01\x03'>,
<9, b'\x01'>,
]
with an empty HAP Param Value TLV 0100
causes the Home app to attempt a provision of the HomePod Mini network creds:
HAPThreadControlPoint write: <redacted>
PDU: control=0x0 opcode=0x2 tid=0x4D iid=119 datalen=69 data=<redacted>
THREAD CONTROL hap_write new_val=<redacted>
[
<1, b'... redacted tlv8 bytes in a HAP Param Value, decoded below ...'>,
<9, b'\x01'>,
]
[
<1, b'\x01'>,
<2, [
<1, ... str network name ...>,
<2, ... int channel ...>,
<3, ... int PAN ID ...>,
<4, ... int extended PAN ID ...>,
<5, b'... key bytes ...'>,
]>,
<3, b'\x00'>,
]
TODO
- test iOS Home Thread credentials again with TLV tag 3 set to 0 and 1
- find a good way to discover devices that have successfully joined Thread & are no longer available over BLE
- make sure that, although comms switch to CoAP/Thread, if the BR goes down that HA can find the device over BLE again
Happy for suggestions on 2 and 3.
Anything else jump out at you @Jc2k from a high-level perspective or from my WIP HA/core branch?
I haven't looked yet but was originally thinking a proxy that implements the AbstractPairing and picks the best actual pairing.
If there was a exception like AccessoryNotFound or not connected it would try the next backend.
And then eventually with the refactoring that is in progress the idea is that each controller when started will track devices it can talk to, so the proxy will be able to get availability updates from that so it would try the ones it thought was available in priority order.
Although there are a lot of details here, I'd want to get @bdraco involved in the design as he has been doing a lot of heavy lifting recently while I'm distracted by a baby.
A simpler option could be we confirm that the device joined the thread network successfully and then switch it from BLE to CoAP and there's no magic failover - punt that to V2 and make sure everything is stable before we add that layer.
Just had a quick look at https://github.com/home-assistant/core/compare/dev...roysjosh:core:hap-thread-provision. It's not much code is it! So used to the handshakes in HAP i thought there would be a 6 step dance, but its barely different to setting a WiFi password!
Some thoughts:
- I assume this was next, but we should add this to aiohomekit, on the pairing class.
- Can you try adapting this for the IP backend? I assume we can provision border routers with the same API?
- And for completeness, does it work for the CoAP backend? (Hypothetical stupid example - if you wanted to rename your thread network)
- Do you know if the secret key has any cryptographic properties (like is it really a key that needs generating with certain parameters), or is it definitely random data, or do we just not know? Do you think we can generate our own PAN ID etc or do we have to let a Thread device set them up and pick a channel?
Congrats on the distraction! Yes, the plan is to move it to aiohomekit's pairing classes. This was just quicker to test :) I'll see about the IP backend. I don't know if this code will provision a Border Router & start up a new network or not. Today, all of the values are grabbed from the Android Nanoleaf app (iOS hides a few of the values) so we aren't responsible for picking them.
Cheers :)
For Thread nubs like me :)
https://openthread.io/guides/thread-primer/network-discovery
Covers what a PAN ID etc is.
- Supposed to pick least busy channel
- Supposed to pick a PAN ID that is not in use
- Both of these mean that something with a thread radio seemingly must create the thread network
https://openthread.io/guides/pyspinel/wireshark
Talks about the master key, suggests its "AES-128 Encryption, 32-bit Integrity Protection"
So while we probably could generate the key, we can't safely generate our own network configuration without a thread radio i think.
That said, it would still be cool to be able to provision secondary border routers with this (if you have multiple shapes you get failover, which is pretty cool!).
With Silabs addon or paring one OTFD to the addon its possible paring devices with normal thread credentials and searing the complete OTBR / meh network with CLI or over IPV6.
The network parameters for doing the joinier PSKd is easy getting (Open thread papers) with CLI.
> dataset active
Active Timestamp: 1
Channel: 15
Channel Mask: 0x07fff800
Ext PAN ID: ff111111222222ee
Mesh Local Prefix: fd78:6b43:414a:a7a0::/64
Network Key: TeStNeTwOrKKeY
Network Name: BillyOpenThread
PAN ID: 0x1ef4
PSKc: NoTfOrYoUrEaYs
Security Policy: 672 onrc
Done
Its also possible getting it as one string with dataset active -x
and its one function to importing the dataset to HA implanted in the addon.
Only 2 things i cant doing with EVE energy and Nanoleaf lights is getting them in thread paring mode and getting there pin for paring one thread network (is not the same as the HK code).
If both settings was possible putting in HA GUI they is in the thread network in 2 minutes with CLI :-)))
HA is working on a thread integration:
https://github.com/home-assistant/core/tree/dev/homeassistant/components/thread
The HA ecosystem will sync thread network connection settings into the store in this integration.
Right now you can see how you can list and get thread network details from this integration. There is a plan to add a get_preferred_dataset
type API that we should use.
So we should be able to seamlessly pair a device over BLE and then upgrade it to Thread, without having to ask the user about network keys and pan ids etc.
Going to close this, as we did this ages ago and theres now a button in HA to move a device from bluetooth to thread.