raulgbcr / lednetwf_ble

Home Assistant custom integration for LEDnetWF devices
MIT License
26 stars 4 forks source link

Lights previously working stopped working in v0.0.10 #29

Open sleavitt opened 4 days ago

sleavitt commented 4 days ago

I have some lights that identify as LEDnetWF that the previous home owners left behind when they moved out, so I'm not sure where they were acquired from or what brand they are. However, they did basically work with v0.0.9 (though the functionality was very basic and limited). However, with v0.0.10 and later, they stopped working (they now simply fail to set up); the debug logs for this integration yield the following log entries:

2024-11-23 13:53:36.845 DEBUG (MainThread) [custom_components.lednetwf_ble.lednetwf] Service info: {'name': 'LEDnetWF02000813C11C', 'address': '08:65:F0:13:C1:1C', 'rssi': -74, 'manufacturer_data': {}, 'service_data': {}, 'service_uuids': ['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'], 'source': '88:B1:11:7F:C4:38', 'advertisement': AdvertisementData(local_name='LEDnetWF02000813C11C', service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'], rssi=-74), 'device': BLEDevice(08:65:F0:13:C1:1C, LEDnetWF02000813C11C), 'connectable': True, 'time': 73679.113680523, 'tx_power': None}
2024-11-23 13:53:36.845 DEBUG (MainThread) [custom_components.lednetwf_ble.lednetwf] Service info keys: dict_keys(['name', 'address', 'rssi', 'manufacturer_data', 'service_data', 'service_uuids', 'source', 'advertisement', 'device', 'connectable', 'time', 'tx_power'])
2024-11-23 13:53:36.845 ERROR (MainThread) [homeassistant.config_entries] Error setting up entry LEDnetWF02000813C11C (C11C) for lednetwf_ble
Traceback (most recent call last):
  File "/config/custom_components/lednetwf_ble/__init__.py", line 22, in async_setup_entry
    instance   = LEDNETWFInstance(entry.data[CONF_MAC], hass, config, options)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/lednetwf.py", line 167, in __init__
    self._model                 = self._detect_model(service_info['manufacturer_data'])
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/lednetwf.py", line 192, in _detect_model
    manu_data_id = next(iter(manu_data))
                   ^^^^^^^^^^^^^^^^^^^^^
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 635, in __async_setup_with_context
    result = await component.async_setup_entry(hass, self)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: coroutine raised StopIteration

Please let me know if there is any further information you need, I am happy to help debug further if I can.

8none1 commented 4 days ago

It looks like it's failing because the manufacturer_data data is empty.

I'm not sure why that would be.

More than likely a bug in our code.

I'm currently working on a new branch: https://github.com/raulgbcr/lednetwf_ble/tree/8none1/new_device

This has fixed a few bugs and also makes it easier for us to add support for new models in the future.

There is a lot of extra debugging in that branch that will gradually get removed, but if you want try that branch it would be useful feedback and might even fix your problem.

To install it you'd need to remove the existing integration and then clone from git directly in to your custom_components directory and then checkout that branch.

OR

You could just download the files from github and copy them over.

I'm hoping to get things in good enough shape to make a new release in the next week or so.

8none1 commented 3 days ago

I suspect that this is the fix:

https://github.com/raulgbcr/lednetwf_ble/commit/52605ee6d086f4fb0877647f54d2d078077a0ab6#diff-7ccc04804cec3bcf1e51bd52a8edfd9fc758987e63025b18c405dea81cbc0533R182

sleavitt commented 3 days ago

So far, no joy on the new_device branch. On branch v0.0.9, Home Assistant shows the following:

image

In branch new_device, I get the following log entries (the 3rd line warning was me enabling line 39 in config_flow.py as a LOGGER.warning to get the device data):

2024-11-24 19:12:21.757 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration lednetwf_ble which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2024-11-24 19:12:21.758 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration hacs which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2024-11-24 19:12:36.127 WARNING (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-66 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=hci0 connectable=True time=179210.501932136 tx_power=None>
2024-11-24 19:12:36.133 ERROR (MainThread) [homeassistant] Error doing job: Task exception was never retrieved (None)
Traceback (most recent call last):
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 44, in __init__
    manu_data = next(iter(manu_data))
                ^^^^^^^^^^^^^^^^^^^^^
StopIteration
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/discovery_flow.py", line 137, in _async_start
    await gather_with_limited_concurrency(FLOW_INIT_LIMIT, *init_coros)
  File "/usr/src/homeassistant/homeassistant/util/async_.py", line 114, in gather_with_limited_concurrency
    return await gather(
           ^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/util/async_.py", line 112, in sem_task
    return await task
           ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 1301, in async_init
    flow, result = await self._async_init(flow_id, handler, context, data)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 1336, in _async_init
    result = await self._async_handle_step(flow, flow.init_step, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 517, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 91, in async_step_bluetooth
    self.device_data = DeviceData(discovery_info)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 51, in __init__
    raise Exception("Error parsing manufacturer data")
Exception: Error parsing manufacturer data

I hope this helps, let me know if I can do anything further to assist.

8none1 commented 2 days ago

It looks like either your device is not sending any manufacture data or it's getting squashed somewhere.

I think we should be able to proceed without it, but we can't tell which model it is (we use the first byte of the version as an indicator as to which protocol to use).

Since your device was working on 0.0.9 then we can default to 0x53 and it should work.

This is on my radar, I'll try and work out a fix in the branch and let you know.

8none1 commented 1 day ago

I pushed another (hacky) bunch of changes to try and deal with this without crashing.

It's hard to test because I don't have a device which doesn't provide manu_data, but I think it's worth giving it a go.

Something worth mentioning. If possible, please delete your device and re-add it when you update the branch on HA.

sleavitt commented 1 day ago

Old device deleted and HACS integration removed. Checked out code into /config/custom_components. After adding some debugging code, I determined that I had to add 0x00 to the SUPPORTED_MODELS in const.py as follows In order to get the device detected:

diff --git a/custom_components/lednetwf_ble/const.py b/custom_components/lednetwf_ble/const.py
index 7935042..40ee36c 100644
--- a/custom_components/lednetwf_ble/const.py
+++ b/custom_components/lednetwf_ble/const.py
@@ -8,7 +8,7 @@ CONF_LEDCOUNT     = "ledcount"
 CONF_LEDTYPE      = "ledtype"
 CONF_COLORORDER   = "colororder"
 CONF_MODEL        = "model"
-SUPPORTED_MODELS  = [0x53, 0x54, 0x56, 0x62]
+SUPPORTED_MODELS  = [0x00, 0x53, 0x54, 0x56, 0x62]

 class LedTypes_StripLight(Enum):

This did cause Home Assistant to offer to set up the new device, but that failed with the following:

2024-11-26 17:44:12.557 ERROR (MainThread) [custom_components.lednetwf_ble.lednetwf] Manufacturer data not found.
2024-11-26 17:44:12.557 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 200, in toggle_light
    self._instance = LEDNETWFInstance(self.mac, self.hass, data)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/lednetwf.py", line 165, in __init__
    self._model_interface = model_class(service_info['manufacturer_data'])
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/model_0x53.py", line 136, in __init__
    super().__init__(manu_data)
  File "/config/custom_components/lednetwf_ble/model_abstractions.py", line 24, in __init__
    manu_data_id           = next(iter(manu_data))
                             ^^^^^^^^^^^^^^^^^^^^^
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 477, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_app.py", line 567, in _handle
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 83, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 32, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 81, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 222, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
    return await method(view, request, data, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 122, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 367, in async_configure
    result = await self._async_configure(flow_id, user_input)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 414, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 517, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 118, in async_step_user
    return await self.async_step_validate()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 172, in async_step_validate
    error = await self.toggle_light()
            ^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: coroutine raised StopIteration

I hope this helps, happy to provide more information as necessary.

sleavitt commented 1 day ago

I have enabled debug level logging for the custom_components.lednetwf_ble integration in HA, and I get the following in the HA logs when I try to enable the device (the web UI says that an unknown error occurred):

2024-11-26 18:20:21.861 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration lednetwf_ble which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2024-11-26 18:20:21.861 WARNING (SyncWorker_0) [homeassistant.loader] We found a custom integration hacs which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you experience issues with Home Assistant
2024-11-26 18:20:35.935 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] ASB: Discovered bluetooth devices: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-71 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=hci0 connectable=True time=348890.644078739 tx_power=None>
2024-11-26 18:20:35.935 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-71 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=hci0 connectable=True time=348890.644078739 tx_power=None>
2024-11-26 18:20:35.935 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: LEDnetWF02000813C11C
2024-11-26 18:20:35.935 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: None
2024-11-26 18:20:35.935 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-71 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=hci0 connectable=True time=348890.644078739 tx_power=None>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=06-2F-F5-87-55-4D address=06:2F:F5:87:55:4D rssi=-84 manufacturer_data={} service_data={'0000fcf1-0000-1000-8000-00805f9b34fb': b'\x04?\xc5\xc4\x0f{\xac\xe7\x02%K\xd0\x8e\xb8\x82\xf0\xd4R<T\xa1('} service_uuids=['0000fcf1-0000-1000-8000-00805f9b34fb'] source=hci0 connectable=True time=348890.644078739 tx_power=None>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: 06-2F-F5-87-55-4D
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: None
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=OBT0E4836 address=F0:C8:67:28:B7:25 rssi=-94 manufacturer_data={} service_data={} service_uuids=[] source=hci0 connectable=True time=348890.644078739 tx_power=None>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: OBT0E4836
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: None
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=47-67-34-41-C4-C9 address=47:67:34:41:C4:C9 rssi=-65 manufacturer_data={76: b'\x10\x060\x1d\xc9\xa7\r\x80'} service_data={} service_uuids=[] source=88:B1:11:7F:C4:38 connectable=True time=348899.54201689 tx_power=12>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: 47-67-34-41-C4-C9
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: b'\x10\x060\x1d\xc9\xa7\r\x80'
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DISCOVERY manufacturer fw_major: 0x10
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=FA-25-51-05-4B-B1 address=FA:25:51:05:4B:B1 rssi=-78 manufacturer_data={64: b'\x00\xb4\x02'} service_data={} service_uuids=['802a0000-4ef4-4e59-b573-2bed4a4ac159'] source=88:B1:11:7F:C4:38 connectable=True time=348900.52601005 tx_power=None>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: FA-25-51-05-4B-B1
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: b'\x00\xb4\x02'
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DISCOVERY manufacturer fw_major: 0x00
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-79 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=88:B1:11:7F:C4:38 connectable=True time=348903.079992297 tx_power=None>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: LEDnetWF02000813C11C
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: None
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-79 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=88:B1:11:7F:C4:38 connectable=True time=348903.079992297 tx_power=None>
2024-11-26 18:20:35.936 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] X Discovered device: <custom_components.lednetwf_ble.config_flow.DeviceData object at 0x7f6ab476ae10>
2024-11-26 18:25:24.087 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=FA-25-51-05-4B-B1 address=FA:25:51:05:4B:B1 rssi=-81 manufacturer_data={64: b'\x00\xb4\x02'} service_data={} service_uuids=['802a0000-4ef4-4e59-b573-2bed4a4ac159'] source=88:B1:11:7F:C4:38 connectable=True time=349188.788004743 tx_power=None>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: FA-25-51-05-4B-B1
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: b'\x00\xb4\x02'
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DISCOVERY manufacturer fw_major: 0x00
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-70 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=88:B1:11:7F:C4:38 connectable=True time=349190.896990062 tx_power=None>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: LEDnetWF02000813C11C
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: None
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=LEDnetWF02000813C11C address=08:65:F0:13:C1:1C rssi=-70 manufacturer_data={} service_data={} service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'] source=88:B1:11:7F:C4:38 connectable=True time=349190.896990062 tx_power=None>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] X Discovered device: <custom_components.lednetwf_ble.config_flow.DeviceData object at 0x7f6ab28f4740>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=68-2E-DD-B3-15-0F address=68:2E:DD:B3:15:0F rssi=-94 manufacturer_data={117: b'\x02\x18a\xb1\xed\t \x9d\x9f(\xe7\xc70\x181>\x00\xdc\x9eR\xc0B\xcf\x05'} service_data={} service_uuids=[] source=88:B1:11:7F:C4:38 connectable=True time=349174.275105765 tx_power=None>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: 68-2E-DD-B3-15-0F
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: b'\x02\x18a\xb1\xed\t \x9d\x9f(\xe7\xc70\x181>\x00\xdc\x9eR\xc0B\xcf\x05'
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DISCOVERY manufacturer fw_major: 0x02
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=31-33-A5-47-C4-CF address=31:33:A5:47:C4:CF rssi=-86 manufacturer_data={} service_data={'0000fcf1-0000-1000-8000-00805f9b34fb': b'\x04D`;7h\xa3E\xa6\xfc?4\xfb\xc7\xe2\x1d\x0c\x89LIg\x03'} service_uuids=['0000fcf1-0000-1000-8000-00805f9b34fb'] source=88:B1:11:7F:C4:38 connectable=True time=349191.014989241 tx_power=None>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: 31-33-A5-47-C4-CF
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: None
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DeviceData: <BluetoothServiceInfoBleak name=78-24-FA-58-7E-4E address=78:24:FA:58:7E:4E rssi=-65 manufacturer_data={76: b'\x10\x06>\x1dB\xd16\x80'} service_data={} service_uuids=[] source=88:B1:11:7F:C4:38 connectable=True time=349191.184988058 tx_power=12>
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Name: 78-24-FA-58-7E-4E
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Manufacturer data: b'\x10\x06>\x1dB\xd16\x80'
2024-11-26 18:25:24.088 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] DISCOVERY manufacturer fw_major: 0x10
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] async step user with User input: {'mac': '08:65:F0:13:C1:1C'}
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.config_flow] Device data is None, creating new data to pass up: {'mac': '08:65:F0:13:C1:1C', 'name': 'LEDnetWF02000813C11C (C11C)', 'delay': 120, 'model': 0}
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.lednetwf] Data: {'mac': '08:65:F0:13:C1:1C', 'name': 'LEDnetWF02000813C11C (C11C)', 'delay': 120, 'model': 0}
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.lednetwf] Service info: {'name': 'LEDnetWF02000813C11C', 'address': '08:65:F0:13:C1:1C', 'rssi': -71, 'manufacturer_data': {}, 'service_data': {}, 'service_uuids': ['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'], 'source': '88:B1:11:7F:C4:38', 'advertisement': AdvertisementData(local_name='LEDnetWF02000813C11C', service_uuids=['00001800-0000-1000-8000-00805f9b34fb', '00001801-0000-1000-8000-00805f9b34fb', '0000fe00-0000-1000-8000-00805f9b34fb', '0000ffff-0000-1000-8000-00805f9b34fb'], rssi=-71), 'device': BLEDevice(08:65:F0:13:C1:1C, LEDnetWF02000813C11C), 'connectable': True, 'time': 349193.029975214, 'tx_power': None}
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.lednetwf] Service info keys: dict_keys(['name', 'address', 'rssi', 'manufacturer_data', 'service_data', 'service_uuids', 'source', 'advertisement', 'device', 'connectable', 'time', 'tx_power'])
2024-11-26 18:25:26.047 ERROR (MainThread) [custom_components.lednetwf_ble.lednetwf] Manufacturer data not found.
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.lednetwf] Model class name: Model0x53
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.model_0x53] Model 0x53 init
2024-11-26 18:25:26.047 DEBUG (MainThread) [custom_components.lednetwf_ble.model_abstractions] Manu data: {}
2024-11-26 18:25:26.048 ERROR (MainThread) [aiohttp.server] Error handling request
Traceback (most recent call last):
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 193, in toggle_light
    self._instance = LEDNETWFInstance(self.mac, self.hass, data)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/lednetwf.py", line 165, in __init__
    self._model_interface = model_class(service_info['manufacturer_data'])
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/model_0x53.py", line 136, in __init__
    super().__init__(manu_data)
  File "/config/custom_components/lednetwf_ble/model_abstractions.py", line 24, in __init__
    manu_data_id           = next(iter(manu_data))
                             ^^^^^^^^^^^^^^^^^^^^^
