diff --git a/homeassistant/components/sfr_box/__init__.py b/homeassistant/components/sfr_box/__init__.py index 4873acf753e..b4014c159ad 100644 --- a/homeassistant/components/sfr_box/__init__.py +++ b/homeassistant/components/sfr_box/__init__.py @@ -1,11 +1,13 @@ """SFR Box.""" from __future__ import annotations +import asyncio + from sfrbox_api.bridge import SFRBox from sfrbox_api.exceptions import SFRBoxAuthenticationError, SFRBoxError 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.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady from homeassistant.helpers import device_registry as dr @@ -37,15 +39,17 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: system=SFRDataUpdateCoordinator( 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() 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": - await data.dsl.async_config_entry_first_refresh() - else: - platforms = list(platforms) - platforms.remove(Platform.BINARY_SENSOR) + tasks.append(data.dsl.async_config_entry_first_refresh()) + await asyncio.gather(*tasks) hass.data.setdefault(DOMAIN, {})[entry.entry_id] = data diff --git a/homeassistant/components/sfr_box/binary_sensor.py b/homeassistant/components/sfr_box/binary_sensor.py index 8b3883c6eee..83c7cd8d106 100644 --- a/homeassistant/components/sfr_box/binary_sensor.py +++ b/homeassistant/components/sfr_box/binary_sensor.py @@ -5,7 +5,7 @@ from collections.abc import Callable from dataclasses import dataclass 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 ( BinarySensorDeviceClass, @@ -48,6 +48,15 @@ DSL_SENSOR_TYPES: tuple[SFRBoxBinarySensorEntityDescription[DslInfo], ...] = ( 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( @@ -56,10 +65,15 @@ async def async_setup_entry( """Set up the sensors.""" data: DomainData = hass.data[DOMAIN][entry.entry_id] - entities = [ - SFRBoxBinarySensor(data.dsl, description, data.system.data) - for description in DSL_SENSOR_TYPES + entities: list[SFRBoxBinarySensor] = [ + SFRBoxBinarySensor(data.wan, description, data.system.data) + 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) diff --git a/homeassistant/components/sfr_box/diagnostics.py b/homeassistant/components/sfr_box/diagnostics.py index 60df2173968..e85bd602b71 100644 --- a/homeassistant/components/sfr_box/diagnostics.py +++ b/homeassistant/components/sfr_box/diagnostics.py @@ -11,7 +11,7 @@ from homeassistant.core import HomeAssistant from .const import DOMAIN 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( @@ -33,8 +33,6 @@ async def async_get_config_entry_diagnostics( "system": async_redact_data( dataclasses.asdict(data.system.data), TO_REDACT ), - "wan": async_redact_data( - dataclasses.asdict(await data.system.box.wan_get_info()), TO_REDACT - ), + "wan": async_redact_data(dataclasses.asdict(data.wan.data), TO_REDACT), }, } diff --git a/homeassistant/components/sfr_box/models.py b/homeassistant/components/sfr_box/models.py index e2f86aeb924..9302de83e77 100644 --- a/homeassistant/components/sfr_box/models.py +++ b/homeassistant/components/sfr_box/models.py @@ -2,7 +2,7 @@ from dataclasses import dataclass 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 @@ -14,3 +14,4 @@ class DomainData: box: SFRBox dsl: SFRDataUpdateCoordinator[DslInfo] system: SFRDataUpdateCoordinator[SystemInfo] + wan: SFRDataUpdateCoordinator[WanInfo] diff --git a/homeassistant/components/sfr_box/sensor.py b/homeassistant/components/sfr_box/sensor.py index 48d1c16d0ff..d276d308214 100644 --- a/homeassistant/components/sfr_box/sensor.py +++ b/homeassistant/components/sfr_box/sensor.py @@ -3,7 +3,7 @@ from collections.abc import Callable from dataclasses import dataclass 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 ( SensorDeviceClass, @@ -195,6 +195,24 @@ SYSTEM_SENSOR_TYPES: tuple[SFRBoxSensorEntityDescription[SystemInfo], ...] = ( 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( @@ -207,6 +225,10 @@ async def async_setup_entry( SFRBoxSensor(data.system, description, data.system.data) 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": entities.extend( SFRBoxSensor(data.dsl, description, data.system.data) diff --git a/homeassistant/components/sfr_box/strings.json b/homeassistant/components/sfr_box/strings.json index ddff342a10d..2141abad872 100644 --- a/homeassistant/components/sfr_box/strings.json +++ b/homeassistant/components/sfr_box/strings.json @@ -63,6 +63,15 @@ "showtime": "Showtime", "unknown": "Unknown" } + }, + "wan_mode": { + "state": { + "adsl_ppp": "ADSL (PPP)", + "adsl_routed": "ADSL (Routed)", + "ftth_routed": "FTTH (Routed)", + "grps_ppp": "GPRS (PPP)", + "unknown": "Unknown" + } } } } diff --git a/tests/components/sfr_box/snapshots/test_binary_sensor.ambr b/tests/components/sfr_box/snapshots/test_binary_sensor.ambr index c3442c08e24..a932a3beae3 100644 --- a/tests/components/sfr_box/snapshots/test_binary_sensor.ambr +++ b/tests/components/sfr_box/snapshots/test_binary_sensor.ambr @@ -30,6 +30,34 @@ # --- # name: test_binary_sensors.1 list([ + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.sfr_box_wan_status', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + '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({ 'aliases': set({ }), @@ -73,3 +101,16 @@ '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': , + 'entity_id': 'binary_sensor.sfr_box_wan_status', + 'last_changed': , + 'last_updated': , + 'state': 'on', + }) +# --- diff --git a/tests/components/sfr_box/snapshots/test_diagnostics.ambr b/tests/components/sfr_box/snapshots/test_diagnostics.ambr index 2e25259268d..fe9268358f9 100644 --- a/tests/components/sfr_box/snapshots/test_diagnostics.ambr +++ b/tests/components/sfr_box/snapshots/test_diagnostics.ambr @@ -41,7 +41,7 @@ 'wan': dict({ 'infra': 'adsl', 'infra6': '', - 'ip_addr': '1.2.3.4', + 'ip_addr': '**REDACTED**', 'ipv6_addr': '', 'mode': 'adsl/routed', 'status': 'up', diff --git a/tests/components/sfr_box/snapshots/test_sensor.ambr b/tests/components/sfr_box/snapshots/test_sensor.ambr index a5788a1d6c5..82e5f3aa15f 100644 --- a/tests/components/sfr_box/snapshots/test_sensor.ambr +++ b/tests/components/sfr_box/snapshots/test_sensor.ambr @@ -119,6 +119,42 @@ 'unique_id': 'e4:5d:51:00:11:22_system_temperature', 'unit_of_measurement': , }), + EntityRegistryEntrySnapshot({ + 'aliases': set({ + }), + 'area_id': None, + 'capabilities': dict({ + 'options': list([ + 'adsl_ppp', + 'adsl_routed', + 'ftth_routed', + 'grps_ppp', + 'unknown', + ]), + }), + 'config_entry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': , + 'domain': 'sensor', + 'entity_category': , + 'entity_id': 'sensor.sfr_box_wan_mode', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'name': None, + 'options': dict({ + }), + 'original_device_class': , + '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({ 'aliases': set({ }), @@ -682,3 +718,23 @@ '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': , + 'entity_id': 'sensor.sfr_box_wan_mode', + 'last_changed': , + 'last_updated': , + 'state': 'adsl_routed', + }) +# --- diff --git a/tests/components/sfr_box/test_binary_sensor.py b/tests/components/sfr_box/test_binary_sensor.py index 03e0677713b..c7a643a9168 100644 --- a/tests/components/sfr_box/test_binary_sensor.py +++ b/tests/components/sfr_box/test_binary_sensor.py @@ -10,7 +10,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant 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) diff --git a/tests/components/sfr_box/test_button.py b/tests/components/sfr_box/test_button.py index d1bb06fc79c..202593e4825 100644 --- a/tests/components/sfr_box/test_button.py +++ b/tests/components/sfr_box/test_button.py @@ -13,7 +13,7 @@ from homeassistant.core import HomeAssistant from homeassistant.exceptions import HomeAssistantError 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) diff --git a/tests/components/sfr_box/test_init.py b/tests/components/sfr_box/test_init.py index 3a740753b21..df4d1242e02 100644 --- a/tests/components/sfr_box/test_init.py +++ b/tests/components/sfr_box/test_init.py @@ -17,7 +17,7 @@ def override_platforms() -> Generator[None, None, None]: 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( hass: HomeAssistant, config_entry: ConfigEntry ) -> None: diff --git a/tests/components/sfr_box/test_sensor.py b/tests/components/sfr_box/test_sensor.py index 4e2c9e33a74..ff84defb832 100644 --- a/tests/components/sfr_box/test_sensor.py +++ b/tests/components/sfr_box/test_sensor.py @@ -11,7 +11,7 @@ from homeassistant.const import Platform from homeassistant.core import HomeAssistant 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)