JavaScript Sample App

JavaScript Sample App

The Sonos Javascript Control API sample app demonstrates how easy it is to connect to a Sonos player using WebSockets and shows best practices for handling Sonos system events.

Because of planned security restrictions, browser-based apps will not be able to connect to websockets on Sonos players. Therefore, this sample consists of a Node.js/Electron app to find Sonos players and groups on the local network, with a user interface that displays album art, metadata, playback and volume controls for a selected group.

This is an early release version of the sample app and may be lacking features or may have unresolved bugs. See the README.md for details.

Download Source Code Package


Installing and running the sample app

Click the button above to download the JavaScript Sample App Source Code Package. The app requires a Node.js runtime environment and NPM, the Node Package Manager. Follow the instructions in the README.md to install and run the app.

In this overview, we’ll be focusing on using WebSockets and handling events. See the Discover (LAN) overview for details about player and group discovery.


Connect using WebSockets

The sample app listens for players on the network and displays the list of groups when you click the group selector area:

JSApp2b

Select a group to control playback and volume. When you select a group, the sample app creates a WebSocket connection to the group coordinator, as shown in the connect method of the SonosConnector object in connector.js:

The WebSocket constructor creates a WebSocket to the URL (with your API key appended) using the v1.api.smartspeaker.audio sub-protocol. The connect function also stores the household and group for later use when constructing messages to send to the group coordinator. It also registers callbacks on the WebSocket. We use the onMessage callback to separate messages by Control API namespace to pass to a user interface function to handle. For example, to display the state of the play/pause button. We’ll go over this in more detail in the section below.

Note that your app should not send Origin headers in WebSocket connections to Sonos players on local networks. This is to prevent unauthorized websites from opening WebSocket connections to your players. See Connect (LAN) for details. 


Handling events

The Sonos system may include multiple apps making changes to the system. Therefore, your app must handle events to show the current state of the system, so that changes made by different apps are reflected in your app. For example, you might use your app to start music in the living room, but your great grandmother, resting on the couch, may not want to hear it, so she may use her Sonos Controller app for Android to stop it. In this case, your app would have to handle the playbackStatus event to show that the music has been paused.

You can see an example of this in the sample app in the code snippet below from index.jade:

The sample app registers a callback function to receive playback namespace events using the subscribe method. When your great grandmother presses pause on her Sonos app, your sample app receives a playbackStatus event from the group coordinator with the playback state value PLAYBACK_STATE_PAUSED. This event invokes the callback function, which verifies the message type as a playbackStatus event, determines that the player is no longer playing using the playbackState value in the message body, and changes the control to the pause button.

By tying the UI display state to the playbackStatus event, your app stays in sync with changes.


Sending commands

When you click a playback button to make a change, for example, such as pressing the play button to play music, the app builds the Control API play command (in playback.js):

and sends it through the WebSocket (in connector.js) to the group coordinator:

All commands require a target ID, such as the householdId and groupId for the play command above. These IDs come from discovery. See the Discover (LAN) overview for details.


Stay tuned

We’ll update this sample with more guidance on key features and best practices, about:

  • The volume control slider – since players event back volume changes after you send them, there are some best practices for improving the user experience of the volume slider so that it doesn’t appear jumpy when you use it.
  • SSDP in the Node Server – we’ll add some details about how the sample app discovers groups using SSDP.