8000 Add freebox device connectivty and signal sensors · home-assistant/core@46a5f1a · GitHub
[go: up one dir, main page]

Skip to content

Commit 46a5f1a

Browse files
committed
Add freebox device connectivty and signal sensors
1 parent f59001d commit 46a5f1a

File tree

2 files changed

+133
-3
lines changed

2 files changed

+133
-3
lines changed

homeassistant/components/freebox/const.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,18 @@ class FreeboxHomeCategory(enum.StrEnum):
9393
FreeboxHomeCategory.PIR,
9494
FreeboxHomeCategory.RTS,
9595
]
96+
97+
98+
class DeviceConnectivityType(enum.StrEnum):
99+
"""Freebox Connectivity types for device."""
100+
101+
ETHERNET = "Ethernet"
102+
WIFI = "Wifi"
103+
WIFI_2D4GHZ = "Wifi 2.4 GHz"
104+
WIFI_5GHZ = "Wifi 5 GHz"
105+
106+
107+
WIFI_BANDS_TO_CONNECTIVITY = {
108+
"2d4g": DeviceConnectivityType.WIFI_2D4GHZ,
109+
"5g": DeviceConnectivityType.WIFI_5GHZ,
110+
}

homeassistant/components/freebox/sensor.py

Lines changed: 118 additions & 3 deletions
10000
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,20 @@
1111
SensorEntityDescription,
1212
SensorStateClass,
1313
)
14-
from homeassistant.const import PERCENTAGE, UnitOfDataRate, UnitOfTemperature
14+
from homeassistant.const import (
15+
PERCENTAGE,
16+
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
17+
EntityCategory,
18+
UnitOfDataRate,
19+
UnitOfTemperature,
20+
)
1521
from homeassistant.core import HomeAssistant, callback
16-
from homeassistant.helpers.device_registry import DeviceInfo
22+
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
1723
from homeassistant.helpers.dispatcher import async_dispatcher_connect
1824
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
1925
from homeassistant.util import dt as dt_util
2026

21-
from .const import DOMAIN
27+
from .const import DOMAIN, WIFI_BANDS_TO_CONNECTIVITY, DeviceConnectivityType
2228
from .entity import FreeboxHomeEntity
2329
from .router import FreeboxConfigEntry, FreeboxRouter
2430

@@ -60,6 +66,38 @@
6066
),
6167
)
6268

69+
DEVICE_SENSORS: tuple[SensorEntityDescription, ...] = (
70+
SensorEntityDescription(
71+
key="connectivity",
72+
name="Connectivity",
73+
device_class=SensorDeviceClass.ENUM,
74+
options=[e.value for e in DeviceConnectivityType.__members__.values()],
75+
icon="mdi:network",
76+
entity_category=EntityCategory.DIAGNOSTIC,
77+
entity_registry_enabled_default=True,
78+
),
79+
)
80+
81+
WIFI_DEVICE_SENSORS: tuple[SensorEntityDescription, ...] = (
82+
SensorEntityDescription(
83+
key="wifi_signal_dbm",
84+
name="Wifi signal strength",
85+
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
86+
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
87+
icon="mdi:signal",
88+
entity_category=EntityCategory.DIAGNOSTIC,
89+
entity_registry_enabled_default=True,
90+
),
91+
SensorEntityDescription(
92+
key="wifi_signal_percentage",
93+
name="Wifi signal level",
94+
native_unit_of_measurement=PERCENTAGE,
95+
icon="mdi:signal",
96+
entity_category=EntityCategory.DIAGNOSTIC,
97+
entity_registry_enabled_default=True,
98+
),
99+
)
100+
63101

64102
async def async_setup_entry(
65103
hass: HomeAssistant,
@@ -113,6 +151,20 @@ async def async_setup_entry(
113151
):
114152
entities.append(FreeboxBatterySensor(hass, router, node, endpoint))
115153

154+
for device in router.devices.values():
155+
if not device.get("persistent", False):
156+
continue
157+
entities.extend(
158+
FreeboxDeviceSensor(router, device, description)
159+
for description in DEVICE_SENSORS
160+
)
161+
if (
162+
connectivity_type := get_device_connectity_type(device)
163+
) and connectivity_type != DeviceConnectivityType.ETHERNET:
164+
entities.extend(
165+
FreeboxDeviceSensor(router, device, description)
166+
for description in WIFI_DEVICE_SENSORS
167+
)
116168
if entities:
117169
async_add_entities(entities, True)
118170

@@ -241,3 +293,66 @@ class FreeboxBatterySensor(FreeboxHomeEntity, SensorEntity):
241293
def native_value(self) -> int:
242294
"""Return the current state of the device."""
243295
return self.get_value("signal", "battery")
296+
297+
298+
class FreeboxDeviceSensor(FreeboxSensor):
299+
"""Representation of a Freebox device sensor."""
300+
301+
def __init__(
302+
self,
303+
router: FreeboxRouter,
304+
device: dict[str, Any],
305+
description: SensorEntityDescription,
306+
) -> None:
307+
"""Initialize a Freebox device sensor."""
308+
super().__init__(router, description)
309+
self._device = device
310+
mac_address = device["l2ident"]["id"]
311+
self._attr_unique_id = f"{router.mac} {description.key} {mac_address}"
312+
self._attr_device_info = DeviceInfo(
313+
identifiers={(DOMAIN, mac_address)},
314+
manufacturer=device["vendor_name"],
315+
name=device["primary_name"],
316+
via_device=(DOMAIN, router.mac),
317+
connections={(CONNECTION_NETWORK_MAC, mac_address)},
318+
)
319+
self._attr_name = f"{device['primary_name']} {description.name}"
320+
321+
def async_update_state(self) -> None:
322+
"""Update the Freebox device sensor."""
323+
if self.entity_description.key == "connectivity":
324+
self._attr_native_value = get_device_connectity_type(self._device)
325+
elif self.entity_description.key == "wifi_signal_dbm":
326+
self._attr_native_value = get_device_wifi_signal_strength_dbm(self._device)
327+
elif self.entity_description.key == "wifi_signal_percentage":
328+
self._attr_native_value = get_device_wifi_signal_strength_percentage(
329+
self._device
330+
)
331+
332+
333+
def get_device_connectity_type(device: dict[str, Any]) -> str | None:
334+
"""Get the connectivity type of a device."""
335+
result = None
336+
access_point = device.get("access_point", {})
337+
if connectivity_type := access_point.get("connectivity_type"):
338+
if connectivity_type == "wifi":
339+
wifi_information = access_point.get("wifi_information", {})
340+
band = wifi_information.get("band", "")
341+
result = WIFI_BANDS_TO_CONNECTIVITY.get(band, DeviceConnectivityType.WIFI)
342+
if connectivity_type == "ethernet":
343+
result = DeviceConnectivityType.ETHERNET
344+
return result.value if result else None
345+
346+
347+
def get_device_wifi_signal_strength_dbm(device: dict[str, Any]) -> int | None:
348+
"""Get the wifi signal strength of a device in dBm."""
349+
access_point = device.get("access_point", {})
350+
wifi_information = access_point.get("wifi_information", {})
351+
return wifi_information.get("signal")
352+
353+
354+
def get_device_wifi_signal_strength_percentage(device: dict[str, Any]) -> int | None:
355+
"""Get the wifi signal strength of a device in percentage."""
356+
if dbm := get_device_wifi_signal_strength_dbm(device):
357+
return min(max(2 * (dbm + 100), 0), 100)
358+
return None

0 commit comments

Comments
 (0)
0