diff --git a/homeassistant/components/device_tracker/bt_home_hub_5.py b/homeassistant/components/device_tracker/bt_home_hub_5.py index 93bc9270650f11..21c41df3a1d2ba 100644 --- a/homeassistant/components/device_tracker/bt_home_hub_5.py +++ b/homeassistant/components/device_tracker/bt_home_hub_5.py @@ -5,24 +5,22 @@ https://home-assistant.io/components/device_tracker.bt_home_hub_5/ """ import logging -import re -import xml.etree.ElementTree as ET -import json -from urllib.parse import unquote -import requests import voluptuous as vol import homeassistant.helpers.config_validation as cv -from homeassistant.components.device_tracker import ( - DOMAIN, PLATFORM_SCHEMA, DeviceScanner) +from homeassistant.components.device_tracker import (DOMAIN, PLATFORM_SCHEMA, + DeviceScanner) from homeassistant.const import CONF_HOST +REQUIREMENTS = ['bthomehub5-devicelist==0.1.1'] + _LOGGER = logging.getLogger(__name__) -_MAC_REGEX = re.compile(r'(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})') + +CONF_DEFAULT_IP = '192.168.1.254' PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string + vol.Optional(CONF_HOST, default=CONF_DEFAULT_IP): cv.string, }) @@ -38,18 +36,19 @@ class BTHomeHub5DeviceScanner(DeviceScanner): def __init__(self, config): """Initialise the scanner.""" + import bthomehub5_devicelist + _LOGGER.info("Initialising BT Home Hub 5") - self.host = config.get(CONF_HOST, '192.168.1.254') + self.host = config[CONF_HOST] self.last_results = {} - self.url = 'http://{}/nonAuth/home_status.xml'.format(self.host) # Test the router is accessible - data = _get_homehub_data(self.url) + data = bthomehub5_devicelist.get_devicelist(self.host) self.success_init = data is not None def scan_devices(self): """Scan for new devices and return a list with found device IDs.""" - self._update_info() + self.update_info() return (device for device in self.last_results) @@ -57,71 +56,23 @@ def get_device_name(self, device): """Return the name of the given device or None if we don't know.""" # If not initialised and not already scanned and not found. if device not in self.last_results: - self._update_info() + self.update_info() if not self.last_results: return None return self.last_results.get(device) - def _update_info(self): - """Ensure the information from the BT Home Hub 5 is up to date. - - Return boolean if scanning successful. - """ - if not self.success_init: - return False + def update_info(self): + """Ensure the information from the BT Home Hub 5 is up to date.""" + import bthomehub5_devicelist _LOGGER.info("Scanning") - data = _get_homehub_data(self.url) + data = bthomehub5_devicelist.get_devicelist(self.host) if not data: _LOGGER.warning("Error scanning devices") - return False + return self.last_results = data - - return True - - -def _get_homehub_data(url): - """Retrieve data from BT Home Hub 5 and return parsed result.""" - try: - response = requests.get(url, timeout=5) - except requests.exceptions.Timeout: - _LOGGER.exception("Connection to the router timed out") - return - if response.status_code == 200: - return _parse_homehub_response(response.text) - _LOGGER.error("Invalid response from Home Hub: %s", response) - - -def _parse_homehub_response(data_str): - """Parse the BT Home Hub 5 data format.""" - root = ET.fromstring(data_str) - - dirty_json = root.find('known_device_list').get('value') - - # Normalise the JavaScript data to JSON. - clean_json = unquote(dirty_json.replace('\'', '\"') - .replace('{', '{\"') - .replace(':\"', '\":\"') - .replace('\",', '\",\"')) - - known_devices = [x for x in json.loads(clean_json) if x] - - devices = {} - - for device in known_devices: - name = device.get('name') - mac = device.get('mac') - - if _MAC_REGEX.match(mac) or ',' in mac: - for mac_addr in mac.split(','): - if _MAC_REGEX.match(mac_addr): - devices[mac_addr] = name - else: - devices[mac] = name - - return devices diff --git a/requirements_all.txt b/requirements_all.txt index 5345694c379345..2ee58f9033471c 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -208,6 +208,9 @@ brunt==0.1.2 # homeassistant.components.device_tracker.bluetooth_tracker bt_proximity==0.1.2 +# homeassistant.components.device_tracker.bt_home_hub_5 +bthomehub5-devicelist==0.1.1 + # homeassistant.components.sensor.buienradar # homeassistant.components.weather.buienradar buienradar==0.91 diff --git a/tests/components/device_tracker/test_bt_home_hub_5.py b/tests/components/device_tracker/test_bt_home_hub_5.py deleted file mode 100644 index fd9692ec2b47c0..00000000000000 --- a/tests/components/device_tracker/test_bt_home_hub_5.py +++ /dev/null @@ -1,53 +0,0 @@ -"""The tests for the BT Home Hub 5 device tracker platform.""" -import unittest -from unittest.mock import patch - -from homeassistant.components.device_tracker import bt_home_hub_5 -from homeassistant.const import CONF_HOST - -patch_file = 'homeassistant.components.device_tracker.bt_home_hub_5' - - -def _get_homehub_data(url): - """Return mock homehub data.""" - return ''' - [ - { - "mac": "AA:BB:CC:DD:EE:FF, - "hostname": "hostname", - "ip": "192.168.1.43", - "ipv6": "", - "name": "hostname", - "activity": "1", - "os": "Unknown", - "device": "Unknown", - "time_first_seen": "2016/06/05 11:14:45", - "time_last_active": "2016/06/06 11:33:08", - "dhcp_option": "39043T90430T9TGK0EKGE5KGE3K904390K45GK054", - "port": "wl0", - "ipv6_ll": "fe80::gd67:ghrr:fuud:4332", - "activity_ip": "1", - "activity_ipv6_ll": "0", - "activity_ipv6": "0", - "device_oui": "NA", - "device_serial": "NA", - "device_class": "NA" - } - ] - ''' - - -class TestBTHomeHub5DeviceTracker(unittest.TestCase): - """Test BT Home Hub 5 device tracker platform.""" - - @patch('{}._get_homehub_data'.format(patch_file), new=_get_homehub_data) - def test_config_minimal(self): - """Test the setup with minimal configuration.""" - config = { - 'device_tracker': { - CONF_HOST: 'foo' - } - } - result = bt_home_hub_5.get_scanner(None, config) - - self.assertIsNotNone(result)