StopIteration
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_protocol.py", line 477, in _handle_request
    resp = await request_handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_app.py", line 567, in _handle
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/security_filter.py", line 92, in security_filter_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/forwarded.py", line 83, in forwarded_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/request_context.py", line 26, in request_context_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/ban.py", line 86, in ban_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/auth.py", line 242, in auth_middleware
    return await handler(request)
           ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/headers.py", line 32, in headers_middleware
    response = await handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/http.py", line 73, in handle
    result = await handler(request, **request.match_info)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/decorators.py", line 81, in with_admin
    return await func(self, request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/config/config_entries.py", line 222, in post
    return await super().post(request, flow_id)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/http/data_validator.py", line 74, in wrapper
    return await method(view, request, data, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/data_entry_flow.py", line 122, in post
    result = await self._flow_mgr.async_configure(flow_id, data)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 367, in async_configure
    result = await self._async_configure(flow_id, user_input)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 414, in _async_configure
    result = await self._async_handle_step(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/data_entry_flow.py", line 517, in _async_handle_step
    result: _FlowResultT = await getattr(flow, method)(user_input)
                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 118, in async_step_user
    return await self.async_step_validate()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/config/custom_components/lednetwf_ble/config_flow.py", line 165, in async_step_validate
    error = await self.toggle_light()
            ^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: coroutine raised StopIteration
raulgbcr commented 1 day ago

Out of curiosity, have you actually tried the original app? Maybe you have an older model and there is some kind of update available for it

8none1 commented 19 hours ago

I determined that I had to add 0x00 to the SUPPORTED_MODELS in const.py

Oh! Whoops. Thank you! Fixed.

This did cause Home Assistant to offer to set up the new device, but that failed with the following:

Darn it. I thought I'd caught all of those.... fixing....

8none1 commented 19 hours ago

I've reviewed the logs a bit more, thanks for attaching them.

The additional debugging shows that this device is indeed missing all the manu_data. Strange, but I think we can manage. It's a bit of a shame as there is quite a lot of logic to improve the UX by pre-populating things like the current power state, colour setting etc.

But worst case is that the initial device view in HA is out of sync with reality for a short time until a change is made via the UI. No biggy.

Now we just need to provide an alternate path to deal with this data being missing. That's probably a good idea anyway and will make the code more robust. In the refactoring to support new models I was trying (believe it or not) to reduce the spaghettification. But to deal with this use case will need even more if statements.

sleavitt commented 17 hours ago

Out of curiosity, have you actually tried the original app? Maybe you have an older model and there is some kind of update available for it

I have the Zengge app from the Google Play Store, which is the app I am led to when I scan the QR code on the body of the controller. It does have a firmware update feature, and it appears to offer an upgrade from 53_0008_0F_02 to 53_0008_12_02, and it appears to proceed, but when it completes, it shows a red circle with an "i" in it, as if though it's an information button on what went wrong, but pressing it simply causes it to try the upgrade again.

The 53 at the beginning seems to explain why it seemed to have been working previously, as it seems reasonable to me that it indicates it is model 0x53.

8none1 commented 16 hours ago

Very interesting, perhaps the fw update failed and that's why it's in this strange state. No matter, it's a 0x53 and we can deal with that I think. I did some fixes at lunch, lemme push up to the branch...

... done.

Please update and try (yet) again :crossed_fingers:

sleavitt commented 12 hours ago

@8none1 I tend to agree that the state might be related to a failed firmware update.

The latest updates ALMOST got it, and with a minor amount of tweaking, I was able to get it to work as follows:

diff --git a/custom_components/lednetwf_ble/model_abstractions.py b/custom_components/lednetwf_ble/model_abstractions.py
index 638c975..effe810 100644
--- a/custom_components/lednetwf_ble/model_abstractions.py
+++ b/custom_components/lednetwf_ble/model_abstractions.py
@@ -39,7 +39,7 @@ class DefaultModelAbstraction:

     def process_manu_data(self, manu_data):
         LOGGER.debug(f"Manu data: {manu_data}")
-        if manu_data is not None:
+        if manu_data:
             manu_data_id           = next(iter(manu_data))
             self.manu_data         = bytearray(manu_data[manu_data_id])
             self.fw_major          = self.manu_data[0]
@@ -50,6 +50,7 @@ class DefaultModelAbstraction:
             self.is_on             = True if self.manu_data[14] == 0x23 else False
         else:
             LOGGER.debug("No manu data")
+            self.manu_data         = chr(0) * 25  # 25 character long string of null characters
             self.fw_major          = 0x00
             self.fw_minor          = "Unknown version"
             self.led_count         = None

Checking manu_data for truthiness rather than "is not None" appears to have been necessary, since manu_data is seen as an empty dict, and not as None at that point (at least in my case). Also, populating self.manu_data with a 25 character null string appears to be necessary to avoid index out of bounds issues. But with those changes, I was able to add the lights and see them blink, and they are now seen in Home Assistant properly.

8none1 commented 12 hours ago

Good call on making manu_data a string of nulls - that should prevent future issues when I break it again.

I've incorporated your changes, thank you very much for the testing & help. I've also incorporated a similar logic change in to config_flow to stop checking for "is not none"s.

Hopefully I can get this finished and merged this weekend. In the meantime, really happy to hear that you've got working lights again!

sleavitt commented 11 hours ago

No problem, happy to help. The only additional feedback I can think to provide is that if it is feasible to do so, alert the user that no manufacturer's data was detected, and allow them to select the model rather than defaulting it to 0x53, as I won't be surprised to see other models that don't have manufacturer data in them that are not the 0x53 model. But for my use case, this does seem to address things.