Page 1 of 3

Bose Soundtouch control

Posted: Saturday 24 February 2018 12:31
by MikeF
I have a Bose Soundtouch 20 Series II (Airplay version), and I recently came across this python library https://github.com/CharlesBlonde/libsoundtouch for accessing and controlling it.

I have created two simple (i.e., can be improved!) python scripts: selector and volume control.

Selector
This script uses a Domoticz selector switch to select from the 6 stored presets; I have extended it to add two streaming URLs, as well as the Soundtouch's AUX input:
Image
(I'm using 10 levels - 0 to 90 - but this can be extended / reduced as required.)

The code (see later) takes a single argument (0 to 9), corresponding to the above levels, and the selector actions have been set up as follows:
Image
Obviously, change this to correspond to the names for your presets!

Code:
Spoiler: show

Code: Select all

#!/usr/bin/env python

from libsoundtouch import soundtouch_device
from libsoundtouch.utils import Source, Type
import sys

bose = '<your Soundtouch wifi address>'
# put your stream URLs here			
url1 = 'http://178.33.232.106:8034/stream' 			
url2 = 'http://direct.fipradio.fr/live/fip-webradio2.mp3'

device = soundtouch_device(bose)
device.power_on()
presets = device.presets()

# read arg
arg = int(sys.argv[1])
print arg

if arg == 0: # power off
	device.power_off()
	
if 1 <= arg <= 6: # presets 1-6
	device.select_preset(presets[arg-1])

if arg == 7: # HTTP URL (not HTTPS)
	device.play_url(url1)

if arg == 8: # HTTP URL (not HTTPS)
	device.play_url(url2)
	
if arg == 9: # AUX
	device.select_source_aux()
Save this with the name and location specified in the selector actions (I used /home/pi/devices/bose.py).

Volume control
Set up a dummy switch in Domoticz, and change it to type 'dimmer' (0 - 100%).
Image

This uses the following python script:
Spoiler: show

Code: Select all

#!/usr/bin/env python

from libsoundtouch import soundtouch_device
from libsoundtouch.utils import Source, Type
from time import sleep
import requests
import json

bose = '<your Soundtouch wifi address>'
volIdx = '<Domoticz idx for dimmer switch>'
url = 'http://<domoticz url:port>/json.htm?type=devices&rid=' + volIdx
oldStatus = ''

device = soundtouch_device(bose)
device.power_on()

def domoticzread(var):
	response = requests.get(url)
	jsonData = json.loads(response.text)
	result = jsonData['result'][0][var]
	return result

while 1:
	volume = domoticzread('Level')
	status = domoticzread('Status')
	
	if status != oldStatus: 
		#print volume, status
		if status == 'Off':
			device.set_volume(0)
		else:
			# status = 'On' or 'Set Level: <x> %'
			device.set_volume(volume)
	oldStatus = status
	
	sleep(0.2)
This needs to be run in background, e.g.,

Code: Select all

python /home/pi/devices/bose_volume.py &
or started on boot in crontab.

(In both scripts, insert your own values in angle brackets: <...>)

I'm interested in any comments / suggestions for improvement.

Re: Bose Soundtouch control

Posted: Thursday 26 July 2018 22:08
by PhJack
Hi,
thank you for you post and sorry for my english approximate.
I used a script inspired by yours to turn on,select aux or turn off my bose soundbar from domoticz on a bananapi.
Howewer, it's been a few days that the "select aux" is not working anymore. I wonder if it's not due to an upgrade of firmware. Have you notice the same problem ?
I was realy happy having found this method thanks to your post since my attempt to duplicate the IR telecommand of the bose was a failure ...

Thank you for your help

Re: Bose Soundtouch control

Posted: Saturday 28 July 2018 18:09
by MikeF
Selecting AUX with my script works OK for me. I’m using the libsoundtouch library, and calling device.select_source_aux() in my Python script.

I haven’t upgraded the firmware on my Bose - I’m reluctant to do so, as the model I bought (on eBay) is a Series II, which has AirPlay support, and I don’t want to lose that.

Re: Bose Soundtouch control

Posted: Thursday 16 August 2018 18:37
by Furiousz23
I want to integrate my Bose Soundtouch into Domoticz, but cant figure out how to use this plugin. Can anybody point me in the right direction?

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 0:34
by MikeF
First of all, this is not a python plugin - I'm not familiar with the python plugin architecture - but a pair of python scripts which I knocked up quickly (sort of proof of concept).

1. Selector
The first one makes use of a selector switch in Domoticz (have a look at the Domoticz wiki if you're not au fait with this). It has 10 levels:
0 - Off
10 - 60: these match your Soundtouch presets
70 - 80: you can add 2 streaming URLs for additional radio stations here (these are url1 and url2 in bose.py)
90: selects AUX input.

You don't need 7 - 9, or you could add more levels.

Copy and save this as bose.py in your preferred location - I used the folder /home/pi/devices/ on my Raspberry Pi. You'll need to install the libsoundtouch python library for this to run - see the link at the start of my first post.

Edit the selector levels (click on Edit on the selector switch you've created), and enter the level names as you want them to appear in the selector dropdown (and choose selector style: select menu). You also need to add the selector actions for the levels you've chosen. The format for each action is as follows:

Code: Select all

script:///<path to saved bose.py> <n>
where <n> is a consecutive number from 0 - 9 (in my case, as I have 10 levels: 0 - 90). E.g., for level 10 in my system:

Code: Select all

script:///home/pi/devices/bose.py 1
2. Volume control
This is pretty much as I described it in my initial post. Again, copy and save this as bose_volume.py in your preferred location.


These scripts could certainly be improved (e.g., as a plugin), but as I said, this was primarily a proof of concept, and they work for me!

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 8:44
by Furiousz23
Great!!! Thank you for the details! The most of the steps i understand. It's specifically about installing the library.

All I have to do is SSH into the Pi and "pip install libsoundtouch"? Creating the script part and the selectors I get...

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 9:04
by MikeF
Yes (you might need to precede it with sudo).

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 11:25
by Furiousz23
Ok, installed the library with "sudo pip install libsoundtouch" and restarted the Domoticz service. Created the script and called it Bose.py, created the selector switch in Domoticz .

When i click on "Off" at the created selector in Domoticz i get the following error:

Code: Select all

2018-08-17 11:16:31.938 Error: Error executing script command (/home/pi/domoticz/scripts/Bose.py). returned: 256

Code: Select all

#!/usr/bin/env python

from libsoundtouch import soundtouch_device
from libsoundtouch.utils import Source, Type
import sys

bose = 'http://192.168.1.XX'
# put your stream URLs here			
url1 = 'http://178.33.232.106:8034/stream' 			
url2 = 'http://direct.fipradio.fr/live/fip-webradio2.mp3'

device = soundtouch_device(bose)
device.power_on()
presets = device.presets()

# read arg
arg = int(sys.argv[1])
print arg

if arg == 0: # power off
	device.power_off()
	
if 1 <= arg <= 6: # presets 1-6
	device.select_preset(presets[arg-1])

if arg == 7: # HTTP URL (not HTTPS)
	device.play_url(url1)

if arg == 8: # HTTP URL (not HTTPS)
	device.play_url(url2)
	
if arg == 9: # AUX
	device.select_source_aux()
In Domoticz it looks like this (just created the two selectors for testing)
Image

Running the Bose.py on the command line give`s this result:

Code: Select all

Traceback (most recent call last):
  File "./Bose.py", line 12, in <module>
    device = soundtouch_device(bose)
  File "/usr/local/lib/python2.7/dist-packages/libsoundtouch/__init__.py", line 23, in soundtouch_device
    s_device = SoundTouchDevice(host, port)
  File "/usr/local/lib/python2.7/dist-packages/libsoundtouch/device.py", line 122, in __init__
    self.__init_config()
  File "/usr/local/lib/python2.7/dist-packages/libsoundtouch/device.py", line 137, in __init_config
    "http://" + self._host + ":" + str(self._port) + "/info")
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 70, in get
    return request('get', url, params=params, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/api.py", line 56, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 488, in request
    resp = self.send(prep, **send_kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/sessions.py", line 609, in send
    r = adapter.send(request, **kwargs)
  File "/usr/lib/python2.7/dist-packages/requests/adapters.py", line 487, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='http', port=80): Max retries exceeded with url: //192.168.1.XX:8090/info (Caused by NewConnectionError('<requests.packages.urllib3.connection.HTTPConnection object at 0x75e499f0>: Failed to establish a new connection: [Errno -2] Name or service not known',))

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 15:15
by MikeF
It looks like your network can't see your Bose. At the risk of asking the obvious, have you got the correct ip address for your Bose (looking at this line in your script: bose = 'http://192.168.1.XX')? Can you do a network scan to check? (I can't remember what I did originally to configure my Bose.)

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 15:51
by Furiousz23
MikeF wrote: Friday 17 August 2018 15:15 It looks like your network can't see your Bose. At the risk of asking the obvious, have you got the correct ip address for your Bose (looking at this line in your script: bose = 'http://192.168.1.XX')? Can you do a network scan to check? (I can't remember what I did originally to configure my Bose.)
Yes, it`s absolute the right address. When i open http://192.168.1.XX i see the Bose Soundtouch "interface".

Re: Bose Soundtouch control

Posted: Friday 17 August 2018 20:18
by MikeF
Try the following commands in python 'immediate mode':

Code: Select all

from libsoundtouch import soundtouch_device
device = soundtouch_device('192.168.xx.xx') # substitute Bose url
print device.config.name
(taken from link in my first post - note: discover_devices produces an error).

If this errors / doesn't display your Soundtouch name, suggests a firmware incompatibility?

Re: Bose Soundtouch control

Posted: Saturday 18 August 2018 11:51
by Furiousz23
MikeF wrote: Friday 17 August 2018 20:18 Try the following commands in python 'immediate mode':

Code: Select all

from libsoundtouch import soundtouch_device
device = soundtouch_device('192.168.xx.xx') # substitute Bose url
print device.config.name
(taken from link in my first post - note: discover_devices produces an error).

If this errors / doesn't display your Soundtouch name, suggests a firmware incompatibility?
Will try that! Can you tell me wich command I have to use :| ?

Re: Bose Soundtouch control

Posted: Saturday 18 August 2018 13:25
by MikeF
Just type 'python' (no quotes!), and then enter each line at a time, after the '>>>' prompt.

Re: Bose Soundtouch control

Posted: Saturday 18 August 2018 18:11
by Furiousz23
MikeF wrote: Saturday 18 August 2018 13:25 Just type 'python' (no quotes!), and then enter each line at a time, after the '>>>' prompt.

Code: Select all

pi@raspberrypi:~ $ python
Python 2.7.13 (default, Nov 24 2017, 17:33:09) 
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from libsoundtouch import soundtouch_device
>>> device = soundtouch_device('192.168.1.5')
>>> print device.config.name
Bose Soundbar
>>> 
This is the result of typing the commands

Re: Bose Soundtouch control

Posted: Saturday 18 August 2018 23:10
by MikeF
...then it should work - try changing line 12 in your script to:

Code: Select all

device = soundtouch_device('192.168.1.5')

Re: Bose Soundtouch control

Posted: Sunday 19 August 2018 16:00
by Furiousz23
I think i got it working :shock: .

Last week i made a backup of my Raspberry Pi sd card and today i reversed to that backup. Installed the libsoundtouch again, created the Bose.py script and created the selector in Domoticz. First time i hit the selector i got an error:

Code: Select all

returned: 32256
After "sudo chmod 0777 Bose.py" the selector works ok and without errors. I`m not at home right now so i can`t check if the Bose responds to the commands. Will check this evening.

Thank you for your help :geek: !!!

Re: Bose Soundtouch control

Posted: Wednesday 22 August 2018 22:47
by PhJack
Hi Furiousz23,
can you tell me please what is the current firmware of your Bose soundtouch ? Is the cal of the function "device.select_source_aux()" working for you ?

Re: Bose Soundtouch control

Posted: Friday 24 August 2018 22:43
by Furiousz23
PhJack wrote: Wednesday 22 August 2018 22:47 Hi Furiousz23,
can you tell me please what is the current firmware of your Bose soundtouch ? Is the cal of the function "device.select_source_aux()" working for you ?

Hi

Unfortunately the selector switch didn't work after all, only the volume slider worked. In the Domoticz log there where no errors, but the sound touch didn't respond to the Domoticz selector commands. At the moment I just made a fresh install on my Raspberry, so I will try to get the Bose script working again.

Re: Bose Soundtouch control

Posted: Saturday 25 August 2018 22:35
by MikeF
Have you got your presets set up on your Bose Soundtouch? Try typing

Code: Select all

./Bose.py 1
to see if your Bose responds directly to the script - if it does, then you need to check your selector settings in Domoticz.

Re: Bose Soundtouch control

Posted: Sunday 26 August 2018 21:06
by Furiousz23
Ok... still having some problems. I just installed the libsoundtouch again and created the selectors in Domoticz. The dummy selector for inputs is working ok, but the volume selector isn`t working. In domoticz i get the following error:

Code: Select all

2018-08-26 21:01:14.445 Error: Error executing script command (/home/pi/domoticz/scripts/python/Bosevolume.py). returned: 256
When i type ./Bosevolume.py on the command line i get this error:

Code: Select all

Traceback (most recent call last):
  File "./Bosevolume.py", line 24, in <module>
    volume = domoticzread('Level')
  File "./Bosevolume.py", line 19, in domoticzread
    jsonData = json.loads(response.text)
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded