1 """The Network Configuration integration."""
3 from __future__
import annotations
5 from ipaddress
import IPv4Address, IPv6Address, ip_interface
22 from .models
import Adapter
23 from .network
import Network, async_get_network
25 _LOGGER = logging.getLogger(__name__)
27 CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
32 """Get the network adapter configuration."""
34 return network.adapters
39 hass: HomeAssistant, target_ip: str | UndefinedType = UNDEFINED
41 """Get the source ip for a target ip."""
44 for adapter
in adapters:
45 if adapter[
"enabled"]
and (ipv4s := adapter[
"ipv4"]):
46 all_ipv4s.extend([ipv4[
"address"]
for ipv4
in ipv4s])
48 if target_ip
is UNDEFINED:
50 util.async_get_source_ip(PUBLIC_TARGET_IP)
51 or util.async_get_source_ip(MDNS_TARGET_IP)
52 or util.async_get_source_ip(LOOPBACK_TARGET_IP)
55 source_ip = util.async_get_source_ip(target_ip)
59 "Because the system does not have any enabled IPv4 addresses, source"
60 " address detection may be inaccurate"
64 "Could not determine source ip because the system does not have any"
65 " enabled IPv4 addresses and creating a socket failed"
69 return source_ip
if source_ip
in all_ipv4s
else all_ipv4s[0]
75 ) -> list[IPv4Address | IPv6Address]:
76 """Build the list of enabled source ips."""
78 sources: list[IPv4Address | IPv6Address] = []
79 for adapter
in adapters:
80 if not adapter[
"enabled"]:
83 addrs_ipv4 = [IPv4Address(ipv4[
"address"])
for ipv4
in adapter[
"ipv4"]]
84 sources.extend(addrs_ipv4)
87 IPv6Address(f
"{ipv6['address']}%{ipv6['scope_id']}")
88 for ipv6
in adapter[
"ipv6"]
90 sources.extend(addrs_ipv6)
97 """Check to see if any non-default adapter is enabled."""
99 adapter[
"enabled"]
and not adapter[
"default"]
for adapter
in adapters
105 """Return a set of broadcast addresses."""
106 broadcast_addresses: set[IPv4Address] = {IPv4Address(IPV4_BROADCAST_ADDR)}
109 return broadcast_addresses
110 for adapter
in adapters:
111 if not adapter[
"enabled"]:
113 for ip_info
in adapter[
"ipv4"]:
114 interface = ip_interface(
115 f
"{ip_info['address']}/{ip_info['network_prefix']}"
117 broadcast_addresses.add(
118 IPv4Address(interface.network.broadcast_address.exploded)
120 return broadcast_addresses
124 """Return a list of IP addresses to announce/use via zeroconf/ssdp/etc.
126 The default ip address is always returned first if available.
129 addresses: list[str] = []
130 default_ip: str |
None =
None
131 for adapter
in adapters:
132 if not adapter[
"enabled"]:
134 addresses.extend(
str(IPv4Address(ips[
"address"]))
for ips
in adapter[
"ipv4"])
135 addresses.extend(
str(IPv6Address(ips[
"address"]))
for ips
in adapter[
"ipv6"])
141 if default_ip
in addresses:
142 addresses.remove(default_ip)
143 return [default_ip, *addresses]
144 return list(addresses)
147 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
148 """Set up network for Home Assistant."""
150 from .websocket
import (
151 async_register_websocket_commands,
Network async_get_network(HomeAssistant hass)
None async_register_websocket_commands(HomeAssistant hass)
bool async_only_default_interface_enabled(list[Adapter] adapters)
bool async_setup(HomeAssistant hass, ConfigType config)
set[IPv4Address] async_get_ipv4_broadcast_addresses(HomeAssistant hass)
list[IPv4Address|IPv6Address] async_get_enabled_source_ips(HomeAssistant hass)
list[Adapter] async_get_adapters(HomeAssistant hass)
list[str] async_get_announce_addresses(HomeAssistant hass)
str async_get_source_ip(HomeAssistant hass, str|UndefinedType target_ip=UNDEFINED)