Repository navigation
UniFi Play v1.4.0
What's new in 1.4.0
This is the quality-standards release. It is the same stack that shipped as
v1.4.0-beta.1, now marked stable. The last stable tag was v1.3.7.
The integration still talks to each speaker over MQTT on TCP 8883 with the
certificates the Play app uses. Nothing about the wire protocol was guessed
for this release: unverified discovery matchers and an async MQTT client stay
documented todos.
Restart Home Assistant after updating. Reloading a config entry does not
reload Python; only a restart picks up the new code.
Requirements
| 1.3.7 | 1.4.0 | |
|---|---|---|
| Home Assistant | 2024.1.0 | 2025.8.0 or newer |
| Python | whatever HA ran | 3.13 (HA's own) |
paho-mqtt |
>=2.0.0 |
>=2.1.0,<3.0.0 |
HACS will not offer 1.4.0 on a Home Assistant older than 2025.8.0. Update
Home Assistant first. Existing config entries, entity IDs and zone documents
on the speakers are unchanged.
Every push is tested against 2025.8.0 (Python 3.13) and the current
stable Home Assistant (Python 3.14).
Zones
A zone is a replace-all document on every speaker, and the protocol does not
propagate. 1.4.0 treats that as a constraint rather than hoping the speakers
agree.
- All or nothing. Create, rename, reorder, membership change and delete
preflight every required speaker, write to all of them or none, and raise
if anyone is missing. A half-applied zone is how a change "undoes itself"
later. - Submitted state is held until readback. A second Home Assistant edit
before the speakers report no longer rebuilds from the pre-write document,
so a rename then an index change keeps both. - Earlier Home Assistant writes are remembered. A delayed echo of the
first write does not discard a newer pending change. History is capped and
deduplicated; overflow is marked incomplete so an evicted echo is not
treated as a Play-app edit. - A Play-app edit that lands first wins once the speakers agree. The
pending Home Assistant snapshot is dropped when every speaker converges on
a foreign document. Last write still wins; that is the protocol. - Unconfirmed writes expire only after the last host-election re-read
and a short grace, not when that re-read is issued. One stale MQTT reply
must not drop a write the rest of the zone is about to confirm. - Zone events fire once from a merged view, not once per speaker copy.
Startup and reconnect do not emit "created" for zones that were already
there. - Reload no longer destroys zone entities. A reload used to sweep them
and take dashboard cards with it.
Overlapping config entries
Unique IDs are MAC-based (unifi_play_<MAC>_…). Two entries covering the
same speaker mint colliding IDs; Home Assistant rejects the later ones and
they read unavailable forever.
1.4.0 refuses the overlap on every discovery pass, not only at setup, and
opens a per-entry repair that names every owner. Unloading one entry
does not delete the other's repair. The remaining entry can adopt the
speakers and the repair closes.
Connection and commands
- A registered MQTT client is not a connected one. Commands that used to
no-op while disconnected and report success now raise. A dead connection
no longer looks like a broken service layer. - MQTT runs on paho's own thread (
loop_start()), not on a Home
Assistant executor worker.client.loop()in a task held one executor
worker permanently per speaker. - A stood-down Audio Port comes back. A Port that had exhausted
reconnects and then went silent on UDP 10001 was never offered to
_ensure_mqttagain. The poll now rebuilds that client. - Apollo failures are not an empty house. A console that returns HTML
(no Apollo) or an error used to parse as "no devices", which then looked
like every speaker had been removed. - Certificate fallback is unchanged and still used on connect and on the
discovery probe: both bundled generations are tried. Firmware 1.0.41
rotated the CA.
Console TLS
New console entries offer certificate verification and default it on.
A console reached at its LAN address will fail that check — Ubiquiti signs
for a name you are not connecting by — and setup says so. You can clear the
box.
Entries created before the option existed keep verification off, which
is what they did in 1.3.7. Reconfigure can turn it on if you reach the
console by a name your Home Assistant trusts.
Entities, translations, diagnostics
- Every entity name is a translation key. Settings are CONFIG, technical
status is DIAGNOSTIC, and the ten EQ bands stay disabled by default. - Download diagnostics is safe to paste: no API key, no certificates, no
raw MQTT. Addresses, MACs, zone IDs and device IDs are hashed consistently
within one report. Names and track titles are present-or-absent, never
quoted. - Brand icons ship under
custom_components/unifi_play/brand/for Home
Assistant 2026.3 (256×256 / 512×512 icons; logos at the brands shortest-
side maxima). - Actions are registered once for the whole run. Unloading a second config
entry no longer takes the actions away from the first.
What this release does not do
These are deliberate, documented gaps, not missing checklist items.
- No Home Assistant dhcp / zeroconf / ssdp discovery. The integration
still finds speakers itself (UDP 10001 on PowerAmp; MQTT identification
for Audio Ports). The Ubiquiti OUI is shared with APs and consoles; a
matcher that has not been measured on both models would open setup flows
for the wrong hardware. Seedocs/api.md. paho-mqttis still the runtime dependency. Replacing it needs a
candidate verified on both models against mutual TLS (both certificate
generations), BinMe, reconnect/fallback, and clean setup/reload/unload.
That evidence does not exist yet.- No published Home Assistant blueprint. The README still has an inline
automation onunifi_play_zone_member_changed. - Hardware smoke on both models is still the release checklist, not CI.
This tag was cut after the suite, both HA lanes, typing, hassfest, HACS
and the protocol guards passed. It is not a substitute for listening to
eARC on a PowerAmp and an Audio Port.
The Quality Scale tracker (custom_components/unifi_play/quality_scale.yaml)
is a self-assessment: 49 done, 2 exempt, 3 todo. The manifest does not claim
a hassfest tier. A weekly job compares the pinned official rule list to
hassfest so the tracker cannot silently rot.
Install
HACS installs from the repository as usual and will offer 1.4.0 as the
latest release. For a manual install, download unifi_play.zip and unpack
it into config/custom_components/, then restart Home Assistant.
The archive is built from the tagged commit with fixed timestamps and file
modes, so rebuilding it from this tag reproduces the published checksum:
python scripts/build_release_archive.py
sha256sum -c dist/unifi_play.zip.sha256