xZetsubou / hass-localtuya

🔹 A Home Assistant integration to handle Tuya devices locally "fork from localtuya"
https://xzetsubou.github.io/hass-localtuya/
GNU General Public License v3.0
360 stars 37 forks source link

[Bug]: Exception with BLE bulbs #190

Closed Lurker00 closed 3 months ago

Lurker00 commented 5 months ago

LocalTuya Version

3.2.5.1

Home Assistant Version

2024.03.1

Environment

What happened?

I have some BLE bulbs, and experience the problems discussed in issue #90. Probably I'll create another issue later, but, for now, I ask you to make a small change in the source code: https://github.com/xZetsubou/hass-localtuya/blob/master/custom_components/localtuya/light.py

  1. In the class LocaltuyaLight(LocalTuyaEntity, LightEntity), remove line self._brightness = None (currently 146).
  2. Add after the current line 153: self._brightness = self._upper_brightness

I.e. initialize self._brightness with a suitable integer value instead of None.

Explanation: The bulbs don't allow to connect to their datapoints, but sometimes they report something, including brightness change. In the event handler, brightness method is called, which calls map_range with self._brightness as the 1st parameter (=None), causing an exception when None is used in the arithmetic expression.

I believe you understand that this change does not hurt! The second one I've made you've already implemented in 3.2.5.1 (self._scenes = {} instead of None). It caused me exceptions as well when a BLE bulb reported mode change.

Thanks in advance!

Steps to reproduce.

You need to have a BLE bulb and change its parameters by Smart Life automatition. So please just trust me :)

Relevant log output

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/asyncio/events.py", line 88, in _run
    self._context.run(self._callback, *self._args)
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 992, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1113, in _async_write_ha_state
    state, attr, capabilities, shadowed_attr = self.__async_calculate_state()
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1052, in __async_calculate_state
    attr.update(self.state_attributes or {})
                ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/light/__init__.py", line 1202, in state_attributes
    data[ATTR_BRIGHTNESS] = self.brightness
                            ^^^^^^^^^^^^^^^
  File "/config/custom_components/localtuya/light.py", line 192, in brightness
    return map_range(
           ^^^^^^^^^^
  File "/config/custom_components/localtuya/light.py", line 101, in map_range
    mapped = (value - from_lower) * (to_upper - to_lower) / (
              ~~~~~~^~~~~~~~~~~~
TypeError: unsupported operand type(s) for -: 'NoneType' and 'int'

Diagnostics information.

No response

xZetsubou commented 5 months ago

Why not add a condition in brightness to ensure the brightness is not None? https://github.com/xZetsubou/hass-localtuya/blob/cdc12573967e7db6dbfb5fbcf4cb711ab7536807/custom_components/localtuya/light.py#L189-L195

With condition:

    def brightness(self):
        """Return the brightness of the light."""
        if self._brightness is not None and (self.is_color_mode or self.is_white_mode):
            return map_range(
                self._brightness, self._lower_brightness, self._upper_brightness, 0, 255
            )
        return None

edit: do mind posting the device diagnostics I want to take a look to the device properties.

Lurker00 commented 5 months ago

Why not add a condition in brightness to ensure the brightness is not None?

For two reasons:

  1. As a programmer: I'm not sure how the upper level (HA engine that makes the call) would deal with the case "a bulb reports its brightness, but the value is None". As I understand, the whole code (both HA abstraction level and the integration) was written presuming that all the propeties were initialized by querying the bulb initially.
  2. As such bulbs owner: My goal is to make the engine to allow me to control the bulbs in automatition, but it is disabled until ... I'm yet to find until what, and how exactly make it, but currently, with my change in the code, it became usable 😄

do mind posting the device diagnostics

If I understand you correctly, I've attached it. You can see that I forced all the properties to be "cloud pull". localtuya-944c1616039a1d1ec6b9745179bff74e-КЛ1_ LED BULB B5K-1ae4e56ffcf36ae73a5bd7ddf02dd49e (2).json

xZetsubou commented 5 months ago

The calls will made every time the status updated, so I think adding the condition is better and it won't update the brightness unless the brightness defined which is will do if the device later sent an update for brightness DPID.

A tip you may want to try is rather than using non-existing DPIDs such as 101 or so. is putting only "0" on manual DPS this will ignore the handshake and later I can changed it so it will restore old cached states in HA, so on the next times you connect to the device it restore the old states rather then waiting for the device to reports.

So here Is what I want to test:

  1. Add a condition as I suggest in https://github.com/xZetsubou/hass-localtuya/issues/190#issuecomment-2033269239
  2. Re-add the device and insert only "0" in manual DPS field.
Lurker00 commented 5 months ago

OK, I'll do the tests you asked for and report.

But one more wish then: could you please document these "magic" numbers - +100 (to force cloud pull) or 0 for manual DPS! It took me a while until I found +100 in issue #90, and I never saw about 0.

xZetsubou commented 5 months ago

It does kinda exists in IR Remote FAQ because this was made for IR Remote purpose. 😅 The FAQ page has been added recently.

Lurker00 commented 5 months ago

So here Is what I want to test:

  1. Add a condition as I suggest in [Bug]: Exception with BLE bulbs #190 (comment)
  2. Re-add the device and insert only "0" in manual DPS field.

It works: bulbs were added, they are active, no exceptions after I controlled them using scene switch buttons. I can control them from automation.

github-actions[bot] commented 3 months ago

This issue was closed because it was resolved on the release: []()