mirror of
https://github.com/home-assistant/core.git
synced 2025-07-25 22:27:07 +00:00
Add WAN information to SFR Box (#89678)
This commit is contained in:
parent
cb74b934dc
commit
c416d18506
@ -1,11 +1,13 @@
|
|||||||
"""SFR Box."""
|
"""SFR Box."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
|
||||||
from sfrbox_api.bridge import SFRBox
|
from sfrbox_api.bridge import SFRBox
|
||||||
from sfrbox_api.exceptions import SFRBoxAuthenticationError, SFRBoxError
|
from sfrbox_api.exceptions import SFRBoxAuthenticationError, SFRBoxError
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform
|
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
@ -37,15 +39,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
system=SFRDataUpdateCoordinator(
|
system=SFRDataUpdateCoordinator(
|
||||||
hass, box, "system", lambda b: b.system_get_info()
|
hass, box, "system", lambda b: b.system_get_info()
|
||||||
),
|
),
|
||||||
|
wan=SFRDataUpdateCoordinator(hass, box, "wan", lambda b: b.wan_get_info()),
|
||||||
)
|
)
|
||||||
|
# Preload system information
|
||||||
await data.system.async_config_entry_first_refresh()
|
await data.system.async_config_entry_first_refresh()
|
||||||
system_info = data.system.data
|
system_info = data.system.data
|
||||||
|
|
||||||
|
# Preload other coordinators (based on net infrastructure)
|
||||||
|
tasks = [data.wan.async_config_entry_first_refresh()]
|
||||||
if system_info.net_infra == "adsl":
|
if system_info.net_infra == "adsl":
|
||||||
await data.dsl.async_config_entry_first_refresh()
|
tasks.append(data.dsl.async_config_entry_first_refresh())
|
||||||
else:
|
await asyncio.gather(*tasks)
|
||||||
platforms = list(platforms)
|
|
||||||
platforms.remove(Platform.BINARY_SENSOR)
|
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = data
|
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = data
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ from collections.abc import Callable
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Generic, TypeVar
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
from sfrbox_api.models import DslInfo, SystemInfo
|
from sfrbox_api.models import DslInfo, SystemInfo, WanInfo
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import (
|
from homeassistant.components.binary_sensor import (
|
||||||
BinarySensorDeviceClass,
|
BinarySensorDeviceClass,
|
||||||
@ -48,6 +48,15 @@ DSL_SENSOR_TYPES: tuple[SFRBoxBinarySensorEntityDescription[DslInfo], ...] = (
|
|||||||
value_fn=lambda x: x.status == "up",
|
value_fn=lambda x: x.status == "up",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
WAN_SENSOR_TYPES: tuple[SFRBoxBinarySensorEntityDescription[WanInfo], ...] = (
|
||||||
|
SFRBoxBinarySensorEntityDescription[WanInfo](
|
||||||
|
key="status",
|
||||||
|
name="WAN status",
|
||||||
|
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
value_fn=lambda x: x.status == "up",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -56,10 +65,15 @@ async def async_setup_entry(
|
|||||||
"""Set up the sensors."""
|
"""Set up the sensors."""
|
||||||
data: DomainData = hass.data[DOMAIN][entry.entry_id]
|
data: DomainData = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
|
||||||
entities = [
|
entities: list[SFRBoxBinarySensor] = [
|
||||||
SFRBoxBinarySensor(data.dsl, description, data.system.data)
|
SFRBoxBinarySensor(data.wan, description, data.system.data)
|
||||||
for description in DSL_SENSOR_TYPES
|
for description in WAN_SENSOR_TYPES
|
||||||
]
|
]
|
||||||
|
if data.system.data.net_infra == "adsl":
|
||||||
|
entities.extend(
|
||||||
|
SFRBoxBinarySensor(data.dsl, description, data.system.data)
|
||||||
|
for description in DSL_SENSOR_TYPES
|
||||||
|
)
|
||||||
|
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .models import DomainData
|
from .models import DomainData
|
||||||
|
|
||||||
TO_REDACT = {"mac_addr", "serial_number"}
|
TO_REDACT = {"mac_addr", "serial_number", "ip_addr", "ipv6_addr"}
|
||||||
|
|
||||||
|
|
||||||
async def async_get_config_entry_diagnostics(
|
async def async_get_config_entry_diagnostics(
|
||||||
@ -33,8 +33,6 @@ async def async_get_config_entry_diagnostics(
|
|||||||
"system": async_redact_data(
|
"system": async_redact_data(
|
||||||
dataclasses.asdict(data.system.data), TO_REDACT
|
dataclasses.asdict(data.system.data), TO_REDACT
|
||||||
),
|
),
|
||||||
"wan": async_redact_data(
|
"wan": async_redact_data(dataclasses.asdict(data.wan.data), TO_REDACT),
|
||||||
dataclasses.asdict(await data.system.box.wan_get_info()), TO_REDACT
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from sfrbox_api.bridge import SFRBox
|
from sfrbox_api.bridge import SFRBox
|
||||||
from sfrbox_api.models import DslInfo, SystemInfo
|
from sfrbox_api.models import DslInfo, SystemInfo, WanInfo
|
||||||
|
|
||||||
from .coordinator import SFRDataUpdateCoordinator
|
from .coordinator import SFRDataUpdateCoordinator
|
||||||
|
|
||||||
@ -14,3 +14,4 @@ class DomainData:
|
|||||||
box: SFRBox
|
box: SFRBox
|
||||||
dsl: SFRDataUpdateCoordinator[DslInfo]
|
dsl: SFRDataUpdateCoordinator[DslInfo]
|
||||||
system: SFRDataUpdateCoordinator[SystemInfo]
|
system: SFRDataUpdateCoordinator[SystemInfo]
|
||||||
|
wan: SFRDataUpdateCoordinator[WanInfo]
|
||||||
|
@ -3,7 +3,7 @@ from collections.abc import Callable
|
|||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Generic, TypeVar
|
from typing import Generic, TypeVar
|
||||||
|
|
||||||
from sfrbox_api.models import DslInfo, SystemInfo
|
from sfrbox_api.models import DslInfo, SystemInfo, WanInfo
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
@ -195,6 +195,24 @@ SYSTEM_SENSOR_TYPES: tuple[SFRBoxSensorEntityDescription[SystemInfo], ...] = (
|
|||||||
value_fn=lambda x: x.temperature / 1000,
|
value_fn=lambda x: x.temperature / 1000,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
WAN_SENSOR_TYPES: tuple[SFRBoxSensorEntityDescription[WanInfo], ...] = (
|
||||||
|
SFRBoxSensorEntityDescription[WanInfo](
|
||||||
|
key="mode",
|
||||||
|
name="WAN mode",
|
||||||
|
device_class=SensorDeviceClass.ENUM,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
options=[
|
||||||
|
"adsl_ppp",
|
||||||
|
"adsl_routed",
|
||||||
|
"ftth_routed",
|
||||||
|
"grps_ppp",
|
||||||
|
"unknown",
|
||||||
|
],
|
||||||
|
translation_key="wan_mode",
|
||||||
|
value_fn=lambda x: x.mode.replace("/", "_"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -207,6 +225,10 @@ async def async_setup_entry(
|
|||||||
SFRBoxSensor(data.system, description, data.system.data)
|
SFRBoxSensor(data.system, description, data.system.data)
|
||||||
for description in SYSTEM_SENSOR_TYPES
|
for description in SYSTEM_SENSOR_TYPES
|
||||||
]
|
]
|
||||||
|
entities.extend(
|
||||||
|
SFRBoxSensor(data.wan, description, data.system.data)
|
||||||
|
for description in WAN_SENSOR_TYPES
|
||||||
|
)
|
||||||
if data.system.data.net_infra == "adsl":
|
if data.system.data.net_infra == "adsl":
|
||||||
entities.extend(
|
entities.extend(
|
||||||
SFRBoxSensor(data.dsl, description, data.system.data)
|
SFRBoxSensor(data.dsl, description, data.system.data)
|
||||||
|
@ -63,6 +63,15 @@
|
|||||||
"showtime": "Showtime",
|
"showtime": "Showtime",
|
||||||
"unknown": "Unknown"
|
"unknown": "Unknown"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"wan_mode": {
|
||||||
|
"state": {
|
||||||
|
"adsl_ppp": "ADSL (PPP)",
|
||||||
|
"adsl_routed": "ADSL (Routed)",
|
||||||
|
"ftth_routed": "FTTH (Routed)",
|
||||||
|
"grps_ppp": "GPRS (PPP)",
|
||||||
|
"unknown": "Unknown"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,34 @@
|
|||||||
# ---
|
# ---
|
||||||
# name: test_binary_sensors.1
|
# name: test_binary_sensors.1
|
||||||
list([
|
list([
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': None,
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': None,
|
||||||
|
'domain': 'binary_sensor',
|
||||||
|
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||||
|
'entity_id': 'binary_sensor.sfr_box_wan_status',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <BinarySensorDeviceClass.CONNECTIVITY: 'connectivity'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'WAN status',
|
||||||
|
'platform': 'sfr_box',
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': None,
|
||||||
|
'unique_id': 'e4:5d:51:00:11:22_wan_status',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
}),
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
}),
|
}),
|
||||||
@ -73,3 +101,16 @@
|
|||||||
'state': 'on',
|
'state': 'on',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_binary_sensors[binary_sensor.sfr_box_wan_status]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'connectivity',
|
||||||
|
'friendly_name': 'SFR Box WAN status',
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'binary_sensor.sfr_box_wan_status',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'on',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
'wan': dict({
|
'wan': dict({
|
||||||
'infra': 'adsl',
|
'infra': 'adsl',
|
||||||
'infra6': '',
|
'infra6': '',
|
||||||
'ip_addr': '1.2.3.4',
|
'ip_addr': '**REDACTED**',
|
||||||
'ipv6_addr': '',
|
'ipv6_addr': '',
|
||||||
'mode': 'adsl/routed',
|
'mode': 'adsl/routed',
|
||||||
'status': 'up',
|
'status': 'up',
|
||||||
|
@ -119,6 +119,42 @@
|
|||||||
'unique_id': 'e4:5d:51:00:11:22_system_temperature',
|
'unique_id': 'e4:5d:51:00:11:22_system_temperature',
|
||||||
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
'unit_of_measurement': <UnitOfTemperature.CELSIUS: '°C'>,
|
||||||
}),
|
}),
|
||||||
|
EntityRegistryEntrySnapshot({
|
||||||
|
'aliases': set({
|
||||||
|
}),
|
||||||
|
'area_id': None,
|
||||||
|
'capabilities': dict({
|
||||||
|
'options': list([
|
||||||
|
'adsl_ppp',
|
||||||
|
'adsl_routed',
|
||||||
|
'ftth_routed',
|
||||||
|
'grps_ppp',
|
||||||
|
'unknown',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'config_entry_id': <ANY>,
|
||||||
|
'device_class': None,
|
||||||
|
'device_id': <ANY>,
|
||||||
|
'disabled_by': <RegistryEntryDisabler.INTEGRATION: 'integration'>,
|
||||||
|
'domain': 'sensor',
|
||||||
|
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||||
|
'entity_id': 'sensor.sfr_box_wan_mode',
|
||||||
|
'has_entity_name': True,
|
||||||
|
'hidden_by': None,
|
||||||
|
'icon': None,
|
||||||
|
'id': <ANY>,
|
||||||
|
'name': None,
|
||||||
|
'options': dict({
|
||||||
|
}),
|
||||||
|
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||||
|
'original_icon': None,
|
||||||
|
'original_name': 'WAN mode',
|
||||||
|
'platform': 'sfr_box',
|
||||||
|
'supported_features': 0,
|
||||||
|
'translation_key': 'wan_mode',
|
||||||
|
'unique_id': 'e4:5d:51:00:11:22_wan_mode',
|
||||||
|
'unit_of_measurement': None,
|
||||||
|
}),
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
}),
|
}),
|
||||||
@ -682,3 +718,23 @@
|
|||||||
'state': '12251',
|
'state': '12251',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
|
# name: test_sensors[sensor.sfr_box_wan_mode]
|
||||||
|
StateSnapshot({
|
||||||
|
'attributes': ReadOnlyDict({
|
||||||
|
'device_class': 'enum',
|
||||||
|
'friendly_name': 'SFR Box WAN mode',
|
||||||
|
'options': list([
|
||||||
|
'adsl_ppp',
|
||||||
|
'adsl_routed',
|
||||||
|
'ftth_routed',
|
||||||
|
'grps_ppp',
|
||||||
|
'unknown',
|
||||||
|
]),
|
||||||
|
}),
|
||||||
|
'context': <ANY>,
|
||||||
|
'entity_id': 'sensor.sfr_box_wan_mode',
|
||||||
|
'last_changed': <ANY>,
|
||||||
|
'last_updated': <ANY>,
|
||||||
|
'state': 'adsl_routed',
|
||||||
|
})
|
||||||
|
# ---
|
||||||
|
@ -10,7 +10,7 @@ from homeassistant.const import Platform
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures("system_get_info", "dsl_get_info")
|
pytestmark = pytest.mark.usefixtures("system_get_info", "dsl_get_info", "wan_get_info")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
@ -13,7 +13,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures("system_get_info", "dsl_get_info")
|
pytestmark = pytest.mark.usefixtures("system_get_info", "dsl_get_info", "wan_get_info")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
@ -17,7 +17,7 @@ def override_platforms() -> Generator[None, None, None]:
|
|||||||
yield
|
yield
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("system_get_info", "dsl_get_info")
|
@pytest.mark.usefixtures("system_get_info", "dsl_get_info", "wan_get_info")
|
||||||
async def test_setup_unload_entry(
|
async def test_setup_unload_entry(
|
||||||
hass: HomeAssistant, config_entry: ConfigEntry
|
hass: HomeAssistant, config_entry: ConfigEntry
|
||||||
) -> None:
|
) -> None:
|
||||||
|
@ -11,7 +11,7 @@ from homeassistant.const import Platform
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||||
|
|
||||||
pytestmark = pytest.mark.usefixtures("system_get_info", "dsl_get_info")
|
pytestmark = pytest.mark.usefixtures("system_get_info", "dsl_get_info", "wan_get_info")
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(autouse=True)
|
@pytest.fixture(autouse=True)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user