Philips Hue restore brightness after transition (#101293)

This commit is contained in:
starkillerOG 2023-10-25 07:46:49 +02:00 committed by GitHub
parent 4bf475185e
commit 93a8b60c2b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 4 deletions

View File

@ -96,6 +96,8 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
self.api: HueBridgeV2 = bridge.api
self._attr_supported_features |= LightEntityFeature.FLASH
self._attr_supported_features |= LightEntityFeature.TRANSITION
self._restore_brightness: float | None = None
self._brightness_pct: float = 0
# we create a virtual service/device for Hue zones/rooms
# so we have a parent for grouped lights and scenes
self._attr_device_info = DeviceInfo(
@ -153,6 +155,18 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS))
flash = kwargs.get(ATTR_FLASH)
if self._restore_brightness and brightness is None:
# The Hue bridge sets the brightness to 1% when turning on a bulb
# when a transition was used to turn off the bulb.
# This issue has been reported on the Hue forum several times:
# https://developers.meethue.com/forum/t/brightness-turns-down-to-1-automatically-shortly-after-sending-off-signal-hue-bug/5692
# https://developers.meethue.com/forum/t/lights-turn-on-with-lowest-brightness-via-siri-if-turned-off-via-api/6700
# https://developers.meethue.com/forum/t/using-transitiontime-with-on-false-resets-bri-to-1/4585
# https://developers.meethue.com/forum/t/bri-value-changing-in-switching-lights-on-off/6323
# https://developers.meethue.com/forum/t/fade-in-fade-out/6673
brightness = self._restore_brightness
self._restore_brightness = None
if flash is not None:
await self.async_set_flash(flash)
return
@ -170,6 +184,8 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
if transition is not None:
self._restore_brightness = self._brightness_pct
flash = kwargs.get(ATTR_FLASH)
if flash is not None:
@ -244,6 +260,7 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
if len(supported_color_modes) == 0:
# only add color mode brightness if no color variants
supported_color_modes.add(ColorMode.BRIGHTNESS)
self._brightness_pct = total_brightness / lights_with_dimming_support
self._attr_brightness = round(
((total_brightness / lights_with_dimming_support) / 100) * 255
)

View File

@ -94,6 +94,7 @@ class HueLight(HueBaseEntity, LightEntity):
self._supported_color_modes.add(ColorMode.BRIGHTNESS)
# support transition if brightness control
self._attr_supported_features |= LightEntityFeature.TRANSITION
self._last_brightness: float | None = None
self._color_temp_active: bool = False
# get list of supported effects (combine effects and timed_effects)
self._attr_effect_list = []
@ -209,6 +210,17 @@ class HueLight(HueBaseEntity, LightEntity):
xy_color = kwargs.get(ATTR_XY_COLOR)
color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP))
brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS))
if self._last_brightness and brightness is None:
# The Hue bridge sets the brightness to 1% when turning on a bulb
# when a transition was used to turn off the bulb.
# This issue has been reported on the Hue forum several times:
# https://developers.meethue.com/forum/t/brightness-turns-down-to-1-automatically-shortly-after-sending-off-signal-hue-bug/5692
# https://developers.meethue.com/forum/t/lights-turn-on-with-lowest-brightness-via-siri-if-turned-off-via-api/6700
# https://developers.meethue.com/forum/t/using-transitiontime-with-on-false-resets-bri-to-1/4585
# https://developers.meethue.com/forum/t/bri-value-changing-in-switching-lights-on-off/6323
# https://developers.meethue.com/forum/t/fade-in-fade-out/6673
brightness = self._last_brightness
self._last_brightness = None
self._color_temp_active = color_temp is not None
flash = kwargs.get(ATTR_FLASH)
effect = effect_str = kwargs.get(ATTR_EFFECT)
@ -245,6 +257,8 @@ class HueLight(HueBaseEntity, LightEntity):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
if transition is not None and self.resource.dimming:
self._last_brightness = self.resource.dimming.brightness
flash = kwargs.get(ATTR_FLASH)
if flash is not None:

View File

@ -217,6 +217,7 @@ async def test_light_turn_off_service(
# verify the light is on before we start
assert hass.states.get(test_light_id).state == "on"
brightness_pct = hass.states.get(test_light_id).attributes["brightness"] / 255 * 100
# now call the HA turn_off service
await hass.services.async_call(
@ -256,6 +257,23 @@ async def test_light_turn_off_service(
assert mock_bridge_v2.mock_requests[1]["json"]["on"]["on"] is False
assert mock_bridge_v2.mock_requests[1]["json"]["dynamics"]["duration"] == 200
# test turn_on resets brightness
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": test_light_id},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 3
assert mock_bridge_v2.mock_requests[2]["json"]["on"]["on"] is True
assert (
round(
mock_bridge_v2.mock_requests[2]["json"]["dimming"]["brightness"]
- brightness_pct
)
== 0
)
# test again with sending long flash
await hass.services.async_call(
"light",
@ -263,8 +281,8 @@ async def test_light_turn_off_service(
{"entity_id": test_light_id, "flash": "long"},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 3
assert mock_bridge_v2.mock_requests[2]["json"]["alert"]["action"] == "breathe"
assert len(mock_bridge_v2.mock_requests) == 4
assert mock_bridge_v2.mock_requests[3]["json"]["alert"]["action"] == "breathe"
# test again with sending short flash
await hass.services.async_call(
@ -273,8 +291,8 @@ async def test_light_turn_off_service(
{"entity_id": test_light_id, "flash": "short"},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 4
assert mock_bridge_v2.mock_requests[3]["json"]["identify"]["action"] == "identify"
assert len(mock_bridge_v2.mock_requests) == 5
assert mock_bridge_v2.mock_requests[4]["json"]["identify"]["action"] == "identify"
async def test_light_added(hass: HomeAssistant, mock_bridge_v2) -> None:
@ -481,6 +499,17 @@ async def test_grouped_lights(
assert mock_bridge_v2.mock_requests[0]["json"]["on"]["on"] is False
assert mock_bridge_v2.mock_requests[0]["json"]["dynamics"]["duration"] == 200
# Test turn_on resets brightness
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": test_light_id},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 2
assert mock_bridge_v2.mock_requests[1]["json"]["on"]["on"] is True
assert mock_bridge_v2.mock_requests[1]["json"]["dimming"]["brightness"] == 100
# Test sending short flash effect to a grouped light
mock_bridge_v2.mock_requests.clear()
test_light_id = "light.test_zone"