Link Search Menu Expand Document

Getting started

Using sonos2mqtt is really easy.

  1. Prerequisites
  2. Sonos2mqtt details
  3. Configuration
    1. Configuration by json file
  4. Run Sonos2mqtt with docker-compose
  5. Run sonos2mqtt with docker
  6. Run sonos2mqtt with node
  7. Events explained
    1. Event troubleshooting

Prerequisites

  • (local) mqtt server
  • always on (single board) computer

Sonos2mqtt details

What Value
Docker image ghcr.io/svrooij/sonos2mqtt:latest or svrooij/sonos2mqtt:latest
Docker image (beta) ghcr.io/svrooij/sonos2mqtt:beta or svrooij/sonos2mqtt:beta
NPM https://www.npmjs.com/package/sonos2mqtt

Configuration

Every setting of this library can be set with environment variables prefixed with SONOS2MQTT_. Like SONOS2MQTT_PREFIX=music to change the topic prefix to music.

sonos2mqtt 0.0.0-development
Control and monitor Sonos speakers through MQTT

Usage: index.js [options]

Options:
      --prefix         instance name. used as prefix for all topics     [default: "sonos"]
      --mqtt           mqtt broker url. See
                       https://sonos2mqtt.svrooij.io/getting-started.html#configuration
                                                             [default: "mqtt://127.0.0.1"]
      --clientid       Specify the client id to be used
      --wait           Number of seconds to search for speakers     [number] [default: 30]
      --log            Set the loglevel       [choices: "warning", "information", "debug"]
  -d, --distinct       Publish distinct track states                             [boolean]
  -h, --help           Show help                                                 [boolean]
      --ttslang        Default TTS language                             [default: "en-US"]
      --ttsendpoint    Default endpoint for text-to-speech
      --device         Start with one known IP instead of device discovery.
      --discovery      Emit retained auto-discovery messages for each player.    [boolean]
      --friendlynames  Use device name or uuid in topics         [choices: "name", "uuid"]
      --tvGroup        The UUID of the coordinator to which the Soundbar should be joined
      --tvUuid         The UUID of the soundbar which should auto stop the tvGroup
      --tvVolume       Volume the soundbar should go to when TV playback starts
      --experimental   Activate some cutting edge features                       [boolean]
      --version        Show version number                                       [boolean]

You can configure the mqtt url by setting a supported URL.

Most used format is mqtt(s)://[user]:[password]@[host]:[port] like mqtt://user:password@hostname:1883, or mqtts://user:password@hostname:8883 for a mqtt server supporting TLS.

Configuration by json file

Some systems don’t like the preferred docker way of configuration (which is environment settings), so it will also check for a json file when starting up.

  • Default path: /data/options.json
  • Override by setting: CONFIG_PATH

Sample file:

{
  "mqtt": "",
  "prefix": "sonos",
  "distinct": false,
  "device": "192.168.x.x",
  "ttslang": "en-US",
  "ttsendpoint": "",
  "discovery": false,
  "discoveryprefix": "homeassistant",
  "log": "information",
  "clientid": "",
  "friendlynames": "name"
}

Run Sonos2mqtt with docker-compose

We automatically build a multi-architecture image for amd64, arm64, armv7 and i386. This means you can run sonos2mqtt in docker on almost any device.

version: "3.7"
services:
  sonos:
    image: ghcr.io/svrooij/sonos2mqtt
    # or the dockerhub svrooij/sonos2mqtt
    restart: unless-stopped
    ports:
      - "6329:6329"
    environment:
      - SONOS2MQTT_DEVICE=192.168.50.4 # Service discovery doesn't work very well inside docker, so start with one device.
      - SONOS2MQTT_MQTT=mqtt://emqx:1883 # EMQX is a nice mqtt broker
      # - SONOS2MQTT_DISTINCT=true # if your want distinct topics
      # - SONOS2MQTT_MQTT_CA_PATH=/path/to/ca.crt # If you use a self-signed certificate
      # - SONOS2MQTT_MQTT_CERT_PATH=/path/to/cert.crt # If you want a secure connection
      # - SONOS2MQTT_MQTT_KEY_PATH=/path/to/key.key # If you want a secure connection
      # - SONOS2MQTT_MQTT_REJECT_UNAUTHORIZED=true # If you use official signed certificates
      - SONOS_LISTENER_HOST=192.168.50.44 # Docker host IP
      - SONOS_TTS_ENDPOINT=http://sonos-tts:5601/api/generate # If you deployed the TTS with the same docker-compose
    depends_on:
      - emqx

# You can skip the TTS server if you want. See https://github.com/svrooij/node-sonos-ts#text-to-speech
# Set the amazon keys to your own
# Set the SONOS_TTS_CACHE_URI to http://[ip_of_docker_host]:5601/cache
  sonos-tts:
    image: svrooij/sonos-tts-polly
    ports:
      - "5601:5601"
    environment:
      - SONOS_TTS_AMAZON_KEY=your_key_id_here
      - SONOS_TTS_AMAZON_SECRET=your_secret_access_token_here
      - SONOS_TTS_AMAZON_REGION=eu-west-1
      - SONOS_TTS_CACHE_URI=http://192.168.50.44:5601/cache

# Optional MQTT server (I like emqx over mosquitto)
  emqx:
    image: emqx/emqx
    restart: unless-stopped
    ports:
      - "1883:1883"
      - "18083:18083"

Run sonos2mqtt with docker

  1. Create an .env file with the following settings.
  2. Set the required values.
  3. Run docker run --env-file .env -p 6329:6329 ghcr.io/svrooij/sonos2mqtt
# Set the IP of one known sonos speaker (device discovery doesnt always work inside docker.)
SONOS2MQTT_DEVICE=192.168.x.x
# Set the mqtt connection string
SONOS2MQTT_MQTT=mqtt://ip_or_host_of_mqtt
# Publish distinct if your want
# SONOS2MQTT_DISTINCT=true
# Set the IP of the docker host (so node-sonos-ts knows where the events should be send to)
SONOS_LISTENER_HOST=192.168.x.x
# Set text-to-speech endpoint (optional)
# SONOS_TTS_ENDPOINT=https://tts.server.com/api/generate
# SONOS2MQTT_TV_UUID=RINCON_xxx01400 # Group coordinator of livingroom which coordinates media playbar
# SONOS2MQTT_TV_GROUP=RINCON_xxx01400 # Soundbar with Auto leave group when playback starts enabled
# SONOS2MQTT_TV_VOLUME=25 # Optional default volume for Soundbar

See configuration for additional settings.

Run sonos2mqtt with node

While you can run sonos2mqtt on bare metal (or a VM), it’s best avoided. It means you’re also responsible for making sure it’s restarted if there is an error. You can use a process manager for that task like, PM2 but setting it up is not supported by us.

Install the app globally sudo npm install -g sonos2mqtt

And start the app sonos2mqtt --mqtt mqtt://mqtt-host:1883 --device {sonos_ip_or_hostname}

Events explained

Sonos2mqtt doesn’t use any pull mechanism, it uses event subscriptions to get notified as soon as something on the speakers changes. Once this app is started, it tries to get an ip that should be used in the callback url. If you run this application inside docker, the application has no idea what the local ip of the machine running this application is.

That is why you have to tell the application the local ip of the docker host with the SONOS_LISTENER_HOST environment variable.

sequenceDiagram;
    participant s2m as Sonos2MQTT
    participant d as docker
    participant s as Sonos Speaker
    Note right of s2m: Create new subscription
    s2m-->>d: What ip is reachable for sonos speaker?
    d-->>s2m: Use this IP
    s2m->>s: Send service updates to http://ip:port please?
    s->>s2m: Here is your subscription ID
    Note right of s2m: Wait for updates
    loop When there is an update
        s->>d: "Service update" to (http://docker-ip:port)
        d->>s2m: "Service update" to (http://sonos2mqtt-ip:port)
        s2m->>s: Update received
    end
    Note right of s2m: Unsubscribe
    s2m-->>s: Cancel subscription with ID?
    s-->>s2m: Ok

Event troubleshooting

If you don’t see any messages from your sonos speaker, check the output of the container first. It should give you some good pointers.

We have a status page available for the event listener, at http://ip:6329/status where you should see a json document describing all the sonos subscriptions. If this doesn’t work, try through the following steps one by one until it works:

  1. Verify SONOS_LISTENER_HOST is set to the host machine ip
  2. Verify port 6329 has been bound in docker (See the docker-compose.yml below)
  3. Create an exception for 6329 in the firewall
  4. Make sure port 6329 is not in use by another service