Skip to main content

Networking and Discovery

Some integrations may need to discover devices on the network via mDNS/Zeroconf, SSDP, or another method once they have been enabled. The primary use case is to find devices that do not have a known fixed IP Address or for integrations that can dynamically add and remove any number of compatible discoverable devices.

Home Assistant has built-in helpers to support mDNS/Zeroconf and SSDP. If your integration uses another discovery method that needs to determine which network interfaces to use to broadcast traffic, the Network integration provides a helper API to access the user's interface preferences.

mDNS/Zeroconf#

Home Assistant uses the python-zeroconf package for mDNS support. As running multiple mDNS implementations on a single host is not recommended, Home Assistant provides internal helper APIs to access the running Zeroconf and AsyncZeroconf instances.

Before using these helpers, be sure to add zeroconf to dependencies in your integration's manifest.json

Obtaining the AsyncZeroconf object#

from homeassistant.components import zeroconf
...
aiozc = await zeroconf.async_get_async_instance(hass)

Obtaining the Zeroconf object#

from homeassistant.components import zeroconf
...
zc = await zeroconf.async_get_instance(hass)

Using the AsyncZeroconf and Zeroconf objects#

python-zeroconf provides examples on how to use both objects examples.

SSDP#

Home Assistant provides built-in discovery via SSDP.

Before using these helpers, be sure to add ssdp to dependencies in your integration's manifest.json

Obtaining the list of discovered devices#

The list of discovered SSDP devices can be obtained using the following built-in helper APIs. The SSDP integration provides the following helper APIs to lookup existing SSDP discoveries from the cache: ssdp.async_get_discovery_info_by_udn_st, ssdp.async_get_discovery_info_by_st, ssdp.async_get_discovery_info_by_udn

Looking up a specific device#

The ssdp.async_get_discovery_info_by_udn_st API returns a single discovery_info or None when provided an SSDP, UDN and ST.

from homeassistant.components import ssdp
...
discovery_info = ssdp.async_get_discovery_info_by_udn_st(hass, udn, st)

Looking up devices by ST#

If you want to look for a specific type of discovered devices, calling ssdp.async_get_discovery_info_by_st will return a list of all discovered devices that match the SSDP ST. The below example returns a list of discovery info for every Sonos player discovered on the network.

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

Looking up devices by UDN#

If you want to see a list of the services provided by a specific UDN, calling ssdp.async_get_discovery_info_by_udn will return a list of all discovered devices that match the UPNP UDN.

from homeassistant.components import ssdp
...
discovery_infos = ssdp.async_get_discovery_info_by_udn(hass, udn)
for discovery_info in discovery_infos:
...

Subscribing to SSDP discoveries#

Some integrations may need to know when a device is discovered right away. The SSDP integration provides a registration API to receive callbacks when a new device is discovered that matches specific key values. The same format for ssdp in manifest.json is used for matching.

The function ssdp.async_register_callback is provided to enable this ability. The function returns a callback that will cancel the registration when called.

The below example shows registering to get callbacks when a Sonos player is seen on the network.

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"}
)
)

The below example shows registering to get callbacks when the x-rincon-bootseq header is present.

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}
)
)

Network#

For integrations that use a discovery method that is not built-in and need to access the user's network adapter configuration, the following helper API should be used.

from homeassistant.components import network
...
adapters = await network.async_get_adapters(hass)

Example async_get_adapters data structure#

[
{
"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",
},
]

Obtaining the IP Network from an adapter#

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 adapater["ipv4"]:
local_ip = ip_info["address"]
network_prefix = ip_info["network_prefix"]
ip_net = ip_network(f"{local_ip}/{network_prefix}", False)
Last updated on