From a02a9b7647a7cba2d3c35565a657205b2740fb0c Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 19 Feb 2024 14:32:08 +0100 Subject: [PATCH 1/5] Add Reolink HDD storage sensors --- homeassistant/components/reolink/sensor.py | 65 +++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 6f4af489fe5018..685d185c0db00f 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -36,7 +36,7 @@ class ReolinkSensorEntityDescription( ): """A class that describes sensor entities for a camera channel.""" - value: Callable[[Host, int], int] + value: Callable[[Host, int], int | float] @dataclass(frozen=True, kw_only=True) @@ -76,6 +76,29 @@ class ReolinkHostSensorEntityDescription( ), ) +HDD_SENSORS = ( + ReolinkSensorEntityDescription( + key="hdd_storage", + cmd_key="GetHddInfo", + translation_key="hdd_storage", + icon="mdi:harddisk", + state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, + value=lambda api, idx: api.hdd_storage(idx), + supported=lambda api, idx: api.supported(None, "hdd") and api.hdd_type(idx) == "HDD", + ), + ReolinkSensorEntityDescription( + key="sd_storage", + cmd_key="GetHddInfo", + translation_key="sd_storage", + icon="mdi:micro-sd", + state_class=SensorStateClass.MEASUREMENT, + entity_category=EntityCategory.DIAGNOSTIC, + value=lambda api, idx: api.hdd_storage(idx), + supported=lambda api, idx: api.supported(None, "hdd") and api.hdd_type(idx) == "SD", + ), +) + async def async_setup_entry( hass: HomeAssistant, @@ -85,7 +108,7 @@ async def async_setup_entry( """Set up a Reolink IP Camera.""" reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] - entities: list[ReolinkSensorEntity | ReolinkHostSensorEntity] = [ + entities: list[ReolinkSensorEntity | ReolinkHostSensorEntity | ReolinkHddSensorEntity] = [ ReolinkSensorEntity(reolink_data, channel, entity_description) for entity_description in SENSORS for channel in reolink_data.host.api.channels @@ -98,6 +121,14 @@ async def async_setup_entry( if entity_description.supported(reolink_data.host.api) ] ) + entities.extend( + [ + ReolinkHddSensorEntity(reolink_data, hdd_index, entity_description) + for entity_description in HDD_SENSORS + for hdd_index in reolink_data.host.api.hdd_list + if entity_description.supported(reolink_data.host.api, hdd_index) + ] + ) async_add_entities(entities) @@ -140,3 +171,33 @@ def __init__( def native_value(self) -> StateType | date | datetime | Decimal: """Return the value reported by the sensor.""" return self.entity_description.value(self._host.api) + + +class ReolinkHddSensorEntity(ReolinkHostCoordinatorEntity, SensorEntity): + """Base sensor class for Reolink host sensors.""" + + entity_description: ReolinkSensorEntityDescription + + def __init__( + self, + reolink_data: ReolinkData, + hdd_index: int, + entity_description: ReolinkSensorEntityDescription, + ) -> None: + """Initialize Reolink host sensor.""" + self.entity_description = entity_description + super().__init__(reolink_data) + self._hdd_index = hdd_index + self._attr_unique_id = ( + f"{self._host.unique_id}_{hdd_index}_{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._hdd_index) + + @property + def available(self) -> bool: + """Return True if entity is available.""" + return self._host.api.hdd_available(self._hdd_index) and super().available From bf6c7646f804230fc97916f5fb9b2679179dcbed Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 19 Feb 2024 14:50:09 +0100 Subject: [PATCH 2/5] finish --- homeassistant/components/reolink/sensor.py | 7 ++++++- homeassistant/components/reolink/strings.json | 6 ++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 685d185c0db00f..eee8180a43892d 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -14,7 +14,7 @@ SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import EntityCategory +from homeassistant.const import EntityCategory, PERCENTAGE from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType @@ -82,8 +82,10 @@ class ReolinkHostSensorEntityDescription( cmd_key="GetHddInfo", translation_key="hdd_storage", icon="mdi:harddisk", + native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, value=lambda api, idx: api.hdd_storage(idx), supported=lambda api, idx: api.supported(None, "hdd") and api.hdd_type(idx) == "HDD", ), @@ -92,8 +94,10 @@ class ReolinkHostSensorEntityDescription( cmd_key="GetHddInfo", translation_key="sd_storage", icon="mdi:micro-sd", + native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, value=lambda api, idx: api.hdd_storage(idx), supported=lambda api, idx: api.supported(None, "hdd") and api.hdd_type(idx) == "SD", ), @@ -188,6 +192,7 @@ def __init__( self.entity_description = entity_description super().__init__(reolink_data) self._hdd_index = hdd_index + self._attr_translation_placeholders = {"hdd_index": str(hdd_index)} self._attr_unique_id = ( f"{self._host.unique_id}_{hdd_index}_{entity_description.key}" ) diff --git a/homeassistant/components/reolink/strings.json b/homeassistant/components/reolink/strings.json index 92e9a6164f8649..01c3c2f154843d 100644 --- a/homeassistant/components/reolink/strings.json +++ b/homeassistant/components/reolink/strings.json @@ -377,6 +377,12 @@ }, "ptz_pan_position": { "name": "PTZ pan position" + }, + "hdd_storage": { + "name": "HDD {hdd_index} storage" + }, + "sd_storage": { + "name": "SD {hdd_index} storage" } }, "siren": { From cca2ea2e6b8e8050f29dccf61d0b4580cc7ad58b Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 19 Feb 2024 15:05:00 +0100 Subject: [PATCH 3/5] fix styling --- homeassistant/components/reolink/sensor.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index eee8180a43892d..267facef042e85 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -14,7 +14,7 @@ SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import EntityCategory, PERCENTAGE +from homeassistant.const import PERCENTAGE, EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType @@ -87,7 +87,9 @@ class ReolinkHostSensorEntityDescription( entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, value=lambda api, idx: api.hdd_storage(idx), - supported=lambda api, idx: api.supported(None, "hdd") and api.hdd_type(idx) == "HDD", + supported=lambda api, idx: ( + api.supported(None, "hdd") and api.hdd_type(idx) == "HDD" + ), ), ReolinkSensorEntityDescription( key="sd_storage", @@ -99,7 +101,9 @@ class ReolinkHostSensorEntityDescription( entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, value=lambda api, idx: api.hdd_storage(idx), - supported=lambda api, idx: api.supported(None, "hdd") and api.hdd_type(idx) == "SD", + supported=lambda api, idx: ( + api.supported(None, "hdd") and api.hdd_type(idx) == "SD" + ), ), ) @@ -112,7 +116,9 @@ async def async_setup_entry( """Set up a Reolink IP Camera.""" reolink_data: ReolinkData = hass.data[DOMAIN][config_entry.entry_id] - entities: list[ReolinkSensorEntity | ReolinkHostSensorEntity | ReolinkHddSensorEntity] = [ + entities: list[ + ReolinkSensorEntity | ReolinkHostSensorEntity | ReolinkHddSensorEntity + ] = [ ReolinkSensorEntity(reolink_data, channel, entity_description) for entity_description in SENSORS for channel in reolink_data.host.api.channels From dae84e8671c5eed8e7066c474bf3bb1d7ca83466 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Sat, 9 Mar 2024 20:42:29 +0100 Subject: [PATCH 4/5] Simplify --- homeassistant/components/reolink/icons.json | 6 ++++++ homeassistant/components/reolink/sensor.py | 22 +++++---------------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/reolink/icons.json b/homeassistant/components/reolink/icons.json index 15c3c00ecf8f94..fcf88fb67268f5 100644 --- a/homeassistant/components/reolink/icons.json +++ b/homeassistant/components/reolink/icons.json @@ -202,6 +202,12 @@ }, "wifi_signal": { "default": "mdi:wifi" + }, + "hdd_storage": { + "default": "mdi:harddisk" + }, + "sd_storage": { + "default": "mdi:micro-sd" } }, "siren": { diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 1cdeea89518e64..17cb98cf77d438 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -77,10 +77,8 @@ class ReolinkHostSensorEntityDescription( HDD_SENSORS = ( ReolinkSensorEntityDescription( - key="hdd_storage", + key="storage", cmd_key="GetHddInfo", - translation_key="hdd_storage", - icon="mdi:harddisk", native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, @@ -90,20 +88,6 @@ class ReolinkHostSensorEntityDescription( api.supported(None, "hdd") and api.hdd_type(idx) == "HDD" ), ), - ReolinkSensorEntityDescription( - key="sd_storage", - cmd_key="GetHddInfo", - translation_key="sd_storage", - icon="mdi:micro-sd", - native_unit_of_measurement=PERCENTAGE, - state_class=SensorStateClass.MEASUREMENT, - entity_category=EntityCategory.DIAGNOSTIC, - entity_registry_enabled_default=False, - value=lambda api, idx: api.hdd_storage(idx), - supported=lambda api, idx: ( - api.supported(None, "hdd") and api.hdd_type(idx) == "SD" - ), - ), ) @@ -201,6 +185,10 @@ def __init__( self._attr_unique_id = ( f"{self._host.unique_id}_{hdd_index}_{entity_description.key}" ) + if self._host.api.hdd_type(hdd_index) == "HDD": + self._attr_translation_key = "hdd_storage" + else: + self._attr_translation_key = "sd_storage" @property def native_value(self) -> StateType | date | datetime | Decimal: From 0e856bded3656c8a341e96023da52ef9a6bd4269 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Thu, 21 Mar 2024 11:32:34 +0100 Subject: [PATCH 5/5] Update sensor.py --- homeassistant/components/reolink/sensor.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/homeassistant/components/reolink/sensor.py b/homeassistant/components/reolink/sensor.py index 17cb98cf77d438..36363beaf802df 100644 --- a/homeassistant/components/reolink/sensor.py +++ b/homeassistant/components/reolink/sensor.py @@ -84,9 +84,7 @@ class ReolinkHostSensorEntityDescription( entity_category=EntityCategory.DIAGNOSTIC, entity_registry_enabled_default=False, value=lambda api, idx: api.hdd_storage(idx), - supported=lambda api, idx: ( - api.supported(None, "hdd") and api.hdd_type(idx) == "HDD" - ), + supported=lambda api, idx: api.supported(None, "hdd"), ), )