Use EntityDescription - qnap (#55410)

* Use EntityDescription - qnap

* Remove default values
This commit is contained in:
Marc Mueller 2021-08-30 21:59:50 +02:00 committed by GitHub
parent 3bd9be2f6d
commit 1c01ff401f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,11 +1,17 @@
"""Support for QNAP NAS Sensors.""" """Support for QNAP NAS Sensors."""
from __future__ import annotations
from datetime import timedelta from datetime import timedelta
import logging import logging
from qnapstats import QNAPStats from qnapstats import QNAPStats
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity from homeassistant.components.sensor import (
PLATFORM_SCHEMA,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import ( from homeassistant.const import (
ATTR_NAME, ATTR_NAME,
CONF_HOST, CONF_HOST,
@ -56,57 +62,117 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=1)
NOTIFICATION_ID = "qnap_notification" NOTIFICATION_ID = "qnap_notification"
NOTIFICATION_TITLE = "QNAP Sensor Setup" NOTIFICATION_TITLE = "QNAP Sensor Setup"
_SYSTEM_MON_COND = { _SYSTEM_MON_COND: tuple[SensorEntityDescription, ...] = (
"status": ["Status", None, "mdi:checkbox-marked-circle-outline", None], SensorEntityDescription(
"system_temp": ["System Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE], key="status",
} name="Status",
_CPU_MON_COND = { icon="mdi:checkbox-marked-circle-outline",
"cpu_temp": ["CPU Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE], ),
"cpu_usage": ["CPU Usage", PERCENTAGE, "mdi:chip", None], SensorEntityDescription(
} key="system_temp",
_MEMORY_MON_COND = { name="System Temperature",
"memory_free": ["Memory Available", DATA_GIBIBYTES, "mdi:memory", None], native_unit_of_measurement=TEMP_CELSIUS,
"memory_used": ["Memory Used", DATA_GIBIBYTES, "mdi:memory", None], device_class=DEVICE_CLASS_TEMPERATURE,
"memory_percent_used": ["Memory Usage", PERCENTAGE, "mdi:memory", None], ),
}
_NETWORK_MON_COND = {
"network_link_status": [
"Network Link",
None,
"mdi:checkbox-marked-circle-outline",
None,
],
"network_tx": ["Network Up", DATA_RATE_MEBIBYTES_PER_SECOND, "mdi:upload", None],
"network_rx": [
"Network Down",
DATA_RATE_MEBIBYTES_PER_SECOND,
"mdi:download",
None,
],
}
_DRIVE_MON_COND = {
"drive_smart_status": [
"SMART Status",
None,
"mdi:checkbox-marked-circle-outline",
None,
],
"drive_temp": ["Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
}
_VOLUME_MON_COND = {
"volume_size_used": ["Used Space", DATA_GIBIBYTES, "mdi:chart-pie", None],
"volume_size_free": ["Free Space", DATA_GIBIBYTES, "mdi:chart-pie", None],
"volume_percentage_used": ["Volume Used", PERCENTAGE, "mdi:chart-pie", None],
}
_MONITORED_CONDITIONS = (
list(_SYSTEM_MON_COND)
+ list(_CPU_MON_COND)
+ list(_MEMORY_MON_COND)
+ list(_NETWORK_MON_COND)
+ list(_DRIVE_MON_COND)
+ list(_VOLUME_MON_COND)
) )
_CPU_MON_COND: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="cpu_temp",
name="CPU Temperature",
native_unit_of_measurement=TEMP_CELSIUS,
device_class=DEVICE_CLASS_TEMPERATURE,
),
SensorEntityDescription(
key="cpu_usage",
name="CPU Usage",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:chip",
),
)
_MEMORY_MON_COND: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="memory_free",
name="Memory Available",
native_unit_of_measurement=DATA_GIBIBYTES,
icon="mdi:memory",
),
SensorEntityDescription(
key="memory_used",
name="Memory Used",
native_unit_of_measurement=DATA_GIBIBYTES,
icon="mdi:memory",
),
SensorEntityDescription(
key="memory_percent_used",
name="Memory Usage",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:memory",
),
)
_NETWORK_MON_COND: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="network_link_status",
name="Network Link",
icon="mdi:checkbox-marked-circle-outline",
),
SensorEntityDescription(
key="network_tx",
name="Network Up",
native_unit_of_measurement=DATA_RATE_MEBIBYTES_PER_SECOND,
icon="mdi:upload",
),
SensorEntityDescription(
key="network_rx",
name="Network Down",
native_unit_of_measurement=DATA_RATE_MEBIBYTES_PER_SECOND,
icon="mdi:download",
),
)
_DRIVE_MON_COND: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="drive_smart_status",
name="SMART Status",
icon="mdi:checkbox-marked-circle-outline",
),
SensorEntityDescription(
key="drive_temp",
name="Temperature",
native_unit_of_measurement=TEMP_CELSIUS,
device_class=DEVICE_CLASS_TEMPERATURE,
),
)
_VOLUME_MON_COND: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="volume_size_used",
name="Used Space",
native_unit_of_measurement=DATA_GIBIBYTES,
icon="mdi:chart-pie",
),
SensorEntityDescription(
key="volume_size_free",
name="Free Space",
native_unit_of_measurement=DATA_GIBIBYTES,
icon="mdi:chart-pie",
),
SensorEntityDescription(
key="volume_percentage_used",
name="Volume Used",
native_unit_of_measurement=PERCENTAGE,
icon="mdi:chart-pie",
),
)
SENSOR_KEYS: list[str] = [
desc.key
for desc in (
*_SYSTEM_MON_COND,
*_CPU_MON_COND,
*_MEMORY_MON_COND,
*_NETWORK_MON_COND,
*_DRIVE_MON_COND,
*_VOLUME_MON_COND,
)
]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
{ {
@ -118,7 +184,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string, vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_MONITORED_CONDITIONS): vol.All( vol.Optional(CONF_MONITORED_CONDITIONS): vol.All(
cv.ensure_list, [vol.In(_MONITORED_CONDITIONS)] cv.ensure_list, [vol.In(SENSOR_KEYS)]
), ),
vol.Optional(CONF_NICS): cv.ensure_list, vol.Optional(CONF_NICS): cv.ensure_list,
vol.Optional(CONF_DRIVES): cv.ensure_list, vol.Optional(CONF_DRIVES): cv.ensure_list,
@ -136,40 +202,61 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
if not api.data: if not api.data:
raise PlatformNotReady raise PlatformNotReady
monitored_conditions = config[CONF_MONITORED_CONDITIONS]
sensors = [] sensors = []
# Basic sensors # Basic sensors
for variable in config[CONF_MONITORED_CONDITIONS]: sensors.extend(
if variable in _SYSTEM_MON_COND: [
sensors.append(QNAPSystemSensor(api, variable, _SYSTEM_MON_COND[variable])) QNAPSystemSensor(api, description)
if variable in _CPU_MON_COND: for description in _SYSTEM_MON_COND
sensors.append(QNAPCPUSensor(api, variable, _CPU_MON_COND[variable])) if description.key in monitored_conditions
if variable in _MEMORY_MON_COND: ]
sensors.append(QNAPMemorySensor(api, variable, _MEMORY_MON_COND[variable])) )
sensors.extend(
[
QNAPCPUSensor(api, description)
for description in _CPU_MON_COND
if description.key in monitored_conditions
]
)
sensors.extend(
[
QNAPMemorySensor(api, description)
for description in _MEMORY_MON_COND
if description.key in monitored_conditions
]
)
# Network sensors # Network sensors
for nic in config.get(CONF_NICS, api.data["system_stats"]["nics"]): sensors.extend(
sensors += [ [
QNAPNetworkSensor(api, variable, _NETWORK_MON_COND[variable], nic) QNAPNetworkSensor(api, description, nic)
for variable in config[CONF_MONITORED_CONDITIONS] for nic in config.get(CONF_NICS, api.data["system_stats"]["nics"])
if variable in _NETWORK_MON_COND for description in _NETWORK_MON_COND
if description.key in monitored_conditions
] ]
)
# Drive sensors # Drive sensors
for drive in config.get(CONF_DRIVES, api.data["smart_drive_health"]): sensors.extend(
sensors += [ [
QNAPDriveSensor(api, variable, _DRIVE_MON_COND[variable], drive) QNAPDriveSensor(api, description, drive)
for variable in config[CONF_MONITORED_CONDITIONS] for drive in config.get(CONF_DRIVES, api.data["smart_drive_health"])
if variable in _DRIVE_MON_COND for description in _DRIVE_MON_COND
if description.key in monitored_conditions
] ]
)
# Volume sensors # Volume sensors
for volume in config.get(CONF_VOLUMES, api.data["volumes"]): sensors.extend(
sensors += [ [
QNAPVolumeSensor(api, variable, _VOLUME_MON_COND[variable], volume) QNAPVolumeSensor(api, description, volume)
for variable in config[CONF_MONITORED_CONDITIONS] for volume in config.get(CONF_VOLUMES, api.data["volumes"])
if variable in _VOLUME_MON_COND for description in _VOLUME_MON_COND
if description.key in monitored_conditions
] ]
)
add_entities(sensors) add_entities(sensors)
@ -218,15 +305,11 @@ class QNAPStatsAPI:
class QNAPSensor(SensorEntity): class QNAPSensor(SensorEntity):
"""Base class for a QNAP sensor.""" """Base class for a QNAP sensor."""
def __init__(self, api, variable, variable_info, monitor_device=None): def __init__(self, api, description: SensorEntityDescription, monitor_device=None):
"""Initialize the sensor.""" """Initialize the sensor."""
self.var_id = variable self.entity_description = description
self.var_name = variable_info[0]
self.var_units = variable_info[1]
self.var_icon = variable_info[2]
self.monitor_device = monitor_device self.monitor_device = monitor_device
self._api = api self._api = api
self._attr_device_class = variable_info[3]
@property @property
def name(self): def name(self):
@ -234,18 +317,10 @@ class QNAPSensor(SensorEntity):
server_name = self._api.data["system_stats"]["system"]["name"] server_name = self._api.data["system_stats"]["system"]["name"]
if self.monitor_device is not None: if self.monitor_device is not None:
return f"{server_name} {self.var_name} ({self.monitor_device})" return (
return f"{server_name} {self.var_name}" f"{server_name} {self.entity_description.name} ({self.monitor_device})"
)
@property return f"{server_name} {self.entity_description.name}"
def icon(self):
"""Return the icon to use in the frontend, if any."""
return self.var_icon
@property
def native_unit_of_measurement(self):
"""Return the unit the value is expressed in."""
return self.var_units
def update(self): def update(self):
"""Get the latest data for the states.""" """Get the latest data for the states."""
@ -258,9 +333,9 @@ class QNAPCPUSensor(QNAPSensor):
@property @property
def native_value(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.var_id == "cpu_temp": if self.entity_description.key == "cpu_temp":
return self._api.data["system_stats"]["cpu"]["temp_c"] return self._api.data["system_stats"]["cpu"]["temp_c"]
if self.var_id == "cpu_usage": if self.entity_description.key == "cpu_usage":
return self._api.data["system_stats"]["cpu"]["usage_percent"] return self._api.data["system_stats"]["cpu"]["usage_percent"]
@ -271,16 +346,16 @@ class QNAPMemorySensor(QNAPSensor):
def native_value(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
free = float(self._api.data["system_stats"]["memory"]["free"]) / 1024 free = float(self._api.data["system_stats"]["memory"]["free"]) / 1024
if self.var_id == "memory_free": if self.entity_description.key == "memory_free":
return round_nicely(free) return round_nicely(free)
total = float(self._api.data["system_stats"]["memory"]["total"]) / 1024 total = float(self._api.data["system_stats"]["memory"]["total"]) / 1024
used = total - free used = total - free
if self.var_id == "memory_used": if self.entity_description.key == "memory_used":
return round_nicely(used) return round_nicely(used)
if self.var_id == "memory_percent_used": if self.entity_description.key == "memory_percent_used":
return round(used / total * 100) return round(used / total * 100)
@property @property
@ -298,15 +373,15 @@ class QNAPNetworkSensor(QNAPSensor):
@property @property
def native_value(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.var_id == "network_link_status": if self.entity_description.key == "network_link_status":
nic = self._api.data["system_stats"]["nics"][self.monitor_device] nic = self._api.data["system_stats"]["nics"][self.monitor_device]
return nic["link_status"] return nic["link_status"]
data = self._api.data["bandwidth"][self.monitor_device] data = self._api.data["bandwidth"][self.monitor_device]
if self.var_id == "network_tx": if self.entity_description.key == "network_tx":
return round_nicely(data["tx"] / 1024 / 1024) return round_nicely(data["tx"] / 1024 / 1024)
if self.var_id == "network_rx": if self.entity_description.key == "network_rx":
return round_nicely(data["rx"] / 1024 / 1024) return round_nicely(data["rx"] / 1024 / 1024)
@property @property
@ -331,10 +406,10 @@ class QNAPSystemSensor(QNAPSensor):
@property @property
def native_value(self): def native_value(self):
"""Return the state of the sensor.""" """Return the state of the sensor."""
if self.var_id == "status": if self.entity_description.key == "status":
return self._api.data["system_health"] return self._api.data["system_health"]
if self.var_id == "system_temp": if self.entity_description.key == "system_temp":
return int(self._api.data["system_stats"]["system"]["temp_c"]) return int(self._api.data["system_stats"]["system"]["temp_c"])
@property @property
@ -362,10 +437,10 @@ class QNAPDriveSensor(QNAPSensor):
"""Return the state of the sensor.""" """Return the state of the sensor."""
data = self._api.data["smart_drive_health"][self.monitor_device] data = self._api.data["smart_drive_health"][self.monitor_device]
if self.var_id == "drive_smart_status": if self.entity_description.key == "drive_smart_status":
return data["health"] return data["health"]
if self.var_id == "drive_temp": if self.entity_description.key == "drive_temp":
return int(data["temp_c"]) if data["temp_c"] is not None else 0 return int(data["temp_c"]) if data["temp_c"] is not None else 0
@property @property
@ -373,7 +448,7 @@ class QNAPDriveSensor(QNAPSensor):
"""Return the name of the sensor, if any.""" """Return the name of the sensor, if any."""
server_name = self._api.data["system_stats"]["system"]["name"] server_name = self._api.data["system_stats"]["system"]["name"]
return f"{server_name} {self.var_name} (Drive {self.monitor_device})" return f"{server_name} {self.entity_description.name} (Drive {self.monitor_device})"
@property @property
def extra_state_attributes(self): def extra_state_attributes(self):
@ -397,16 +472,16 @@ class QNAPVolumeSensor(QNAPSensor):
data = self._api.data["volumes"][self.monitor_device] data = self._api.data["volumes"][self.monitor_device]
free_gb = int(data["free_size"]) / 1024 / 1024 / 1024 free_gb = int(data["free_size"]) / 1024 / 1024 / 1024
if self.var_id == "volume_size_free": if self.entity_description.key == "volume_size_free":
return round_nicely(free_gb) return round_nicely(free_gb)
total_gb = int(data["total_size"]) / 1024 / 1024 / 1024 total_gb = int(data["total_size"]) / 1024 / 1024 / 1024
used_gb = total_gb - free_gb used_gb = total_gb - free_gb
if self.var_id == "volume_size_used": if self.entity_description.key == "volume_size_used":
return round_nicely(used_gb) return round_nicely(used_gb)
if self.var_id == "volume_percentage_used": if self.entity_description.key == "volume_percentage_used":
return round(used_gb / total_gb * 100) return round(used_gb / total_gb * 100)
@property @property