Releases: sonn-audio/node-sonos
Release list
v0.3.0
The S1 backend no longer depends on @svrooij/sonos. It speaks UPnP itself, on top of @sonn-audio/node-upnp.
Why
That package's npm latest is 2.5.0, published in June 2022, and it pins fast-xml-parser 3.19.0 — a line carrying two unpatched advisories (prototype pollution via a tag or attribute name; XMLBuilder CDATA injection) whose fixes exist only in 4.x and 5.x. No range bump could reach them.
What we actually used of it was small: device identity, ZoneGroupState, GetPositionInfo/GetMediaInfo, nine events and six transport commands. All of it is plain UPnP.
What's new
- Radio now-playing works. Read out of Sonos's own
r:streamContent, wheredc:titlestays fixed on the station name.streamInfoused to always beundefined. - Group reshuffles arrive as ZoneGroupTopology events instead of waiting up to 30 s for the poll, which is now only a safety net.
- Commands are addressed with the coordinator's own host and port from the topology, rather than the port the client was constructed with.
npm auditis clean.
Testing
There is no S1 hardware in this loop, so scripts/s1-probe.mjs drives the client against a fake speaker reproducing the wire format — device description, SOAP control, and GENA NOTIFYs carrying the double-escaped DIDL that real firmware sends. It found two real bugs during development. Run it with npm run build && npm run probe:s1.
Breaking changes
S1SonosGroupandS1SonosPlayertake(client, seed); theSonosDeviceargument is gone.- Track metadata on the group's
apply*methods isUpnpTrack(lowercase fields), not@svrooij/sonos'sTrack.
v0.2.4
fix(websocket): reconnect after the socket dies instead of wedging fo…
v0.2.3
Move to the @sonn-audio npm scope (formerly @lox-audioserver/node-sonos).
v0.2.2
fix(websocket): request Sonos subprotocol via ws protocols arg The S2 WebSocket sent 'Sec-WebSocket-Protocol: v1.api.smartspeaker.audio' as a raw header. ws only tracks a requested-protocol set when the subprotocol is passed as the constructor's protocols argument; with the header form that set is empty, so when Sonos echoes the subprotocol in its 101 response ws aborts with 'Server sent a subprotocol but none was requested'. The handshake reached 101 but then errored — observed in the field as 'Failed to connect (upgrade 101 Switching Protocols)', leaving the state controller in an endless reconnect loop and no external events. Pass the subprotocol as the protocols argument instead. Bump 0.2.2.
v0.2.1
fix(discovery): disable TLS validation on S2 generation probe detectGeneration probed https://host:1443 with plain undici fetch, which rejects Sonos S2's self-signed cert (DEPTH_ZERO_SELF_SIGNED_CERT). The probe then fell through to the S1 branch, and since S2 speakers also serve the legacy UPnP device description on :1400, every S2 unit was misclassified as S1 and routed to the SOAP backend instead of the WebSocket event stream. Pass the same rejectUnauthorized:false dispatcher that getDiscoveryInfo and the WebSocket client already use; expose it as an override. Bump 0.2.1.
v0.2.0
docs: update README for S1 support Fixes the broken `@lox-audioserver/sonos` import example (was missing the `node-` prefix), and documents the new S1 path: `S1Client`, `detectGeneration`, the auto-detect pattern, S1-specific options, and which features are S2-only.
v0.1.4
fix: refresh active group on every groups event handleGroupsEvent only called player.checkActiveGroup() indirectly via setupGroup for newly added groups. After updates or removals the cached activeGroup went stale, so player.group could return a stale or null group and follow-up commands (e.g. resume after pause) were silently dropped by consumers. Call checkActiveGroup() once after processing all adds/updates/removals. Bump to 0.1.4.
v0.1.3
Surface WebSocket upgrade failures and discovery info The WS connect path previously collapsed any handshake failure into a generic "Failed to connect" error, hiding the HTTP status that the player returned. Capture the unexpected-response event so the status code, status message, headers, and body (first 512 bytes) end up in the logs and in the resulting CannotConnect message. Also log the discovery result (playerId, householdId, websocketUrl) on success and emit a warn if the discovery HTTP call itself fails. Bump to 0.1.3.
v0.1.2
Rename project from lox-sonos-controller to node-sonos