mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
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
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
|
# homeassistant.components.edp_redy
|
||||||
edp_redy==0.0.3
|
edp_redy==0.0.3
|
||||||
|
|
||||||
|
# homeassistant.components.device_tracker.ee_brightbox
|
||||||
|
eebrightbox==0.0.4
|
||||||
|
|
||||||
# homeassistant.components.media_player.horizon
|
# homeassistant.components.media_player.horizon
|
||||||
einder==0.3.1
|
einder==0.3.1
|
||||||
|
|
||||||
|
@ -61,6 +61,9 @@ defusedxml==0.5.0
|
|||||||
# homeassistant.components.sensor.dsmr
|
# homeassistant.components.sensor.dsmr
|
||||||
dsmr_parser==0.12
|
dsmr_parser==0.12
|
||||||
|
|
||||||
|
# homeassistant.components.device_tracker.ee_brightbox
|
||||||
|
eebrightbox==0.0.4
|
||||||
|
|
||||||
# homeassistant.components.emulated_roku
|
# homeassistant.components.emulated_roku
|
||||||
emulated_roku==0.1.7
|
emulated_roku==0.1.7
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ TEST_REQUIREMENTS = (
|
|||||||
'coinmarketcap',
|
'coinmarketcap',
|
||||||
'defusedxml',
|
'defusedxml',
|
||||||
'dsmr_parser',
|
'dsmr_parser',
|
||||||
|
'eebrightbox',
|
||||||
'emulated_roku',
|
'emulated_roku',
|
||||||
'enturclient',
|
'enturclient',
|
||||||
'ephem',
|
'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…
x
Reference in New Issue
Block a user