From 6cacf35a583fd292acfe3f7c16025c14696286e2 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Thu, 17 Aug 2023 17:06:26 +0200 Subject: [PATCH 1/3] Add PTZ pan position sensor --- homeassistant/components/reolink/sensor.py | 78 +++++++++++++++++-- homeassistant/components/reolink/strings.json | 3 + 2 files changed, 73 insertions(+), 8 deletions(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index af8d049dbc67e2..5384dfc3e6802d 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -21,14 +21,30 @@ from . import ReolinkData from .const import DOMAIN -from .entity import ReolinkHostCoordinatorEntity +from .entity import ReolinkChannelCoordinatorEntity, ReolinkHostCoordinatorEntity + + +@dataclass +class ReolinkSensorEntityDescriptionMixin: + """Mixin values for Reolink sensor entities for a camera channel.""" + + value: Callable[[Host, int], Any] + + +@dataclass +class ReolinkSensorEntityDescription( + SensorEntityDescription, ReolinkSensorEntityDescriptionMixin +): + """A class that describes sensor entities for a camera channel.""" + + supported: Callable[[Host, int], bool] = lambda api, ch: True @dataclass class ReolinkHostSensorEntityDescriptionMixin: """Mixin values for Reolink host sensor entities.""" - value: Callable[[Host], bool] + value: Callable[[Host], Any] @dataclass @@ -37,9 +53,21 @@ class ReolinkHostSensorEntityDescription( ): """A class that describes host sensor entities.""" - supported: Callable[[Host], bool] = lambda host: True + supported: Callable[[Host], bool] = lambda api: True +SENSORS = ( + ReolinkSensorEntityDescription( + key="ptz_pan_position", + translation_key="ptz_pan_position", + icon="mdi:pan", + state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, + value=lambda api, ch: api.ptz_pan_position(ch), + supported=lambda api, ch: api.supported(ch, "ptz_position"), + ), +) + HOST_SENSORS = ( ReolinkHostSensorEntityDescription( key="wifi_signal", @@ -62,11 +90,45 @@ async def async_setup_entry( """Set up a Reolink IP Camera.""" reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] - async_add_entities( - ReolinkHostSensorEntity(reolink_data, entity_description) - for entity_description in HOST_SENSORS - if entity_description.supported(reolink_data.host.api) + entities: list[ReolinkSensorEntity | ReolinkHostSensorEntity] = [ + ReolinkSensorEntity(reolink_data, channel, entity_description) + for entity_description in SENSORS + for channel in reolink_data.host.api.channels + if entity_description.supported(reolink_data.host.api, channel) + ] + entities.extend( + [ + ReolinkHostSensorEntity(reolink_data, entity_description) + for entity_description in HOST_SENSORS + if entity_description.supported(reolink_data.host.api) + ] ) + async_add_entities(entities) + + +class ReolinkSensorEntity(ReolinkChannelCoordinatorEntity, SensorEntity): + """Base sensor class for Reolink IP camera sensors.""" + + entity_description: ReolinkSensorEntityDescription + + def __init__( + self, + reolink_data: ReolinkData, + channel: int, + entity_description: ReolinkSensorEntityDescription, + ) -> None: + """Initialize Reolink sensor.""" + super().__init__(reolink_data, channel) + self.entity_description = entity_description + + self._attr_unique_id = ( + f"{self._host.unique_id}_{channel}_{entity_description.key}" + ) + + @property + def native_value(self) -> StateType | date | datetime | Decimal: + """Return the value reported by the sensor.""" + return self.entity_description.value(self._host.api, self._channel) class ReolinkHostSensorEntity(ReolinkHostCoordinatorEntity, SensorEntity): @@ -79,7 +141,7 @@ def __init__( reolink_data: ReolinkData, entity_description: ReolinkHostSensorEntityDescription, ) -> None: - """Initialize Reolink binary sensor.""" + """Initialize Reolink host sensor.""" super().__init__(reolink_data) self.entity_description = entity_description diff --git a/homeassistant/components/reolink/strings.json b/homeassistant/components/reolink/strings.json index 08ee78fd9300ce..cdaeb7d06560c0 100644 --- a/homeassistant/components/reolink/strings.json +++ b/homeassistant/components/reolink/strings.json @@ -102,6 +102,9 @@ "sensor": { "wifi_signal": { "name": "Wi-Fi signal" + }, + "ptz_pan_position": { + "name": "PTZ pan position" } } } From 9762dfdce8a9fce040bb6e286208903878e63a07 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Thu, 17 Aug 2023 18:39:48 +0200 Subject: [PATCH 2/3] fix typing --- homeassistant/components/reolink/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 5384dfc3e6802d..231b5fd891edea 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -28,7 +28,7 @@ class ReolinkSensorEntityDescriptionMixin: """Mixin values for Reolink sensor entities for a camera channel.""" - value: Callable[[Host, int], Any] + value: Callable[[Host, int], float] @dataclass @@ -44,7 +44,7 @@ class ReolinkSensorEntityDescription( class ReolinkHostSensorEntityDescriptionMixin: """Mixin values for Reolink host sensor entities.""" - value: Callable[[Host], Any] + value: Callable[[Host], float] @dataclass From b0070277f47316a16e2c19127ff55836377ac2b1 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 19 Aug 2023 12:02:30 +0200 Subject: [PATCH 3/3] fix typing --- homeassistant/components/reolink/sensor.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 231b5fd891edea..6282f29e4424b3 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -28,7 +28,7 @@ class ReolinkSensorEntityDescriptionMixin: """Mixin values for Reolink sensor entities for a camera channel.""" - value: Callable[[Host, int], float] + value: Callable[[Host, int], int] @dataclass @@ -44,7 +44,7 @@ class ReolinkSensorEntityDescription( class ReolinkHostSensorEntityDescriptionMixin: """Mixin values for Reolink host sensor entities.""" - value: Callable[[Host], float] + value: Callable[[Host], int] @dataclass