diff --git a/homeassistant/components/reolink/number.py b/homeassistant/components/reolink/number.py index c1baf4b156f..05956aff355 100644 --- a/homeassistant/components/reolink/number.py +++ b/homeassistant/components/reolink/number.py @@ -13,6 +13,7 @@ from homeassistant.components.number import ( NumberMode, ) from homeassistant.config_entries import ConfigEntry +from homeassistant.const import EntityCategory, UnitOfTime from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -25,10 +26,8 @@ from .entity import ReolinkCoordinatorEntity class ReolinkNumberEntityDescriptionMixin: """Mixin values for Reolink number entities.""" - value: Callable[[Host, int | None], bool] - get_min_value: Callable[[Host, int | None], float] - get_max_value: Callable[[Host, int | None], float] - method: Callable[[Host, int | None, float], Any] + value: Callable[[Host, int], float] + method: Callable[[Host, int, float], Any] @dataclass @@ -38,7 +37,9 @@ class ReolinkNumberEntityDescription( """A class that describes number entities.""" mode: NumberMode = NumberMode.AUTO - supported: Callable[[Host, int | None], bool] = lambda api, ch: True + supported: Callable[[Host, int], bool] = lambda api, ch: True + get_min_value: Callable[[Host, int], float] | None = None + get_max_value: Callable[[Host, int], float] | None = None NUMBER_ENTITIES = ( @@ -50,7 +51,7 @@ NUMBER_ENTITIES = ( native_step=1, get_min_value=lambda api, ch: api.zoom_range(ch)["zoom"]["pos"]["min"], get_max_value=lambda api, ch: api.zoom_range(ch)["zoom"]["pos"]["max"], - supported=lambda api, ch: api.zoom_supported(ch), + supported=lambda api, ch: api.supported(ch, "zoom"), value=lambda api, ch: api.get_zoom(ch), method=lambda api, ch, value: api.set_zoom(ch, int(value)), ), @@ -62,10 +63,115 @@ NUMBER_ENTITIES = ( native_step=1, get_min_value=lambda api, ch: api.zoom_range(ch)["focus"]["pos"]["min"], get_max_value=lambda api, ch: api.zoom_range(ch)["focus"]["pos"]["max"], - supported=lambda api, ch: api.zoom_supported(ch), + supported=lambda api, ch: api.supported(ch, "zoom"), value=lambda api, ch: api.get_focus(ch), method=lambda api, ch, value: api.set_zoom(ch, int(value)), ), + ReolinkNumberEntityDescription( + key="floodlight_brightness", + name="Floodlight turn on brightness", + icon="mdi:spotlight-beam", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=1, + native_max_value=100, + supported=lambda api, ch: api.supported(ch, "floodLight"), + value=lambda api, ch: api.whiteled_brightness(ch), + method=lambda api, ch, value: api.set_whiteled(ch, brightness=int(value)), + ), + ReolinkNumberEntityDescription( + key="volume", + name="Volume", + icon="mdi:volume-high", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=0, + native_max_value=100, + supported=lambda api, ch: api.supported(ch, "volume"), + value=lambda api, ch: api.volume(ch), + method=lambda api, ch, value: api.set_volume(ch, volume=int(value)), + ), + ReolinkNumberEntityDescription( + key="guard_return_time", + name="Guard return time", + icon="mdi:crosshairs-gps", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_unit_of_measurement=UnitOfTime.SECONDS, + native_min_value=10, + native_max_value=300, + supported=lambda api, ch: api.supported(ch, "ptz_guard"), + value=lambda api, ch: api.ptz_guard_time(ch), + method=lambda api, ch, value: api.set_ptz_guard(ch, time=int(value)), + ), + ReolinkNumberEntityDescription( + key="motion_sensitivity", + name="Motion sensitivity", + icon="mdi:motion-sensor", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=1, + native_max_value=50, + supported=lambda api, ch: api.supported(ch, "md_sensitivity"), + value=lambda api, ch: api.md_sensitivity(ch), + method=lambda api, ch, value: api.set_md_sensitivity(ch, int(value)), + ), + ReolinkNumberEntityDescription( + key="ai_face_sensititvity", + name="AI face sensitivity", + icon="mdi:face-recognition", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=0, + native_max_value=100, + supported=lambda api, ch: ( + api.supported(ch, "ai_sensitivity") and api.ai_supported(ch, "face") + ), + value=lambda api, ch: api.ai_sensitivity(ch, "face"), + method=lambda api, ch, value: api.set_ai_sensitivity(ch, int(value), "face"), + ), + ReolinkNumberEntityDescription( + key="ai_person_sensititvity", + name="AI person sensitivity", + icon="mdi:account", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=0, + native_max_value=100, + supported=lambda api, ch: ( + api.supported(ch, "ai_sensitivity") and api.ai_supported(ch, "people") + ), + value=lambda api, ch: api.ai_sensitivity(ch, "people"), + method=lambda api, ch, value: api.set_ai_sensitivity(ch, int(value), "people"), + ), + ReolinkNumberEntityDescription( + key="ai_vehicle_sensititvity", + name="AI vehicle sensitivity", + icon="mdi:car", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=0, + native_max_value=100, + supported=lambda api, ch: ( + api.supported(ch, "ai_sensitivity") and api.ai_supported(ch, "vehicle") + ), + value=lambda api, ch: api.ai_sensitivity(ch, "vehicle"), + method=lambda api, ch, value: api.set_ai_sensitivity(ch, int(value), "vehicle"), + ), + ReolinkNumberEntityDescription( + key="ai_pet_sensititvity", + name="AI pet sensitivity", + icon="mdi:dog-side", + entity_category=EntityCategory.CONFIG, + native_step=1, + native_min_value=0, + native_max_value=100, + supported=lambda api, ch: ( + api.supported(ch, "ai_sensitivity") and api.ai_supported(ch, "dog_cat") + ), + value=lambda api, ch: api.ai_sensitivity(ch, "dog_cat"), + method=lambda api, ch, value: api.set_ai_sensitivity(ch, int(value), "dog_cat"), + ), ) @@ -100,15 +206,17 @@ class ReolinkNumberEntity(ReolinkCoordinatorEntity, NumberEntity): super().__init__(reolink_data, channel) self.entity_description = entity_description - self._attr_native_min_value = self.entity_description.get_min_value( - self._host.api, self._channel - ) - self._attr_native_max_value = self.entity_description.get_max_value( - self._host.api, self._channel - ) + if entity_description.get_min_value is not None: + self._attr_native_min_value = entity_description.get_min_value( + self._host.api, channel + ) + if entity_description.get_max_value is not None: + self._attr_native_max_value = entity_description.get_max_value( + self._host.api, channel + ) self._attr_mode = entity_description.mode self._attr_unique_id = ( - f"{self._host.unique_id}_{self._channel}_{entity_description.key}" + f"{self._host.unique_id}_{channel}_{entity_description.key}" ) @property @@ -119,3 +227,4 @@ class ReolinkNumberEntity(ReolinkCoordinatorEntity, NumberEntity): async def async_set_native_value(self, value: float) -> None: """Update the current value.""" await self.entity_description.method(self._host.api, self._channel, value) + self.async_write_ha_state()