core/homeassistant/components/deluge/sensor.py

147 lines
5.4 KiB
Python

"""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 (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import STATE_IDLE, Platform, UnitOfDataRate
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from . import DelugeConfigEntry
from .const import DelugeGetSessionStatusKeys, DelugeSensorType
from .coordinator import DelugeDataUpdateCoordinator
from .entity import DelugeEntity
def get_state(data: dict[str, float], key: str) -> str | float:
"""Get current download/upload state."""
upload = data[DelugeGetSessionStatusKeys.UPLOAD_RATE.value]
download = data[DelugeGetSessionStatusKeys.DOWNLOAD_RATE.value]
protocol_upload = data[DelugeGetSessionStatusKeys.DHT_UPLOAD_RATE.value]
protocol_download = data[DelugeGetSessionStatusKeys.DHT_DOWNLOAD_RATE.value]
# if key is CURRENT_STATUS, we just return whether we are uploading / downloading / idle
if key == DelugeSensorType.CURRENT_STATUS_SENSOR:
if upload > 0 and download > 0:
return "seeding_and_downloading"
if upload > 0 and download == 0:
return "seeding"
if upload == 0 and download > 0:
return "downloading"
return STATE_IDLE
# if not, return the transfer rate for the given key
rate = 0.0
if key == DelugeSensorType.DOWNLOAD_SPEED_SENSOR:
rate = download
elif key == DelugeSensorType.UPLOAD_SPEED_SENSOR:
rate = upload
elif key == DelugeSensorType.PROTOCOL_TRAFFIC_DOWNLOAD_SPEED_SENSOR:
rate = protocol_download
else:
rate = protocol_upload
# convert to KiB/s and round
kb_spd = rate / 1024
return round(kb_spd, 2 if kb_spd < 0.1 else 1)
@dataclass(frozen=True)
class DelugeSensorEntityDescription(SensorEntityDescription):
"""Class to describe a Deluge sensor."""
value: Callable[[dict[str, float]], Any] = lambda val: val
SENSOR_TYPES: tuple[DelugeSensorEntityDescription, ...] = (
DelugeSensorEntityDescription(
key=DelugeSensorType.CURRENT_STATUS_SENSOR.value,
translation_key="status",
value=lambda data: get_state(
data, DelugeSensorType.CURRENT_STATUS_SENSOR.value
),
device_class=SensorDeviceClass.ENUM,
options=["seeding_and_downloading", "seeding", "downloading", "idle"],
),
DelugeSensorEntityDescription(
key=DelugeSensorType.DOWNLOAD_SPEED_SENSOR.value,
translation_key=DelugeSensorType.DOWNLOAD_SPEED_SENSOR.value,
device_class=SensorDeviceClass.DATA_RATE,
native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
state_class=SensorStateClass.MEASUREMENT,
value=lambda data: get_state(
data, DelugeSensorType.DOWNLOAD_SPEED_SENSOR.value
),
),
DelugeSensorEntityDescription(
key=DelugeSensorType.UPLOAD_SPEED_SENSOR.value,
translation_key=DelugeSensorType.UPLOAD_SPEED_SENSOR.value,
device_class=SensorDeviceClass.DATA_RATE,
native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
state_class=SensorStateClass.MEASUREMENT,
value=lambda data: get_state(data, DelugeSensorType.UPLOAD_SPEED_SENSOR.value),
),
DelugeSensorEntityDescription(
key=DelugeSensorType.PROTOCOL_TRAFFIC_UPLOAD_SPEED_SENSOR.value,
translation_key=DelugeSensorType.PROTOCOL_TRAFFIC_UPLOAD_SPEED_SENSOR.value,
device_class=SensorDeviceClass.DATA_RATE,
native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
state_class=SensorStateClass.MEASUREMENT,
value=lambda data: get_state(
data, DelugeSensorType.PROTOCOL_TRAFFIC_UPLOAD_SPEED_SENSOR.value
),
),
DelugeSensorEntityDescription(
key=DelugeSensorType.PROTOCOL_TRAFFIC_DOWNLOAD_SPEED_SENSOR.value,
translation_key=DelugeSensorType.PROTOCOL_TRAFFIC_DOWNLOAD_SPEED_SENSOR.value,
device_class=SensorDeviceClass.DATA_RATE,
native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
state_class=SensorStateClass.MEASUREMENT,
value=lambda data: get_state(
data, DelugeSensorType.PROTOCOL_TRAFFIC_DOWNLOAD_SPEED_SENSOR.value
),
),
)
async def async_setup_entry(
hass: HomeAssistant,
entry: DelugeConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Deluge sensor."""
async_add_entities(
DelugeSensor(entry.runtime_data, description) for description in SENSOR_TYPES
)
class DelugeSensor(DelugeEntity, SensorEntity):
"""Representation of a Deluge sensor."""
entity_description: DelugeSensorEntityDescription
def __init__(
self,
coordinator: DelugeDataUpdateCoordinator,
description: DelugeSensorEntityDescription,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self.entity_description = description
self._attr_unique_id = f"{coordinator.config_entry.entry_id}_{description.key}"
@property
def native_value(self) -> StateType:
"""Return the state of the sensor."""
return self.entity_description.value(self.coordinator.data[Platform.SENSOR])