Home Assistant Unofficial Reference 2024.12.1
device_tracker.py
Go to the documentation of this file.
1 """Support for BT Smart Hub (Sometimes referred to as BT Home Hub 6)."""
2 
3 from __future__ import annotations
4 
5 from collections import namedtuple
6 import logging
7 
8 from btsmarthub_devicelist import BTSmartHub
9 import voluptuous as vol
10 
12  DOMAIN as DEVICE_TRACKER_DOMAIN,
13  PLATFORM_SCHEMA as DEVICE_TRACKER_PLATFORM_SCHEMA,
14  DeviceScanner,
15 )
16 from homeassistant.const import CONF_HOST
17 from homeassistant.core import HomeAssistant
19 from homeassistant.helpers.typing import ConfigType
20 
21 _LOGGER = logging.getLogger(__name__)
22 
23 CONF_DEFAULT_IP = "192.168.1.254"
24 CONF_SMARTHUB_MODEL = "smarthub_model"
25 
26 PLATFORM_SCHEMA = DEVICE_TRACKER_PLATFORM_SCHEMA.extend(
27  {
28  vol.Optional(CONF_HOST, default=CONF_DEFAULT_IP): cv.string,
29  vol.Optional(CONF_SMARTHUB_MODEL): vol.In([1, 2]),
30  }
31 )
32 
33 
34 def get_scanner(hass: HomeAssistant, config: ConfigType) -> BTSmartHubScanner | None:
35  """Return a BT Smart Hub scanner if successful."""
36  info = config[DEVICE_TRACKER_DOMAIN]
37  smarthub_client = BTSmartHub(
38  router_ip=info[CONF_HOST], smarthub_model=info.get(CONF_SMARTHUB_MODEL)
39  )
40  scanner = BTSmartHubScanner(smarthub_client)
41  return scanner if scanner.success_init else None
42 
43 
44 def _create_device(data):
45  """Create new device from the dict."""
46  ip_address = data.get("IPAddress")
47  mac = data.get("PhysAddress")
48  host = data.get("UserHostName")
49  status = data.get("Active")
50  name = data.get("name")
51  return _Device(ip_address, mac, host, status, name)
52 
53 
54 _Device = namedtuple("_Device", ["ip_address", "mac", "host", "status", "name"]) # noqa: PYI024
55 
56 
57 class BTSmartHubScanner(DeviceScanner):
58  """Class which queries a BT Smart Hub."""
59 
60  def __init__(self, smarthub_client):
61  """Initialise the scanner."""
62  self.smarthubsmarthub = smarthub_client
63  self.last_resultslast_results = []
64  self.success_initsuccess_init = False
65 
66  # Test the router is accessible
67  if self.get_bt_smarthub_dataget_bt_smarthub_data():
68  self.success_initsuccess_init = True
69  else:
70  _LOGGER.warning("Failed to connect to %s", self.smarthubsmarthub.router_ip)
71 
72  def scan_devices(self):
73  """Scan for new devices and return a list with found device IDs."""
74  self._update_info_update_info()
75  return [device.mac for device in self.last_resultslast_results]
76 
77  def get_device_name(self, device):
78  """Return the name of the given device or None if we don't know."""
79  if not self.last_resultslast_results:
80  return None
81  for result_device in self.last_resultslast_results:
82  if result_device.mac == device:
83  return result_device.name or result_device.host
84  return None
85 
86  def _update_info(self):
87  """Ensure the information from the BT Smart Hub is up to date."""
88  if not self.success_initsuccess_init:
89  return
90 
91  _LOGGER.debug("Scanning")
92  if not (data := self.get_bt_smarthub_dataget_bt_smarthub_data()):
93  _LOGGER.warning("Error scanning devices")
94  return
95  self.last_resultslast_results = data
96 
98  """Retrieve data from BT Smart Hub and return parsed result."""
99  # Request data from bt smarthub into a list of dicts.
100  data = self.smarthubsmarthub.get_devicelist(only_active_devices=True)
101  return [_create_device(d) for d in data if d.get("PhysAddress")]
BTSmartHubScanner|None get_scanner(HomeAssistant hass, ConfigType config)