Home Assistant Unofficial Reference 2024.12.1
device_tracker.py
Go to the documentation of this file.
1 """Device tracker for Synology SRM routers."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 import synology_srm
8 import voluptuous as vol
9 
11  DOMAIN as DEVICE_TRACKER_DOMAIN,
12  PLATFORM_SCHEMA as DEVICE_TRACKER_PLATFORM_SCHEMA,
13  DeviceScanner,
14 )
15 from homeassistant.const import (
16  CONF_HOST,
17  CONF_PASSWORD,
18  CONF_PORT,
19  CONF_SSL,
20  CONF_USERNAME,
21  CONF_VERIFY_SSL,
22 )
23 from homeassistant.core import HomeAssistant
25 from homeassistant.helpers.typing import ConfigType
26 
27 _LOGGER = logging.getLogger(__name__)
28 
29 DEFAULT_USERNAME = "admin"
30 DEFAULT_PORT = 8001
31 DEFAULT_SSL = True
32 DEFAULT_VERIFY_SSL = False
33 
34 PLATFORM_SCHEMA = DEVICE_TRACKER_PLATFORM_SCHEMA.extend(
35  {
36  vol.Required(CONF_HOST): cv.string,
37  vol.Required(CONF_USERNAME, default=DEFAULT_USERNAME): cv.string,
38  vol.Required(CONF_PASSWORD): cv.string,
39  vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
40  vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
41  vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
42  }
43 )
44 
45 ATTRIBUTE_ALIAS = {
46  "band": None,
47  "connection": None,
48  "current_rate": None,
49  "dev_type": None,
50  "hostname": None,
51  "ip6_addr": None,
52  "ip_addr": None,
53  "is_baned": "is_banned",
54  "is_beamforming_on": None,
55  "is_guest": None,
56  "is_high_qos": None,
57  "is_low_qos": None,
58  "is_manual_dev_type": None,
59  "is_manual_hostname": None,
60  "is_online": None,
61  "is_parental_controled": "is_parental_controlled",
62  "is_qos": None,
63  "is_wireless": None,
64  "mac": None,
65  "max_rate": None,
66  "mesh_node_id": None,
67  "rate_quality": None,
68  "signalstrength": "signal_strength",
69  "transferRXRate": "transfer_rx_rate",
70  "transferTXRate": "transfer_tx_rate",
71 }
72 
73 
75  hass: HomeAssistant, config: ConfigType
76 ) -> SynologySrmDeviceScanner | None:
77  """Validate the configuration and return Synology SRM scanner."""
78  scanner = SynologySrmDeviceScanner(config[DEVICE_TRACKER_DOMAIN])
79 
80  return scanner if scanner.success_init else None
81 
82 
83 class SynologySrmDeviceScanner(DeviceScanner):
84  """Scanner for devices connected to a Synology SRM router."""
85 
86  def __init__(self, config):
87  """Initialize the scanner."""
88 
89  self.clientclient = synology_srm.Client(
90  host=config[CONF_HOST],
91  port=config[CONF_PORT],
92  username=config[CONF_USERNAME],
93  password=config[CONF_PASSWORD],
94  https=config[CONF_SSL],
95  )
96 
97  if not config[CONF_VERIFY_SSL]:
98  self.clientclient.http.disable_https_verify()
99 
100  self.devicesdevices = []
101  self.success_initsuccess_init = self._update_info_update_info()
102 
103  def scan_devices(self):
104  """Scan for new devices and return a list with found device IDs."""
105  self._update_info_update_info()
106 
107  return [device["mac"] for device in self.devicesdevices]
108 
109  def get_extra_attributes(self, device) -> dict:
110  """Get the extra attributes of a device."""
111  device = next(
112  (result for result in self.devicesdevices if result["mac"] == device), None
113  )
114  filtered_attributes: dict[str, str] = {}
115  if not device:
116  return filtered_attributes
117  for attribute, alias in ATTRIBUTE_ALIAS.items():
118  if (value := device.get(attribute)) is None:
119  continue
120  attr = alias or attribute
121  filtered_attributes[attr] = value
122  return filtered_attributes
123 
124  def get_device_name(self, device):
125  """Return the name of the given device or None if we don't know."""
126  filter_named = [
127  result["hostname"] for result in self.devicesdevices if result["mac"] == device
128  ]
129 
130  if filter_named:
131  return filter_named[0]
132 
133  return None
134 
135  def _update_info(self):
136  """Check the router for connected devices."""
137  _LOGGER.debug("Scanning for connected devices")
138 
139  try:
140  self.devicesdevices = self.clientclient.core.get_network_nsm_device({"is_online": True})
141  except synology_srm.http.SynologyException as ex:
142  _LOGGER.error("Error with the Synology SRM: %s", ex)
143  return False
144 
145  _LOGGER.debug("Found %d device(s) connected to the router", len(self.devicesdevices))
146 
147  return True
SynologySrmDeviceScanner|None get_scanner(HomeAssistant hass, ConfigType config)