Skip to content

UniFi Play v1.4.0

Choose a tag to compare

@github-actions github-actions released this 05 Sep 07:52
5ca3963

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_mqtt again. 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. See docs/api.md.
  • paho-mqtt is 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 on unifi_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