AWS IoT button and Sonos

IoT button

UPDATE 29/04/2016: I fixed this issue - see here.

I picked up an AWS IoT button at re:Invent this year. I didn’t really know what I would do with it and it sat in a drawer for a few weeks waiting for an idea to appear. Last week, one finally did.

At home we have a Sonos system for multi-room audio. My wife’s main use case is to listen to triplej in the kitchen/diner and bedroom areas in the morning before she goes to work or uni. We have a few ways to control the Sonos system, each with pros and cons:

So how about using the button? Press once to start triplej. Press again to stop playback. Sounds achievable.

Logical diagram


  1. Link the AWS IoT button to the IoT service. The wizard does a decent job of registering your ‘Thing’ (button) and creating a default linked certificate (to authenticate your button), a policy (granting AWS access for the button) and a rule (what happens when the button is pressed).

  2. Write Lambda code. In pseudo-code we’re just doing

    get current Sonos playing state
        if not playing
    start triplej
    pause playback

    node.js is the language most of the Sonos and Echo integrations use. In particular I use the node-sonos-http-api project to expose an API for Sonos play/pause/group/volume functions. I set this up a while back to support use of the echo-sonos project, including an external endpoint running on a server in my internal network, so Lambda has an endpoint to talk to. My code is here, if you use it you should

    • add more error checking
    • fill in your own server IP or DNS name and port that is used for external access to your node-sonos API server
    • set up your own presets within node-sonos
  3. Set the IoT rule to trigger your Lambda function on button press.

So we end up with something that looks like this:

IoT console

The revoked certificates are from testing (there appears to be no way to delete a certificate — so the console will get messy) and we will come to the reason for the S3 and SNS actions..

I tried testing from a starting state of silence and… yes, triplej plays. Then stops. Then plays again. Try again. It starts… and stops. Odd. Checking the Lambda logs in CloudWatch Logs shows the function is running multiple times. As I’m not an experienced node.js or Lambda developer this led me down the rabbit hole of ‘why is my code looping?’. After a while I suspected that the IoT button was triggering multiple invocations of my Lambda function but as the IoT service doesn’t directly support logging I needed another way to prove this — which is where the S3 and SNS rule actions come in. I set things up to log to S3 and to an SNS topic and then to email when the button was pressed, pressed the button once and got this:

One click, two notifications. It looks like there is an issue with my IoT button. I’ve contacted AWS to see if this is a known issue and if I can get a replacement, but given these were given away at a convention in the U.S. it’s unlikely they have spares or would be willing to ship one to me in Australia.

Back in the drawer with you, button. Not every project can be a success.