Skip to content

Commit 530c189

Browse files
authored
Add Bluetooth WiFi provisioning for Shelly (home-assistant#155822)
1 parent f05fef9 commit 530c189

File tree

7 files changed

+1773
-8
lines changed

7 files changed

+1773
-8
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
"""BLE provisioning helpers for Shelly integration."""
2+
3+
from __future__ import annotations
4+
5+
import asyncio
6+
from dataclasses import dataclass, field
7+
import logging
8+
9+
from homeassistant.core import HomeAssistant, callback
10+
from homeassistant.helpers.device_registry import format_mac
11+
from homeassistant.util.hass_dict import HassKey
12+
13+
_LOGGER = logging.getLogger(__name__)
14+
15+
16+
@dataclass
17+
class ProvisioningState:
18+
"""State for tracking zeroconf discovery during BLE provisioning."""
19+
20+
event: asyncio.Event = field(default_factory=asyncio.Event)
21+
host: str | None = None
22+
port: int | None = None
23+
24+
25+
PROVISIONING_FUTURES: HassKey[dict[str, ProvisioningState]] = HassKey(
26+
"shelly_provisioning_futures"
27+
)
28+
29+
30+
@callback
31+
def async_get_provisioning_registry(
32+
hass: HomeAssistant,
33+
) -> dict[str, ProvisioningState]:
34+
"""Get the provisioning registry, creating it if needed.
35+
36+
This is a helper function for internal use.
37+
It ensures the registry exists without requiring async_setup to run first.
38+
"""
39+
return hass.data.setdefault(PROVISIONING_FUTURES, {})
40+
41+
42+
@callback
43+
def async_register_zeroconf_discovery(
44+
hass: HomeAssistant, mac: str, host: str, port: int
45+
) -> None:
46+
"""Register a zeroconf discovery for a device that was provisioned via BLE.
47+
48+
Called by zeroconf discovery when it finds a device that may have been
49+
provisioned via BLE. If BLE provisioning is waiting for this device,
50+
the host and port will be stored (replacing any previous values).
51+
52+
Multiple zeroconf discoveries can happen (Shelly service, HTTP service, etc.)
53+
and the last one wins.
54+
55+
Args:
56+
hass: Home Assistant instance
57+
mac: Device MAC address (will be normalized)
58+
host: Device IP address/hostname from zeroconf
59+
port: Device port from zeroconf
60+
61+
"""
62+
registry = async_get_provisioning_registry(hass)
63+
normalized_mac = format_mac(mac)
64+
65+
state = registry.get(normalized_mac)
66+
if not state:
67+
_LOGGER.debug(
68+
"No BLE provisioning state found for %s (host %s, port %s)",
69+
normalized_mac,
70+
host,
71+
port,
72+
)
73+
return
74+
75+
_LOGGER.debug(
76+
"Registering zeroconf discovery for %s at %s:%s (replacing previous)",
77+
normalized_mac,
78+
host,
79+
port,
80+
)
81+
82+
# Store host and port (replacing any previous values) and signal the event
83+
state.host = host
84+
state.port = port
85+
state.event.set()

0 commit comments

Comments
 (0)