This commit is contained in:
J. Nick Koston 2025-04-16 10:46:53 -10:00
parent 710f1ab2fd
commit aba0fa0190
No known key found for this signature in database
4 changed files with 29 additions and 40 deletions

View File

@ -10,7 +10,7 @@ from functools import lru_cache, partial
import itertools import itertools
import logging import logging
import re import re
from typing import TYPE_CHECKING, Any, Final from typing import Any, Final
import aiodhcpwatcher import aiodhcpwatcher
from aiodiscover import DiscoverHosts from aiodiscover import DiscoverHosts
@ -124,7 +124,7 @@ def async_index_integration_matchers(
@callback @callback
def async_register_dhcp_callback_internal( def async_register_dhcp_callback_internal(
hass: HomeAssistant, hass: HomeAssistant,
callback_: Callable[[_DhcpServiceInfo], None], callback_: Callable[[dict[str, DHCPAddressData]], None],
) -> CALLBACK_TYPE: ) -> CALLBACK_TYPE:
"""Register a dhcp callback. """Register a dhcp callback.
@ -293,20 +293,24 @@ class WatcherBase:
_LOGGER.debug("Matched %s against %s", data, matcher) _LOGGER.debug("Matched %s against %s", data, matcher)
matched_domains.add(domain) matched_domains.add(domain)
if self._callbacks:
address_data: dict[str, DHCPAddressData] = {
mac_address: {
"ip": compressed_ip_address,
"hostname": lowercase_hostname,
}
}
for callback_ in self._callbacks:
callback_(address_data)
service_info: _DhcpServiceInfo | None = None service_info: _DhcpServiceInfo | None = None
if self._callbacks or matched_domains: if not matched_domains:
return
service_info = _DhcpServiceInfo( service_info = _DhcpServiceInfo(
ip=ip_address, ip=ip_address,
hostname=lowercase_hostname, hostname=lowercase_hostname,
macaddress=mac_address, macaddress=mac_address,
) )
if TYPE_CHECKING:
assert service_info is not None
for callback_ in self._callbacks:
callback_(service_info)
discovery_key = DiscoveryKey( discovery_key = DiscoveryKey(
domain=DOMAIN, domain=DOMAIN,
key=mac_address, key=mac_address,

View File

@ -6,7 +6,6 @@ from collections.abc import Callable
from functools import partial from functools import partial
from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo as _DhcpServiceInfo
from .models import DATA_DHCP, DHCPAddressData from .models import DATA_DHCP, DHCPAddressData
@ -14,7 +13,7 @@ from .models import DATA_DHCP, DHCPAddressData
@callback @callback
def async_register_dhcp_callback_internal( def async_register_dhcp_callback_internal(
hass: HomeAssistant, hass: HomeAssistant,
callback_: Callable[[_DhcpServiceInfo], None], callback_: Callable[[dict[str, DHCPAddressData]], None],
) -> CALLBACK_TYPE: ) -> CALLBACK_TYPE:
"""Register a dhcp callback. """Register a dhcp callback.

View File

@ -7,7 +7,6 @@ import dataclasses
from dataclasses import dataclass from dataclasses import dataclass
from typing import TypedDict from typing import TypedDict
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo as _DhcpServiceInfo
from homeassistant.loader import DHCPMatcher from homeassistant.loader import DHCPMatcher
from homeassistant.util.hass_dict import HassKey from homeassistant.util.hass_dict import HassKey
@ -35,7 +34,7 @@ class DHCPData:
"""Data for the dhcp component.""" """Data for the dhcp component."""
integration_matchers: DhcpMatchers integration_matchers: DhcpMatchers
callbacks: set[Callable[[_DhcpServiceInfo], None]] = dataclasses.field( callbacks: set[Callable[[dict[str, DHCPAddressData]], None]] = dataclasses.field(
default_factory=set default_factory=set
) )
address_data: dict[str, DHCPAddressData] = dataclasses.field(default_factory=dict) address_data: dict[str, DHCPAddressData] = dataclasses.field(default_factory=dict)

View File

@ -10,13 +10,13 @@ from homeassistant.components import websocket_api
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.json import json_bytes from homeassistant.helpers.json import json_bytes
from homeassistant.helpers.service_info.dhcp import DhcpServiceInfo as _DhcpServiceInfo
from .const import HOSTNAME, IP_ADDRESS from .const import HOSTNAME, IP_ADDRESS
from .helpers import ( from .helpers import (
async_get_address_data_internal, async_get_address_data_internal,
async_register_dhcp_callback_internal, async_register_dhcp_callback_internal,
) )
from .models import DHCPAddressData
@callback @callback
@ -46,22 +46,24 @@ class _DiscoverySubscription:
connection.subscriptions[self.ws_msg_id] = ( connection.subscriptions[self.ws_msg_id] = (
async_register_dhcp_callback_internal( async_register_dhcp_callback_internal(
self.hass, self.hass,
self._async_on_discovery, self._async_send_address_data,
) )
) )
connection.send_message( connection.send_message(
json_bytes(websocket_api.result_message(self.ws_msg_id)) json_bytes(websocket_api.result_message(self.ws_msg_id))
) )
self._async_send_current_address_data() self._async_send_address_data(
async_get_address_data_internal(self.hass),
)
def _async_event_message(self, message: dict[str, Any]) -> None: def _async_event_message(self, message: dict[str, Any]) -> None:
self.connection.send_message( self.connection.send_message(
json_bytes(websocket_api.event_message(self.ws_msg_id, message)) json_bytes(websocket_api.event_message(self.ws_msg_id, message))
) )
def _async_send_current_address_data(self) -> None: def _async_send_address_data(
"""Send the current address data.""" self, address_data: dict[str, DHCPAddressData]
address_data = async_get_address_data_internal(self.hass) ) -> None:
self._async_event_message( self._async_event_message(
{ {
"add": [ "add": [
@ -75,21 +77,6 @@ class _DiscoverySubscription:
} }
) )
@callback
def _async_on_discovery(self, service_info: _DhcpServiceInfo) -> None:
"""Handle the callback."""
self._async_event_message(
{
"add": [
{
"mac_address": dr.format_mac(service_info.macaddress).upper(),
"hostname": service_info.hostname,
"ip_address": service_info.ip,
}
]
}
)
@websocket_api.require_admin @websocket_api.require_admin
@websocket_api.websocket_command( @websocket_api.websocket_command(