Use the Last Seen attribute in unify (#8998)

* Uses the Last Seen attribute in unify

* Update unifi.py

fix format

* Update unifi.py

formatting again

* update test_unifi to call CONF_CONSIDER_HOME

Updated.

* Update test_unifi.py

* Update test_unifi.py

* More unit test test

* Update where consider_home comes from.

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update test_unifi.py

* fix hound

* Update test_unifi.py

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update test_unifi.py

* Update unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update unifi.py

* Update unifi.py

* Update test_unifi.py

Fix the butcher of tests.

* Update unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update test_unifi.py

* Update unifi.py

* Update test_unifi.py

* Update unifi.py

* Update unifi.py

* Update unifi.py

* Update unifi.py
This commit is contained in:
rbflurry 2017-10-13 04:13:58 -04:00 committed by Pascal Vizeli
parent f7545fe85c
commit b00d0a1253
2 changed files with 44 additions and 19 deletions

View file

@ -5,6 +5,7 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.unifi/ https://home-assistant.io/components/device_tracker.unifi/
""" """
import logging import logging
from datetime import timedelta
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -12,16 +13,19 @@ from homeassistant.components.device_tracker import (
DOMAIN, PLATFORM_SCHEMA, DeviceScanner) DOMAIN, PLATFORM_SCHEMA, DeviceScanner)
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
from homeassistant.const import CONF_VERIFY_SSL from homeassistant.const import CONF_VERIFY_SSL
import homeassistant.util.dt as dt_util
REQUIREMENTS = ['pyunifi==2.13'] REQUIREMENTS = ['pyunifi==2.13']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
CONF_PORT = 'port' CONF_PORT = 'port'
CONF_SITE_ID = 'site_id' CONF_SITE_ID = 'site_id'
CONF_DETECTION_TIME = 'detection_time'
DEFAULT_HOST = 'localhost' DEFAULT_HOST = 'localhost'
DEFAULT_PORT = 8443 DEFAULT_PORT = 8443
DEFAULT_VERIFY_SSL = True DEFAULT_VERIFY_SSL = True
DEFAULT_DETECTION_TIME = timedelta(seconds=300)
NOTIFICATION_ID = 'unifi_notification' NOTIFICATION_ID = 'unifi_notification'
NOTIFICATION_TITLE = 'Unifi Device Tracker Setup' NOTIFICATION_TITLE = 'Unifi Device Tracker Setup'
@ -33,7 +37,9 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_USERNAME): cv.string, vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PORT, default=DEFAULT_PORT): cv.port, vol.Required(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): vol.Any( vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): vol.Any(
cv.boolean, cv.isfile) cv.boolean, cv.isfile),
vol.Optional(CONF_DETECTION_TIME, default=DEFAULT_DETECTION_TIME): vol.All(
cv.time_period, cv.positive_timedelta)
}) })
@ -47,6 +53,7 @@ def get_scanner(hass, config):
site_id = config[DOMAIN].get(CONF_SITE_ID) site_id = config[DOMAIN].get(CONF_SITE_ID)
port = config[DOMAIN].get(CONF_PORT) port = config[DOMAIN].get(CONF_PORT)
verify_ssl = config[DOMAIN].get(CONF_VERIFY_SSL) verify_ssl = config[DOMAIN].get(CONF_VERIFY_SSL)
detection_time = config[DOMAIN].get(CONF_DETECTION_TIME)
try: try:
ctrl = Controller(host, username, password, port, version='v4', ctrl = Controller(host, username, password, port, version='v4',
@ -62,14 +69,15 @@ def get_scanner(hass, config):
notification_id=NOTIFICATION_ID) notification_id=NOTIFICATION_ID)
return False return False
return UnifiScanner(ctrl) return UnifiScanner(ctrl, detection_time)
class UnifiScanner(DeviceScanner): class UnifiScanner(DeviceScanner):
"""Provide device_tracker support from Unifi WAP client data.""" """Provide device_tracker support from Unifi WAP client data."""
def __init__(self, controller): def __init__(self, controller, detection_time: timedelta):
"""Initialize the scanner.""" """Initialize the scanner."""
self._detection_time = detection_time
self._controller = controller self._controller = controller
self._update() self._update()
@ -82,7 +90,11 @@ class UnifiScanner(DeviceScanner):
_LOGGER.error("Failed to scan clients: %s", ex) _LOGGER.error("Failed to scan clients: %s", ex)
clients = [] clients = []
self._clients = {client['mac']: client for client in clients} self._clients = {
client['mac']: client
for client in clients
if (dt_util.utcnow() - dt_util.utc_from_timestamp(float(
client['last_seen']))) < self._detection_time}
def scan_devices(self): def scan_devices(self):
"""Scan for devices.""" """Scan for devices."""
@ -97,5 +109,5 @@ class UnifiScanner(DeviceScanner):
""" """
client = self._clients.get(mac, {}) client = self._clients.get(mac, {})
name = client.get('name') or client.get('hostname') name = client.get('name') or client.get('hostname')
_LOGGER.debug("Device %s name %s", mac, name) _LOGGER.debug("Device mac %s name %s", mac, name)
return name return name

View file

