1 """Platform for sensor integration."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import datetime, timedelta
8 from enum
import StrEnum
11 from devolo_plc_api.device_api
import ConnectedStationInfo, NeighborAPInfo
12 from devolo_plc_api.plcnet_api
import REMOTE, DataRate, LogicalNetwork
17 SensorEntityDescription,
25 from .
import DevoloHomeNetworkConfigEntry
27 CONNECTED_PLC_DEVICES,
28 CONNECTED_WIFI_CLIENTS,
30 NEIGHBORING_WIFI_NETWORKS,
34 from .coordinator
import DevoloDataUpdateCoordinator
35 from .entity
import DevoloCoordinatorEntity
41 """Calculate uptime. As fetching the data might also take some time, let's floor to the nearest 5 seconds."""
46 -
timedelta(seconds=(now.timestamp() - runtime) % 5)
50 type _CoordinatorDataType = (
51 LogicalNetwork | DataRate | list[ConnectedStationInfo] | list[NeighborAPInfo] | int
53 type _SensorDataType = int | float | datetime
57 """Direction of data transfer."""
63 @dataclass(frozen=True, kw_only=True)
65 _CoordinatorDataT: _CoordinatorDataType,
66 _SensorDataT: _SensorDataType,
67 ](SensorEntityDescription):
68 """Describes devolo sensor entity."""
70 value_func: Callable[[_CoordinatorDataT], _SensorDataT]
73 SENSOR_TYPES: dict[str, DevoloSensorEntityDescription[Any, Any]] = {
74 CONNECTED_PLC_DEVICES: DevoloSensorEntityDescription[LogicalNetwork, int](
75 key=CONNECTED_PLC_DEVICES,
76 entity_category=EntityCategory.DIAGNOSTIC,
77 entity_registry_enabled_default=
False,
78 value_func=
lambda data: len(
79 {device.mac_address_from
for device
in data.data_rates}
82 CONNECTED_WIFI_CLIENTS: DevoloSensorEntityDescription[
83 list[ConnectedStationInfo], int
85 key=CONNECTED_WIFI_CLIENTS,
86 state_class=SensorStateClass.MEASUREMENT,
89 NEIGHBORING_WIFI_NETWORKS: DevoloSensorEntityDescription[list[NeighborAPInfo], int](
90 key=NEIGHBORING_WIFI_NETWORKS,
91 entity_category=EntityCategory.DIAGNOSTIC,
92 entity_registry_enabled_default=
False,
95 PLC_RX_RATE: DevoloSensorEntityDescription[DataRate, float](
97 entity_category=EntityCategory.DIAGNOSTIC,
98 name=
"PLC downlink PHY rate",
99 device_class=SensorDeviceClass.DATA_RATE,
100 native_unit_of_measurement=UnitOfDataRate.MEGABITS_PER_SECOND,
101 value_func=
lambda data: getattr(data, DataRateDirection.RX, 0),
102 suggested_display_precision=0,
104 PLC_TX_RATE: DevoloSensorEntityDescription[DataRate, float](
106 entity_category=EntityCategory.DIAGNOSTIC,
107 name=
"PLC uplink PHY rate",
108 device_class=SensorDeviceClass.DATA_RATE,
109 native_unit_of_measurement=UnitOfDataRate.MEGABITS_PER_SECOND,
110 value_func=
lambda data: getattr(data, DataRateDirection.TX, 0),
111 suggested_display_precision=0,
113 LAST_RESTART: DevoloSensorEntityDescription[int, datetime](
115 entity_category=EntityCategory.DIAGNOSTIC,
116 entity_registry_enabled_default=
False,
117 device_class=SensorDeviceClass.TIMESTAMP,
118 value_func=_last_restart,
125 entry: DevoloHomeNetworkConfigEntry,
126 async_add_entities: AddEntitiesCallback,
128 """Get all devices and sensors and setup them via config entry."""
129 device = entry.runtime_data.device
130 coordinators = entry.runtime_data.coordinators
132 entities: list[BaseDevoloSensorEntity[Any, Any, Any]] = []
137 coordinators[CONNECTED_PLC_DEVICES],
138 SENSOR_TYPES[CONNECTED_PLC_DEVICES],
141 network = await device.plcnet.async_get_network_overview()
143 peer.mac_address
for peer
in network.devices
if peer.topology == REMOTE
149 coordinators[CONNECTED_PLC_DEVICES],
150 SENSOR_TYPES[PLC_TX_RATE],
157 coordinators[CONNECTED_PLC_DEVICES],
158 SENSOR_TYPES[PLC_RX_RATE],
162 if device.device
and "restart" in device.device.features:
166 coordinators[LAST_RESTART],
167 SENSOR_TYPES[LAST_RESTART],
170 if device.device
and "wifi1" in device.device.features:
174 coordinators[CONNECTED_WIFI_CLIENTS],
175 SENSOR_TYPES[CONNECTED_WIFI_CLIENTS],
181 coordinators[NEIGHBORING_WIFI_NETWORKS],
182 SENSOR_TYPES[NEIGHBORING_WIFI_NETWORKS],
189 _CoordinatorDataT: _CoordinatorDataType,
190 _ValueDataT: _CoordinatorDataType,
191 _SensorDataT: _SensorDataType,
193 DevoloCoordinatorEntity[_CoordinatorDataT],
196 """Representation of a devolo sensor."""
200 entry: DevoloHomeNetworkConfigEntry,
201 coordinator: DevoloDataUpdateCoordinator[_CoordinatorDataT],
202 description: DevoloSensorEntityDescription[_ValueDataT, _SensorDataT],
204 """Initialize entity."""
205 self.entity_description = description
206 super().
__init__(entry, coordinator)
210 _CoordinatorDataT: _CoordinatorDataType,
211 _ValueDataT: _CoordinatorDataType,
212 _SensorDataT: _SensorDataType,
213 ](BaseDevoloSensorEntity[_CoordinatorDataT, _ValueDataT, _SensorDataT]):
214 """Representation of a generic devolo sensor."""
216 entity_description: DevoloSensorEntityDescription[_CoordinatorDataT, _SensorDataT]
220 """State of the sensor."""
221 return self.entity_description.
value_func(self.coordinator.data)
225 BaseDevoloSensorEntity[LogicalNetwork, DataRate, float]
227 """Representation of a devolo PLC data rate sensor."""
229 entity_description: DevoloSensorEntityDescription[DataRate, float]
233 entry: DevoloHomeNetworkConfigEntry,
234 coordinator: DevoloDataUpdateCoordinator[LogicalNetwork],
235 description: DevoloSensorEntityDescription[DataRate, float],
238 """Initialize entity."""
239 super().
__init__(entry, coordinator, description)
243 for device
in self.coordinator.data.devices
244 if device.mac_address == peer
248 self.
_attr_name_attr_name = f
"{description.name} ({peer_device.user_device_name})"
253 """State of the sensor."""
257 for data_rate
in self.coordinator.data.data_rates
258 if data_rate.mac_address_from == self.device.mac
259 and data_rate.mac_address_to == self.
_peer_peer
_attr_entity_registry_enabled_default
None __init__(self, DevoloHomeNetworkConfigEntry entry, DevoloDataUpdateCoordinator[LogicalNetwork] coordinator, DevoloSensorEntityDescription[DataRate, float] description, str peer)
datetime _last_restart(int runtime)
None async_setup_entry(HomeAssistant hass, DevoloHomeNetworkConfigEntry entry, AddEntitiesCallback async_add_entities)
int|float|datetime native_value(self)
None __init__(self, DevoloHomeNetworkConfigEntry entry, DevoloDataUpdateCoordinator[_CoordinatorDataT] coordinator, DevoloSensorEntityDescription[_ValueDataT, _SensorDataT] description)