From 72dbca4f5bc3a40ac96b2c8fc355ce85bedd003c Mon Sep 17 00:00:00 2001 From: Robert Hillis Date: Sat, 21 May 2022 05:20:37 -0400 Subject: [PATCH] Address late feedback on Deluge config flow (#71497) Address late feedback on Deluge --- homeassistant/components/deluge/const.py | 10 ++- .../components/deluge/coordinator.py | 12 +-- homeassistant/components/deluge/sensor.py | 76 +++++++++++-------- 3 files changed, 54 insertions(+), 44 deletions(-) diff --git a/homeassistant/components/deluge/const.py b/homeassistant/components/deluge/const.py index 505c20e860f..704c024c41b 100644 --- a/homeassistant/components/deluge/const.py +++ b/homeassistant/components/deluge/const.py @@ -1,12 +1,16 @@ """Constants for the Deluge integration.""" import logging +from typing import Final CONF_WEB_PORT = "web_port" +CURRENT_STATUS = "current_status" +DATA_KEYS = ["upload_rate", "download_rate", "dht_upload_rate", "dht_download_rate"] DEFAULT_NAME = "Deluge" DEFAULT_RPC_PORT = 58846 DEFAULT_WEB_PORT = 8112 -DHT_UPLOAD = 1000 -DHT_DOWNLOAD = 1000 -DOMAIN = "deluge" +DOMAIN: Final = "deluge" +DOWNLOAD_SPEED = "download_speed" LOGGER = logging.getLogger(__package__) + +UPLOAD_SPEED = "upload_speed" diff --git a/homeassistant/components/deluge/coordinator.py b/homeassistant/components/deluge/coordinator.py index 0ac97e77674..89f9afc31ad 100644 --- a/homeassistant/components/deluge/coordinator.py +++ b/homeassistant/components/deluge/coordinator.py @@ -13,7 +13,7 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .const import LOGGER +from .const import DATA_KEYS, LOGGER class DelugeDataUpdateCoordinator(DataUpdateCoordinator): @@ -38,16 +38,12 @@ class DelugeDataUpdateCoordinator(DataUpdateCoordinator): """Get the latest data from Deluge and updates the state.""" data = {} try: - data[Platform.SENSOR] = await self.hass.async_add_executor_job( + _data = await self.hass.async_add_executor_job( self.api.call, "core.get_session_status", - [ - "upload_rate", - "download_rate", - "dht_upload_rate", - "dht_download_rate", - ], + DATA_KEYS, ) + data[Platform.SENSOR] = {k.decode(): v for k, v in _data.items()} data[Platform.SWITCH] = await self.hass.async_add_executor_job( self.api.call, "core.get_torrents_status", {}, ["paused"] ) diff --git a/homeassistant/components/deluge/sensor.py b/homeassistant/components/deluge/sensor.py index bad535def96..8a8e8f64657 100644 --- a/homeassistant/components/deluge/sensor.py +++ b/homeassistant/components/deluge/sensor.py @@ -1,6 +1,10 @@ """Support for monitoring the Deluge BitTorrent client API.""" from __future__ import annotations +from collections.abc import Callable +from dataclasses import dataclass +from typing import Any + from homeassistant.components.sensor import ( SensorEntity, SensorEntityDescription, @@ -13,25 +17,52 @@ from homeassistant.helpers import entity_platform from homeassistant.helpers.typing import StateType from . import DelugeEntity -from .const import DOMAIN +from .const import CURRENT_STATUS, DATA_KEYS, DOMAIN, DOWNLOAD_SPEED, UPLOAD_SPEED from .coordinator import DelugeDataUpdateCoordinator -SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( - SensorEntityDescription( - key="current_status", + +def get_state(data: dict[str, float], key: str) -> str | float: + """Get current download/upload state.""" + upload = data[DATA_KEYS[0]] - data[DATA_KEYS[2]] + download = data[DATA_KEYS[1]] - data[DATA_KEYS[3]] + if key == CURRENT_STATUS: + if upload > 0 and download > 0: + return "Up/Down" + if upload > 0 and download == 0: + return "Seeding" + if upload == 0 and download > 0: + return "Downloading" + return STATE_IDLE + kb_spd = float(upload if key == UPLOAD_SPEED else download) / 1024 + return round(kb_spd, 2 if kb_spd < 0.1 else 1) + + +@dataclass +class DelugeSensorEntityDescription(SensorEntityDescription): + """Class to describe a Deluge sensor.""" + + value: Callable[[dict[str, float]], Any] = lambda val: val + + +SENSOR_TYPES: tuple[DelugeSensorEntityDescription, ...] = ( + DelugeSensorEntityDescription( + key=CURRENT_STATUS, name="Status", + value=lambda data: get_state(data, CURRENT_STATUS), ), - SensorEntityDescription( - key="download_speed", + DelugeSensorEntityDescription( + key=DOWNLOAD_SPEED, name="Down Speed", native_unit_of_measurement=DATA_RATE_KILOBYTES_PER_SECOND, state_class=SensorStateClass.MEASUREMENT, + value=lambda data: get_state(data, DOWNLOAD_SPEED), ), - SensorEntityDescription( - key="upload_speed", + DelugeSensorEntityDescription( + key=UPLOAD_SPEED, name="Up Speed", native_unit_of_measurement=DATA_RATE_KILOBYTES_PER_SECOND, state_class=SensorStateClass.MEASUREMENT, + value=lambda data: get_state(data, UPLOAD_SPEED), ), ) @@ -51,10 +82,12 @@ async def async_setup_entry( class DelugeSensor(DelugeEntity, SensorEntity): """Representation of a Deluge sensor.""" + entity_description: DelugeSensorEntityDescription + def __init__( self, coordinator: DelugeDataUpdateCoordinator, - description: SensorEntityDescription, + description: DelugeSensorEntityDescription, ) -> None: """Initialize the sensor.""" super().__init__(coordinator) @@ -65,27 +98,4 @@ class DelugeSensor(DelugeEntity, SensorEntity): @property def native_value(self) -> StateType: """Return the state of the sensor.""" - if self.coordinator.data: - data = self.coordinator.data[Platform.SENSOR] - upload = data[b"upload_rate"] - data[b"dht_upload_rate"] - download = data[b"download_rate"] - data[b"dht_download_rate"] - if self.entity_description.key == "current_status": - if data: - if upload > 0 and download > 0: - return "Up/Down" - if upload > 0 and download == 0: - return "Seeding" - if upload == 0 and download > 0: - return "Downloading" - return STATE_IDLE - - if data: - if self.entity_description.key == "download_speed": - kb_spd = float(download) - kb_spd = kb_spd / 1024 - return round(kb_spd, 2 if kb_spd < 0.1 else 1) - if self.entity_description.key == "upload_speed": - kb_spd = float(upload) - kb_spd = kb_spd / 1024 - return round(kb_spd, 2 if kb_spd < 0.1 else 1) - return None + return self.entity_description.value(self.coordinator.data[Platform.SENSOR])