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:
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.