"""Support for BT Smart Hub (Sometimes referred to as BT Home Hub 6).""" from collections import namedtuple import logging from btsmarthub_devicelist import BTSmartHub import voluptuous as vol from homeassistant.components.device_tracker import ( DOMAIN, PLATFORM_SCHEMA as PARENT_PLATFORM_SCHEMA, DeviceScanner, ) from homeassistant.const import CONF_HOST import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) CONF_DEFAULT_IP = "192.168.1.254" CONF_SMARTHUB_MODEL = "smarthub_model" PLATFORM_SCHEMA = PARENT_PLATFORM_SCHEMA.extend( { vol.Optional(CONF_HOST, default=CONF_DEFAULT_IP): cv.string, vol.Optional(CONF_SMARTHUB_MODEL): vol.In([1, 2]), } ) def get_scanner(hass, config): """Return a BT Smart Hub scanner if successful.""" info = config[DOMAIN] smarthub_client = BTSmartHub( router_ip=info[CONF_HOST], smarthub_model=info.get(CONF_SMARTHUB_MODEL) ) scanner = BTSmartHubScanner(smarthub_client) return scanner if scanner.success_init else None def _create_device(data): """Create new device from the dict.""" ip_address = data.get("IPAddress") mac = data.get("PhysAddress") host = data.get("UserHostName") status = data.get("Active") name = data.get("name") return _Device(ip_address, mac, host, status, name) _Device = namedtuple("_Device", ["ip_address", "mac", "host", "status", "name"]) class BTSmartHubScanner(DeviceScanner): """This class queries a BT Smart Hub.""" def __init__(self, smarthub_client): """Initialise the scanner.""" self.smarthub = smarthub_client 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.smarthub.router_ip) def scan_devices(self): """Scan for new devices and return a list with found device IDs.""" self._update_info() return [device.mac for device 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 result_device in self.last_results: if result_device.mac == device: return result_device.name or result_device.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 self.last_results = data def get_bt_smarthub_data(self): """Retrieve data from BT Smart Hub and return parsed result.""" # Request data from bt smarthub into a list of dicts. data = self.smarthub.get_devicelist(only_active_devices=True) return [_create_device(d) for d in data if d.get("PhysAddress")]