1 """Support for DD-WRT routers."""
3 from __future__
import annotations
5 from http
import HTTPStatus
10 import voluptuous
as vol
13 DOMAIN
as DEVICE_TRACKER_DOMAIN,
14 PLATFORM_SCHEMA
as DEVICE_TRACKER_PLATFORM_SCHEMA,
28 _LOGGER = logging.getLogger(__name__)
30 _DDWRT_DATA_REGEX = re.compile(
r"\{(\w+)::([^\}]*)\}")
31 _MAC_REGEX = re.compile(
r"(([0-9A-Fa-f]{1,2}\:){5}[0-9A-Fa-f]{1,2})")
34 DEFAULT_VERIFY_SSL =
True
35 CONF_WIRELESS_ONLY =
"wireless_only"
36 DEFAULT_WIRELESS_ONLY =
True
38 PLATFORM_SCHEMA = DEVICE_TRACKER_PLATFORM_SCHEMA.extend(
40 vol.Required(CONF_HOST): cv.string,
41 vol.Required(CONF_PASSWORD): cv.string,
42 vol.Required(CONF_USERNAME): cv.string,
43 vol.Optional(CONF_SSL, default=DEFAULT_SSL): cv.boolean,
44 vol.Optional(CONF_VERIFY_SSL, default=DEFAULT_VERIFY_SSL): cv.boolean,
45 vol.Optional(CONF_WIRELESS_ONLY, default=DEFAULT_WIRELESS_ONLY): cv.boolean,
50 def get_scanner(hass: HomeAssistant, config: ConfigType) -> DdWrtDeviceScanner |
None:
51 """Validate the configuration and return a DD-WRT scanner."""
54 except ConnectionError:
59 """Class which queries a wireless router running DD-WRT firmware."""
62 """Initialize the DD-WRT scanner."""
63 self.
protocolprotocol =
"https" if config[CONF_SSL]
else "http"
65 self.
hosthost = config[CONF_HOST]
74 url = f
"{self.protocol}://{self.host}/Status_Wireless.live.asp"
76 raise ConnectionError(
"Cannot connect to DD-Wrt router")
79 """Scan for new devices and return a list with found device IDs."""
85 """Return the name of the given device or None if we don't know."""
87 if device
not in self.
mac2namemac2name:
88 url = f
"{self.protocol}://{self.host}/Status_Lan.live.asp"
93 if not (dhcp_leases := data.get(
"dhcp_leases")):
97 cleaned_str = dhcp_leases.replace(
'"',
"").replace(
"'",
"").replace(
" ",
"")
98 elements = cleaned_str.split(
",")
99 num_clients =
int(len(elements) / 5)
101 for idx
in range(num_clients):
105 mac_index = (idx * 5) + 2
106 if mac_index < len(elements):
107 mac = elements[mac_index]
108 self.
mac2namemac2name[mac] = elements[idx * 5]
113 """Ensure the information from the DD-WRT router is up to date.
115 Return boolean if scanning successful.
117 _LOGGER.debug(
"Checking ARP")
119 endpoint =
"Wireless" if self.
wireless_onlywireless_only
else "Lan"
120 url = f
"{self.protocol}://{self.host}/Status_{endpoint}.live.asp"
128 active_clients = data.get(
"active_wireless")
130 active_clients = data.get(
"arp_table")
131 if not active_clients:
137 clean_str = active_clients.strip().strip(
"'")
138 elements = clean_str.split(
"','")
140 self.
last_resultslast_results.extend(item
for item
in elements
if _MAC_REGEX.match(item))
145 """Retrieve data from DD-WRT and return parsed result."""
147 response = requests.get(
153 except requests.exceptions.Timeout:
154 _LOGGER.exception(
"Connection to the router timed out")
156 if response.status_code == HTTPStatus.OK:
158 if response.status_code == HTTPStatus.UNAUTHORIZED:
161 "Failed to authenticate, check your username and password"
164 _LOGGER.error(
"Invalid response from DD-WRT: %s", response)
169 """Parse the DD-WRT data format."""
170 return dict(_DDWRT_DATA_REGEX.findall(data_str))
def get_device_name(self, device)
def get_ddwrt_data(self, url)
def __init__(self, config)
web.Response get(self, web.Request request, str config_key)
def _parse_ddwrt_response(data_str)
DdWrtDeviceScanner|None get_scanner(HomeAssistant hass, ConfigType config)