Skip to main content

网络与发现

某些集成可能需要通过 mDNS/ZeroconfSSDP 或其他方法在启用后发现网络上的设备。主要用例是查找没有已知固定 IP 地址的设备,或用于能够动态添加和删除任意数量的兼容可发现设备的集成。

Home Assistant 内置了支持 mDNS/Zeroconf 和 SSDP 的助手。如果您的集成使用其他发现方法并需要确定使用哪些网络接口来广播流量,网络 集成提供了一个助手 API 来访问用户的接口偏好设置。

mDNS/Zeroconf

Home Assistant 使用 python-zeroconf 包来支持 mDNS。由于在单个主机上运行多个 mDNS 实现并不推荐,因此 Home Assistant 提供了内部助手 API 来访问正在运行的 ZeroconfAsyncZeroconf 实例。

在使用这些助手之前,请确保在集成的 manifest.json 中将 zeroconf 添加到 dependencies

获取 AsyncZeroconf 对象

from homeassistant.components import zeroconf

...
aiozc = await zeroconf.async_get_async_instance(hass)

获取 Zeroconf 对象

from homeassistant.components import zeroconf

...
zc = await zeroconf.async_get_instance(hass)

使用 AsyncZeroconfZeroconf 对象

python-zeroconf 提供了如何使用这两个对象的示例 examples

SSDP

Home Assistant 提供通过 SSDP 的内置发现。

在使用这些助手之前,请确保在集成的 manifest.json 中将 ssdp 添加到 dependencies

获取发现设备的列表

可以使用以下内置助手 API 获得发现的 SSDP 设备的列表。SSDP 集成提供以下助手 API 以从缓存中查找现有的 SSDP 发现:ssdp.async_get_discovery_info_by_udn_stssdp.async_get_discovery_info_by_stssdp.async_get_discovery_info_by_udn

查找特定设备

ssdp.async_get_discovery_info_by_udn_st API 在提供 SSDPUDNST 时返回单个 discovery_infoNone

from homeassistant.components import ssdp

...

discovery_info = await ssdp.async_get_discovery_info_by_udn_st(hass, udn, st)

ST 查找设备

如果您想查找特定类型的发现设备,调用 ssdp.async_get_discovery_info_by_st 将返回与 SSDP ST 匹配的所有发现设备的列表。以下示例返回网络上发现的每个 Sonos 播放器的发现信息列表。

from homeassistant.components import ssdp

...

discovery_infos = await ssdp.async_get_discovery_info_by_st(hass, "urn:schemas-upnp-org:device:ZonePlayer:1")
for discovery_info in discovery_infos:
...

UDN 查找设备

如果您想查看特定 UDN 提供的服务列表,调用 ssdp.async_get_discovery_info_by_udn 将返回与 UPNP UDN 匹配的所有发现设备的列表。

from homeassistant.components import ssdp

...

discovery_infos = await ssdp.async_get_discovery_info_by_udn(hass, udn)
for discovery_info in discovery_infos:
...

订阅 SSDP 发现

某些集成可能需要立即了解设备的发现情况。SSDP 集成提供了一个注册 API,以在发现与特定键值匹配的新设备时接收回调。ssdpmanifest.json 中使用相同的格式进行匹配。

提供了 ssdp.async_register_callback 函数以启用此功能。该函数返回一个回调,当调用时将取消注册。

以下示例展示了在网络上看到 Sonos 播放器时注册以获取回调。

from homeassistant.components import ssdp

...

entry.async_on_unload(
ssdp.async_register_callback(
hass, _async_discovered_player, {"st": "urn:schemas-upnp-org:device:ZonePlayer:1"}
)
)

以下示例展示了在存在 x-rincon-bootseq 头时注册以获取回调。

from homeassistant.components import ssdp
from homeassistant.const import MATCH_ALL

...

entry.async_on_unload(
ssdp.async_register_callback(
hass, _async_discovered_player, {"x-rincon-bootseq": MATCH_ALL}
)
)

网络

对于使用非内置发现方法的集成,并且需要访问用户的网络适配器配置,应使用以下助手 API。

from homeassistant.components import network

...
adapters = await network.async_get_adapters(hass)

示例 async_get_adapters 数据结构

[
{
"auto": True,
"default": False,
"enabled": True,
"ipv4": [],
"ipv6": [
{
"address": "2001:db8::",
"network_prefix": 8,
"flowinfo": 1,
"scope_id": 1,
}
],
"name": "eth0",
},
{
"auto": True,
"default": False,
"enabled": True,
"ipv4": [{"address": "192.168.1.5", "network_prefix": 23}],
"ipv6": [],
"name": "eth1",
},
{
"auto": False,
"default": False,
"enabled": False,
"ipv4": [{"address": "169.254.3.2", "network_prefix": 16}],
"ipv6": [],
"name": "vtun0",
},
]

从适配器获取 IP 网络

from ipaddress import ip_network
from homeassistant.components import network

...

adapters = await network.async_get_adapters(hass)

for adapter in adapters:
for ip_info in adapter["ipv4"]:
local_ip = ip_info["address"]
network_prefix = ip_info["network_prefix"]
ip_net = ip_network(f"{local_ip}/{network_prefix}", False)

USB

USB 集成在启动时、访问集成页面时以及插入时发现新的 USB 设备,前提是底层系统支持 pyudev

检查特定适配器是否已插入

调用 async_is_plugged_in API 来检查特定适配器是否在系统上。

from homeassistant.components import usb

...

if not usb.async_is_plugged_in(hass, {"serial_number": "A1234", "manufacturer": "xtech"}):
raise ConfigEntryNotReady("USB 设备缺失")

知道何时查找新的兼容 USB 设备

调用 async_register_scan_request_callback API 以请求在新兼容 USB 设备可能可用时的回调。

from homeassistant.components import usb
from homeassistant.core import callback

...

@callback
def _async_check_for_usb() -> None:
"""检查新的兼容蓝牙 USB 适配器。"""

entry.async_on_unload(
bluetooth.async_register_scan_request_callback(hass, _async_check_for_usb)
)