Fix device tracker of freebox component to get devices from all interfaces (#142668)

This commit is contained in:
turakamou 2025-04-23 12:14:37 +02:00 committed by GitHub
parent b785d5297a
commit beab4e0d7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 117 additions and 8 deletions

View File

@ -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)))

View File

@ -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)})"

View File

@ -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"
)

View File

@ -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"
}
]

View File

@ -0,0 +1,4 @@
[
{ "name": "pub", "host_count": 4 },
{ "name": "wifiguest", "host_count": 1 }
]

View File

@ -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

View File

@ -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(