Real-time events socket for an OAuth-connected account
(wss://<server>:6113/shelly/wss/hk_sock?t=<token>).
Start one per account with a handler; the handler receives normalized events in its own right — persistence, PubSub, whatever — while this process owns the connection and reconnects with backoff:
Shelly.Events.start_link(
server: account.user_api_url,
token: account.access_token,
handler: fn
{:status, device_id, status} -> MyApp.handle_status(device_id, status)
{:online, device_id, online?} -> MyApp.handle_online(device_id, online?)
{:other, _message} -> :ok
end
)device_id is normalized to lowercase hex (integer ids arrive on
some generations and are hex-converted; string ids pass through).
status is the raw payload for Shelly.Status.parse/4 — guard
before parsing: events may be partial deltas (only sys, an input
or battery changed), and parsing those as a full status reports a
false "off". Check Shelly.Status.has_component?/2, and when you
know the device's component, prefer comparing
Shelly.Status.component_of/2 against it.
Reconnection uses in-process exponential backoff with jitter (a WebSockex constraint — the process is unresponsive while it waits) and gives up after 10 consecutive failures, letting your supervisor's restart policy take over. Note the access token rides the websocket URL (Shelly's protocol); this module never logs the URL and redacts disconnect reasons.
Summary
Functions
Normalize a device id to lowercase hex (events arrive hex or decimal).