Add device tracker support for EE Brightbox 2 router (#19611)
* Added device tracker support for EE Brightbox 2 * removed timeago dependency * get scanner checks and improved tests * fixed lint issues * removed redundant timeago from test requirements * fixed variable naming in test * removed unecessary blank line
This commit is contained in:
parent
5a30b0507d
commit
a8ef7a2774
5 changed files with 236 additions and 0 deletions
107
homeassistant/components/device_tracker/ee_brightbox.py
Normal file
107
homeassistant/components/device_tracker/ee_brightbox.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
"""
|
||||
Support for EE Brightbox router.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/device_tracker.ee_brightbox/
|
||||
"""
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.device_tracker import (
|
||||
DOMAIN, PLATFORM_SCHEMA, DeviceScanner)
|
||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
REQUIREMENTS = ['eebrightbox==0.0.4']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_VERSION = 'version'
|
||||
|
||||
CONF_DEFAULT_IP = '192.168.1.1'
|
||||
CONF_DEFAULT_USERNAME = 'admin'
|
||||
CONF_DEFAULT_VERSION = 2
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_VERSION, default=CONF_DEFAULT_VERSION): cv.positive_int,
|
||||
vol.Required(CONF_HOST, default=CONF_DEFAULT_IP): cv.string,
|
||||
vol.Required(CONF_USERNAME, default=CONF_DEFAULT_USERNAME): cv.string,
|
||||
vol.Required(CONF_PASSWORD): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def get_scanner(hass, config):
|
||||
"""Return a router scanner instance."""
|
||||
scanner = EEBrightBoxScanner(config[DOMAIN])
|
||||
|
||||
return scanner if scanner.check_config() else None
|
||||
|
||||
|
||||
class EEBrightBoxScanner(DeviceScanner):
|
||||
"""Scan EE Brightbox router."""
|
||||
|
||||
def __init__(self, config):
|
||||
"""Initialise the scanner."""
|
||||
self.config = config
|
||||
self.devices = {}
|
||||
|
||||
def check_config(self):
|
||||
"""Check if provided configuration and credentials are correct."""
|
||||
from eebrightbox import EEBrightBox, EEBrightBoxException
|
||||
|
||||
try:
|
||||
with EEBrightBox(self.config) as ee_brightbox:
|
||||
return bool(ee_brightbox.get_devices())
|
||||
except EEBrightBoxException:
|
||||
_LOGGER.exception("Failed to connect to the router")
|
||||
return False
|
||||
|
||||
def scan_devices(self):
|
||||
"""Scan for devices."""
|
||||
from eebrightbox import EEBrightBox
|
||||
|
||||
with EEBrightBox(self.config) as ee_brightbox:
|
||||
self.devices = {d['mac']: d for d in ee_brightbox.get_devices()}
|
||||
|
||||
macs = [d['mac'] for d in self.devices.values() if d['activity_ip']]
|
||||
|
||||
_LOGGER.debug('Scan devices %s', macs)
|
||||
|
||||
return macs
|
||||
|
||||
def get_device_name(self, device):
|
||||
"""Get the name of a device from hostname."""
|
||||
if device in self.devices:
|
||||
return self.devices[device]['hostname'] or None
|
||||
|
||||
return None
|
||||
|
||||
def get_extra_attributes(self, device):
|
||||
"""
|
||||
Get the extra attributes of a device.
|
||||
|
||||
Extra attributes include:
|
||||
- ip
|
||||
- mac
|
||||
- port - ethX or wifiX
|
||||
- last_active
|
||||
"""
|
||||
port_map = {
|
||||
'wl1': 'wifi5Ghz',
|
||||
'wl0': 'wifi2.4Ghz',
|
||||
'eth0': 'eth0',
|
||||
'eth1': 'eth1',
|
||||
'eth2': 'eth2',
|
||||
'eth3': 'eth3',
|
||||
}
|
||||
|
||||
if device in self.devices:
|
||||
return {
|
||||
'ip': self.devices[device]['ip'],
|
||||
'mac': self.devices[device]['mac'],
|
||||
'port': port_map[self.devices[device]['port']],
|
||||
'last_active': self.devices[device]['time_last_active'],
|
||||
}
|
||||
|
||||
return {}
|
|
@ -342,6 +342,9 @@ dweepy==0.3.0
|
|||
# homeassistant.components.edp_redy
|
||||
edp_redy==0.0.3
|
||||
|
||||
# homeassistant.components.device_tracker.ee_brightbox
|
||||
eebrightbox==0.0.4
|
||||
|
||||
# homeassistant.components.media_player.horizon
|
||||
einder==0.3.1
|
||||
|
||||
|
|
|
@ -61,6 +61,9 @@ defusedxml==0.5.0
|
|||
# homeassistant.components.sensor.dsmr
|
||||
dsmr_parser==0.12
|
||||
|
||||
# homeassistant.components.device_tracker.ee_brightbox
|
||||
eebrightbox==0.0.4
|
||||
|
||||
# homeassistant.components.emulated_roku
|
||||
emulated_roku==0.1.7
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ TEST_REQUIREMENTS = (
|
|||
'coinmarketcap',
|
||||
'defusedxml',
|
||||
'dsmr_parser',
|
||||
'eebrightbox',
|
||||
'emulated_roku',
|
||||
'enturclient',
|
||||
'ephem',
|
||||
|
|
122
tests/components/device_tracker/test_ee_brightbox.py
Normal file
122
tests/components/device_tracker/test_ee_brightbox.py
Normal file
|
@ -0,0 +1,122 @@
|
|||
"""Tests for the EE BrightBox device scanner."""
|
||||
from datetime import datetime
|
||||
|
||||
from asynctest import patch
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.device_tracker import DOMAIN
|
||||
from homeassistant.const import (
|
||||
CONF_PASSWORD, CONF_PLATFORM)
|
||||
from homeassistant.setup import async_setup_component
|
||||
|
||||
|
||||
def _configure_mock_get_devices(eebrightbox_mock):
|
||||
eebrightbox_instance = eebrightbox_mock.return_value
|
||||
eebrightbox_instance.__enter__.return_value = eebrightbox_instance
|
||||
eebrightbox_instance.get_devices.return_value = [
|
||||
{
|
||||
'mac': 'AA:BB:CC:DD:EE:FF',
|
||||
'ip': '192.168.1.10',
|
||||
'hostname': 'hostnameAA',
|
||||
'activity_ip': True,
|
||||
'port': 'eth0',
|
||||
'time_last_active': datetime(2019, 1, 20, 16, 4, 0),
|
||||
},
|
||||
{
|
||||
'mac': '11:22:33:44:55:66',
|
||||
'hostname': 'hostname11',
|
||||
'ip': '192.168.1.11',
|
||||
'activity_ip': True,
|
||||
'port': 'wl0',
|
||||
'time_last_active': datetime(2019, 1, 20, 11, 9, 0),
|
||||
},
|
||||
{
|
||||
'mac': 'FF:FF:FF:FF:FF:FF',
|
||||
'hostname': 'hostnameFF',
|
||||
'ip': '192.168.1.12',
|
||||
'activity_ip': False,
|
||||
'port': 'wl1',
|
||||
'time_last_active': datetime(2019, 1, 15, 16, 9, 0),
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
def _configure_mock_failed_config_check(eebrightbox_mock):
|
||||
from eebrightbox import EEBrightBoxException
|
||||
eebrightbox_instance = eebrightbox_mock.return_value
|
||||
eebrightbox_instance.__enter__.side_effect = EEBrightBoxException(
|
||||
"Failed to connect to the router")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def mock_dev_track(mock_device_tracker_conf):
|
||||
"""Mock device tracker config loading."""
|
||||
pass
|
||||
|
||||
|
||||
@patch('eebrightbox.EEBrightBox')
|
||||
async def test_missing_credentials(eebrightbox_mock, hass):
|
||||
"""Test missing credentials."""
|
||||
_configure_mock_get_devices(eebrightbox_mock)
|
||||
|
||||
result = await async_setup_component(hass, DOMAIN, {
|
||||
DOMAIN: {
|
||||
CONF_PLATFORM: 'ee_brightbox',
|
||||
}
|
||||
})
|
||||
|
||||
assert result
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get('device_tracker.hostnameaa') is None
|
||||
assert hass.states.get('device_tracker.hostname11') is None
|
||||
assert hass.states.get('device_tracker.hostnameff') is None
|
||||
|
||||
|
||||
@patch('eebrightbox.EEBrightBox')
|
||||
async def test_invalid_credentials(eebrightbox_mock, hass):
|
||||
"""Test invalid credentials."""
|
||||
_configure_mock_failed_config_check(eebrightbox_mock)
|
||||
|
||||
result = await async_setup_component(hass, DOMAIN, {
|
||||
DOMAIN: {
|
||||
CONF_PLATFORM: 'ee_brightbox',
|
||||
CONF_PASSWORD: 'test_password',
|
||||
}
|
||||
})
|
||||
|
||||
assert result
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get('device_tracker.hostnameaa') is None
|
||||
assert hass.states.get('device_tracker.hostname11') is None
|
||||
assert hass.states.get('device_tracker.hostnameff') is None
|
||||
|
||||
|
||||
@patch('eebrightbox.EEBrightBox')
|
||||
async def test_get_devices(eebrightbox_mock, hass):
|
||||
"""Test valid configuration."""
|
||||
_configure_mock_get_devices(eebrightbox_mock)
|
||||
|
||||
result = await async_setup_component(hass, DOMAIN, {
|
||||
DOMAIN: {
|
||||
CONF_PLATFORM: 'ee_brightbox',
|
||||
CONF_PASSWORD: 'test_password',
|
||||
}
|
||||
})
|
||||
|
||||
assert result
|
||||
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert hass.states.get('device_tracker.hostnameaa') is not None
|
||||
assert hass.states.get('device_tracker.hostname11') is not None
|
||||
assert hass.states.get('device_tracker.hostnameff') is None
|
||||
|
||||
state = hass.states.get('device_tracker.hostnameaa')
|
||||
assert state.attributes['mac'] == 'AA:BB:CC:DD:EE:FF'
|
||||
assert state.attributes['ip'] == '192.168.1.10'
|
||||
assert state.attributes['port'] == 'eth0'
|
||||
assert state.attributes['last_active'] == datetime(2019, 1, 20, 16, 4, 0)
|
Loading…
Add table
Reference in a new issue