diff --git a/homeassistant/components/freebox/router.py b/homeassistant/components/freebox/router.py index efa96eca5a7..753bdff8cec 100644 --- a/homeassistant/components/freebox/router.py +++ b/homeassistant/components/freebox/router.py @@ -72,7 +72,11 @@ async def get_hosts_list_if_supported( supports_hosts: bool = True fbx_devices: list[dict[str, Any]] = [] try: - fbx_devices = await fbx_api.lan.get_hosts_list() or [] + fbx_interfaces = await fbx_api.lan.get_interfaces() or [] + for interface in fbx_interfaces: + fbx_devices.extend( + await fbx_api.lan.get_hosts_list(interface["name"]) or [] + ) except HttpRequestError as err: if ( (matcher := re.search(r"Request failed \(APIResponse: (.+)\)", str(err))) diff --git a/tests/components/freebox/conftest.py b/tests/components/freebox/conftest.py index e6adae572f3..abf0153fede 100644 --- a/tests/components/freebox/conftest.py +++ b/tests/components/freebox/conftest.py @@ -16,7 +16,9 @@ from .const import ( DATA_HOME_PIR_GET_VALUE, DATA_HOME_SET_VALUE, DATA_LAN_GET_HOSTS_LIST, + DATA_LAN_GET_HOSTS_LIST_GUEST, DATA_LAN_GET_HOSTS_LIST_MODE_BRIDGE, + DATA_LAN_GET_INTERFACES, DATA_STORAGE_GET_DISKS, DATA_STORAGE_GET_RAIDS, DATA_SYSTEM_GET_CONFIG, @@ -68,7 +70,12 @@ def mock_router(mock_device_registry_devices): instance.open = AsyncMock() instance.system.get_config = AsyncMock(return_value=DATA_SYSTEM_GET_CONFIG) # device_tracker - instance.lan.get_hosts_list = AsyncMock(return_value=DATA_LAN_GET_HOSTS_LIST) + instance.lan.get_interfaces = AsyncMock(return_value=DATA_LAN_GET_INTERFACES) + instance.lan.get_hosts_list = AsyncMock( + side_effect=lambda interface: DATA_LAN_GET_HOSTS_LIST + if interface == "pub" + else DATA_LAN_GET_HOSTS_LIST_GUEST + ) # sensor instance.call.get_calls_log = AsyncMock(return_value=DATA_CALL_GET_CALLS_LOG) instance.storage.get_disks = AsyncMock(return_value=DATA_STORAGE_GET_DISKS) @@ -96,6 +103,12 @@ def mock_router(mock_device_registry_devices): def mock_router_bridge_mode(mock_device_registry_devices, router): """Mock a successful connection to Freebox Bridge mode.""" + router().lan.get_interfaces = AsyncMock( + side_effect=HttpRequestError( + f"Request failed (APIResponse: {json.dumps(DATA_LAN_GET_HOSTS_LIST_MODE_BRIDGE)})" + ) + ) + router().lan.get_hosts_list = AsyncMock( side_effect=HttpRequestError( f"Request failed (APIResponse: {json.dumps(DATA_LAN_GET_HOSTS_LIST_MODE_BRIDGE)})" diff --git a/tests/components/freebox/const.py b/tests/components/freebox/const.py index 5211b793918..47dfac636a7 100644 --- a/tests/components/freebox/const.py +++ b/tests/components/freebox/const.py @@ -25,7 +25,11 @@ DATA_WIFI_GET_GLOBAL_CONFIG = load_json_object_fixture( ) # device_tracker +DATA_LAN_GET_INTERFACES = load_json_array_fixture("freebox/lan_get_interfaces.json") DATA_LAN_GET_HOSTS_LIST = load_json_array_fixture("freebox/lan_get_hosts_list.json") +DATA_LAN_GET_HOSTS_LIST_GUEST = load_json_array_fixture( + "freebox/lan_get_hosts_list_guest.json" +) DATA_LAN_GET_HOSTS_LIST_MODE_BRIDGE = load_json_object_fixture( "freebox/lan_get_hosts_list_bridge.json" ) diff --git a/tests/components/freebox/fixtures/lan_get_hosts_list_guest.json b/tests/components/freebox/fixtures/lan_get_hosts_list_guest.json new file mode 100644 index 00000000000..9e2cdffef0a --- /dev/null +++ b/tests/components/freebox/fixtures/lan_get_hosts_list_guest.json @@ -0,0 +1,81 @@ +[ + { + "l2ident": { + "id": "8C:97:EA:00:00:01", + "type": "mac_address" + }, + "active": true, + "persistent": false, + "names": [ + { + "name": "d633d0c8-958c-42cc-e807-d881b476924b", + "source": "mdns" + }, + { + "name": "Freebox Player POP 2", + "source": "mdns_srv" + } + ], + "vendor_name": "Freebox SAS", + "host_type": "smartphone", + "interface": "pub", + "id": "ether-8c:97:ea:00:00:01", + "last_time_reachable": 1614107662, + "primary_name_manual": false, + "l3connectivities": [ + { + "addr": "192.168.27.181", + "active": true, + "reachable": true, + "last_activity": 1614107614, + "af": "ipv4", + "last_time_reachable": 1614104242 + }, + { + "addr": "fe80::dcef:dbba:6604:31d1", + "active": true, + "reachable": true, + "last_activity": 1614107645, + "af": "ipv6", + "last_time_reachable": 1614107645 + }, + { + "addr": "2a01:e34:eda1:eb40:8102:4704:7ce0:2ace", + "active": false, + "reachable": false, + "last_activity": 1611574428, + "af": "ipv6", + "last_time_reachable": 1611574428 + }, + { + "addr": "2a01:e34:eda1:eb40:c8e5:c524:c96d:5f5e", + "active": false, + "reachable": false, + "last_activity": 1612475101, + "af": "ipv6", + "last_time_reachable": 1612475101 + }, + { + "addr": "2a01:e34:eda1:eb40:583a:49df:1df0:c2df", + "active": true, + "reachable": true, + "last_activity": 1614107652, + "af": "ipv6", + "last_time_reachable": 1614107652 + }, + { + "addr": "2a01:e34:eda1:eb40:147e:3569:86ab:6aaa", + "active": false, + "reachable": false, + "last_activity": 1612486752, + "af": "ipv6", + "last_time_reachable": 1612486752 + } + ], + "default_name": "Freebox Player POP", + "model": "fbx8am", + "reachable": true, + "last_activity": 1614107652, + "primary_name": "Freebox Player POP" + } +] diff --git a/tests/components/freebox/fixtures/lan_get_interfaces.json b/tests/components/freebox/fixtures/lan_get_interfaces.json new file mode 100644 index 00000000000..2646ee38b50 --- /dev/null +++ b/tests/components/freebox/fixtures/lan_get_interfaces.json @@ -0,0 +1,4 @@ +[ + { "name": "pub", "host_count": 4 }, + { "name": "wifiguest", "host_count": 1 } +] diff --git a/tests/components/freebox/test_device_tracker.py b/tests/components/freebox/test_device_tracker.py index 405166d6ba2..f0821daabc3 100644 --- a/tests/components/freebox/test_device_tracker.py +++ b/tests/components/freebox/test_device_tracker.py @@ -21,14 +21,14 @@ async def test_router_mode( """Test get_hosts_list invoqued multiple times if freebox into router mode.""" await setup_platform(hass, DEVICE_TRACKER_DOMAIN) - assert router().lan.get_hosts_list.call_count == 1 + assert router().lan.get_hosts_list.call_count == 2 # Simulate an update freezer.tick(SCAN_INTERVAL) async_fire_time_changed(hass) await hass.async_block_till_done() - assert router().lan.get_hosts_list.call_count == 2 + assert router().lan.get_hosts_list.call_count == 4 async def test_bridge_mode( @@ -36,15 +36,15 @@ async def test_bridge_mode( freezer: FrozenDateTimeFactory, router_bridge_mode: Mock, ) -> None: - """Test get_hosts_list invoqued once if freebox into bridge mode.""" + """Test get_interfaces invoqued once if freebox into bridge mode.""" await setup_platform(hass, DEVICE_TRACKER_DOMAIN) - assert router_bridge_mode().lan.get_hosts_list.call_count == 1 + assert router_bridge_mode().lan.get_interfaces.call_count == 1 # Simulate an update freezer.tick(SCAN_INTERVAL) async_fire_time_changed(hass) await hass.async_block_till_done() - # If get_hosts_list failed, not called again - assert router_bridge_mode().lan.get_hosts_list.call_count == 1 + # If get_interfaces failed, not called again + assert router_bridge_mode().lan.get_interfaces.call_count == 1 diff --git a/tests/components/freebox/test_router.py b/tests/components/freebox/test_router.py index 623f595e1ad..3d98abf71a2 100644 --- a/tests/components/freebox/test_router.py +++ b/tests/components/freebox/test_router.py @@ -35,7 +35,10 @@ async def test_get_hosts_list_if_supported( assert supports_hosts is True # List must not be empty; but it's content depends on how many unit tests are executed... assert fbx_devices + # We expect 4 devices from lan_get_hosts_list.json and 1 from lan_get_hosts_list_guest.json + assert len(fbx_devices) == 5 assert "d633d0c8-958c-43cc-e807-d881b076924b" in str(fbx_devices) + assert "d633d0c8-958c-42cc-e807-d881b476924b" in str(fbx_devices) async def test_get_hosts_list_if_supported_bridge(