1 """Support for monitoring the qBittorrent API."""
3 from __future__
import annotations
5 from collections.abc
import Callable, Mapping
6 from dataclasses
import dataclass
8 from typing
import Any, cast
13 SensorEntityDescription,
24 from .const
import DOMAIN, STATE_DOWNLOADING, STATE_SEEDING, STATE_UP_DOWN
25 from .coordinator
import QBittorrentDataCoordinator
27 _LOGGER = logging.getLogger(__name__)
29 SENSOR_TYPE_CURRENT_STATUS =
"current_status"
30 SENSOR_TYPE_DOWNLOAD_SPEED =
"download_speed"
31 SENSOR_TYPE_UPLOAD_SPEED =
"upload_speed"
32 SENSOR_TYPE_ALL_TORRENTS =
"all_torrents"
33 SENSOR_TYPE_PAUSED_TORRENTS =
"paused_torrents"
34 SENSOR_TYPE_ACTIVE_TORRENTS =
"active_torrents"
35 SENSOR_TYPE_INACTIVE_TORRENTS =
"inactive_torrents"
38 def get_state(coordinator: QBittorrentDataCoordinator) -> str:
39 """Get current download/upload state."""
40 server_state = cast(Mapping, coordinator.data.get(
"server_state"))
41 upload = cast(int, server_state.get(
"up_info_speed"))
42 download = cast(int, server_state.get(
"dl_info_speed"))
44 if upload > 0
and download > 0:
46 if upload > 0
and download == 0:
48 if upload == 0
and download > 0:
49 return STATE_DOWNLOADING
53 def get_dl(coordinator: QBittorrentDataCoordinator) -> int:
54 """Get current download speed."""
55 server_state = cast(Mapping, coordinator.data.get(
"server_state"))
56 return cast(int, server_state.get(
"dl_info_speed"))
59 def get_up(coordinator: QBittorrentDataCoordinator) -> int:
60 """Get current upload speed."""
61 server_state = cast(Mapping[str, Any], coordinator.data.get(
"server_state"))
62 return cast(int, server_state.get(
"up_info_speed"))
65 @dataclass(frozen=True, kw_only=True)
67 """Entity description class for qBittorent sensors."""
69 value_fn: Callable[[QBittorrentDataCoordinator], StateType]
72 SENSOR_TYPES: tuple[QBittorrentSensorEntityDescription, ...] = (
74 key=SENSOR_TYPE_CURRENT_STATUS,
75 translation_key=
"current_status",
76 device_class=SensorDeviceClass.ENUM,
77 options=[STATE_IDLE, STATE_UP_DOWN, STATE_SEEDING, STATE_DOWNLOADING],
81 key=SENSOR_TYPE_DOWNLOAD_SPEED,
82 translation_key=
"download_speed",
83 state_class=SensorStateClass.MEASUREMENT,
84 device_class=SensorDeviceClass.DATA_RATE,
85 native_unit_of_measurement=UnitOfDataRate.BYTES_PER_SECOND,
86 suggested_display_precision=2,
87 suggested_unit_of_measurement=UnitOfDataRate.MEGABYTES_PER_SECOND,
91 key=SENSOR_TYPE_UPLOAD_SPEED,
92 translation_key=
"upload_speed",
93 state_class=SensorStateClass.MEASUREMENT,
94 device_class=SensorDeviceClass.DATA_RATE,
95 native_unit_of_measurement=UnitOfDataRate.BYTES_PER_SECOND,
96 suggested_display_precision=2,
97 suggested_unit_of_measurement=UnitOfDataRate.MEGABYTES_PER_SECOND,
101 key=SENSOR_TYPE_ALL_TORRENTS,
102 translation_key=
"all_torrents",
106 key=SENSOR_TYPE_ACTIVE_TORRENTS,
107 translation_key=
"active_torrents",
109 coordinator, [
"downloading",
"uploading"]
113 key=SENSOR_TYPE_INACTIVE_TORRENTS,
114 translation_key=
"inactive_torrents",
116 coordinator, [
"stalledDL",
"stalledUP"]
120 key=SENSOR_TYPE_PAUSED_TORRENTS,
121 translation_key=
"paused_torrents",
123 coordinator, [
"pausedDL",
"pausedUP"]
131 config_entry: ConfigEntry,
132 async_add_entities: AddEntitiesCallback,
134 """Set up qBittorrent sensor entries."""
136 coordinator: QBittorrentDataCoordinator = hass.data[DOMAIN][config_entry.entry_id]
140 for description
in SENSOR_TYPES
145 """Representation of a qBittorrent sensor."""
147 _attr_has_entity_name =
True
148 entity_description: QBittorrentSensorEntityDescription
152 coordinator: QBittorrentDataCoordinator,
153 config_entry: ConfigEntry,
154 entity_description: QBittorrentSensorEntityDescription,
156 """Initialize the qBittorrent sensor."""
159 self.
_attr_unique_id_attr_unique_id = f
"{config_entry.entry_id}-{entity_description.key}"
161 entry_type=DeviceEntryType.SERVICE,
162 identifiers={(DOMAIN, config_entry.entry_id)},
163 manufacturer=
"QBittorrent",
168 """Return the value of the sensor."""
173 coordinator: QBittorrentDataCoordinator, states: list[str]
175 """Count the number of torrents in specified states."""
178 torrents = cast(Mapping[str, Mapping], coordinator.data.get(
"torrents"))
186 [torrent
for torrent
in torrents.values()
if torrent.get(
"state")
in states]
188 except AttributeError:
None __init__(self, QBittorrentDataCoordinator coordinator, ConfigEntry config_entry, QBittorrentSensorEntityDescription entity_description)
StateType native_value(self)
str get_state(QBittorrentDataCoordinator coordinator)
int get_up(QBittorrentDataCoordinator coordinator)
int get_dl(QBittorrentDataCoordinator coordinator)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
int count_torrents_in_states(QBittorrentDataCoordinator coordinator, list[str] states)