Skip to content

fix(sonos): show room name, model and IP in discovery list - #396

Closed
vittobe wants to merge 1 commit into
sonn-audio:devfrom
vittobe:fix/sonos-discovery-room-name
Closed

vittobe wants to merge 1 commit into
sonn-audio:devfrom
vittobe:fix/sonos-discovery-room-name

Conversation

@vittobe

@vittobe vittobe commented Sep 26, 2026

Copy link
Copy Markdown
Contributor

Sonos discovery: show room name, model and IP in the output picker

Component: sonn-audio/core — Sonos output discovery (GET /transports/sonos/devices)
Tested on: ghcr.io/sonn-audio/core:beta, Sonos S2 firmware 97.1-80312 (Beam, Sub, 2× One)

Problem

In Zones → Output routing → Devices, Sonos speakers were listed by their raw UPnP friendlyName:

172.16.0.178 - Sonos Beam - RINCON_949F3ED056A401400

The room name configured in the Sonos app (e.g. Television) was never shown, which makes picking the right speaker hard in a larger household.

Root cause

Three issues in src/adapters/outputs/sonos/sonosDiscovery.ts:

  1. Wrong priority. resolveDeviceFromLocation() set name: friendlyName ?? status?.roomName. friendlyName is always present, so the room name never won. The admin UI renders device.name first.
  2. Room name read from the wrong place. It was only looked up in /status/zp. Current S2 firmware has no <RoomName> there; the <ZoneName> fallback includes a channel suffix (Television (LF,RF)).
  3. Available data ignored. The device description XML — already fetched during discovery — contains <roomName>Television</roomName> and <modelName>Sonos Beam</modelName>, but neither was parsed.

Changes

src/adapters/outputs/sonos/sonosDiscovery.ts

  • Parse <roomName> from the device description and use it as the primary room name, falling back to /status/zp.
  • Parse <modelName> and return it as a new model field.
  • name now prefers the room name over friendlyName.
  • New helper stripChannelSuffix() removes suffixes like (LF,RF), (LF), (RF) from the <ZoneName> fallback (still used by the network-scan path).

src/adapters/http/adminApi/transports/transportsHandlers.ts

  • handleSonosDiscovery() builds the display name as roomName · model · host and also returns model as a separate field.

src/ports/OutputDiscoveryPort.ts

  • Added optional model?: string to SonosDiscoveredDevice.

Result

Before After
172.16.0.104 - Sonos One - RINCON_48A6B8F652EA01400 Kitchen · Sonos One · 172.16.0.104
172.16.0.178 - Sonos Beam - RINCON_949F3ED056A401400 Television · Sonos Beam · 172.16.0.178
172.16.0.150 - Sonos Sub - RINCON_949F3EA0BBEE01400 Television · Sonos Sub · 172.16.0.150
172.16.0.117 - Sonos One - RINCON_48A6B8F652A201400 Dining Room · Sonos One · 172.16.0.117

The subtitle line (Sonos <householdId>) is unchanged; it is produced by the admin UI (sonn-audio/adminui, ZonesView.tsx), not by core.

Side effects

  • The admin UI stores the selected device's name as the zone's deviceName. Newly selected devices will store the new room · model · host string. This is harmless: host is stored as well and takes precedence; previously the raw friendlyName was stored, which was equally verbose.
  • deviceName is only used as a fallback match when no host is configured.

Known remaining issue (not fixed here)

Bonded satellites (Sub, surrounds, the passive member of a stereo pair) are still listed as separate devices. enrichWithTopology() is meant to hide them, but:

  • parseTopology() only matches <ZoneGroupMember> elements, while home-theatre satellites are nested <Satellite> elements;
  • /status/topology may not be served by current S2 firmware, in which case the filter silently does nothing.

Suggested fix: determine satellites via the ZoneGroupTopology SOAP action GetZoneGroupState on port 1400.

rudyberends added a commit that referenced this pull request Oct 3, 2026
The picker listed speakers as "192.168.1.20 - Sonos Beam": the device
description's friendlyName names the box, not the room. S2 firmware also
dropped <RoomName> from /status/zp, leaving a ZoneName with the channels
glued on, "Living Room (LF,RF)". The room now comes from the description's
<roomName>, a ZoneName loses only real Sonos channel codes (so "Office (AV)"
stays), and XML entities are decoded. The model is reported alongside, so
the picker can tell two speakers apart without folding it into the name a
zone saves and rediscovers by.

Refs #396

Co-Authored-By: Jeroen Van Daele <github.com@vitto.eu>
@rudyberends rudyberends closed this Oct 3, 2026
rudyberends added a commit that referenced this pull request Oct 3, 2026
The picker listed bonded speakers as rooms ("Television · Sonos Sub"), and
a zone pointed at one sent its audio to a speaker that only follows. The
topology meant to hide them and map them to their coordinator was read
from /status/topology, which S2 no longer serves and whose shape the
parser never matched, so neither ever happened. It now comes from the
ZoneGroupTopology GetZoneGroupState action, and a home theatre's Sub and
surrounds, nested as <Satellite> elements, count as passive alongside an
invisible stereo-pair member.

Refs #396

Co-Authored-By: Jeroen Van Daele <github.com@vitto.eu>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants