HomeKit Accessory Protocol (HAP) over CoAP/UDP (was: Nanoleaf Essentials bulb via Thread/CoAP)

@damru see if you have a package that provides coap-client, in Fedora it is libcoap-utils Try this from your HA RPI:

coap-client -m put -e '%00%01%00%07lb/0/id%00%02%00%00' \
  coap://[YOUR-BULB-IPv6]/nlpublic

The square brackets around the IPv6 address are important. That should cause your bulb to flash.

Hey @lambdafunction I’ve been following this over the past few weeks and it looks like there have been rapid fire updates. Just checking to see what code changes are still needed.

I was able to change the line 36 in the /const.py file, but I’m guessing that they finally patched line 187 on the /ws.py. When I vi into the code you provided the line of 187 is a line break and none of the code even remotely looks similar to what you copied.

That being said, I was able to add about 4 of my nanoleaf devices via BLE but now I’m hitting a wall on adding the other bulbs via same protocol. (turns out when you have a pile of nanoleaf bulbs in front of you it is easy to get the codes mixed up. I reolved the BLE issue but still want to make sure i’m on the right path with the recent updates.

For starters here is my const.py file just to make sure I didnt start off on the wrong foot.

import os
import sys

BLE_TRANSPORT_SUPPORTED = True
COAP_TRANSPORT_SUPPORTED = True
IP_TRANSPORT_SUPPORTED = False

if "bleak" in sys.modules:
    BLE_TRANSPORT_SUPPORTED = True
else:
    try:
        if "AIOHOMEKIT_TRANSPORT_BLE" in os.environ:
            __import__("bleak")
            BLE_TRANSPORT_SUPPORTED = True
    except ModuleNotFoundError:
        pass


try:
    if True:
        __import__("aiocoap")
        COAP_TRANSPORT_SUPPORTED = True
except ModuleNotFoundError:
    pass

try:
    __import__("zeroconf")
    IP_TRANSPORT_SUPPORTED = True
except ModuleNotFoundError:
    pass

I’ll wait to hear back if the second string of code was updated or not to try to keep this post smaller.

Next, I’ve enabled the three logs that were posted up above and I do see the bulb that i just added via BLE in my logs broadcasting a hap.udp.local service update.

2022-08-23 20:27:52.102 DEBUG (MainThread) [homeassistant.components.zeroconf] service_update: type=_hap._udp.local. name=Encode Plus._hap._udp.local. state_change=ServiceStateChange.Updated
2022-08-23 20:27:52.103 DEBUG (MainThread) [homeassistant.components.zeroconf] service_update: type=_hap._udp.local. name=Nanoleaf A19 7BSK._hap._udp.local. state_change=ServiceStateChange.Updated
2022-08-23 20:27:52.103 DEBUG (MainThread) [homeassistant.components.zeroconf] Discovered new device Encode Plus._hap._udp.local. ZeroconfServiceInfo(host='fd54:6e34:1e50:0:ecc5:dea1:f1c9:609d', addresses=['fd54:6e34:1e50:0:ecc5:dea1:f1c9:609d'], port=5683, hostname='Encode-Plus.local.', type='_hap._udp.local.', name='Encode Plus._hap._udp.local.', properties={'_raw': {'c#': b'1', 'ff': b'1', 'id': b'C8:15:DD:9E:F2:31', 'md': b'be499WB', 'pv': b'1.2', 's#': b'7', 'sf': b'0', 'ci': b'6', 'sh': b'VYYK3A=='}, 'c#': '1', 'ff': '1', 'id': 'C8:15:DD:9E:F2:31', 'md': 'be499WB', 'pv': '1.2', 's#': '7', 'sf': '0', 'ci': '6', 'sh': 'VYYK3A=='})
2022-08-23 20:27:52.104 DEBUG (MainThread) [homeassistant.components.zeroconf] Discovered new device Nanoleaf A19 7BSK._hap._udp.local. ZeroconfServiceInfo(host='fd54:6e34:1e50:0:d179:d25a:4f37:5d36', addresses=['fd54:6e34:1e50:0:d179:d25a:4f37:5d36'], port=5683, hostname='Nanoleaf-A19-7BSK.local.', type='_hap._udp.local.', name='Nanoleaf A19 7BSK._hap._udp.local.', properties={'_raw': {'c#': b'2', 'ff': b'2', 'id': b'35:F9:9C:95:D5:B9', 'md': b'NL45', 'pv': b'1.2', 's#': b'91', 'sf': b'0', 'ci': b'5', 'sh': b'vW6VBA=='}, 'c#': '2', 'ff': '2', 'id': '35:F9:9C:95:D5:B9', 'md': 'NL45', 'pv': '1.2', 's#': '91', 'sf': '0', 'ci': '5', 'sh': 'vW6VBA=='})

Then, following your other instructons below i tried pinging via ip6:

~ # ping6 Nanoleaf-A19-7BSK.local
PING Nanoleaf-A19-7BSK.local (fd54:6e34:1e50:0:d179:d25a:4f37:5d36): 56 data byt                       es
ping6: sendto: Network unreachable

So it appears that my HA can see the bulb via thread and now my next step is just to add via android nanoleaf app?

Then once I added it, i was able to look at the diagnostics on the device itself to confirm it is looking for zaroconf & BLE, and confirmed it was connected via BLE.

"integration_manifest": {
    "domain": "homekit_controller",
    "name": "HomeKit Controller",
    "config_flow": true,
    "documentation": "https://www.home-assistant.io/integrations/homekit_controller",
    "requirements": [
      "aiohomekit==1.2.11"
    ],
    "zeroconf": [
      "_hap._tcp.local.",
      "_hap._udp.local."
    ],
    "bluetooth": [
      {
        "manufacturer_id": 76,
        "manufacturer_data_start": [
          6
        ]
      }
    ],
    "dependencies": [
      "bluetooth",
      "zeroconf"
    ],
    "codeowners": [
      "@Jc2k",
      "@bdraco"
    ],
    "iot_class": "local_push",
    "loggers": [
      "aiohomekit",
      "commentjson"
    ],
    "is_built_in": true
  },
  "data": {
    "config-entry": {
      "title": "Nanoleaf A19 7BSK",
      "version": 1,
      "data": {
        "AccessoryPairingID": "7F:65:53:5E:74:11",
        "AccessoryLTPK": "6ead75958511249a88097cf74710c4ec149a2447cbfb3d2b04ce79323f936046",
        "iOSPairingId": "577d937d-2168-4785-8dfb-d2e571f0e677",
        "iOSDeviceLTSK": "**REDACTED**",
        "iOSDeviceLTPK": "c552bdd9e97c7a87ea8c3e2697079c48caf83b91fc06bc7b30040c08886947c7",
        "AccessoryAddress": "F6:39:12:4A:6F:3B",
        "Connection": "BLE"
      }
    },

Thanks!

Correct, aiocoap released 0.4.4 with the requested change. You may need to apply Fix CoAP pairing to not unsubscribe nothing (#153) · Jc2k/aiohomekit@c77fae9 · GitHub as well for the time being; that commit will be in 2022.9.

You are seeing the zeroconf advertisements but it looks like your IPv6 networking is borked. I can’t verify ATM but the Thread Border Router should be advertising itself, via IPv6 Router Advertisements, to be a router to the Thread IPv6 network. Your main router/WAP should also be assigning a public address (2000::/3), if your ISP supports IPv6, or a private ULA address (fd00::/8). Finally, your devices should all be assigning link-local IPv6 addresses (fe80::/10). Any of those should be able to get you to the Thread IPv6 network unless you have a complex network.

Check ip -6 addr from your HA to see if you have any of the above types of addresses and also check ip -6 route for something like fd54:6e34:1e50::/64 via fe80... to see if your HA picked up the RA.

Hmmm. I wasnt able to find that file so I might just have to wait unitl 2022.9 releases for that.

I did see my HomePod Mini BR advertising itself, it was just in another device cluster: I had previously added it to HA via the Apple TV integration.

2022-08-24 08:30:04.568 DEBUG (MainThread) [homeassistant.components.zeroconf] Discovered new device Craft Room._airplay._tcp.local. ZeroconfServiceInfo(host='192.168.20.160', addresses=['192.168.20.160', 'fd1b:a4c9:adad:4298:0:fd54:6e34:1e50'], port=7000, hostname='Craft-Room.local.', type='_airplay._tcp.local.', name='Craft Room._airplay._tcp.local.', properties={'_raw': {'acl': b'0', 'btaddr': b'76:9E:20:D8:8D:D5', 'deviceid': b'94:EA:32:7F:AD:8C', 'fex': b'AMp/StBLNbw', 'features': b'0x4A7FCA00,0xBC354BD0', 'flags': b'0x80404', 'gid': b'91078EFE-19DA-4525-912B-FC0F05437548+0+0C18FB73-2C81-43A2-B40D-72049327A2D3', 'igl': b'1', 'gcgl': b'1', 'model': b'AudioAccessory5,1', 'protovers': b'1.1', 'pi': b'53f87954-e9b2-472c-9986-d5e7282a4153', 'psi': b'B5D33089-F09D-42F2-B550-518E5AFCC2F4', 'pk': b'a9d807ac5ec3b14045390d28a34aa65c65f3644abbb1d1fef9485a110e352778', 'srcvers': b'620.8.2', 'osvers': b'15.6', 'vv': b'2'}, 'acl': '0', 'btaddr': '76:9E:20:D8:8D:D5', 'deviceid': '94:EA:32:7F:AD:8C', 'fex': 'AMp/StBLNbw', 'features': '0x4A7FCA00,0xBC354BD0', 'flags': '0x80404', 'gid': '91078EFE-19DA-4525-912B-FC0F05437548+0+0C18FB73-2C81-43A2-B40D-72049327A2D3', 'igl': '1', 'gcgl': '1', 'model': 'AudioAccessory5,1', 'protovers': '1.1', 'pi': '53f87954-e9b2-472c-9986-d5e7282a4153', 'psi': 'B5D33089-F09D-42F2-B550-518E5AFCC2F4', 'pk': 'a9d807ac5ec3b14045390d28a34aa65c65f3644abbb1d1fef9485a110e352778', 'srcvers': '620.8.2', 'osvers': '15.6', 'vv': '2'})

As for the IPv6 on my WAP, I have a Ubiquity UDM Pro and had IPv6 disabled on my WAN. I just enabled it along with the IPv6 settings on my AP Wifi6 (which was also disabled) for my IOT VLAN.

I have my computers and server running on their own VLAN with firewall rules pointing specific IOT traffic to the HA port group. Will I have to add any additional rules for the IPv6 traffic?

Running the ip -6 addr command I can confirm that my Hassio docker container has a ipv6:

4: hassio: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP
    inet6 fe80::42:***redacted**:fb21/64 scope link

I see plenty of other docker containers but I do not see the Homepod Mini. I’ll do some more digging and see what I can turn up.

Thanks!

Ha, that’s the “complex network” I was worried about. Assuming the HomePod Mini is on the IOT VLAN, you’ll want to make sure that the HomePod Mini’s RA is either making it to HA itself or to your gateway. Then you’ll want to have UDP port 5683 open from HA to the Thread network. You may want to test with the coap-client command mentioned a few posts ago. Side note: can the Android app provision an Apple BR’s Thread network credentials to Essentials?

Not sure yet. I’m going to try to pick up a cheap android device today before I go on the road for work for a week.

Homepod Mini is on IoT VLAN and I will make sure to open up 5683.

Edit: I already had a rule to allow all traffic between IOT network and my HA instance.

@lambdafunction So I’m finally back home from the road and had some time to tinker with my setup. It has been quite the adventure.

  • I broke down and bought another border router other than my Home Pod Mini (Nanoleaf Shapes Mini BR ($50 on amazon)

  • I borrowed an old Samsung Galaxy S5 on android 6.0.2 that would download the nanoleaf app just fine, but wouldn’t connect to the Nanoleaf BR

  • Ended up flashing an old pi4 with LineageOS 18.1 (Andoid 11 OS) that makes the pi into a DIY Android tablet

  • I finally got the mini BR to connect via thread with an A19 essentials bulb.

  • I can see what channel I am on, the PAN ID, Extended PAN ID, and the Master Key.

  • I downloaded mDNS Discovery and can see both my A19 bulb and my Schlage Front Door Lock (Encode Plus) w/ a Wifi 6 IP Address

Now I removed everything from android and factory reset everything.

  • Added the Nanoleaf BR via Homekit controller (not the native Nanoleaf integration) and it is showing added via IP and happy

  • All my bulbs want to connect via BLE so I removed my dongle from my miniPC and no luck. Homekit controller is not able to find my newly factory reset A19 Essentials bulb via HAP.

I’m guessing it has to do with my HA server being on another VLAN and my bulbs, BR routers, etc are all on IOT VLAN. I got frustrated the other night when trying to connect my steam deck to my PC via warpinator and I couldn’t for the life of me get it to work.

Well, Warpinator runs off of mDNS too so I’m guessing somewhere in my Unifi system the mDNS repeater isn’t working properly. I found other threads on forums where people were running into the same deal. I resolved the steamdeck/warpinator issue by just adding my steam deck to my default VLAN.

Am I missing something completely obvious here? If everything that I’ve done so far matches, then I might just move my HA instance over to my IOT VLAN which I was hoping not to have to do.

@mrdj863 the factory reset will have wiped the Thread network credentials from the bulbs. I would try the Android app again, pair the bulbs and let the app get the bulbs on Thread. After they show up via mDNS, probably only the _ltpdu service, you’ll want to turn the bulbs off & back on. They only advertise HAP for a few minutes after boot & then it is turned off. Then try pairing to HA.

1 Like

Copy that. thanks!

I’ll go for another try here in a bit and report back if I run into any issues.

For those who read this later and try to follow the same steps to avoid buying an android tablet, I wish I had just bought a cheap fire tablet a few weeks ago instead of trying to tinker with old gear laying around!

Update: I followed your instructions and with my BLE dongle removed, the Nanoleaf devices showed up via thread.

However they were unable to connect with the 8 digit code. My guess is that my Ubiquity/ Unifi UDM network is to blame.

I’m at the end of my rope here. I really would prefer not to have my HA server on my IOT VLAN due to security reasons and I’ve built IPv6 firewall rules as well to allow all traffic from IPv6 to my HA instance, still no luck.

From other forum posts I believe that the culprit is Ubiquity’s mDNS settings are not as open as the GUI makes us believe.

You mentioned in earlier posts that 2022.9 may bring a native integration to thread without any tweaking. Is that still on track? Should I hold onto this nanoleaf BR or return it while it is still in it’s return period?

@mrdj863 I just tested something similar with an A19 bulb and a HomePod Mini: pair with iOS, wait a minute for it to show up over mDNS, unpair. Wait a minute and toggle the bulb’s power once (may not be needed). The bulb stayed on Thread via the HomePod Mini but sf switched back to 1. I could then pair it with HA. If that works for you, the NL BR could go back.

The Thread provisioning is still getting worked out. There’s some interaction with HA, possibly how it does BLE scanning, that messes with provisioning the bulbs.

I don’t have a UDM to play with but it looks like you’ll want the mDNS repeater (not the reflector?) working and IPv6 connectivity working (test ping6 and coap-client to the bulb from HA itself or something in the same logical network “position” as HA). Turn on firewall logging as you troubleshoot so you can see DROPs.

I keep trying to use the coap-client command and it isn’t a valid command for my system. I have a miniPC running HA via a supervised docker install on Debian 11. Everything I’ve read shows that it should be installed already but no luck so far.

I should have some time tomorrow to try your Homepod Mini trick and dig into the CLI to hopefully get the coap command to work.

If I have enough time, I’m going to temporarily move my HA instance over to my IOT vlan for science and see if my UDM is the culprit. I’ll update with results.

Hello!
First of all, i wanted to thank everyone involved in this thread for their dedication and work.

I stumbled upon this thread and made some progress but now I’m stuck.

I am trying to connect 3 Nanoleaf A19s to HA and use HomePod mini as BR.

I have HA installed on my NAS (Synology) as a VM following the “Alternative” installation guide using the provided ova image. Therefore BLE is not an option for me, as my NAS 1. has no bluetooth and 2. is located too far away from the bulbs to connect via BLE anyway.

On the software side I applied the “hack” in const.py as well as Fix CoAP pairing to not unsubscribe nothing (#153) · Jc2k/aiohomekit@c77fae9 · GitHub and rebooted HA afterwards.

Installed mDNS Browser found my bulbs in _hap._udp. with sf = 0. Deleted them from Nanoleaf, waited one minute, toggled power and took notice that sf changed to 1.
Now the bulbs show up as “Discovered” integrations in HA.

However when trying to configure, I get an error saying “Cannot add pairing as device can no longer be found.”
Screenshot 2022-09-04 at 12.11.57

After this, the discovered lightbulb vanishes from HA.
This happens for all three bulbs. However, I can still see them in _hap._udp. with sf still being 1.

I can “recreate” said behaviour by powering the bulbs off and on. Sometimes, after they vanished from HA Integrations it takes a few minutes for them to appear again without toggling power or doing anything else. Eventually all three disappear from _hap._udp. and I have to re-power them.

All bulbs remain pingable throughout the whole process.

Did I miss something?

Sorry for my vague description, I just setup HA for the first time a few days ago. I am currently in the process of getting to know its ins and outs.
I’d be glad to post some logs, if you can tell me what you need.

Thanks!

@davidungerank I need to see the HA logs, possibly with some components set to debug. First, check Settings → System → Logs, then Load Full Logs at the bottom. Look for stacktraces during the time frame that you tried to pair. Or just restart HA, which clears the log, and try to pair.

If you don’t see anything, go to Developer Tools → Services and look for the “Logger: Set level” service. Switch to YAML mode. Paste the following into the text box and click Call Service:

service: logger.set_level
data:
  aiohomekit: debug
  homeassistant.components.homekit_controller: debug

Afterwards, try to pair again and check for logs.

I fixed my problem.
Prior to reading your answer, I already tried setting those components to debug but something seemed to be broken with my logger add-on as it didn’t show conclusive output.

I reinstalled the add-on and tried again today.
I had two issues in my “fixed” code.
While editing const.py I used tabs instead of spaces, which threw an error according to my logs. (silly me)
Didn’t know that at the time, because I have no experience with python.

...
File
"/usr/local/lib/python3.10/site-packages/aiohomekit/controller/coap/connection.py",line630
iids = (int (aid_iidl1]) for aid_iid in ids]
TabError: inconsistent use of tabs and spaces in indentation

Then I had the following error which I fixed with this post

2022-09-07 08:22:07.843 DEBUG (MainThread) [aiohomekit.protocol] #1 ios -> accessory: send SRP start request
2022-09-07 08:22:07.844 DEBUG (MainThread) (aiohomekit.protocol.tv] sending [
6 (State): (1 bytes/) 0x01
• (Method): (1 bytes/) 0x00
2022-09-07 08:22:10.322 INFO (MainThread) [coap] Retransmission, Message ID: 42846.
2022-09-07 08:22:23.851 ERROR (MainThread) [homeassistant.components.homekit controller.config flow] Pairing
attempt failed with an unhandled exception
Traceback (most recent call last) :
File '
"/usr/local/lib/python3.10/asyncio/tasks.py", line 456, in wait_for
return fut.result ()
asyncio.exceptions.CancelledError
The above exception was the direct cause of the following exception:
Traceback (most recent call last) :
File "/usr/src/homeassistant/homeassistant/components/homekit_controller/config_flow.py",line502,in
async_step_pair
self. finish _pairing = await discovery.async_start_pairing(self.hkid)
File "/usr/local/lib/python3.10/site-packages/aiohomekit/controller/coap/discovery.py",
line 57, in
async_start_pairing
salt, srpB = await self. connection.do_pair_setup/
File "/usr/local/lib/python3.10/site-packages/aiohomekit/controller/coap/connection.py",line291,
in
do_pair_setup
response = await asyncio.wait_forl
File "/us/local/lib/python3.10/asyncio/tasks.py", line 458, in wait_for
raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError

So yeah, it seems I have to warm up a bit with HA and especially python.

Thanks for your help.

PS: I’m curious: how will 2022.9 change the whole process of integrating essentials to HA? I skimmed through this thread and read about some changes coming with the update.

@davidungerank The changes will mostly be behind the scenes fixes. All of the issues discovered so far have patches merged. HAP over Thread/CoAP will still need the const.py tweak or an environment variable set but I’m hoping to have that active by default soon now that aiocoap has put out a release. The Thread provisioning feature is stalled for now as something in HA seems to interrupt the communications to the bulbs. That’s okay for the time being as we have the workaround of pairing using the NL app, waiting for it to show up on Thread, and then unpairing.

1 Like

Realized that while I am trying to get these bulbs connected that I did not have an aiohomekit folder (at least one I could find browsing in terminal) and needed to start with post 91’s instructions. Is there a reason I’m getting a repository not found error when trying to add the developers repository to the Add-on Store? Did some web searching and didn’t really see any other posts having this issue.

@Leiesoldat I wouldn’t start there at this point, it is too out of date. The 2022.9 release has fixes for multiple issues discovered in this thread. My Home Assistant OS install has aiohomekit at /usr/local/lib/python3.10/site-packages/aiohomekit or you can use find / -name aiohomekit. You should only need to change the line in const.py from if "AIOHOMEKIT_TRANSPORT_COAP" in os.environ: to if True:.

Awesome that worked! Thanks!

Edit: for those that don’t have access to an Android phone, I was able to do the pairing of the bulbs in the iOS Nanoleaf (NL) app, see the sf=0 under _hap._udp section within an iOS app called “Discovery - DNS-SD Browser,” and then unpair the light. Shortly after unpairing/removing the bulb from NL (a couple of seconds at most), the integration popped up in Home Assistant (HA). I had duplicate entries pop up for some reason unbeknownst to me, but I ignored the duplicates once I found the correct entry that allowed me to input the 8 digit code in the form of XXX-XX-XXX. Setting up a HomeKit integration as a bridge back to Home Kit proper allowed me to reprogram some of the Flic switches to govern the lights in the house (which is a must-have directive from the boss).

2 Likes

@lambdafunction I followed your latest instructions and changed const.py, then followed @Leiesoldat steps (don’t have an android device available). I see the A19 Essentials bulb join Thread network in NL all, I’m able to see the right values in the “Discovery-DNS-SD Browser”, sf turns to 1 after deleting from NL app, bulb is then discovered by Home Assistant, replies to ping6 but pairing fails with timeout.
I use Home Assistant 2022.9.2.

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/asyncio/tasks.py", line 456, in wait_for
    return fut.result()
asyncio.exceptions.CancelledError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/homekit_controller/config_flow.py", line 479, in async_step_pair
    self.finish_pairing = await discovery.async_start_pairing(self.hkid)
  File "/usr/local/lib/python3.10/site-packages/aiohomekit/controller/coap/discovery.py", line 57, in async_start_pairing
    salt, srpB = await self.connection.do_pair_setup(
  File "/usr/local/lib/python3.10/site-packages/aiohomekit/controller/coap/connection.py", line 283, in do_pair_setup
    response = await asyncio.wait_for(
  File "/usr/local/lib/python3.10/asyncio/tasks.py", line 458, in wait_for
    raise exceptions.TimeoutError() from exc
asyncio.exceptions.TimeoutError

Any thoughts on what I should try next?
Thanks