mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Free color selection for Fritz!Smarthome lights (#66213)
* Fritz light free color selection * Use setcolor as fallback * better debug log message Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com> * change if-clause Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
This commit is contained in:
parent
1e4690626f
commit
804c888098
@ -3,6 +3,8 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from requests.exceptions import HTTPError
|
||||||
|
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
ATTR_COLOR_TEMP,
|
ATTR_COLOR_TEMP,
|
||||||
@ -21,6 +23,7 @@ from .const import (
|
|||||||
COLOR_TEMP_MODE,
|
COLOR_TEMP_MODE,
|
||||||
CONF_COORDINATOR,
|
CONF_COORDINATOR,
|
||||||
DOMAIN as FRITZBOX_DOMAIN,
|
DOMAIN as FRITZBOX_DOMAIN,
|
||||||
|
LOGGER,
|
||||||
)
|
)
|
||||||
from .coordinator import FritzboxDataUpdateCoordinator
|
from .coordinator import FritzboxDataUpdateCoordinator
|
||||||
|
|
||||||
@ -135,16 +138,33 @@ class FritzboxLight(FritzBoxEntity, LightEntity):
|
|||||||
level = kwargs[ATTR_BRIGHTNESS]
|
level = kwargs[ATTR_BRIGHTNESS]
|
||||||
await self.hass.async_add_executor_job(self.device.set_level, level)
|
await self.hass.async_add_executor_job(self.device.set_level, level)
|
||||||
if kwargs.get(ATTR_HS_COLOR) is not None:
|
if kwargs.get(ATTR_HS_COLOR) is not None:
|
||||||
hass_hue = int(kwargs[ATTR_HS_COLOR][0])
|
# Try setunmappedcolor first. This allows free color selection,
|
||||||
hass_saturation = round(kwargs[ATTR_HS_COLOR][1] * 255.0 / 100.0)
|
# but we don't know if its supported by all devices.
|
||||||
# find supported hs values closest to what user selected
|
try:
|
||||||
hue = min(self._supported_hs.keys(), key=lambda x: abs(x - hass_hue))
|
# HA gives 0..360 for hue, fritz light only supports 0..359
|
||||||
saturation = min(
|
unmapped_hue = int(kwargs[ATTR_HS_COLOR][0] % 360)
|
||||||
self._supported_hs[hue], key=lambda x: abs(x - hass_saturation)
|
unmapped_saturation = round(kwargs[ATTR_HS_COLOR][1] * 255.0 / 100.0)
|
||||||
)
|
await self.hass.async_add_executor_job(
|
||||||
await self.hass.async_add_executor_job(
|
self.device.set_unmapped_color, (unmapped_hue, unmapped_saturation)
|
||||||
self.device.set_color, (hue, saturation)
|
)
|
||||||
)
|
# This will raise 400 BAD REQUEST if the setunmappedcolor is not available
|
||||||
|
except HTTPError as err:
|
||||||
|
if err.response.status_code != 400:
|
||||||
|
raise
|
||||||
|
LOGGER.debug(
|
||||||
|
"fritzbox does not support method 'setunmappedcolor', fallback to 'setcolor'"
|
||||||
|
)
|
||||||
|
# find supported hs values closest to what user selected
|
||||||
|
hue = min(
|
||||||
|
self._supported_hs.keys(), key=lambda x: abs(x - unmapped_hue)
|
||||||
|
)
|
||||||
|
saturation = min(
|
||||||
|
self._supported_hs[hue],
|
||||||
|
key=lambda x: abs(x - unmapped_saturation),
|
||||||
|
)
|
||||||
|
await self.hass.async_add_executor_job(
|
||||||
|
self.device.set_color, (hue, saturation)
|
||||||
|
)
|
||||||
|
|
||||||
if kwargs.get(ATTR_COLOR_TEMP) is not None:
|
if kwargs.get(ATTR_COLOR_TEMP) is not None:
|
||||||
kelvin = color.color_temperature_kelvin_to_mired(kwargs[ATTR_COLOR_TEMP])
|
kelvin = color.color_temperature_kelvin_to_mired(kwargs[ATTR_COLOR_TEMP])
|
||||||
|
@ -113,7 +113,34 @@ async def test_turn_on_color(hass: HomeAssistant, fritz: Mock):
|
|||||||
assert await setup_config_entry(
|
assert await setup_config_entry(
|
||||||
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
||||||
)
|
)
|
||||||
|
assert await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_ENTITY_ID: ENTITY_ID, ATTR_BRIGHTNESS: 100, ATTR_HS_COLOR: (100, 70)},
|
||||||
|
True,
|
||||||
|
)
|
||||||
|
assert device.set_state_on.call_count == 1
|
||||||
|
assert device.set_level.call_count == 1
|
||||||
|
assert device.set_unmapped_color.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
async def test_turn_on_color_unsupported_api_method(hass: HomeAssistant, fritz: Mock):
|
||||||
|
"""Test turn device on in mapped color mode if unmapped is not supported."""
|
||||||
|
device = FritzDeviceLightMock()
|
||||||
|
device.get_color_temps.return_value = [2700, 6500]
|
||||||
|
device.get_colors.return_value = {
|
||||||
|
"Red": [("100", "70", "10"), ("100", "50", "10"), ("100", "30", "10")]
|
||||||
|
}
|
||||||
|
mockresponse = Mock()
|
||||||
|
mockresponse.status_code = 400
|
||||||
|
|
||||||
|
error = HTTPError("Bad Request")
|
||||||
|
error.response = mockresponse
|
||||||
|
device.set_unmapped_color.side_effect = error
|
||||||
|
|
||||||
|
assert await setup_config_entry(
|
||||||
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
||||||
|
)
|
||||||
assert await hass.services.async_call(
|
assert await hass.services.async_call(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
@ -135,7 +162,6 @@ async def test_turn_off(hass: HomeAssistant, fritz: Mock):
|
|||||||
assert await setup_config_entry(
|
assert await setup_config_entry(
|
||||||
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
hass, MOCK_CONFIG[FB_DOMAIN][CONF_DEVICES][0], ENTITY_ID, device, fritz
|
||||||
)
|
)
|
||||||
|
|
||||||
assert await hass.services.async_call(
|
assert await hass.services.async_call(
|
||||||
DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: ENTITY_ID}, True
|
DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: ENTITY_ID}, True
|
||||||
)
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user