diff --git a/custom_components/localtuya/__init__.py b/custom_components/localtuya/__init__.py index 3f7b0c6f4..ae2c893c2 100644 --- a/custom_components/localtuya/__init__.py +++ b/custom_components/localtuya/__init__.py @@ -34,6 +34,8 @@ friendly_name: Device Light id: 4 brightness: 20 + brightness_lower: 29 # Optional + brightness_upper: 1000 # Optional color_temp: 21 - platform: sensor diff --git a/custom_components/localtuya/const.py b/custom_components/localtuya/const.py index d3310fca7..2b57240cc 100644 --- a/custom_components/localtuya/const.py +++ b/custom_components/localtuya/const.py @@ -8,6 +8,10 @@ CONF_PROTOCOL_VERSION = "protocol_version" CONF_DPS_STRINGS = "dps_strings" +# light +CONF_BRIGHTNESS_LOWER = "brightness_lower" +CONF_BRIGHTNESS_UPPER = "brightness_upper" + # switch CONF_CURRENT = "current" CONF_CURRENT_CONSUMPTION = "current_consumption" diff --git a/custom_components/localtuya/light.py b/custom_components/localtuya/light.py index 39e0a8797..4f8174455 100644 --- a/custom_components/localtuya/light.py +++ b/custom_components/localtuya/light.py @@ -19,18 +19,36 @@ ) from .common import LocalTuyaEntity, async_setup_entry +from .const import CONF_BRIGHTNESS_LOWER, CONF_BRIGHTNESS_UPPER _LOGGER = logging.getLogger(__name__) MIN_MIRED = 153 MAX_MIRED = 370 +DEFAULT_LOWER_BRIGHTNESS = 29 +DEFAULT_UPPER_BRIGHTNESS = 1000 + + +def map_range(value, from_lower, from_upper, to_lower, to_upper): + """Map a value in one range to another.""" + mapped = (value - from_lower) * (to_upper - to_lower) / ( + from_upper - from_lower + ) + to_lower + return round(min(max(mapped, to_lower), to_upper)) + def flow_schema(dps): """Return schema used in config flow.""" return { vol.Optional(CONF_BRIGHTNESS): vol.In(dps), vol.Optional(CONF_COLOR_TEMP): vol.In(dps), + 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) + ), } @@ -47,8 +65,14 @@ def __init__( """Initialize the Tuya light.""" super().__init__(device, config_entry, lightid, **kwargs) self._state = False - self._brightness = 127 - self._color_temp = 127 + self._brightness = None + self._color_temp = None + self._lower_brightness = self._config.get( + CONF_BRIGHTNESS_LOWER, DEFAULT_LOWER_BRIGHTNESS + ) + self._upper_brightness = self._config.get( + CONF_BRIGHTNESS_UPPER, DEFAULT_UPPER_BRIGHTNESS + ) @property def is_on(self): @@ -63,10 +87,9 @@ def brightness(self): @property def color_temp(self): """Return the color_temp of the light.""" - try: + if self.has_config(CONF_COLOR_TEMP): return int(MAX_MIRED - (((MAX_MIRED - MIN_MIRED) / 255) * self._color_temp)) - except TypeError: - pass + return None @property def min_mireds(self): @@ -81,24 +104,32 @@ def max_mireds(self): @property def supported_features(self): """Flag supported features.""" - supports = SUPPORT_BRIGHTNESS - if self._color_temp is not None: - supports = supports | SUPPORT_COLOR_TEMP + supports = 0 + if self.has_config(CONF_BRIGHTNESS): + supports |= SUPPORT_BRIGHTNESS + if self.has_config(CONF_COLOR_TEMP): + supports |= SUPPORT_COLOR_TEMP return supports async def async_turn_on(self, **kwargs): """Turn on or control the light.""" await self._device.set_dp(True, self._dp_id) - - if ATTR_BRIGHTNESS in kwargs: - await self._device.set_dp( - max(int(kwargs[ATTR_BRIGHTNESS]), 25), self._config.get(CONF_BRIGHTNESS) + features = self.supported_features + + if ATTR_BRIGHTNESS in kwargs and (features & SUPPORT_BRIGHTNESS): + brightness = map_range( + int(kwargs[ATTR_BRIGHTNESS]), + 0, + 255, + self._lower_brightness, + self._upper_brightness, ) + await self._device.set_dp(brightness, self._config.get(CONF_BRIGHTNESS)) if ATTR_HS_COLOR in kwargs: raise ValueError(" TODO implement RGB from HS") - if ATTR_COLOR_TEMP in kwargs: + if ATTR_COLOR_TEMP in kwargs and (features & SUPPORT_COLOR_TEMP): color_temp = int( 255 - (255 / (MAX_MIRED - MIN_MIRED)) @@ -113,14 +144,22 @@ async def async_turn_off(self, **kwargs): def status_updated(self): """Device status was updated.""" self._state = self.dps(self._dp_id) - - brightness = self.dps_conf(CONF_BRIGHTNESS) - if brightness is not None: - brightness = min(brightness, 255) - brightness = max(brightness, 25) - self._brightness = brightness - - self._color_temp = self.dps_conf(CONF_COLOR_TEMP) + supported = self.supported_features + + if supported & SUPPORT_BRIGHTNESS: + brightness = self.dps_conf(CONF_BRIGHTNESS) + if brightness is not None: + brightness = map_range( + brightness, + self._lower_brightness, + self._upper_brightness, + 0, + 255, + ) + self._brightness = brightness + + if supported & SUPPORT_COLOR_TEMP: + self._color_temp = self.dps_conf(CONF_COLOR_TEMP) async_setup_entry = partial(async_setup_entry, DOMAIN, LocaltuyaLight, flow_schema) diff --git a/custom_components/localtuya/translations/en.json b/custom_components/localtuya/translations/en.json index 5ab3783f1..3193735e8 100644 --- a/custom_components/localtuya/translations/en.json +++ b/custom_components/localtuya/translations/en.json @@ -57,6 +57,8 @@ "state_on": "On Value", "state_off": "Off Value", "brightness": "Brightness", + "brightness_lower": "Brightness Lower Value", + "brightness_upper": "Brightness Upper Value", "color_temp": "Color Temperature" } } @@ -94,6 +96,8 @@ "state_on": "On Value", "state_off": "Off Value", "brightness": "Brightness", + "brightness_lower": "Brightness Lower Value", + "brightness_upper": "Brightness Upper Value", "color_temp": "Color Temperature" } },