diff --git a/.coveragerc b/.coveragerc index 378dba5ef2a341..5db925420a67d8 100644 --- a/.coveragerc +++ b/.coveragerc @@ -461,6 +461,7 @@ omit = homeassistant/components/device_tracker/bluetooth_le_tracker.py homeassistant/components/device_tracker/bluetooth_tracker.py homeassistant/components/device_tracker/bt_home_hub_5.py + homeassistant/components/device_tracker/bt_smarthub.py homeassistant/components/device_tracker/cisco_ios.py homeassistant/components/device_tracker/ddwrt.py homeassistant/components/device_tracker/freebox.py diff --git a/homeassistant/components/device_tracker/bt_smarthub.py b/homeassistant/components/device_tracker/bt_smarthub.py new file mode 100644 index 00000000000000..e7d60aaed6dd36 --- /dev/null +++ b/homeassistant/components/device_tracker/bt_smarthub.py @@ -0,0 +1,97 @@ +""" +Support for BT Smart Hub (Sometimes referred to as BT Home Hub 6). + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/device_tracker.bt_smarthub/ +""" +import logging + +import voluptuous as vol + +import homeassistant.helpers.config_validation as cv +from homeassistant.components.device_tracker import ( + DOMAIN, PLATFORM_SCHEMA, DeviceScanner) +from homeassistant.const import CONF_HOST + +REQUIREMENTS = ['btsmarthub_devicelist==0.1.1'] + +_LOGGER = logging.getLogger(__name__) + +CONF_DEFAULT_IP = '192.168.1.254' + +PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ + vol.Optional(CONF_HOST, default=CONF_DEFAULT_IP): cv.string, +}) + + +def get_scanner(hass, config): + """Return a BT Smart Hub scanner if successful.""" + scanner = BTSmartHubScanner(config[DOMAIN]) + + return scanner if scanner.success_init else None + + +class BTSmartHubScanner(DeviceScanner): + """This class queries a BT Smart Hub.""" + + def __init__(self, config): + """Initialise the scanner.""" + _LOGGER.debug("Initialising BT Smart Hub") + self.host = config[CONF_HOST] + self.last_results = {} + self.success_init = False + + # Test the router is accessible + data = self.get_bt_smarthub_data() + if data: + self.success_init = True + else: + _LOGGER.info("Failed to connect to %s", self.host) + + def scan_devices(self): + """Scan for new devices and return a list with found device IDs.""" + self._update_info() + return [client['mac'] for client in self.last_results] + + def get_device_name(self, device): + """Return the name of the given device or None if we don't know.""" + if not self.last_results: + return None + for client in self.last_results: + if client['mac'] == device: + return client['host'] + return None + + def _update_info(self): + """Ensure the information from the BT Smart Hub is up to date.""" + if not self.success_init: + return + + _LOGGER.info("Scanning") + data = self.get_bt_smarthub_data() + if not data: + _LOGGER.warning("Error scanning devices") + return + + clients = [client for client in data.values()] + self.last_results = clients + + def get_bt_smarthub_data(self): + """Retrieve data from BT Smart Hub and return parsed result.""" + import btsmarthub_devicelist + # Request data from bt smarthub into a list of dicts. + data = btsmarthub_devicelist.get_devicelist( + router_ip=self.host, only_active_devices=True) + # Renaming keys from parsed result. + devices = {} + for device in data: + try: + devices[device['UserHostName']] = { + 'ip': device['IPAddress'], + 'mac': device['PhysAddress'], + 'host': device['UserHostName'], + 'status': device['Active'] + } + except KeyError: + pass + return devices diff --git a/requirements_all.txt b/requirements_all.txt index 82a0571b00160a..8cd7c4797eaea6 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -221,6 +221,9 @@ bt_proximity==0.1.2 # homeassistant.components.device_tracker.bt_home_hub_5 bthomehub5-devicelist==0.1.1 +# homeassistant.components.device_tracker.bt_smarthub +btsmarthub_devicelist==0.1.1 + # homeassistant.components.sensor.buienradar # homeassistant.components.weather.buienradar buienradar==0.91