IR Sonos Control

I currently have a URC programmable remote configured with a Sonos option that turns on the receiver, selects the input with the Sonos Connect attached when pressed. At this point, only volume and mute can be operated on the receiver from the remote, no Sonos control.

Sonos speakers have no display, minimal controls (volume/play/pause) and no IR remote control. It must therefore be controlled from a smartphone, tablet, or computer. This is normally desired as these devices provide full control and the ability to browse and select media.

However, it would be nice to have quick play/pause/next/previous control from the IR remote. It’s much quicker to press a physical button on a remote than to open an app.

Getting Started

I’m using an Intel NUC running Kubuntu 18.04 as a home theater PC. It has a built-in IR receiver and has been configured to work with LIRC. How to configure LIRC will not be covered here, it’s assume you already have it working, but if I recall correctly, it worked with no special configuration.

I’m using LIRC already control Kodi which is being used as a front-end to MythTV. A Windows Media Center remote (actually a URC remote configured to send WMC remote codes) is being used to send IR commands to LIRC. Kodi then receives the IR commands from LIRC.

LIRC also has the ability to execute a program via irexec. It simply watches for IR commands and executes a corresponding program. Since the computer is also on the same network as the Sonos, it should be possible to execute a program to send commands to the Sonos.

Controlling Sonos from the Command Line

My search first lead me to sonos-cli. It appears to have the needed options – play, pause, next. Previous seems to be missing though. However, at this time (Oct. 2018), this program does not work, a recent Sonos update appears to have broken it. It also appears to be relative slow, taking a second or two just to start execution.

I was not able to find another Sonos command line control utility, but did find a Python library. The SoCo Python library allows control of a Sonos speaker from a Python script. It turns out it’s very easy to use. Using this I was able to quickly write a simple script to issue the needed commands.

This library was installed via the command:

pip install soco

Python and Pip must also be installed.

On Ubuntu:

apt install python

apt install python-pip

 

I’m new to Python, but was able to quickly create simple scripts for play, pause, next and previous. Only 3 lines of code needed. Later I was able to create an improved single script to provide all functions.

Here’s the play example:

#!/usr/bin/env python
from soco import SoCo

sonos = SoCo('192.168.1.156')

sonos.play()

This makes a connection to the Sonos speaker with IP address 192.168.1.156 and issues a play command. The functions sonos.pause(), sonos.next(), and sonos.previous() are substituted to provide the needed options. There is also a function to connect by speaker name. This is better as the IP may change, however, by IP is about 1/4 second faster.

Here’s a link to the script I came up with and am using for control:

sonos.py

Usage examples:

Start playback using speaker’s name:

sonos --name="Speaker Name" --play

Pause playback using speaker IP address:

sonso --ip-address=192.168.1.2 --pause

Current options:

-i, --ip-address=ADDRESS    Connect using IP address or hostname of Sonos speaker.
-n, --name=NAME             Connect using name of Sonos Speaker. CaSe counts.
                              Ignored if IP address option is specified.
-d, --discover              List Sonos speakers on the network.
--uri=URI                   Play a URI. URI example:
                              "x-rincon-mp3radio://http://server/mp3path".
--nowplaying                Display current playback title.
--status                    Display current playback status.
--play                      Begin playback.
--pause                     Pause playback.
--previous                  Play previous item.
--next                      Play next item.

The –ip-address or –name must be supplied for all commands except –discover. Again, being new to Python, it could be better, errors are not handled well for invalid IP or URI. This script requires Python and the SoCo library installed.

Back to LIRC

Now that we have a working control of the speaker for the command line, LIRC/irexec can now be set up to issue the necessary commands.

4 unused remote buttons must be selected and identified. Since my play, pause, next, previous buttons were already being used by Kodi, I needed to pick other buttons. Since I’m using a programmable URC remote, any code can be assigned to the physical remote buttons.

In a terminal, run the command irw. Press buttons on the remote, irw will print out the LIRC button names. If it does not, LIRC may not be configured correctly. These names will be needed by irexec.

I chose the following buttons:

Remote Button "Audio", LIRC name "KEY_LANGUAGE"
Remote Button "My Radio, LIRC name "KEY_RADIO"
Remote Button "Print", LIRC name "KEY_PRINT"
Remote Button "Subtitle". LIRC name "KEY_TITLE"

With buttons identified, it’s just a matter of telling irexec what to do when they’re pressed. This is done via the irexec.lircrc  configuration file. It is located in /etc/lirc.

Here’s my irexec.lircrc:

begin
prog = irexec
button = KEY_LANGUAGE
config = /usr/local/bin/sonos --name=Theater --previous
end

begin
prog = irexec
button = KEY_RADIO
config = /usr/local/bin/sonos --name=Theater --next
end

begin
prog = irexec
button = KEY_PRINT
config = /usr/local/bin/sonos --name=Theater --play
end

begin
prog = irexec
button = KEY_TITLE
config = /usr/local/bin/sonos --name=Theater --pause
end

Its format is simple, set button equal to the LIRC button found by irw, set config to the program to execute. The irexe daemon needs to be restarted after modifying this file:

service irexec restart

At this point, the remote should now control Sonos. The sonos.py script is located in /usr/local/bin with a symbolic link from sonos to it.