Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Event Support #1

Closed
daveismith opened this issue Dec 31, 2021 · 14 comments
Closed

Event Support #1

daveismith opened this issue Dec 31, 2021 · 14 comments

Comments

@daveismith
Copy link

This is fantastic work. I can control and get the state of my nanoleaf essentials via the thread network. To integrate fully with home assistant, I think there needs to be some sort of real-time update system. Have you managed to discover how that works yet? I could imagine a few scenarios:

  1. A COaP Observe on some URL
  2. Something like https://forum.nanoleaf.me/docs#_l9kelug0qi5s
  3. WebHook style updates
  4. Some broadcast to indicate an update.
@roysjosh
Copy link
Owner

None known, I'll have to dig a little. The app doesn't appear to catch outside state modifications.

@daveismith
Copy link
Author

It may be because I’m on HomeKit but the iOS app updates immediately when I make changes via a voice control on a HomePod.

@roysjosh
Copy link
Owner

roysjosh commented Jan 1, 2022

Interesting. I see the same behavior: the iOS app gets immediate state changes the Android app makes but not vice-versa. A pcap shows the border router doing a CoAP PUT to the iPhone.

@daveismith
Copy link
Author

Interesting. I wonder if the iPhone is registering at some point with the BR or elements to receive push updates.

@roysjosh
Copy link
Owner

roysjosh commented Jan 3, 2022

Bah, it looks like the iOS app is hitting a different CoAP endpoint, /2 (there's also /1 and /0) with a somewhat different packet format. It looks like this is HAP vs the custom Nanoleaf protocol. Not terribly surprising...

Initial POST.

0000   06 01 01 03 20 6e eb 78 f0 ed 63 5f f2 83 4d 08
0010   f4 3e 43 af 4b c2 ad 5f c2 ad 0d 43 18 fb 25 23
0020   13 02 63 0d 7a

06 01 01 would be tag(Sequence number) len(1) value(1)
03 20 ... would be tag(Public key) len(32) value(...)

And the reply

0000   06 01 02 03 20 bc 24 56 33 db d0 c2 34 b9 14 7b
0010   2f ac d8 90 3a 42 1b fc c3 49 88 15 3e 2c 63 4e
0020   36 58 74 28 7e 05 65 f6 f9 19 1a 82 eb fa 76 01
0030   00 04 51 b7 7d b3 fe d4 41 40 1a 6d 56 41 1a 14
0040   90 9b 9c 83 34 3e 3e c6 0f 21 30 35 0b bc 83 08
0050   db 70 d8 32 9f 33 6a b1 cb 7c 6d c6 1b 21 9b e4
0060   fa 86 79 3d 46 aa 1f 51 7d 05 f7 b6 ba cf fe 48
0070   75 1d 2c 57 8f 27 01 cb b9 57 3b 32 aa 1f 30 8d
0080   f8 90 79 35 7c fc 7d ef 99 f0 c2 86

06 01 02 sequence #
03 20 xxx reply public key
05 65 xxx encrypted data

I wonder if we can just modify the existing HA HomeKit integration to also do UDP...

@roysjosh
Copy link
Owner

roysjosh commented Jan 3, 2022

CoAP endpoint /1 is equivalent to pair-setup, /2 is equivalent to pair-verify, looks like normal traffic goes to /.

@roysjosh
Copy link
Owner

roysjosh commented Jan 4, 2022

Hacked something together from other HAP projects. Pair-Setup was successful over /1.

@roysjosh
Copy link
Owner

roysjosh commented Jan 5, 2022

And Pair-Verify over /2 works. I'm not sure how to figure out the HAP data format for CoAP. The first request by the iOS app has a 23 byte payload, 16 of which are likely the ChaCha20Poly1305 cipher's tag. That generates a 1200 byte reply. So I need a 7 byte request. TODO.

@roysjosh
Copy link
Owner

roysjosh commented Jan 6, 2022

Okay, I implemented a fake bulb and had the iOS Home app pair to it. It looks like BLE HAP PDUs...

C  OP TX IID  LEN
00 09 70 0000 0000

0x09 would be a new opcode. The transaction ID (TX) does change with every request... and replaying that request to a NL A19 bulb does generate a huge reply:

0270 0054 0418 ff19 ff1a 0201 0016 ff15
f107 0201 0006 013e 1000 14e6 1314 0502
...

The first 5 bytes match a HAP PDU reply:

02: Control field w/response bit
70: TX ID
00: Status=Success
54 04: Len=1108

@roysjosh
Copy link
Owner

roysjosh commented Jan 7, 2022

The response seems to be a GATT service/characteristic table or whatever you call it. Decoding gives similar data to what is visible over BLE. Repeating this one response to the Home app causes pairing to complete & prompt for a name/room. The Home app goes on to do multiple queries after that in the background, HAP-Characteristic-Read (0x03) as well as another unidentified opcode, 0x0b. Next up, repeating those to the real bulb & seeing if we get push notifications.

@roysjosh
Copy link
Owner

roysjosh commented Jan 7, 2022

Every characteristic in the GATT table that is marked as supporting notification gets hit with a 0x0b opcode. And... yes, that's what triggers push notifications!

@roysjosh
Copy link
Owner

roysjosh commented Jan 7, 2022

Last piece of the puzzle, there is a new encryption context for events with a salt b'Event-Salt' and info b'Event-Read-Encryption-Key'.

PUT HAP PDU
EVENT CTR 0
... 0433000300010100
PUT HAP PDU
EVENT CTR 1
... 0433000300010101

Seems to parse as...

?? IID  Len  TLV8
04 3300 0300 01 01 01
             HAP-Param-Value = 0x01

@roysjosh
Copy link
Owner

roysjosh commented Jan 7, 2022

Pushed hacktastic python script. It can subscribe to things. Yay.

@roysjosh
Copy link
Owner

roysjosh commented Mar 2, 2022

Closing for now. HAP has events but it remains to be seen if/when LTPDU will add events.

@roysjosh roysjosh closed this as completed Mar 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants