raulgbcr/lednetwf_ble

[Bug] Can't connect through ESPHome Bluetooth Proxies

Closed this issue · 4 comments

As the title says, I'm unable to set up a LednetWF device when it would be connecting through an ESPHome BT proxy. Direct connection seems to work but the moment the connection would move over to a proxy, it fails.

The cleanest errors I get through the setup process:

Logger: custom_components.lednetwf_ble.lednetwf
Source: custom_components/lednetwf_ble/lednetwf.py:403
Integration: lednetwf_ble ([documentation](https://github.com/raulgbcr/lednetwf_ble), [issues](https://github.com/raulgbcr/lednetwf_ble/issues))
First occurred: 03:10:23 (1 occurrences)
Last logged: 03:10:23

Error getting status: Characteristic None not found!
Logger: aiohttp.server
Source: /usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py:421
First occurred: 03:10:23 (1 occurrences)
Last logged: 03:10:23

Error handling request
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/aiohttp/web_protocol.py", line 452, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/aiohttp/web_app.py", line 543, in _handle
    resp = await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/aiohttp/web_middlewares.py", line 114, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 85, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 94, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 80, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 233, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 31, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/view.py", line 149, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 63, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 177, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 72, in wrapper
    result = await method(view, request, data, *args, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 110, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 293, in async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 389, in _async_handle_step
    result: FlowResult = await getattr(flow, method)(user_input)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 164, in async_step_manual
    return await self.async_step_validate()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 142, in async_step_validate
    error = await self.toggle_light()
            ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 196, in toggle_light
    await self._instance.stop()
  File "/config/custom_components/lednetwf_ble/lednetwf.py", line 491, in stop
    await self._execute_disconnect()
  File "/config/custom_components/lednetwf_ble/lednetwf.py", line 512, in _execute_disconnect
    await client.stop_notify(read_char) #  TODO:  I don't think this is needed.  Bleak docs say it isnt.
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/bleak/__init__.py", line 852, in stop_notify
    await self._backend.stop_notify(char_specifier)
  File "/usr/src/homeassistant/homeassistant/components/esphome/bluetooth/client.py", line 79, in _async_wrap_bluetooth_operation
    return await func(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/esphome/bluetooth/client.py", line 691, in stop_notify
    characteristic = self._resolve_characteristic(char_specifier)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/esphome/bluetooth/client.py", line 490, in _resolve_characteristic
    raise BleakError(
bleak.exc.BleakError: Dongle One [f4:12:fa:41:43:6c]: MELK-OA10   E9 - BE:11:7A:00:1C:E9: Characteristic None was not found!

MELK-OA10 is the device in question, with the MAC address BE:11:7A:00:1C:E9, whereas Dongle One [f4:12:fa:41:43:6c] is the proxy in question.

The proxy is running the latest 2023.12.3 ESPHome, and I'm trying with the latest release of lednetwf_ble, 0.0.6. HA is also up to date.

Commenting out the mentioned line lednetwf.py:512 does help the process get ahead a bit, however after some digging I realised my device uses different characteristic IDs:

  • instead of 0xFF01, it uses 0xFFF3 (0000fff3-0000-1000-8000-00805f9b34fb)
  • instead of 0xFF02 it uses 0xFFF4 (0000fff4-0000-1000-8000-00805f9b34fb)

Interesting. I had assumed there were other devices out there which looked similar but were different when I noticed that the picture of the remote had changed on Ali Express.

FWIW The version of the devices I have works via ESP proxies.

So I think you're right, that the issue is the characteristics have changed. Hopefully that's all that has changed. If the byte codes for the commands are different then it's going to be a lot more work.

We should be able to detect this during set up but I'm not 100% certain how at this point.

I think a good first step would be for you to make those changes to the code and test it out. If it works well then the code already has the capacity to deal with multiple "versions" of the hardware, so the next steps would be to add the new chars to the code and then find a way to differentiate at setup.

I don't have one of these devices so I'd be working blind. In theory it should be as easy as changing:

WRITE_CHARACTERISTIC_UUIDS = ["0000ff01-0000-1000-8000-00805f9b34fb"]

The device in question is a Jehiatek RGB Floor Lamp with Shelves - it uses the Magic Lantern app, not sure if that makes a difference (that and the other apps used by LednetWF devices I've seen, seem to be the exact same app with different names).

I'll grab the app and decompile it, to verify the protocol.

Decompiling helped a lot. I did a ton of digging around, then turned to Google... And it turns out, it's the ELK-BLEDOM protocol, not LednetWF. Which is a tad bit unfortunate, but at least I found https://github.com/dave-code-ruiz/elkbledom so I can finally integrate with HA.