1
mirror of https://github.com/home-assistant/core synced 2024-07-12 07:21:24 +02:00

Overhaul UniFi Protect NVR Disk sensors (#73197)

* Overhauls NVR Disk sensors

* Updates from latest version of pyunifiprotect
This commit is contained in:
Christopher Bailey 2022-06-08 20:13:56 -04:00 committed by GitHub
parent 5c49d0a761
commit 004ff8fb30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 187 additions and 22 deletions

View File

@ -6,6 +6,7 @@ from dataclasses import dataclass
import logging
from pyunifiprotect.data import NVR, Camera, Event, Light, MountType, Sensor
from pyunifiprotect.data.nvr import UOSDisk
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
@ -13,7 +14,6 @@ from homeassistant.components.binary_sensor import (
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_MODEL
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -131,7 +131,6 @@ DOORLOCK_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
DISK_SENSORS: tuple[ProtectBinaryEntityDescription, ...] = (
ProtectBinaryEntityDescription(
key="disk_health",
name="Disk {index} Health",
device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC,
),
@ -182,14 +181,18 @@ def _async_nvr_entities(
) -> list[ProtectDeviceEntity]:
entities: list[ProtectDeviceEntity] = []
device = data.api.bootstrap.nvr
for index, _ in enumerate(device.system_info.storage.devices):
if device.system_info.ustorage is None:
return entities
for disk in device.system_info.ustorage.disks:
for description in DISK_SENSORS:
entities.append(
ProtectDiskBinarySensor(data, device, description, index=index)
)
if not disk.has_disk:
continue
entities.append(ProtectDiskBinarySensor(data, device, description, disk))
_LOGGER.debug(
"Adding binary sensor entity %s",
(description.name or "{index}").format(index=index),
f"{disk.type} {disk.slot}",
)
return entities
@ -216,6 +219,7 @@ class ProtectDeviceBinarySensor(ProtectDeviceEntity, BinarySensorEntity):
class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):
"""A UniFi Protect NVR Disk Binary Sensor."""
_disk: UOSDisk
entity_description: ProtectBinaryEntityDescription
def __init__(
@ -223,26 +227,35 @@ class ProtectDiskBinarySensor(ProtectNVREntity, BinarySensorEntity):
data: ProtectData,
device: NVR,
description: ProtectBinaryEntityDescription,
index: int,
disk: UOSDisk,
) -> None:
"""Initialize the Binary Sensor."""
self._disk = disk
# backwards compat with old unique IDs
index = self._disk.slot - 1
description = copy(description)
description.key = f"{description.key}_{index}"
description.name = (description.name or "{index}").format(index=index)
self._index = index
description.name = f"{disk.type} {disk.slot}"
super().__init__(data, device, description)
@callback
def _async_update_device_from_protect(self) -> None:
super()._async_update_device_from_protect()
disks = self.device.system_info.storage.devices
disk_available = len(disks) > self._index
self._attr_available = self._attr_available and disk_available
if disk_available:
disk = disks[self._index]
self._attr_is_on = not disk.healthy
self._attr_extra_state_attributes = {ATTR_MODEL: disk.model}
slot = self._disk.slot
self._attr_available = False
if self.device.system_info.ustorage is None:
return
for disk in self.device.system_info.ustorage.disks:
if disk.slot == slot:
self._disk = disk
self._attr_available = True
break
self._attr_is_on = not self._disk.is_healthy
class ProtectEventBinarySensor(EventThumbnailMixin, ProtectDeviceBinarySensor):

View File

@ -117,6 +117,158 @@
}
]
},
"ustorage": {
"disks": [
{
"slot": 1,
"type": "HDD",
"model": "ST16000VE000-2L2103",
"serial": "ABCD1234",
"firmware": "EV02",
"rpm": 7200,
"ata": "ACS-4",
"sata": "SATA 3.3",
"action": "expanding",
"healthy": "good",
"state": "expanding",
"reason": null,
"temperature": 52,
"poweronhrs": 4242,
"life_span": null,
"bad_sector": 0,
"threshold": 10,
"progress": 21.390607518939174,
"estimate": 234395.73300748435
},
{
"slot": 2,
"type": "HDD",
"model": "ST16000VE000-2L2103",
"serial": "ABCD1234",
"firmware": "EV02",
"rpm": 7200,
"ata": "ACS-4",
"sata": "SATA 3.3",
"action": "expanding",
"healthy": "good",
"state": "expanding",
"reason": null,
"temperature": 52,
"poweronhrs": 4242,
"life_span": null,
"bad_sector": 0,
"threshold": 10,
"progress": 21.390607518939174,
"estimate": 234395.73300748435
},
{
"slot": 3,
"type": "HDD",
"model": "ST16000VE000-2L2103",
"serial": "ABCD1234",
"firmware": "EV02",
"rpm": 7200,
"ata": "ACS-4",
"sata": "SATA 3.3",
"action": "expanding",
"healthy": "good",
"state": "expanding",
"reason": null,
"temperature": 51,
"poweronhrs": 4242,
"life_span": null,
"bad_sector": 0,
"threshold": 10,
"progress": 21.390607518939174,
"estimate": 234395.73300748435
},
{
"slot": 4,
"type": "HDD",
"model": "ST16000VE000-2L2103",
"serial": "ABCD1234",
"firmware": "EV02",
"rpm": 7200,
"ata": "ACS-4",
"sata": "SATA 3.3",
"action": "expanding",
"healthy": "good",
"state": "expanding",
"reason": null,
"temperature": 50,
"poweronhrs": 2443,
"life_span": null,
"bad_sector": 0,
"threshold": 10,
"progress": 21.390607518939174,
"estimate": 234395.73300748435
},
{
"slot": 5,
"type": "HDD",
"model": "ST16000VE000-2L2103",
"serial": "ABCD1234",
"firmware": "EV02",
"rpm": 7200,
"ata": "ACS-4",
"sata": "SATA 3.3",
"action": "expanding",
"healthy": "good",
"state": "expanding",
"reason": null,
"temperature": 50,
"poweronhrs": 783,
"life_span": null,
"bad_sector": 0,
"threshold": 10,
"progress": 21.390607518939174,
"estimate": 234395.73300748435
},
{
"slot": 6,
"state": "nodisk"
},
{
"slot": 7,
"type": "HDD",
"model": "ST16000VE002-3BR101",
"serial": "ABCD1234",
"firmware": "EV01",
"rpm": 7200,
"ata": "ACS-4",
"sata": "SATA 3.3",
"action": "expanding",
"healthy": "good",
"state": "expanding",
"reason": null,
"temperature": 45,
"poweronhrs": 18,
"life_span": null,
"bad_sector": 0,
"threshold": 10,
"progress": 21.390607518939174,
"estimate": 234395.73300748435
}
],
"space": [
{
"device": "md3",
"total_bytes": 63713403555840,
"used_bytes": 57006577086464,
"action": "expanding",
"progress": 21.390607518939174,
"estimate": 234395.73300748435
},
{
"device": "md0",
"total_bytes": 0,
"used_bytes": 0,
"action": "syncing",
"progress": 0,
"estimate": null
}
]
},
"tmpfs": {
"available": 934204,
"total": 1048576,

View File

@ -71,7 +71,7 @@ async def camera_fixture(
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
await hass.async_block_till_done()
assert_entity_counts(hass, Platform.BINARY_SENSOR, 3, 3)
assert_entity_counts(hass, Platform.BINARY_SENSOR, 9, 9)
yield camera_obj
@ -103,7 +103,7 @@ async def light_fixture(
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
await hass.async_block_till_done()
assert_entity_counts(hass, Platform.BINARY_SENSOR, 2, 2)
assert_entity_counts(hass, Platform.BINARY_SENSOR, 8, 8)
yield light_obj
@ -138,7 +138,7 @@ async def camera_none_fixture(
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
await hass.async_block_till_done()
assert_entity_counts(hass, Platform.BINARY_SENSOR, 2, 2)
assert_entity_counts(hass, Platform.BINARY_SENSOR, 8, 8)
yield camera_obj
@ -179,7 +179,7 @@ async def sensor_fixture(
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
await hass.async_block_till_done()
assert_entity_counts(hass, Platform.BINARY_SENSOR, 4, 4)
assert_entity_counts(hass, Platform.BINARY_SENSOR, 10, 10)
yield sensor_obj
@ -215,7 +215,7 @@ async def sensor_none_fixture(
await hass.config_entries.async_setup(mock_entry.entry.entry_id)
await hass.async_block_till_done()
assert_entity_counts(hass, Platform.BINARY_SENSOR, 4, 4)
assert_entity_counts(hass, Platform.BINARY_SENSOR, 10, 10)
yield sensor_obj