Sonos controller for Scriptable

Inspired by @marco79’s Sonos now playing widget, I made a Sonos controller module for Scriptable, and I thought I’d share it here in case anyone finds it useful. The GitHub repo contains full documentation and a couple of example scripts.

@geoff thanks for sharing! Works like a charm… fantastic — jay

Thanks for that!
However, I don’t seem to be able to get “PLAYING” as a state for a room:

// Import the controller class and settings.
const SonosController = importModule('SonosController');
const settings = importModule('SonosSettings');

// Create a controller instance.
const controller = new SonosController(settings.sonosServerUrl);
let rooms = await controller.getRooms();
console.log(rooms);
for (let i = 0; i < rooms.length; i++) {
  let r = rooms[i];
  console.log(r);
  let st = await controller.getCurrentPlaybackState(r);
  console.log(`${r}: ${st}`);
  if (st === 'PLAYING') {
    let t = await controller.getCurrentTrack(r); 
    console.log(`${r}: ${t.artist}/${t.title}`)
 }
}

Although there’s music blasting from the three last rooms, I get this output:

2021-01-29 15:09:05: TV,Christians Zimmer,Bad,Wulfs Zimmer,Küche
2021-01-29 15:09:05: TV
2021-01-29 15:09:05: TV: STOPPED
2021-01-29 15:09:05: Christians Zimmer
2021-01-29 15:09:05: Christians Zimmer: STOPPED
2021-01-29 15:09:05: Bad
2021-01-29 15:09:05: Bad: STOPPED
2021-01-29 15:09:05: Wulfs Zimmer
2021-01-29 15:09:05: Wulfs Zimmer: STOPPED
2021-01-29 15:09:05: Küche
2021-01-29 15:09:05: Küche: STOPPED

Am I doing something stupid here? I’m not really comfortable with promises …

Update: After I stopped and restarted the playback on the Sonos controller, the script tells me “STOPPED” for the first two rooms and “undefined” for the state of the rest of them (where actually music is played).

Your script works for me, so I’m not sure what’s going on. You may want to grab SonosController.js from the GitHub repo again just to make sure you have the latest version. I’ve fixed a few bugs since I originally posted it here.

If your script still doesn’t work with the latest controller, try this script and see if it gives you a playback state for every room:

const SonosController = importModule('SonosController');
const settings = importModule('SonosSettings');
const controller = new SonosController(settings.sonosServerUrl);

let rooms = await controller.getRooms();

for (let r of rooms) {
  let state = await controller._getRoomState(r);
  console.log(`${r}: ${state.playbackState}`);
}

Let me know what happens and I’ll dig deeper if necessary.

1 Like

After having read up a bit on the node module, I’ll first try to update to the latest node version – I’m running v12 on a Synology, so that might be the cause…

Hi Geoff,

thanks again for your help. Several hours later and with a lot of new interesting experiences, I’ve now managed to run the Sonos server in a docker image on a Synology NAS. With that setup (and the most recent nodejs version, of course), your code works as promised.
So I avoided getting myself a Pi and learned some things :wink:

You’re welcome. Glad it’s working for you now.