Community. Driven. Weather. Data. | Always Ad-Free | Developer FriendlyChecking statusDiscord
WxAlerts.org, Community Driven Weather Data
Support us
Sign in
Home Assistant

How it connects

One MQTT connection, retained alerts, tombstones instead of expiry math, and the subscription budget you are spending.


Worth understanding if you are debugging, running many zones, or deciding whether to point the integration at a broker of your own.

One connection, two topic trees

The integration opens exactly one MQTT v5 connection over WebSocket to wss://mqtt.wxalerts.org/mqtt on port 443: TLS, public, read-only. The credential wxalerts / wxalerts is published on purpose; the broker’s ACL denies publish on every topic, so there is nothing to protect.

It subscribes only to what you configured:

wxalerts/nws/v1/same/{same}/#     one per distinct county, QoS 1
wxalerts/glm/v1/{g}/{g}/{g}/#     one per distinct lightning box, QoS 0

The alert tree is keyed by SAME code and each hazard occupies its own topic, with the VTEC event tracking number as the last level, which is why two simultaneous tornado warnings for one county stay distinct instead of overwriting each other. The tree is documented in full on the MQTT alerts feed page.

The lightning tree is the same one the live map draws from and is documented in full on the MQTT feed page.

The client identifies itself as wxha-<instance>-<entry>, derived from your Home Assistant instance ID, so two Home Assistants on one network do not fight over a session.

Retained alerts, and tombstones

Live hazards are retained on the broker. Subscribing replays every one of them immediately, so a fresh start or a reconnect repopulates every entity in one burst, with no polling and no window where the sensors say unknown while a warning is in effect.

A hazard ends by way of a tombstone: an empty retained payload on its topic. The integration drops the alert the moment one arrives.

This matters more than it sounds. Expiring alerts on local clock arithmetic means a cancelled warning hangs around until its original end time, and a Home Assistant whose clock has drifted gets it wrong in both directions. The feed’s status field and its tombstones are trusted over any local calculation.

Reconnecting

Connection drops are handled with exponential backoff: 2 seconds, doubling to a 5-minute ceiling, reset once a connection has held for two minutes. The backoff is not politeness: every resubscribe replays the entire retained set, so a hot reconnect loop is expensive for both ends.

While disconnected, every entity is unavailable rather than stale. See Entities and attributes.

Reading the message stream doubles as the liveness check. A held MQTT session with nobody reading the socket does not notice that the other end is gone, which is the classic way an MQTT integration goes quiet for hours without logging anything.

The subscription budget

The broker allows 20 subscriptions per client; the integration spends at most 18 and keeps the rest as headroom. That is roughly nine counties plus nine lightning boxes.

Past that limit, alerts are kept and lightning boxes are dropped from the end, with a warning in the log:

Configuration needs 22 subscriptions but the broker allows 18;
dropping the last 4 lightning subscriptions

Counties and boxes are both deduplicated first, so several zones in one county cost one subscription, and several zones in one lightning box cost one more. Widening the lightning box size is the cheapest way to get back under the cap.

Running against your own broker

If you already bridge the WxAlerts topics into a local Mosquitto or EMQX, with one upstream connection serving a whole house, the MQTT transport in the integration is a single swappable object (FeedClient in coordinator.py).

There is no host override in the UI yet. It is the planned path to a local_push deployment, and the code is arranged for it, but today the broker address is fixed. Follow the repo if you want it.