Fix UniFi device tracker on controllers only reporting events (#72240)
Add events to UniFi client tracker in case controller does not report proper datapull/72435/head
parent
1113d9bea9
commit
dc0d065901
|
@ -3,7 +3,7 @@
|
|||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
from aiounifi.api import SOURCE_DATA
|
||||
from aiounifi.api import SOURCE_DATA, SOURCE_EVENT
|
||||
from aiounifi.events import (
|
||||
ACCESS_POINT_UPGRADED,
|
||||
GATEWAY_UPGRADED,
|
||||
|
@ -156,6 +156,8 @@ class UniFiClientTracker(UniFiClient, ScannerEntity):
|
|||
|
||||
self._controller_connection_state_changed = False
|
||||
|
||||
self._only_listen_to_data_source = False
|
||||
|
||||
last_seen = client.last_seen or 0
|
||||
self.schedule_update = self._is_connected = (
|
||||
self.is_wired == client.is_wired
|
||||
|
@ -224,6 +226,23 @@ class UniFiClientTracker(UniFiClient, ScannerEntity):
|
|||
):
|
||||
self._is_connected = True
|
||||
self.schedule_update = True
|
||||
self._only_listen_to_data_source = True
|
||||
|
||||
elif (
|
||||
self.client.last_updated == SOURCE_EVENT
|
||||
and not self._only_listen_to_data_source
|
||||
):
|
||||
|
||||
if (self.is_wired and self.client.event.event in WIRED_CONNECTION) or (
|
||||
not self.is_wired and self.client.event.event in WIRELESS_CONNECTION
|
||||
):
|
||||
self._is_connected = True
|
||||
self.schedule_update = False
|
||||
self.controller.async_heartbeat(self.unique_id)
|
||||
super().async_update_callback()
|
||||
|
||||
else:
|
||||
self.schedule_update = True
|
||||
|
||||
self._async_log_debug_data("update_callback")
|
||||
|
||||
|
|
|
@ -3,7 +3,12 @@
|
|||
from datetime import timedelta
|
||||
from unittest.mock import patch
|
||||
|
||||
from aiounifi.controller import MESSAGE_CLIENT, MESSAGE_CLIENT_REMOVED, MESSAGE_DEVICE
|
||||
from aiounifi.controller import (
|
||||
MESSAGE_CLIENT,
|
||||
MESSAGE_CLIENT_REMOVED,
|
||||
MESSAGE_DEVICE,
|
||||
MESSAGE_EVENT,
|
||||
)
|
||||
from aiounifi.websocket import STATE_DISCONNECTED, STATE_RUNNING
|
||||
|
||||
from homeassistant import config_entries
|
||||
|
@ -169,6 +174,140 @@ async def test_tracked_clients(
|
|||
assert hass.states.get("device_tracker.client_1").state == STATE_HOME
|
||||
|
||||
|
||||
async def test_tracked_wireless_clients_event_source(
|
||||
hass, aioclient_mock, mock_unifi_websocket, mock_device_registry
|
||||
):
|
||||
"""Verify tracking of wireless clients based on event source."""
|
||||
client = {
|
||||
"ap_mac": "00:00:00:00:02:01",
|
||||
"essid": "ssid",
|
||||
"hostname": "client",
|
||||
"ip": "10.0.0.1",
|
||||
"is_wired": False,
|
||||
"last_seen": 1562600145,
|
||||
"mac": "00:00:00:00:00:01",
|
||||
}
|
||||
config_entry = await setup_unifi_integration(
|
||||
hass, aioclient_mock, clients_response=[client]
|
||||
)
|
||||
controller = hass.data[UNIFI_DOMAIN][config_entry.entry_id]
|
||||
assert len(hass.states.async_entity_ids(TRACKER_DOMAIN)) == 1
|
||||
assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
|
||||
|
||||
# State change signalling works with events
|
||||
|
||||
# Connected event
|
||||
|
||||
event = {
|
||||
"user": client["mac"],
|
||||
"ssid": client["essid"],
|
||||
"ap": client["ap_mac"],
|
||||
"radio": "na",
|
||||
"channel": "44",
|
||||
"hostname": client["hostname"],
|
||||
"key": "EVT_WU_Connected",
|
||||
"subsystem": "wlan",
|
||||
"site_id": "name",
|
||||
"time": 1587753456179,
|
||||
"datetime": "2020-04-24T18:37:36Z",
|
||||
"msg": f'User{[client["mac"]]} has connected to AP[{client["ap_mac"]}] with SSID "{client["essid"]}" on "channel 44(na)"',
|
||||
"_id": "5ea331fa30c49e00f90ddc1a",
|
||||
}
|
||||
mock_unifi_websocket(
|
||||
data={
|
||||
"meta": {"message": MESSAGE_EVENT},
|
||||
"data": [event],
|
||||
}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("device_tracker.client").state == STATE_HOME
|
||||
|
||||
# Disconnected event
|
||||
|
||||
event = {
|
||||
"user": client["mac"],
|
||||
"ssid": client["essid"],
|
||||
"hostname": client["hostname"],
|
||||
"ap": client["ap_mac"],
|
||||
"duration": 467,
|
||||
"bytes": 459039,
|
||||
"key": "EVT_WU_Disconnected",
|
||||
"subsystem": "wlan",
|
||||
"site_id": "name",
|
||||
"time": 1587752927000,
|
||||
"datetime": "2020-04-24T18:28:47Z",
|
||||
"msg": f'User{[client["mac"]]} disconnected from "{client["essid"]}" (7m 47s connected, 448.28K bytes, last AP[{client["ap_mac"]}])',
|
||||
"_id": "5ea32ff730c49e00f90dca1a",
|
||||
}
|
||||
mock_unifi_websocket(
|
||||
data={
|
||||
"meta": {"message": MESSAGE_EVENT},
|
||||
"data": [event],
|
||||
}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("device_tracker.client").state == STATE_HOME
|
||||
|
||||
# Change time to mark client as away
|
||||
new_time = dt_util.utcnow() + controller.option_detection_time
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=new_time):
|
||||
async_fire_time_changed(hass, new_time)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("device_tracker.client").state == STATE_NOT_HOME
|
||||
|
||||
# To limit false positives in client tracker
|
||||
# data sources are prioritized when available
|
||||
# once real data is received events will be ignored.
|
||||
|
||||
# New data
|
||||
|
||||
mock_unifi_websocket(
|
||||
data={
|
||||
"meta": {"message": MESSAGE_CLIENT},
|
||||
"data": [client],
|
||||
}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("device_tracker.client").state == STATE_HOME
|
||||
|
||||
# Disconnection event will be ignored
|
||||
|
||||
event = {
|
||||
"user": client["mac"],
|
||||
"ssid": client["essid"],
|
||||
"hostname": client["hostname"],
|
||||
"ap": client["ap_mac"],
|
||||
"duration": 467,
|
||||
"bytes": 459039,
|
||||
"key": "EVT_WU_Disconnected",
|
||||
"subsystem": "wlan",
|
||||
"site_id": "name",
|
||||
"time": 1587752927000,
|
||||
"datetime": "2020-04-24T18:28:47Z",
|
||||
"msg": f'User{[client["mac"]]} disconnected from "{client["essid"]}" (7m 47s connected, 448.28K bytes, last AP[{client["ap_mac"]}])',
|
||||
"_id": "5ea32ff730c49e00f90dca1a",
|
||||
}
|
||||
mock_unifi_websocket(
|
||||
data={
|
||||
"meta": {"message": MESSAGE_EVENT},
|
||||
"data": [event],
|
||||
}
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert hass.states.get("device_tracker.client").state == STATE_HOME
|
||||
|
||||
# Change time to mark client as away
|
||||
new_time = dt_util.utcnow() + controller.option_detection_time
|
||||
with patch("homeassistant.util.dt.utcnow", return_value=new_time):
|
||||
async_fire_time_changed(hass, new_time)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get("device_tracker.client").state == STATE_HOME
|
||||
|
||||
|
||||
async def test_tracked_devices(
|
||||
hass, aioclient_mock, mock_unifi_websocket, mock_device_registry
|
||||
):
|
||||
|
|
Loading…
Reference in New Issue