Allow integrations to request dhcp discovery flows for registered devices (#66528)

This commit is contained in:
J. Nick Koston 2022-02-15 11:02:52 -06:00 committed by GitHub
parent 2b43293363
commit f069a37f7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 239 additions and 647 deletions

View file

@ -1,4 +1,5 @@
"""The dhcp integration.""" """The dhcp integration."""
from __future__ import annotations
from dataclasses import dataclass from dataclasses import dataclass
from datetime import timedelta from datetime import timedelta
@ -35,7 +36,12 @@ from homeassistant.const import (
from homeassistant.core import Event, HomeAssistant, State, callback from homeassistant.core import Event, HomeAssistant, State, callback
from homeassistant.data_entry_flow import BaseServiceInfo from homeassistant.data_entry_flow import BaseServiceInfo
from homeassistant.helpers import discovery_flow from homeassistant.helpers import discovery_flow
from homeassistant.helpers.device_registry import format_mac from homeassistant.helpers.device_registry import (
CONNECTION_NETWORK_MAC,
DeviceRegistry,
async_get,
format_mac,
)
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
async_track_state_added_domain, async_track_state_added_domain,
async_track_time_interval, async_track_time_interval,
@ -54,9 +60,11 @@ MESSAGE_TYPE = "message-type"
HOSTNAME: Final = "hostname" HOSTNAME: Final = "hostname"
MAC_ADDRESS: Final = "macaddress" MAC_ADDRESS: Final = "macaddress"
IP_ADDRESS: Final = "ip" IP_ADDRESS: Final = "ip"
REGISTERED_DEVICES: Final = "registered_devices"
DHCP_REQUEST = 3 DHCP_REQUEST = 3
SCAN_INTERVAL = timedelta(minutes=60) SCAN_INTERVAL = timedelta(minutes=60)
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -180,7 +188,20 @@ class WatcherBase:
) )
matched_domains = set() matched_domains = set()
device_domains = set()
dev_reg: DeviceRegistry = async_get(self.hass)
if device := dev_reg.async_get_device(
identifiers=set(), connections={(CONNECTION_NETWORK_MAC, uppercase_mac)}
):
for entry_id in device.config_entries:
if entry := self.hass.config_entries.async_get_entry(entry_id):
device_domains.add(entry.domain)
for entry in self._integration_matchers: for entry in self._integration_matchers:
if entry.get(REGISTERED_DEVICES) and not entry["domain"] in device_domains:
continue
if MAC_ADDRESS in entry and not fnmatch.fnmatch( if MAC_ADDRESS in entry and not fnmatch.fnmatch(
uppercase_mac, entry[MAC_ADDRESS] uppercase_mac, entry[MAC_ADDRESS]
): ):
@ -192,14 +213,12 @@ class WatcherBase:
continue continue
_LOGGER.debug("Matched %s against %s", data, entry) _LOGGER.debug("Matched %s against %s", data, entry)
if entry["domain"] in matched_domains:
# Only match once per domain
continue
matched_domains.add(entry["domain"]) matched_domains.add(entry["domain"])
for domain in matched_domains:
discovery_flow.async_create_flow( discovery_flow.async_create_flow(
self.hass, self.hass,
entry["domain"], domain,
{"source": config_entries.SOURCE_DHCP}, {"source": config_entries.SOURCE_DHCP},
DhcpServiceInfo( DhcpServiceInfo(
ip=ip_address, ip=ip_address,

View file

@ -2,639 +2,153 @@
To update, run python3 -m script.hassfest To update, run python3 -m script.hassfest
""" """
from __future__ import annotations
# fmt: off # fmt: off
DHCP = [ DHCP: list[dict[str, str | bool]] = [
{ {'domain': 'august', 'hostname': 'connect', 'macaddress': 'D86162*'},
"domain": "august", {'domain': 'august', 'hostname': 'connect', 'macaddress': 'B8B7F1*'},
"hostname": "connect", {'domain': 'august', 'hostname': 'connect', 'macaddress': '2C9FFB*'},
"macaddress": "D86162*" {'domain': 'august', 'hostname': 'august*', 'macaddress': 'E076D0*'},
}, {'domain': 'axis', 'hostname': 'axis-00408c*', 'macaddress': '00408C*'},
{ {'domain': 'axis', 'hostname': 'axis-accc8e*', 'macaddress': 'ACCC8E*'},
"domain": "august", {'domain': 'axis', 'hostname': 'axis-b8a44f*', 'macaddress': 'B8A44F*'},
"hostname": "connect", {'domain': 'blink', 'hostname': 'blink*', 'macaddress': 'B85F98*'},
"macaddress": "B8B7F1*" {'domain': 'blink', 'hostname': 'blink*', 'macaddress': '00037F*'},
}, {'domain': 'blink', 'hostname': 'blink*', 'macaddress': '20A171*'},
{ {'domain': 'broadlink', 'macaddress': '34EA34*'},
"domain": "august", {'domain': 'broadlink', 'macaddress': '24DFA7*'},
"hostname": "connect", {'domain': 'broadlink', 'macaddress': 'A043B0*'},
"macaddress": "2C9FFB*" {'domain': 'broadlink', 'macaddress': 'B4430D*'},
}, {'domain': 'elkm1', 'macaddress': '00409D*'},
{ {'domain': 'emonitor', 'hostname': 'emonitor*', 'macaddress': '0090C2*'},
"domain": "august", {'domain': 'flume', 'hostname': 'flume-gw-*'},
"hostname": "august*", {'domain': 'flux_led', 'hostname': '[ba][lk]*', 'macaddress': '18B905*'},
"macaddress": "E076D0*" {'domain': 'flux_led', 'hostname': '[ba][lk]*', 'macaddress': '249494*'},
}, {'domain': 'flux_led', 'hostname': '[ba][lk]*', 'macaddress': '7CB94C*'},
{ {'domain': 'flux_led', 'hostname': '[hba][flk]*', 'macaddress': 'ACCF23*'},
"domain": "axis", {'domain': 'flux_led', 'hostname': '[ba][lk]*', 'macaddress': 'B4E842*'},
"hostname": "axis-00408c*", {'domain': 'flux_led', 'hostname': '[hba][flk]*', 'macaddress': 'F0FE6B*'},
"macaddress": "00408C*" {'domain': 'flux_led', 'hostname': 'lwip*', 'macaddress': '8CCE4E*'},
}, {'domain': 'flux_led', 'hostname': 'zengge_[0-9a-f][0-9a-f]_*'},
{ {'domain': 'flux_led', 'hostname': 'sta*', 'macaddress': 'C82E47*'},
"domain": "axis", {'domain': 'fronius', 'macaddress': '0003AC*'},
"hostname": "axis-accc8e*", {'domain': 'goalzero', 'hostname': 'yeti*'},
"macaddress": "ACCC8E*" {'domain': 'gogogate2', 'hostname': 'ismartgate*'},
}, {'domain': 'guardian', 'hostname': 'gvc*', 'macaddress': '30AEA4*'},
{ {'domain': 'guardian', 'hostname': 'gvc*', 'macaddress': 'B4E62D*'},
"domain": "axis", {'domain': 'guardian', 'hostname': 'guardian*', 'macaddress': '30AEA4*'},
"hostname": "axis-b8a44f*", {'domain': 'hunterdouglas_powerview',
"macaddress": "B8A44F*" 'hostname': 'hunter*',
}, 'macaddress': '002674*'},
{ {'domain': 'isy994', 'hostname': 'isy*', 'macaddress': '0021B9*'},
"domain": "blink", {'domain': 'lyric', 'hostname': 'lyric-*', 'macaddress': '48A2E6*'},
"hostname": "blink*", {'domain': 'lyric', 'hostname': 'lyric-*', 'macaddress': 'B82CA0*'},
"macaddress": "B85F98*" {'domain': 'lyric', 'hostname': 'lyric-*', 'macaddress': '00D02D*'},
}, {'domain': 'myq', 'macaddress': '645299*'},
{ {'domain': 'nest', 'macaddress': '18B430*'},
"domain": "blink", {'domain': 'nest', 'macaddress': '641666*'},
"hostname": "blink*", {'domain': 'nest', 'macaddress': 'D8EB46*'},
"macaddress": "00037F*" {'domain': 'nest', 'macaddress': '1C53F9*'},
}, {'domain': 'nexia', 'hostname': 'xl857-*', 'macaddress': '000231*'},
{ {'domain': 'nuheat', 'hostname': 'nuheat', 'macaddress': '002338*'},
"domain": "blink", {'domain': 'nuki', 'hostname': 'nuki_bridge_*'},
"hostname": "blink*", {'domain': 'oncue', 'hostname': 'kohlergen*', 'macaddress': '00146F*'},
"macaddress": "20A171*" {'domain': 'overkiz', 'hostname': 'gateway*', 'macaddress': 'F8811A*'},
}, {'domain': 'powerwall', 'hostname': '1118431-*'},
{ {'domain': 'rachio', 'hostname': 'rachio-*', 'macaddress': '009D6B*'},
"domain": "broadlink", {'domain': 'rachio', 'hostname': 'rachio-*', 'macaddress': 'F0038C*'},
"macaddress": "34EA34*" {'domain': 'rachio', 'hostname': 'rachio-*', 'macaddress': '74C63B*'},
}, {'domain': 'rainforest_eagle', 'macaddress': 'D8D5B9*'},
{ {'domain': 'ring', 'hostname': 'ring*', 'macaddress': '0CAE7D*'},
"domain": "broadlink", {'domain': 'roomba', 'hostname': 'irobot-*', 'macaddress': '501479*'},
"macaddress": "24DFA7*" {'domain': 'roomba', 'hostname': 'roomba-*', 'macaddress': '80A589*'},
}, {'domain': 'roomba', 'hostname': 'roomba-*', 'macaddress': 'DCF505*'},
{ {'domain': 'samsungtv', 'hostname': 'tizen*'},
"domain": "broadlink", {'domain': 'samsungtv', 'macaddress': '8CC8CD*'},
"macaddress": "A043B0*" {'domain': 'samsungtv', 'macaddress': '606BBD*'},
}, {'domain': 'samsungtv', 'macaddress': 'F47B5E*'},
{ {'domain': 'samsungtv', 'macaddress': '4844F7*'},
"domain": "broadlink", {'domain': 'screenlogic', 'hostname': 'pentair: *', 'macaddress': '00C033*'},
"macaddress": "B4430D*" {'domain': 'sense', 'hostname': 'sense-*', 'macaddress': '009D6B*'},
}, {'domain': 'sense', 'hostname': 'sense-*', 'macaddress': 'DCEFCA*'},
{ {'domain': 'sense', 'hostname': 'sense-*', 'macaddress': 'A4D578*'},
"domain": "elkm1", {'domain': 'senseme', 'macaddress': '20F85E*'},
"macaddress": "00409D*" {'domain': 'sensibo', 'hostname': 'sensibo*'},
}, {'domain': 'simplisafe', 'hostname': 'simplisafe*', 'macaddress': '30AEA4*'},
{ {'domain': 'smartthings', 'hostname': 'st*', 'macaddress': '24FD5B*'},
"domain": "emonitor", {'domain': 'smartthings', 'hostname': 'smartthings*', 'macaddress': '24FD5B*'},
"hostname": "emonitor*", {'domain': 'smartthings', 'hostname': 'hub*', 'macaddress': '24FD5B*'},
"macaddress": "0090C2*" {'domain': 'smartthings', 'hostname': 'hub*', 'macaddress': 'D052A8*'},
}, {'domain': 'smartthings', 'hostname': 'hub*', 'macaddress': '286D97*'},
{ {'domain': 'solaredge', 'hostname': 'target', 'macaddress': '002702*'},
"domain": "flume", {'domain': 'somfy_mylink', 'hostname': 'somfy_*', 'macaddress': 'B8B7F1*'},
"hostname": "flume-gw-*" {'domain': 'squeezebox', 'hostname': 'squeezebox*', 'macaddress': '000420*'},
}, {'domain': 'steamist', 'hostname': 'my[45]50*', 'macaddress': '001E0C*'},
{ {'domain': 'tado', 'hostname': 'tado*'},
"domain": "flux_led", {'domain': 'tesla_wall_connector',
"macaddress": "18B905*", 'hostname': 'teslawallconnector_*',
"hostname": "[ba][lk]*" 'macaddress': 'DC44271*'},
}, {'domain': 'tesla_wall_connector',
{ 'hostname': 'teslawallconnector_*',
"domain": "flux_led", 'macaddress': '98ED5C*'},
"macaddress": "249494*", {'domain': 'tesla_wall_connector',
"hostname": "[ba][lk]*" 'hostname': 'teslawallconnector_*',
}, 'macaddress': '4CFCAA*'},
{ {'domain': 'tolo', 'hostname': 'usr-tcp232-ed2'},
"domain": "flux_led", {'domain': 'toon', 'hostname': 'eneco-*', 'macaddress': '74C63B*'},
"macaddress": "7CB94C*", {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '60A4B7*'},
"hostname": "[ba][lk]*" {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '005F67*'},
}, {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '1027F5*'},
{ {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '403F8C*'},
"domain": "flux_led", {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': 'C0C9E3*'},
"macaddress": "ACCF23*", {'domain': 'tplink', 'hostname': 'ep*', 'macaddress': 'E848B8*'},
"hostname": "[hba][flk]*" {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': 'E848B8*'},
}, {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '909A4A*'},
{ {'domain': 'tplink', 'hostname': 'hs*', 'macaddress': '1C3BF3*'},
"domain": "flux_led", {'domain': 'tplink', 'hostname': 'hs*', 'macaddress': '50C7BF*'},
"macaddress": "B4E842*", {'domain': 'tplink', 'hostname': 'hs*', 'macaddress': '68FF7B*'},
"hostname": "[ba][lk]*" {'domain': 'tplink', 'hostname': 'hs*', 'macaddress': '98DAC4*'},
}, {'domain': 'tplink', 'hostname': 'hs*', 'macaddress': 'B09575*'},
{ {'domain': 'tplink', 'hostname': 'hs*', 'macaddress': 'C006C3*'},
"domain": "flux_led", {'domain': 'tplink', 'hostname': 'ep*', 'macaddress': '003192*'},
"macaddress": "F0FE6B*", {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '003192*'},
"hostname": "[hba][flk]*" {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '1C3BF3*'},
}, {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '50C7BF*'},
{ {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '68FF7B*'},
"domain": "flux_led", {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': '98DAC4*'},
"macaddress": "8CCE4E*", {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': 'B09575*'},
"hostname": "lwip*" {'domain': 'tplink', 'hostname': 'k[lp]*', 'macaddress': 'C006C3*'},
}, {'domain': 'tplink', 'hostname': 'lb*', 'macaddress': '1C3BF3*'},
{ {'domain': 'tplink', 'hostname': 'lb*', 'macaddress': '50C7BF*'},
"domain": "flux_led", {'domain': 'tplink', 'hostname': 'lb*', 'macaddress': '68FF7B*'},
"hostname": "zengge_[0-9a-f][0-9a-f]_*" {'domain': 'tplink', 'hostname': 'lb*', 'macaddress': '98DAC4*'},
}, {'domain': 'tplink', 'hostname': 'lb*', 'macaddress': 'B09575*'},
{ {'domain': 'tuya', 'macaddress': '105A17*'},
"domain": "flux_led", {'domain': 'tuya', 'macaddress': '10D561*'},
"macaddress": "C82E47*", {'domain': 'tuya', 'macaddress': '1869D8*'},
"hostname": "sta*" {'domain': 'tuya', 'macaddress': '381F8D*'},
}, {'domain': 'tuya', 'macaddress': '508A06*'},
{ {'domain': 'tuya', 'macaddress': '68572D*'},
"domain": "fronius", {'domain': 'tuya', 'macaddress': '708976*'},
"macaddress": "0003AC*" {'domain': 'tuya', 'macaddress': '7CF666*'},
}, {'domain': 'tuya', 'macaddress': '84E342*'},
{ {'domain': 'tuya', 'macaddress': 'D4A651*'},
"domain": "goalzero", {'domain': 'tuya', 'macaddress': 'D81F12*'},
"hostname": "yeti*" {'domain': 'twinkly', 'hostname': 'twinkly_*'},
}, {'domain': 'unifiprotect', 'macaddress': 'B4FBE4*'},
{ {'domain': 'unifiprotect', 'macaddress': '802AA8*'},
"domain": "gogogate2", {'domain': 'unifiprotect', 'macaddress': 'F09FC2*'},
"hostname": "ismartgate*" {'domain': 'unifiprotect', 'macaddress': '68D79A*'},
}, {'domain': 'unifiprotect', 'macaddress': '18E829*'},
{ {'domain': 'unifiprotect', 'macaddress': '245A4C*'},
"domain": "guardian", {'domain': 'unifiprotect', 'macaddress': '784558*'},
"hostname": "gvc*", {'domain': 'unifiprotect', 'macaddress': 'E063DA*'},
"macaddress": "30AEA4*" {'domain': 'unifiprotect', 'macaddress': '265A4C*'},
}, {'domain': 'unifiprotect', 'macaddress': '74ACB9*'},
{ {'domain': 'verisure', 'macaddress': '0023C1*'},
"domain": "guardian", {'domain': 'vicare', 'macaddress': 'B87424*'},
"hostname": "gvc*", {'domain': 'wiz', 'macaddress': 'A8BB50*'},
"macaddress": "B4E62D*" {'domain': 'wiz', 'hostname': 'wiz_*'},
}, {'domain': 'yeelight', 'hostname': 'yeelink-*'}]
{
"domain": "guardian",
"hostname": "guardian*",
"macaddress": "30AEA4*"
},
{
"domain": "hunterdouglas_powerview",
"hostname": "hunter*",
"macaddress": "002674*"
},
{
"domain": "isy994",
"hostname": "isy*",
"macaddress": "0021B9*"
},
{
"domain": "lyric",
"hostname": "lyric-*",
"macaddress": "48A2E6*"
},
{
"domain": "lyric",
"hostname": "lyric-*",
"macaddress": "B82CA0*"
},
{
"domain": "lyric",
"hostname": "lyric-*",
"macaddress": "00D02D*"
},
{
"domain": "myq",
"macaddress": "645299*"
},
{
"domain": "nest",
"macaddress": "18B430*"
},
{
"domain": "nest",
"macaddress": "641666*"
},
{
"domain": "nest",
"macaddress": "D8EB46*"
},
{
"domain": "nest",
"macaddress": "1C53F9*"
},
{
"domain": "nexia",
"hostname": "xl857-*",
"macaddress": "000231*"
},
{
"domain": "nuheat",
"hostname": "nuheat",
"macaddress": "002338*"
},
{
"domain": "nuki",
"hostname": "nuki_bridge_*"
},
{
"domain": "oncue",
"hostname": "kohlergen*",
"macaddress": "00146F*"
},
{
"domain": "overkiz",
"hostname": "gateway*",
"macaddress": "F8811A*"
},
{
"domain": "powerwall",
"hostname": "1118431-*"
},
{
"domain": "rachio",
"hostname": "rachio-*",
"macaddress": "009D6B*"
},
{
"domain": "rachio",
"hostname": "rachio-*",
"macaddress": "F0038C*"
},
{
"domain": "rachio",
"hostname": "rachio-*",
"macaddress": "74C63B*"
},
{
"domain": "rainforest_eagle",
"macaddress": "D8D5B9*"
},
{
"domain": "ring",
"hostname": "ring*",
"macaddress": "0CAE7D*"
},
{
"domain": "roomba",
"hostname": "irobot-*",
"macaddress": "501479*"
},
{
"domain": "roomba",
"hostname": "roomba-*",
"macaddress": "80A589*"
},
{
"domain": "roomba",
"hostname": "roomba-*",
"macaddress": "DCF505*"
},
{
"domain": "samsungtv",
"hostname": "tizen*"
},
{
"domain": "samsungtv",
"macaddress": "8CC8CD*"
},
{
"domain": "samsungtv",
"macaddress": "606BBD*"
},
{
"domain": "samsungtv",
"macaddress": "F47B5E*"
},
{
"domain": "samsungtv",
"macaddress": "4844F7*"
},
{
"domain": "screenlogic",
"hostname": "pentair: *",
"macaddress": "00C033*"
},
{
"domain": "sense",
"hostname": "sense-*",
"macaddress": "009D6B*"
},
{
"domain": "sense",
"hostname": "sense-*",
"macaddress": "DCEFCA*"
},
{
"domain": "sense",
"hostname": "sense-*",
"macaddress": "A4D578*"
},
{
"domain": "senseme",
"macaddress": "20F85E*"
},
{
"domain": "sensibo",
"hostname": "sensibo*"
},
{
"domain": "simplisafe",
"hostname": "simplisafe*",
"macaddress": "30AEA4*"
},
{
"domain": "smartthings",
"hostname": "st*",
"macaddress": "24FD5B*"
},
{
"domain": "smartthings",
"hostname": "smartthings*",
"macaddress": "24FD5B*"
},
{
"domain": "smartthings",
"hostname": "hub*",
"macaddress": "24FD5B*"
},
{
"domain": "smartthings",
"hostname": "hub*",
"macaddress": "D052A8*"
},
{
"domain": "smartthings",
"hostname": "hub*",
"macaddress": "286D97*"
},
{
"domain": "solaredge",
"hostname": "target",
"macaddress": "002702*"
},
{
"domain": "somfy_mylink",
"hostname": "somfy_*",
"macaddress": "B8B7F1*"
},
{
"domain": "squeezebox",
"hostname": "squeezebox*",
"macaddress": "000420*"
},
{
"domain": "steamist",
"macaddress": "001E0C*",
"hostname": "my[45]50*"
},
{
"domain": "tado",
"hostname": "tado*"
},
{
"domain": "tesla_wall_connector",
"hostname": "teslawallconnector_*",
"macaddress": "DC44271*"
},
{
"domain": "tesla_wall_connector",
"hostname": "teslawallconnector_*",
"macaddress": "98ED5C*"
},
{
"domain": "tesla_wall_connector",
"hostname": "teslawallconnector_*",
"macaddress": "4CFCAA*"
},
{
"domain": "tolo",
"hostname": "usr-tcp232-ed2"
},
{
"domain": "toon",
"hostname": "eneco-*",
"macaddress": "74C63B*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "60A4B7*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "005F67*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "1027F5*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "403F8C*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "C0C9E3*"
},
{
"domain": "tplink",
"hostname": "ep*",
"macaddress": "E848B8*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "E848B8*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "909A4A*"
},
{
"domain": "tplink",
"hostname": "hs*",
"macaddress": "1C3BF3*"
},
{
"domain": "tplink",
"hostname": "hs*",
"macaddress": "50C7BF*"
},
{
"domain": "tplink",
"hostname": "hs*",
"macaddress": "68FF7B*"
},
{
"domain": "tplink",
"hostname": "hs*",
"macaddress": "98DAC4*"
},
{
"domain": "tplink",
"hostname": "hs*",
"macaddress": "B09575*"
},
{
"domain": "tplink",
"hostname": "hs*",
"macaddress": "C006C3*"
},
{
"domain": "tplink",
"hostname": "ep*",
"macaddress": "003192*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "003192*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "1C3BF3*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "50C7BF*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "68FF7B*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "98DAC4*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "B09575*"
},
{
"domain": "tplink",
"hostname": "k[lp]*",
"macaddress": "C006C3*"
},
{
"domain": "tplink",
"hostname": "lb*",
"macaddress": "1C3BF3*"
},
{
"domain": "tplink",
"hostname": "lb*",
"macaddress": "50C7BF*"
},
{
"domain": "tplink",
"hostname": "lb*",
"macaddress": "68FF7B*"
},
{
"domain": "tplink",
"hostname": "lb*",
"macaddress": "98DAC4*"
},
{
"domain": "tplink",
"hostname": "lb*",
"macaddress": "B09575*"
},
{
"domain": "tuya",
"macaddress": "105A17*"
},
{
"domain": "tuya",
"macaddress": "10D561*"
},
{
"domain": "tuya",
"macaddress": "1869D8*"
},
{
"domain": "tuya",
"macaddress": "381F8D*"
},
{
"domain": "tuya",
"macaddress": "508A06*"
},
{
"domain": "tuya",
"macaddress": "68572D*"
},
{
"domain": "tuya",
"macaddress": "708976*"
},
{
"domain": "tuya",
"macaddress": "7CF666*"
},
{
"domain": "tuya",
"macaddress": "84E342*"
},
{
"domain": "tuya",
"macaddress": "D4A651*"
},
{
"domain": "tuya",
"macaddress": "D81F12*"
},
{
"domain": "twinkly",
"hostname": "twinkly_*"
},
{
"domain": "unifiprotect",
"macaddress": "B4FBE4*"
},
{
"domain": "unifiprotect",
"macaddress": "802AA8*"
},
{
"domain": "unifiprotect",
"macaddress": "F09FC2*"
},
{
"domain": "unifiprotect",
"macaddress": "68D79A*"
},
{
"domain": "unifiprotect",
"macaddress": "18E829*"
},
{
"domain": "unifiprotect",
"macaddress": "245A4C*"
},
{
"domain": "unifiprotect",
"macaddress": "784558*"
},
{
"domain": "unifiprotect",
"macaddress": "E063DA*"
},
{
"domain": "unifiprotect",
"macaddress": "265A4C*"
},
{
"domain": "unifiprotect",
"macaddress": "74ACB9*"
},
{
"domain": "verisure",
"macaddress": "0023C1*"
},
{
"domain": "vicare",
"macaddress": "B87424*"
},
{
"domain": "wiz",
"macaddress": "A8BB50*"
},
{
"domain": "wiz",
"hostname": "wiz_*"
},
{
"domain": "yeelight",
"hostname": "yeelink-*"
}
]

View file

@ -82,7 +82,7 @@ class Manifest(TypedDict, total=False):
mqtt: list[str] mqtt: list[str]
ssdp: list[dict[str, str]] ssdp: list[dict[str, str]]
zeroconf: list[str | dict[str, str]] zeroconf: list[str | dict[str, str]]
dhcp: list[dict[str, str]] dhcp: list[dict[str, bool | str]]
usb: list[dict[str, str]] usb: list[dict[str, str]]
homekit: dict[str, list[str]] homekit: dict[str, list[str]]
is_built_in: bool is_built_in: bool
@ -228,9 +228,9 @@ async def async_get_zeroconf(
return zeroconf return zeroconf
async def async_get_dhcp(hass: HomeAssistant) -> list[dict[str, str]]: async def async_get_dhcp(hass: HomeAssistant) -> list[dict[str, str | bool]]:
"""Return cached list of dhcp types.""" """Return cached list of dhcp types."""
dhcp: list[dict[str, str]] = DHCP.copy() dhcp: list[dict[str, str | bool]] = DHCP.copy()
integrations = await async_get_custom_components(hass) integrations = await async_get_custom_components(hass)
for integration in integrations.values(): for integration in integrations.values():
@ -474,7 +474,7 @@ class Integration:
return self.manifest.get("zeroconf") return self.manifest.get("zeroconf")
@property @property
def dhcp(self) -> list[dict[str, str]] | None: def dhcp(self) -> list[dict[str, str | bool]] | None:
"""Return Integration dhcp entries.""" """Return Integration dhcp entries."""
return self.manifest.get("dhcp") return self.manifest.get("dhcp")

View file

@ -1,7 +1,8 @@
"""Generate dhcp file.""" """Generate dhcp file."""
from __future__ import annotations from __future__ import annotations
import json import pprint
import re
from .model import Config, Integration from .model import Config, Integration
@ -10,10 +11,11 @@ BASE = """
To update, run python3 -m script.hassfest To update, run python3 -m script.hassfest
\"\"\" \"\"\"
from __future__ import annotations
# fmt: off # fmt: off
DHCP = {} DHCP: list[dict[str, str | bool]] = {}
""".strip() """.strip()
@ -35,7 +37,14 @@ def generate_and_validate(integrations: list[dict[str, str]]):
for entry in match_types: for entry in match_types:
match_list.append({"domain": domain, **entry}) match_list.append({"domain": domain, **entry})
return BASE.format(json.dumps(match_list, indent=4)) # JSON will format `True` as `true`
# re.sub for flake8 E128
formatted = pprint.pformat(match_list)
formatted_aligned_continuation = re.sub(r"^\[\{", "[\n {", formatted)
formatted_align_indent = re.sub(
r"(?m)^ ", " ", formatted_aligned_continuation, flags=re.MULTILINE, count=0
)
return BASE.format(formatted_align_indent)
def validate(integrations: dict[str, Integration], config: Config): def validate(integrations: dict[str, Integration], config: Config):

View file

@ -218,6 +218,7 @@ MANIFEST_SCHEMA = vol.Schema(
str, verify_uppercase, verify_wildcard str, verify_uppercase, verify_wildcard
), ),
vol.Optional("hostname"): vol.All(str, verify_lowercase), vol.Optional("hostname"): vol.All(str, verify_lowercase),
vol.Optional("registered_devices"): cv.boolean,
} }
) )
], ],

View file

@ -25,10 +25,11 @@ from homeassistant.const import (
STATE_HOME, STATE_HOME,
STATE_NOT_HOME, STATE_NOT_HOME,
) )
import homeassistant.helpers.device_registry as dr
from homeassistant.setup import async_setup_component from homeassistant.setup import async_setup_component
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from tests.common import async_fire_time_changed from tests.common import MockConfigEntry, async_fire_time_changed
# connect b8:b7:f1:6d:b5:33 192.168.210.56 # connect b8:b7:f1:6d:b5:33 192.168.210.56
RAW_DHCP_REQUEST = ( RAW_DHCP_REQUEST = (
@ -207,6 +208,52 @@ async def test_dhcp_renewal_match_hostname_and_macaddress(hass):
) )
async def test_registered_devices(hass):
"""Test discovery flows are created for registered devices."""
integration_matchers = [
{"domain": "not-matching", "registered_devices": True},
{"domain": "mock-domain", "registered_devices": True},
]
packet = Ether(RAW_DHCP_RENEWAL)
registry = dr.async_get(hass)
config_entry = MockConfigEntry(domain="mock-domain", data={})
config_entry.add_to_hass(hass)
registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "50147903852c")},
name="name",
)
# Not enabled should not get flows
config_entry2 = MockConfigEntry(domain="mock-domain-2", data={})
config_entry2.add_to_hass(hass)
registry.async_get_or_create(
config_entry_id=config_entry2.entry_id,
connections={(dr.CONNECTION_NETWORK_MAC, "50147903852c")},
name="name",
)
async_handle_dhcp_packet = await _async_get_handle_dhcp_packet(
hass, integration_matchers
)
with patch.object(hass.config_entries.flow, "async_init") as mock_init:
await async_handle_dhcp_packet(packet)
# Ensure no change is ignored
await async_handle_dhcp_packet(packet)
assert len(mock_init.mock_calls) == 1
assert mock_init.mock_calls[0][1][0] == "mock-domain"
assert mock_init.mock_calls[0][2]["context"] == {
"source": config_entries.SOURCE_DHCP
}
assert mock_init.mock_calls[0][2]["data"] == dhcp.DhcpServiceInfo(
ip="192.168.1.120",
hostname="irobot-ae9ec12dd3b04885bcbfa36afb01e1cc",
macaddress="50147903852c",
)
async def test_dhcp_match_hostname(hass): async def test_dhcp_match_hostname(hass):
"""Test matching based on hostname only.""" """Test matching based on hostname only."""
integration_matchers = [{"domain": "mock-domain", "hostname": "connect"}] integration_matchers = [{"domain": "mock-domain", "hostname": "connect"}]

View file

@ -203,6 +203,7 @@ def test_integration_properties(hass):
{"hostname": "tesla_*", "macaddress": "4CFCAA*"}, {"hostname": "tesla_*", "macaddress": "4CFCAA*"},
{"hostname": "tesla_*", "macaddress": "044EAF*"}, {"hostname": "tesla_*", "macaddress": "044EAF*"},
{"hostname": "tesla_*", "macaddress": "98ED5C*"}, {"hostname": "tesla_*", "macaddress": "98ED5C*"},
{"registered_devices": True},
], ],
"usb": [ "usb": [
{"vid": "10C4", "pid": "EA60"}, {"vid": "10C4", "pid": "EA60"},
@ -233,6 +234,7 @@ def test_integration_properties(hass):
{"hostname": "tesla_*", "macaddress": "4CFCAA*"}, {"hostname": "tesla_*", "macaddress": "4CFCAA*"},
{"hostname": "tesla_*", "macaddress": "044EAF*"}, {"hostname": "tesla_*", "macaddress": "044EAF*"},
{"hostname": "tesla_*", "macaddress": "98ED5C*"}, {"hostname": "tesla_*", "macaddress": "98ED5C*"},
{"registered_devices": True},
] ]
assert integration.usb == [ assert integration.usb == [
{"vid": "10C4", "pid": "EA60"}, {"vid": "10C4", "pid": "EA60"},