@ -1,6 +1,9 @@
"""The tests for the Unifi WAP device tracker platform.""" """The tests for the Unifi WAP device tracker platform."""
from unittest import mock from unittest import mock
from pyunifi.controller import APIError from pyunifi.controller import APIError
import homeassistant.util.dt as dt_util
from datetime import timedelta
import pytest import pytest
import voluptuous as vol import voluptuous as vol
@ -8,6 +11,7 @@ import voluptuous as vol
from homeassistant.components.device_tracker import DOMAIN, unifi as unifi from homeassistant.components.device_tracker import DOMAIN, unifi as unifi
from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD, from homeassistant.const import (CONF_HOST, CONF_USERNAME, CONF_PASSWORD,
CONF_PLATFORM, CONF_VERIFY_SSL) CONF_PLATFORM, CONF_VERIFY_SSL)
DEFAULT_DETECTION_TIME = timedelta(seconds=300)
@pytest.fixture @pytest.fixture
@ -48,7 +52,8 @@ def test_config_valid_verify_ssl(hass, mock_scanner, mock_ctrl):
version='v4', site_id='default', ssl_verify="/tmp/unifi.crt") version='v4', site_id='default', ssl_verify="/tmp/unifi.crt")
assert mock_scanner.call_count == 1 assert mock_scanner.call_count == 1
assert mock_scanner.call_args == mock.call(mock_ctrl.return_value) assert mock_scanner.call_args == mock.call(mock_ctrl.return_value,
DEFAULT_DETECTION_TIME)
def test_config_minimal(hass, mock_scanner, mock_ctrl): def test_config_minimal(hass, mock_scanner, mock_ctrl):
@ -68,7 +73,8 @@ def test_config_minimal(hass, mock_scanner, mock_ctrl):
version='v4', site_id='default', ssl_verify=True) version='v4', site_id='default', ssl_verify=True)
assert mock_scanner.call_count == 1 assert mock_scanner.call_count == 1
assert mock_scanner.call_args == mock.call(mock_ctrl.return_value) assert mock_scanner.call_args == mock.call(mock_ctrl.return_value,
DEFAULT_DETECTION_TIME)
def test_config_full(hass, mock_scanner, mock_ctrl): def test_config_full(hass, mock_scanner, mock_ctrl):
@ -82,6 +88,7 @@ def test_config_full(hass, mock_scanner, mock_ctrl):
CONF_VERIFY_SSL: False, CONF_VERIFY_SSL: False,
'port': 123, 'port': 123,
'site_id': 'abcdef01', 'site_id': 'abcdef01',
'detection_time': 300,
}) })
} }
result = unifi.get_scanner(hass, config) result = unifi.get_scanner(hass, config)
@ -92,7 +99,8 @@ def test_config_full(hass, mock_scanner, mock_ctrl):
version='v4', site_id='abcdef01', ssl_verify=False) version='v4', site_id='abcdef01', ssl_verify=False)
assert mock_scanner.call_count == 1 assert mock_scanner.call_count == 1
assert mock_scanner.call_args == mock.call(mock_ctrl.return_value) assert mock_scanner.call_args == mock.call(mock_ctrl.return_value,
DEFAULT_DETECTION_TIME)
def test_config_error(): def test_config_error():
@ -140,11 +148,11 @@ def test_scanner_update():
"""Test the scanner update.""" """Test the scanner update."""
ctrl = mock.MagicMock() ctrl = mock.MagicMock()
fake_clients = [ fake_clients = [
{'mac': '123'}, {'mac': '123', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())},
{'mac': '234'}, {'mac': '234', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())},
] ]
ctrl.get_clients.return_value = fake_clients ctrl.get_clients.return_value = fake_clients
unifi.UnifiScanner(ctrl) unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME)
assert ctrl.get_clients.call_count == 1 assert ctrl.get_clients.call_count == 1
assert ctrl.get_clients.call_args == mock.call() assert ctrl.get_clients.call_args == mock.call()
@ -154,18 +162,18 @@ def test_scanner_update_error():
ctrl = mock.MagicMock() ctrl = mock.MagicMock()
ctrl.get_clients.side_effect = APIError( ctrl.get_clients.side_effect = APIError(
'/', 500, 'foo', {}, None) '/', 500, 'foo', {}, None)
unifi.UnifiScanner(ctrl) unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME)
def test_scan_devices(): def test_scan_devices():
"""Test the scanning for devices.""" """Test the scanning for devices."""
ctrl = mock.MagicMock() ctrl = mock.MagicMock()
fake_clients = [ fake_clients = [
{'mac': '123'}, {'mac': '123', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())},
{'mac': '234'}, {'mac': '234', 'last_seen': dt_util.as_timestamp(dt_util.utcnow())},
] ]
ctrl.get_clients.return_value = fake_clients ctrl.get_clients.return_value = fake_clients
scanner = unifi.UnifiScanner(ctrl) scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME)
assert set(scanner.scan_devices()) == set(['123', '234']) assert set(scanner.scan_devices()) == set(['123', '234'])
@ -173,12 +181,17 @@ def test_get_device_name():
"""Test the getting of device names.""" """Test the getting of device names."""
ctrl = mock.MagicMock() ctrl = mock.MagicMock()
fake_clients = [ fake_clients = [
{'mac': '123', 'hostname': 'foobar'}, {'mac': '123',
{'mac': '234', 'name': 'Nice Name'}, 'hostname': 'foobar',
{'mac': '456'}, 'last_seen': dt_util.as_timestamp(dt_util.utcnow())},
{'mac': '234',
'name': 'Nice Name',
'last_seen': dt_util.as_timestamp(dt_util.utcnow())},
{'mac': '456',
'last_seen': '1504786810'},
] ]
ctrl.get_clients.return_value = fake_clients ctrl.get_clients.return_value = fake_clients
scanner = unifi.UnifiScanner(ctrl) scanner = unifi.UnifiScanner(ctrl, DEFAULT_DETECTION_TIME)
assert scanner.get_device_name('123') == 'foobar' assert scanner.get_device_name('123') == 'foobar'
assert scanner.get_device_name('234') == 'Nice Name' assert scanner.get_device_name('234') == 'Nice Name'
assert scanner.get_device_name('456') is None assert scanner.get_device_name('456') is None