From 0c4f2326efbdbc47ab2baaa722b0a1f01e64796d Mon Sep 17 00:00:00 2001 From: Raphael Hehl <7577984+RaHehl@users.noreply.github.com> Date: Mon, 1 Dec 2025 11:32:03 +0100 Subject: [PATCH] Use public API for UniFi Protect light brightness control (#157550) --- .../components/unifiprotect/light.py | 35 ++++++++++++++-- tests/components/unifiprotect/test_light.py | 42 ++++++++++++++++--- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/homeassistant/components/unifiprotect/light.py b/homeassistant/components/unifiprotect/light.py index ca4632c3462..109b822a059 100644 --- a/homeassistant/components/unifiprotect/light.py +++ b/homeassistant/components/unifiprotect/light.py @@ -6,8 +6,9 @@ import logging from typing import Any from uiprotect.data import Light, ModelType, ProtectAdoptableDeviceModel +from uiprotect.data.devices import LightDeviceSettings -from homeassistant.components.light import ColorMode, LightEntity +from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback @@ -72,10 +73,36 @@ class ProtectLight(ProtectDeviceEntity, LightEntity): async def async_turn_on(self, **kwargs: Any) -> None: """Turn the light on.""" - _LOGGER.debug("Turning on light") - await self.device.api.set_light_is_led_force_on(self.device.id, True) + brightness = kwargs.get(ATTR_BRIGHTNESS) + led_level: int | None = None + if brightness is not None: + led_level = hass_to_unifi_brightness(brightness) + _LOGGER.debug( + "Turning on light with brightness %s (led_level=%s)", + brightness, + led_level, + ) + else: + _LOGGER.debug("Turning on light") + + await self.device.api.update_light_public( + self.device.id, + is_light_force_enabled=True, + light_device_settings=( + LightDeviceSettings( + is_indicator_enabled=self.device.light_device_settings.is_indicator_enabled, + led_level=led_level, + pir_duration=self.device.light_device_settings.pir_duration, + pir_sensitivity=self.device.light_device_settings.pir_sensitivity, + ) + if led_level is not None + else None + ), + ) async def async_turn_off(self, **kwargs: Any) -> None: """Turn the light off.""" _LOGGER.debug("Turning off light") - await self.device.api.set_light_is_led_force_on(self.device.id, False) + await self.device.api.update_light_public( + self.device.id, is_light_force_enabled=False + ) diff --git a/tests/components/unifiprotect/test_light.py b/tests/components/unifiprotect/test_light.py index 85de85cd1c1..09a4bc1ab23 100644 --- a/tests/components/unifiprotect/test_light.py +++ b/tests/components/unifiprotect/test_light.py @@ -98,7 +98,7 @@ async def test_light_turn_on( """Test light entity turn on.""" light._api = ufp.api - light.api.set_light_is_led_force_on = AsyncMock() + light.api.update_light_public = AsyncMock() await init_entry(hass, ufp, [light, unadopted_light]) assert_entity_counts(hass, Platform.LIGHT, 1, 1) @@ -108,8 +108,36 @@ async def test_light_turn_on( "light", "turn_on", {ATTR_ENTITY_ID: entity_id}, blocking=True ) - assert light.api.set_light_is_led_force_on.called - assert light.api.set_light_is_led_force_on.call_args == ((light.id, True),) + assert light.api.update_light_public.called + light.api.update_light_public.assert_called_once_with( + light.id, is_light_force_enabled=True, light_device_settings=None + ) + + +async def test_light_turn_on_with_brightness( + hass: HomeAssistant, ufp: MockUFPFixture, light: Light, unadopted_light: Light +) -> None: + """Test light entity turn on with brightness.""" + + light._api = ufp.api + light.api.update_light_public = AsyncMock() + + await init_entry(hass, ufp, [light, unadopted_light]) + assert_entity_counts(hass, Platform.LIGHT, 1, 1) + + entity_id = "light.test_light" + await hass.services.async_call( + "light", + "turn_on", + {ATTR_ENTITY_ID: entity_id, ATTR_BRIGHTNESS: 128}, + blocking=True, + ) + + assert light.api.update_light_public.called + call_kwargs = light.api.update_light_public.call_args[1] + assert call_kwargs["is_light_force_enabled"] is True + assert call_kwargs["light_device_settings"] is not None + assert call_kwargs["light_device_settings"].led_level == 3 # 128/255 * 6 ≈ 3 async def test_light_turn_off( @@ -118,7 +146,7 @@ async def test_light_turn_off( """Test light entity turn off.""" light._api = ufp.api - light.api.set_light_is_led_force_on = AsyncMock() + light.api.update_light_public = AsyncMock() await init_entry(hass, ufp, [light, unadopted_light]) assert_entity_counts(hass, Platform.LIGHT, 1, 1) @@ -128,5 +156,7 @@ async def test_light_turn_off( "light", "turn_off", {ATTR_ENTITY_ID: entity_id}, blocking=True ) - assert light.api.set_light_is_led_force_on.called - assert light.api.set_light_is_led_force_on.call_args == ((light.id, False),) + assert light.api.update_light_public.called + light.api.update_light_public.assert_called_once_with( + light.id, is_light_force_enabled=False + )