Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Freebox wifiguest devices #112666

Open
wants to merge 2 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion homeassistant/components/freebox/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ 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_devices_pub = await fbx_api.lan.get_hosts_list("pub") or []
fbx_devices_wifiguest = await fbx_api.lan.get_hosts_list("wifiguest") or []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is wifiguest always correct?
Should we set some flag so we know which device trackers are guests?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no way to configure this value on the Freebox OS.
I got wifiguest value in the result of the following API request: GET /api/v4/lan/browser/interfaces/ (source)

Good point for the flag. But I don't know the best design practices for defining this flag in a device tracker.

Copy link
Contributor

@emontnemery emontnemery Jun 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just implement an extra_state_attributes property in the device tracker entity.
The unifi integration actually has an is_guest flag, I'd suggest to use the same here:

CLIENT_CONNECTED_ATTRIBUTES = [
"_is_guest_by_uap",
"ap_mac",
"authorized",
"essid",
"ip",
"is_11r",
"is_guest",
"note",
"qos_policy_applied",
"radio",
"radio_proto",
"vlan",
]
CLIENT_STATIC_ATTRIBUTES = [
"mac",
"name",
"oui",
]
CLIENT_CONNECTED_ALL_ATTRIBUTES = CLIENT_CONNECTED_ATTRIBUTES + CLIENT_STATIC_ATTRIBUTES

@property
def extra_state_attributes(self) -> Mapping[str, Any] | None:
"""Return the client state attributes."""
if self.entity_description.key != "Client device scanner":
return None
client = self.entity_description.object_fn(self.hub.api, self._obj_id)
raw = client.raw
attributes_to_check = CLIENT_STATIC_ATTRIBUTES
if self.is_connected:
attributes_to_check = CLIENT_CONNECTED_ALL_ATTRIBUTES
return {k: raw[k] for k in attributes_to_check if k in raw}

fbx_devices = fbx_devices_pub + fbx_devices_wifiguest
except HttpRequestError as err:
if (
(matcher := re.search(r"Request failed \(APIResponse: (.+)\)", str(err)))
Expand Down
10 changes: 9 additions & 1 deletion tests/components/freebox/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
DATA_HOME_SET_VALUE,
DATA_LAN_GET_HOSTS_LIST,
DATA_LAN_GET_HOSTS_LIST_MODE_BRIDGE,
DATA_LAN_GET_HOSTS_WIFIGUEST_LIST,
DATA_STORAGE_GET_DISKS,
DATA_STORAGE_GET_RAIDS,
DATA_SYSTEM_GET_CONFIG,
Expand Down Expand Up @@ -77,8 +78,15 @@
instance = service_mock.return_value
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)
def get_hosts_list(interface):
if interface == "pub":
return DATA_LAN_GET_HOSTS_LIST
elif interface == "wifiguest":

Check failure on line 86 in tests/components/freebox/conftest.py

View workflow job for this annotation

GitHub Actions / Check ruff

Ruff (RET505)

tests/components/freebox/conftest.py:86:13: RET505 Unnecessary `elif` after `return` statement
return DATA_LAN_GET_HOSTS_WIFIGUEST_LIST

instance.lan.get_hosts_list = AsyncMock(side_effect=get_hosts_list)
# 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)
Expand Down
3 changes: 3 additions & 0 deletions tests/components/freebox/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@

# device_tracker
DATA_LAN_GET_HOSTS_LIST = load_json_array_fixture("freebox/lan_get_hosts_list.json")
DATA_LAN_GET_HOSTS_WIFIGUEST_LIST = load_json_array_fixture(
"freebox/lan_get_hosts_wifiguest_list.json"
)
DATA_LAN_GET_HOSTS_LIST_MODE_BRIDGE = load_json_object_fixture(
"freebox/lan_get_hosts_list_bridge.json"
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[
{
"l2ident": {
"id": "d0:23:db:36:15:aa",
"type": "mac_address"
},
"active": true,
"id": "ether-d0:23:db:36:15:aa",
"last_time_reachable": 1360669498,
"persistent": true,
"names": [
{
"name": "iPhone-r0ro",
"source": "dhcp"
}
],
"vendor_name": "Apple, Inc.",
"host_type": "smartphone",
"interface": "wifiguest",
"l3connectivities": [
{
"addr": "192.168.69.20",
"active": true,
"af": "ipv4",
"reachable": true,
"last_activity": 1360669498,
"last_time_reachable": 1360669498
}
],
"reachable": true,
"last_activity": 1360669498,
"primary_name_manual": true,
"primary_name": "iPhone r0ro"
}
]
4 changes: 2 additions & 2 deletions tests/components/freebox/test_device_tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions tests/components/freebox/test_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ 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
assert len(fbx_devices) == 5
assert "d633d0c8-958c-43cc-e807-d881b076924b" in str(fbx_devices)
assert "iPhone-r0ro" in str(fbx_devices)


async def test_get_hosts_list_if_supported_bridge(
Expand Down
Loading