-
Notifications
You must be signed in to change notification settings - Fork 70
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
[Bug]: Unable to set RGB Bulb Brightness in 2025.1.1 #499
Comments
Post the device diagnostics |
|
Upon further investigation, if I send light.turn_on with the following data, brightness change works: But with the following data (what my automations were set to and what works in 2024.12.2) it DOES NOT work: Trying to change the brightness from the HA UI, does not work ever, since presumably it is only sending the I've updated my automations to include |
Can you enable the debug for both integration and device and run the tests from HA UI by changing the brightness then paste all the logs then post the logs, I tried the same settings of you bulb it it did works for me. |
|
Same problem here. I have gone back to the previous version which still works like charm |
You can test this copy code block and paste int HA config cover.py
"""Platform to locally control Tuya-based light devices."""
import base64
import logging
import textwrap
import homeassistant.util.color as color_util
import voluptuous as vol
from dataclasses import dataclass
from functools import partial
from homeassistant.helpers import selector
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_COLOR_TEMP_KELVIN,
ATTR_EFFECT,
ATTR_HS_COLOR,
ATTR_WHITE,
ColorMode,
DOMAIN,
LightEntity,
LightEntityFeature,
)
from homeassistant.const import CONF_BRIGHTNESS, CONF_COLOR_TEMP, CONF_SCENE
from .config_flow import col_to_select
from .entity import LocalTuyaEntity, async_setup_entry
from .const import (
CONF_BRIGHTNESS_LOWER,
CONF_BRIGHTNESS_UPPER,
CONF_COLOR,
CONF_COLOR_MODE,
CONF_COLOR_MODE_SET,
CONF_COLOR_TEMP_MAX_KELVIN,
CONF_COLOR_TEMP_MIN_KELVIN,
CONF_COLOR_TEMP_REVERSE,
CONF_MUSIC_MODE,
CONF_SCENE_VALUES,
)
_LOGGER = logging.getLogger(__name__)
DEFAULT_MIN_KELVIN = 2700 # MIRED 370
DEFAULT_MAX_KELVIN = 6500 # MIRED 153
DEFAULT_COLOR_TEMP_REVERSE = False
DEFAULT_LOWER_BRIGHTNESS = 10
DEFAULT_UPPER_BRIGHTNESS = 1000
MODE_MANUAL = "manual"
MODE_COLOR = "colour"
MODE_MUSIC = "music"
MODE_SCENE = "scene"
MODE_WHITE = "white"
SCENE_MUSIC = "Music"
MODES_SET = {"Colour, Music, Scene and White": 0, "Manual, Music, Scene and White": 1}
# https://developer.tuya.com/en/docs/iot/dj?id=K9i5ql3v98hn3#title-10-scene_data
SCENE_LIST_RGBW_255 = {
"Night": "bd76000168ffff",
"Read": "fffcf70168ffff",
"Meeting": "cf38000168ffff",
"Leasure": "3855b40168ffff",
"Scenario 1": "scene_1",
"Scenario 2": "scene_2",
"Scenario 3": "scene_3",
"Scenario 4": "scene_4",
}
# https://developer.tuya.com/en/docs/iot/dj?id=K9i5ql3v98hn3#title-11-scene_data_v2
SCENE_LIST_RGBW_1000 = {
"Night 1": "000e0d0000000000000000c80000",
"Night 2": "000e0d00002e03e802cc00000000",
"Read 1": "010e0d0000000000000003e801f4",
"Read 2": "010e0d000084000003e800000000",
"Meeting": "020e0d0000000000000003e803e8",
"Working": "020e0d00001403e803e800000000",
"Leasure 1": "030e0d0000000000000001f401f4",
"Leisure 2": "030e0d0000e80383031c00000000",
"Soft": "04464602007803e803e800000000464602007803e8000a00000000",
"Rainbow": "05464601000003e803e800000000464601007803e803e80000000046460100f003e803"
+ "e800000000",
"Colorful": "06464601000003e803e800000000464601007803e803e80000000046460100f003e80"
+ "3e800000000464601003d03e803e80000000046460100ae03e803e800000000464601011303e803"
+ "e800000000",
"Beautiful": "07464602000003e803e800000000464602007803e803e80000000046460200f003e8"
+ "03e800000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e80"
+ "3e800000000",
"Forest": "19464601007803e803e800000000464602006e0320025800000000464602005a038403e8"
+ "00000000",
"Dream": "1c4646020104032003e800000000464602011802bc03e800000000464602011303e803e80"
+ "0000000",
"F Style": "1e323201015e01f403e800000000323202003201f403e80000000032320200a001f403e"
+ "800000000",
"A Style": "1f46460100dc02bc03e800000000464602006e03200258000000004646020014038403e"
+ "800000000464601012703e802ee0000000046460100000384028a00000000",
"Halloween": "28464601011303e803e800000000464601001e03e803e800000000",
"Christmas": "225a5a0100f003e803e8000000005a5a01003d03e803e800000000464601000003e80"
+ "3e8000000005a5a0100ae03e803e8000000005a5a01011303e803e800000000464601007803e803e"
+ "800000000",
"Birthday": "20646401003d03e803e800000000646401007803e803e8000000005a5a01011303e803"
+ "e8000000005a5a0100ae03e803e800000000646401003201f403e800000000646401000003e803e8"
+ "00000000",
"Wedding Anniversary": "21323202015e01f403e800000000323202011303e803e800000000",
}
# Same format as SCENE_LIST_RGBW_1000
SCENE_LIST_RGB_1000 = {
"Night": "000e0d00002e03e802cc00000000",
"Read": "010e0d000084000003e800000000",
"Working": "020e0d00001403e803e800000000",
"Leisure": "030e0d0000e80383031c00000000",
"Soft": "04464602007803e803e800000000464602007803e8000a00000000",
"Colorful": "05464601000003e803e800000000464601007803e803e80000000046460100f003e80"
+ "3e800000000464601003d03e803e80000000046460100ae03e803e800000000464601011303e803"
+ "e800000000",
"Dazzling": "06464601000003e803e800000000464601007803e803e80000000046460100f003e80"
+ "3e800000000",
"Gorgeous": "07464602000003e803e800000000464602007803e803e80000000046460200f003e803e8"
+ "00000000464602003d03e803e80000000046460200ae03e803e800000000464602011303e803e80"
+ "0000000",
}
SCENE_LIST_RGBW_BLE = {
"Good Night": "AAAAAGQKQA==",
"Reading": "AQAAAGRkCA==",
"Work": "AgAAAGRkAQ==",
"Leisure": "AwAAAGQ8BA==",
"White Breath": "BgACADxkAYA=",
"White Flashing": "BwABADJkAYA=",
"Warm Breath": "BwABADJkAYA=",
"Warm Flashing": "CQABADJkQIA=",
"Rainbow": "CgACAUtkAQIEECAI",
"Blue & Green Gradient": "CwACAUtkAgQ=",
"Red & Green Gradient": "DAACAUtkAQQ=",
"Red & Blue Gradient": "DQACAUtkAQI=",
"Red & Blue & Green Gradient": "DgACATxkAYACgASA",
"Red Breath": "DwACATxkAYA=",
"Flash": "FAABATJkAQIEECAI",
}
@dataclass(frozen=True)
class Mode:
color: str = MODE_COLOR
music: str = MODE_MUSIC
scene: str = MODE_SCENE
white: str = MODE_WHITE
def as_list(self) -> list:
return [self.color, self.music, self.scene, self.white]
def as_dict(self) -> dict[str, str]:
default = {"Default": self.white}
return {**default, "Mode Color": self.color, "Mode Scene": self.scene}
MAP_MODE_SET = {0: Mode(), 1: Mode(color=MODE_MANUAL)}
def map_range(
value: int, from_min: int, from_max: int, to_min=0, to_max=255, reverse=False
):
"""Maps a value from one range to another."""
if reverse:
value = from_max - (value + from_min)
scale = (to_max - to_min) / (from_max - from_min)
mapped_value = to_min + (value - from_min) * scale
return min(max(round(mapped_value), to_min), to_max)
def map_value_by_percent(value: int, value_max: int, target_max: int, percentage=100):
"""Convert a value from one range to another based on percentage."""
raw_percent = (value / value_max) * percentage
return round((raw_percent / percentage) * target_max)
def flow_schema(dps):
"""Return schema used in config flow."""
return {
vol.Optional(CONF_BRIGHTNESS): col_to_select(dps, is_dps=True),
vol.Optional(CONF_COLOR_TEMP): col_to_select(dps, is_dps=True),
vol.Optional(CONF_BRIGHTNESS_LOWER, default=DEFAULT_LOWER_BRIGHTNESS): vol.All(
vol.Coerce(int), vol.Range(min=0, max=10000)
),
vol.Optional(CONF_BRIGHTNESS_UPPER, default=DEFAULT_UPPER_BRIGHTNESS): vol.All(
vol.Coerce(int), vol.Range(min=0, max=10000)
),
vol.Optional(CONF_COLOR_MODE): col_to_select(dps, is_dps=True),
vol.Required(CONF_COLOR_MODE_SET, default="0"): col_to_select(MODES_SET),
vol.Optional(CONF_COLOR): col_to_select(dps, is_dps=True),
vol.Optional(CONF_COLOR_TEMP_MIN_KELVIN, default=DEFAULT_MIN_KELVIN): vol.All(
vol.Coerce(int), vol.Range(min=1500, max=8000)
),
vol.Optional(CONF_COLOR_TEMP_MAX_KELVIN, default=DEFAULT_MAX_KELVIN): vol.All(
vol.Coerce(int), vol.Range(min=1500, max=8000)
),
vol.Optional(CONF_COLOR_TEMP_REVERSE, default=DEFAULT_COLOR_TEMP_REVERSE): bool,
vol.Optional(CONF_SCENE): col_to_select(dps, is_dps=True),
vol.Optional(CONF_SCENE_VALUES, default={}): selector.ObjectSelector(),
vol.Optional(CONF_MUSIC_MODE, default=False): selector.BooleanSelector(),
}
class LocalTuyaLight(LocalTuyaEntity, LightEntity):
"""Representation of a Tuya light."""
def __init__(
self,
device,
config_entry,
lightid,
**kwargs,
):
"""Initialize the Tuya light."""
super().__init__(device, config_entry, lightid, _LOGGER, **kwargs)
# Light is an active device (mains powered). It should be able
# to respond at any time. But Tuya BLE bulbs are write-only.
self._write_only = self._device.is_write_only
self._state = None
self._color_temp = None
self._lower_brightness = int(
self._config.get(CONF_BRIGHTNESS_LOWER, DEFAULT_LOWER_BRIGHTNESS)
)
self._upper_brightness = int(
self._config.get(CONF_BRIGHTNESS_UPPER, DEFAULT_UPPER_BRIGHTNESS)
)
self._brightness = None if not self._write_only else self._upper_brightness
self._upper_color_temp = self._upper_brightness
self._color_temp_reverse = self._config.get(CONF_COLOR_TEMP_REVERSE, False)
self._modes = MAP_MODE_SET[int(self._config.get(CONF_COLOR_MODE_SET, 0))]
self._hs = None
self._effect = None
self._effect_list = []
self._scenes = {}
self._cached_status = {}
if self._config.get(CONF_MUSIC_MODE):
self._effect_list.append(SCENE_MUSIC)
self._attr_min_color_temp_kelvin = int(
self._config.get(CONF_COLOR_TEMP_MIN_KELVIN, DEFAULT_MIN_KELVIN)
)
self._attr_max_color_temp_kelvin = int(
self._config.get(CONF_COLOR_TEMP_MAX_KELVIN, DEFAULT_MAX_KELVIN)
)
self.__to_color = self.__to_color_common
self.__from_color = self.__from_color_common
def connection_made(self):
"""The connection has made with the device and status retrieved, Configure the entity based on its reserved status."""
super().connection_made()
is_write_only = self._write_only
if self.has_config(CONF_SCENE):
if (scenes := self._config.get(CONF_SCENE_VALUES, {})) and len(scenes):
self._scenes = {v: k for k, v in scenes.items()}
else:
scene_value = self.dp_value(CONF_SCENE)
if is_write_only and not scene_value:
self._scenes = SCENE_LIST_RGBW_BLE
elif scene_value and len(scene_value) <= 20:
self._scenes = SCENE_LIST_RGBW_255
elif self._config.get(CONF_BRIGHTNESS) is None:
self._scenes = SCENE_LIST_RGB_1000
else:
self._scenes = SCENE_LIST_RGBW_1000
self._scenes = {**self._modes.as_dict(), **self._scenes}
self._effect_list = list(self._scenes.keys()) + self._effect_list
if self.has_config(CONF_COLOR):
color_data = self.dp_value(CONF_COLOR)
if is_write_only and not color_data:
self.__to_color = self.__to_color_raw
self.__from_color = self.__from_color_raw
else:
self.__to_color = self.__to_color_common
self.__from_color = self.__from_color_common
if is_write_only and self._cached_status:
self._status.update(self._cached_status)
@property
def extra_state_attributes(self):
"""Return entity specific state attributes to be saved.
These attributes are then available for restore when the
entity is restored at startup.
"""
attributes = super().extra_state_attributes
extra_attrs = (CONF_COLOR_MODE, CONF_COLOR, CONF_BRIGHTNESS, CONF_COLOR_TEMP)
for attr in extra_attrs:
dp = self._config.get(attr)
if dp is not None and (state := self._status.get(dp)) is not None:
attributes[f"raw_{attr}"] = state
return attributes
@property
def is_on(self):
"""Check if Tuya light is on."""
return self._state
@property
def brightness(self):
"""Return the brightness of the light."""
brightness = self._brightness
if brightness is not None and (self.is_color_mode or self.is_white_mode):
return map_value_by_percent(brightness, self._upper_brightness, 255)
return None
@property
def hs_color(self):
"""Return the hs color value."""
if self.is_color_mode:
return self._hs
if (
ColorMode.HS in self.supported_color_modes
and not ColorMode.COLOR_TEMP in self.supported_color_modes
):
return [0, 0]
return None
@property
def color_temp_kelvin(self):
"""Return the color_temp of the light."""
if self._color_temp is not None:
return map_range(
self._color_temp,
self._lower_brightness,
self._upper_brightness,
self.min_color_temp_kelvin,
self.max_color_temp_kelvin,
self._color_temp_reverse,
)
@property
def effect(self):
"""Return the current effect for this light."""
if self.is_scene_mode or self.is_music_mode:
return self._effect
elif (color_mode := self.__get_color_mode()) in self._scenes.values():
return self.__find_scene_by_scene_data(color_mode)
return None
@property
def effect_list(self):
"""Return the list of supported effects for this light."""
if len(self._effect_list) > 0:
return self._effect_list
return None
@property
def supported_color_modes(self) -> set[ColorMode] | set[str] | None:
"""Flag supported color modes."""
color_modes: set[ColorMode] = set()
if self.has_config(CONF_COLOR_TEMP):
color_modes.add(ColorMode.COLOR_TEMP)
elif self.has_config(CONF_BRIGHTNESS):
color_modes.add(ColorMode.WHITE)
if self.has_config(CONF_COLOR):
color_modes.add(ColorMode.HS)
if self.has_config(CONF_COLOR):
color_modes.add(ColorMode.HS)
if color_modes == {ColorMode.WHITE}:
return {ColorMode.BRIGHTNESS}
if not color_modes:
return {ColorMode.ONOFF}
return color_modes
@property
def supported_features(self) -> LightEntityFeature:
"""Flag supported features."""
supports = LightEntityFeature(0)
if self.has_config(CONF_SCENE) or self.has_config(CONF_MUSIC_MODE):
supports |= LightEntityFeature.EFFECT
return supports
@property
def is_white_mode(self):
"""Return true if the light is in white mode."""
color_mode = self.__get_color_mode()
return color_mode is None or color_mode == self._modes.white
@property
def is_color_mode(self):
"""Return true if the light is in color mode."""
color_mode = self.__get_color_mode()
return color_mode is not None and color_mode == self._modes.color
@property
def is_scene_mode(self):
"""Return true if the light is in scene mode."""
color_mode = self.__get_color_mode()
return color_mode is not None and color_mode.startswith(self._modes.scene)
@property
def is_music_mode(self):
"""Return true if the light is in music mode."""
color_mode = self.__get_color_mode()
return color_mode is not None and color_mode == self._modes.music
@property
def color_mode(self) -> ColorMode:
"""Return the color_mode of the light."""
if len(self.supported_color_modes) == 1:
return next(iter(self.supported_color_modes))
if self.is_color_mode:
return ColorMode.HS
if self.is_white_mode:
if self.has_config(CONF_COLOR_TEMP):
return ColorMode.COLOR_TEMP
else:
return ColorMode.WHITE
if self._brightness:
return ColorMode.BRIGHTNESS
return ColorMode.ONOFF
def __is_color_rgb_encoded(self):
# for now we will prefer non encoded if color is none "added by manual or cloud pull dp"
color = self.dp_value(CONF_COLOR)
return False if color is None else len(color) > 12
def __find_scene_by_scene_data(self, data):
return (
next(
(item for item in self._effect_list if self._scenes.get(item) == data),
None,
)
if data is not None
else None
)
def __get_color_mode(self):
return (
self.dp_value(CONF_COLOR_MODE)
if self.has_config(CONF_COLOR_MODE)
else self._modes.white
)
def __to_color_raw(self, hs, brightness):
return base64.b64encode(
# BASE64-encoded 4-byte value: HHSL
bytes(
[
round(hs[0]) // 256,
round(hs[0]) % 256,
round(hs[1]),
round(brightness * 100 / self._upper_brightness),
]
)
).decode("ascii")
def __to_color_(self, hs, brightness):
# https://developer.tuya.com/en/docs/iot/dj?id=K9i5ql3v98hn3#title-8-colour_data
return "{:04x}{:02x}{:02x}".format(
round(hs[0]),
round(hs[1] * 255 / 100),
round(brightness * 255 / self._upper_brightness),
)
def __to_color_v2(self, hs, brightness):
# https://developer.tuya.com/en/docs/iot/dj?id=K9i5ql3v98hn3#title-9-colour_data_v2
return "{:04x}{:04x}{:04x}".format(
round(hs[0]), round(hs[1] * 10.0), brightness
)
def __to_color_common(self, hs, brightness):
"""Converts HSB values to a string."""
if self.__is_color_rgb_encoded():
# Not documented format
rgb = color_util.color_hsv_to_RGB(
hs[0], hs[1], int(brightness * 100 / self._upper_brightness)
)
return "{:02x}{:02x}{:02x}{:04x}{:02x}{:02x}".format(
round(rgb[0]),
round(rgb[1]),
round(rgb[2]),
round(hs[0]),
round(hs[1] * 255 / 100),
brightness,
)
else:
return self.__to_color_v2(hs, brightness)
def __from_color_raw(self, color):
# BASE64-encoded 4-byte value: HHSL
hsl = int.from_bytes(base64.b64decode(color), byteorder="big", signed=False)
hue = hsl // 65536
sat = (hsl // 256) % 256
value = (hsl % 256) * self._upper_brightness / 100
self._hs = [hue, sat]
self._brightness = value
def __from_color_(self, color):
# https://developer.tuya.com/en/docs/iot/dj?id=K9i5ql3v98hn3#title-8-colour_data
hue, sat, value = [int(value, 16) for value in textwrap.wrap(color, 4)]
self._hs = [hue, sat * 100 / 255]
self._brightness = value * self._upper_brightness / 100
def __from_color_v2(self, color):
# https://developer.tuya.com/en/docs/iot/dj?id=K9i5ql3v98hn3#title-9-colour_data_v2
hue, sat, value = [int(value, 16) for value in textwrap.wrap(color, 4)]
self._hs = [hue, sat / 10.0]
self._brightness = value
def __from_color_common(self, color):
"""Convert a string to HSL values."""
if self.__is_color_rgb_encoded():
hue = int(color[6:10], 16)
sat = int(color[10:12], 16)
value = int(color[12:14], 16)
self._hs = [hue, (sat * 100 / 255)]
self._brightness = value
else:
self.__from_color_v2(color)
async def async_turn_on(self, **kwargs):
"""Turn on or control the light."""
states = {}
if not self.is_on or self._write_only:
states[self._dp_id] = True
features = self.supported_features
color_modes = self.supported_color_modes
brightness = None
color_mode = None
if ATTR_EFFECT in kwargs and (features & LightEntityFeature.EFFECT):
effect = kwargs[ATTR_EFFECT]
scene = self._scenes.get(effect)
if scene is not None:
if scene.startswith(self._modes.scene) or scene in (
self._modes.white,
self._modes.color,
):
color_mode = scene
else:
color_mode = self._modes.scene
states[self._config.get(CONF_SCENE)] = scene
elif effect in self._modes.as_list():
color_mode = effect
elif effect == self._modes.music:
color_mode = self._modes.music
if ATTR_BRIGHTNESS in kwargs and (
ColorMode.BRIGHTNESS in color_modes
or self.has_config(CONF_BRIGHTNESS)
or self.has_config(CONF_COLOR)
):
brightness = map_value_by_percent(
int(kwargs[ATTR_BRIGHTNESS]), 255, self._upper_brightness
)
brightness = max(brightness, self._lower_brightness)
if self.is_color_mode and self._hs is not None:
states[self._config.get(CONF_COLOR)] = self.__to_color(
self._hs, brightness
)
color_mode = self._modes.color
else:
states[self._config.get(CONF_BRIGHTNESS)] = brightness
color_mode = self._modes.white
if ATTR_HS_COLOR in kwargs and ColorMode.HS in color_modes:
if brightness is None:
brightness = self._brightness
hs = kwargs[ATTR_HS_COLOR]
if hs[1] == 0 and self.has_config(CONF_BRIGHTNESS):
states[self._config.get(CONF_BRIGHTNESS)] = brightness
color_mode = self._modes.white
else:
states[self._config.get(CONF_COLOR)] = self.__to_color(hs, brightness)
color_mode = self._modes.color
if ATTR_COLOR_TEMP_KELVIN in kwargs and ColorMode.COLOR_TEMP in color_modes:
if brightness is None:
brightness = self._brightness
color_temp = map_range(
int(kwargs[ATTR_COLOR_TEMP_KELVIN]),
self.min_color_temp_kelvin,
self.max_color_temp_kelvin,
self._lower_brightness,
self._upper_color_temp,
self._color_temp_reverse,
)
color_mode = self._modes.white
states[self._config.get(CONF_BRIGHTNESS)] = brightness
states[self._config.get(CONF_COLOR_TEMP)] = color_temp
if ATTR_WHITE in kwargs and ColorMode.WHITE in color_modes:
if brightness is None:
brightness = self._brightness
color_mode = self._modes.white
states[self._config.get(CONF_BRIGHTNESS)] = brightness
if color_mode is not None:
states[self._config.get(CONF_COLOR_MODE)] = color_mode
await self._device.set_dps(states)
async def async_turn_off(self, **kwargs):
"""Turn Tuya light off."""
await self._device.set_dp(False, self._dp_id)
def status_updated(self):
"""Device status was updated."""
self._state = self.dp_value(self._dp_id)
supported = self.supported_features
self._effect = None
if (brightness_dp_value := self.dp_value(CONF_BRIGHTNESS)) is not None:
self._brightness = brightness_dp_value
if ColorMode.HS in self.supported_color_modes:
color = self.dp_value(CONF_COLOR)
if color is not None and not self.is_white_mode:
self.__from_color(color)
elif self._brightness is None:
self._brightness = self._upper_brightness
if ColorMode.COLOR_TEMP in self.supported_color_modes:
self._color_temp = self.dp_value(CONF_COLOR_TEMP)
if self.is_scene_mode and supported & LightEntityFeature.EFFECT:
color_mode = self.dp_value(CONF_COLOR_MODE)
if color_mode != self._modes.scene:
self._effect = self.__find_scene_by_scene_data(color_mode)
else:
self._effect = self.__find_scene_by_scene_data(
self.dp_value(CONF_SCENE)
)
if self._effect is None:
self._effect = self.__find_scene_by_scene_data(color_mode)
if self.is_music_mode and supported & LightEntityFeature.EFFECT:
self._effect = SCENE_MUSIC
def status_restored(self, stored_state) -> None:
"""Device status was restored."""
restore_attrs = (CONF_COLOR_MODE, CONF_COLOR, CONF_BRIGHTNESS, CONF_COLOR_TEMP)
if self._write_only:
for attr in restore_attrs:
dp = self._config.get(attr)
restored_value = stored_state.attributes.get(f"raw_{attr}")
if None in (dp, restored_value):
continue
self._cached_status[dp] = restored_value
self._state = self._last_state
async_setup_entry = partial(async_setup_entry, DOMAIN, LocalTuyaLight, flow_schema) |
I will wait for the next release. I copied the new file you provided but the problem is still there so I have rolled back to 2024.12.1 and it’s working again. Thanks |
LocalTuya Version
2025.1.1
Home Assistant Version
2025.1.2
Environment
What happened?
After upgrading LocalTuya to 2025.1.1 I can no longer control the Brightness of an RGB bulb I have. Light turns on at 100% brightness, changing the brightness in HA does not change the brightness of the bulb or the brightness reported in HA, it stays at 100%.
Color changing, on/off, still work normally.
There are no errors in the logs with debugging mode on, brightness change simply does not work.
This is my only Tuya device, it has been blocked from internet access for almost 2 years now ever since I got it set up with the old LocalTuya integration and has been working fine with both the old integration and this fork until 2025.1.1
Rolling back to LocalTuya 2024.12.1 immediately fixes the issue, I'm staying on that version for now.
I'm guessing this is related to a bug somewhere in #477
Steps to reproduce.
Relevant log output
No errors in logs.
Diagnostics information.
No response
The text was updated successfully, but these errors were encountered: