99 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			99 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Python
		
	
	
"""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")]
 |