openHAB integration to Spotify Web Connect API (player)


(Lukas Gill) #123

Below is the spotify.items file I’m using:

/* Switch to Force Update */
Switch spotify_forceupadte

/* Strings for Primary Auth */
String spotify_auth_code
String spotify_client_id
String spotify_client_secret

/* Strings for Token Auth */
String spotify_access_token "AccessToken [%s]"
String spotify_refresh_token "RefreshToken [%s]"
String spotify_token_expiry "TokenExpiry [%s]"
DateTime spotify_token_issued "TokenIssued [%s]"

/* Strings to store Player Data */
String spotify_current_track
String spotify_current_artist
String spotify_current_cover
String spotify_current_duration
String spotify_current_progress
Number spotify_current_progress_percent
Switch spotify_current_playing
String spotify_current_context_uri
String spotify_current_device
String spotify_current_device_id
Number spotify_current_volume

/* Switches for Player actions */
String spotify_action

DateTime spotify_lastConnectionDateTime

/* Strings to store JSONs */

String spotify_device_list

(Benjamin) #124

Mhm sry my guess was wrong. Actually its status 404 with “Item xxx not exist!” if openhab can’t find an item.

Btw your items file looks fine to me.

The error comes from the Spotify API itself. (https://developer.spotify.com/web-api/user-guide/#error-details -> “Regular error object”. It states “Here, for example is the error that occurs when trying to fetch information for a non-existent track”

Did you touch RAW_ROOT_URL in the spotify script? Replace your spotify script with the original one and redo the steps from the installation for it…

Cheers


(Lukas Gill) #125

I did everything as said in the installation instructions again and I still get the same error… :frowning:


(Benjamin) #126

Could you execute the following command (with a valid access token) and post the Output?

curl -X GET "https://api.spotify.com/v1/me/player" -H "Authorization: Bearer {your access token}"


(Lukas Gill) #127

I did that and it returned “The access token expired”. The openHAB item has an access token inside it, but every time when I reload the spotify-auth.html, it asks me to reauthorize. Any ideas why this is happening?

Thanks for helping me!

Actually…scratch that. I used a valid access token this time around and now it returns:

{
  "error" : {
    "status" : 400,
    "message" : "invalid id"
  }

(Benjamin) #128

Okay, already thought that this is the right place to look for.

Puh… but the error is still pretty mysterious to me. Did you try to delete your spotify application and create a new one?

If that does not help, I’m out out of ideas :-/ it must be something with your token, but it is so weird that you’re getting a ‘valid’ one from spotify to begin with…


(Lukas Gill) #129

I just figured it out after reading through lots of issues on GitHub. I listen to local tracks on my phone and since Spotify doesn’t seem to have an ID for those, it throws an error. When I play an item that’s actually on Spotify, it works flawlessly. Still thanks for your help though!


(Benjamin) #130

No problem! Glad that you made it. :slight_smile:


(fizzi) #131

hey folks,

i have an issue with setting up the spotify webconnect api…

In the instructions at point 7 (Test spotify.py in SSH) I always get an error:

File “/etc/openhab2/scripts/spotify.py”, line 6, in
import requests
ImportError: No module named requests

greetings

Fizzi


(Benjamin) #132

That sounds like you are running the script with Python Version 3. You need version 2 to get it running.

If you already use v2, try this:

OSX/Linux

Use sudo pip install requests if you have pip installed

Alternatively you can also use sudo easy_install -U requests if you have easy_install installed.


(fizzi) #133

thank you so far, I’ll check this when I am back at home…


(Dries) #134

Hi all,

First of all, thank you, @pmpkk for developing this nice script! I’m pretty happy with it. However, I do have some questions.

For some reason, the spotify_current_volume often stays “NULL”:

When I run “/usr/bin/python /etc/openhab2/scripts/spotify.py” I get:

Successfully got state from OpenHab: spotify_client_id
Successfully got state from OpenHab: spotify_client_secret
Successfully got state from OpenHab: spotify_access_token
Successfully got state from OpenHab: spotify_refresh_token
Successfully got state from OpenHab: spotify_token_issued
Successfully got state from OpenHab: spotify_token_expiry
-- Calling Service: Update
{u'progress_ms': 62769, u'timestamp': 1510077753987, u'repeat_state': u'off', u'shuffle_state': True, u'item': {u'album': {u'album_type': u'single', u'name': u'Whispers From The Surface Of A Lake', u'external_urls': {u'spotify': u'https://open.spotify.com/album/0n1BpWPDxPvlwMRV8kdRHH'}, u'uri': u'spotify:album:0n1BpWPDxPvlwMRV8kdRHH', u'href': u'https://api.spotify.com/v1/albums/0n1BpWPDxPvlwMRV8kdRHH', u'artists': [{u'name': u'Hior Chronik', u'external_urls': {u'spotify': u'https://open.spotify.com/artist/0WwDqOLT2m5PuAsFGkEybC'}, u'uri': u'spotify:artist:0WwDqOLT2m5PuAsFGkEybC', u'href': u'https://api.spotify.com/v1/artists/0WwDqOLT2m5PuAsFGkEybC', u'type': u'artist', u'id': u'0WwDqOLT2m5PuAsFGkEybC'}], u'images': [{u'url': u'https://i.scdn.co/image/d8797fde5ee16b8583b62a7608e66a26fc0e838e', u'width': 640, u'height': 640}, {u'url': u'https://i.scdn.co/image/f713eae5bd2deb7b300c32da232f941ecc003cde', u'width': 300, u'height': 300}, {u'url': u'https://i.scdn.co/image/a75c993b50b31dcaf8d7c032f1838289a7ab5cb6', u'width': 64, u'height': 64}], u'type': u'album', u'id': u'0n1BpWPDxPvlwMRV8kdRHH', u'available_markets': [u'AD', u'AR', u'AT', u'AU', u'BE', u'BG', u'BO', u'BR', u'CA', u'CH', u'CL', u'CO', u'CR', u'CY', u'CZ', u'DE', u'DK', u'DO', u'EC', u'EE', u'ES', u'FI', u'FR', u'GB', u'GR', u'GT', u'HK', u'HN', u'HU', u'ID', u'IE', u'IS', u'IT', u'JP', u'LI', u'LT', u'LU', u'LV', u'MC', u'MT', u'MX', u'MY', u'NI', u'NL', u'NO', u'NZ', u'PA', u'PE', u'PH', u'PL', u'PT', u'PY', u'SE', u'SG', u'SK', u'SV', u'TR', u'TW', u'US', u'UY']}, u'name': u'Whispers From The Surface Of A Lake', u'uri': u'spotify:track:24VAOoJabL301mmPSfYp5z', u'external_urls': {u'spotify': u'https://open.spotify.com/track/24VAOoJabL301mmPSfYp5z'}, u'popularity': 50, u'explicit': False, u'preview_url': u'https://p.scdn.co/mp3-preview/17ae089ea544384e310ea6c6a105a87cd5b5870b?cid=84cfb01a9ec74483b9930e16f025d4be', u'track_number': 1, u'disc_number': 1, u'href': u'https://api.spotify.com/v1/tracks/24VAOoJabL301mmPSfYp5z', u'artists': [{u'name': u'Hior Chronik', u'external_urls': {u'spotify': u'https://open.spotify.com/artist/0WwDqOLT2m5PuAsFGkEybC'}, u'uri': u'spotify:artist:0WwDqOLT2m5PuAsFGkEybC', u'href': u'https://api.spotify.com/v1/artists/0WwDqOLT2m5PuAsFGkEybC', u'type': u'artist', u'id': u'0WwDqOLT2m5PuAsFGkEybC'}], u'duration_ms': 163143, u'external_ids': {u'isrc': u'DEG931701144'}, u'type': u'track', u'id': u'24VAOoJabL301mmPSfYp5z', u'available_markets': [u'AD', u'AR', u'AT', u'AU', u'BE', u'BG', u'BO', u'BR', u'CA', u'CH', u'CL', u'CO', u'CR', u'CY', u'CZ', u'DE', u'DK', u'DO', u'EC', u'EE', u'ES', u'FI', u'FR', u'GB', u'GR', u'GT', u'HK', u'HN', u'HU', u'ID', u'IE', u'IS', u'IT', u'JP', u'LI', u'LT', u'LU', u'LV', u'MC', u'MT', u'MX', u'MY', u'NI', u'NL', u'NO', u'NZ', u'PA', u'PE', u'PH', u'PL', u'PT', u'PY', u'SE', u'SG', u'SK', u'SV', u'TR', u'TW', u'US', u'UY']}, u'context': {u'href': u'https://api.spotify.com/v1/users/spotify/playlists/37i9dQZEVXcOW89i3DotWz', u'type': u'playlist', u'uri': u'spotify:user:spotify:playlist:37i9dQZEVXcOW89i3DotWz', u'external_urls': {u'spotify': u'https://open.spotify.com/user/spotify/playlist/37i9dQZEVXcOW89i3DotWz'}}, u'device': {u'name': u'Living', u'volume_percent': None, u'is_active': True, u'is_restricted': False, u'type': u'CastVideo', u'id': u'414901afbea954d6873c39d448045c23'}, u'is_playing': True}
Successfully posted state to OpenHab: spotify_current_track = Whispers From The Surface Of A Lake
Successfully posted state to OpenHab: spotify_current_artist = Hior Chronik
Successfully posted state to OpenHab: spotify_current_cover = https://i.scdn.co/image/f713eae5bd2deb7b300c32da232f941ecc003cde
Successfully posted state to OpenHab: spotify_current_duration = 163143
Successfully posted state to OpenHab: spotify_current_progress = 62769
Successfully posted state to OpenHab: spotify_current_playing = ON
Successfully posted state to OpenHab: spotify_current_device = Living
Successfully posted state to OpenHab: spotify_current_volume = NULL
Successfully posted state to OpenHab: spotify_current_context_uri = spotify:user:spotify:playlist:37i9dQZEVXcOW89i3DotWz
Successfully posted state to OpenHab: spotify_current_device_id = 414901afbea954d6873c39d448045c23
Successfully posted state to OpenHab: spotify_current_progress_percent = 38.47
 -> Success
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-11-07T18:02:47+0000
Done in 0.517739057541 seconds

When I increase the volume (volume_up), I get:

Successfully got state from OpenHab: spotify_client_id
Successfully got state from OpenHab: spotify_client_secret
Successfully got state from OpenHab: spotify_access_token
Successfully got state from OpenHab: spotify_refresh_token
Successfully got state from OpenHab: spotify_token_issued
Successfully got state from OpenHab: spotify_token_expiry
-- Calling Service: Volume Up
Successfully got state from OpenHab: spotify_current_volume
 -> VolumeUp Failure:  <type 'exceptions.ValueError'>
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-11-07T18:05:44+0000
Done in 0.0548009872437 seconds

Another thing I noticed is that not all my devices have a Device ID:

Successfully got state from OpenHab: spotify_client_id
Successfully got state from OpenHab: spotify_client_secret
Successfully got state from OpenHab: spotify_access_token
Successfully got state from OpenHab: spotify_refresh_token
Successfully got state from OpenHab: spotify_token_issued
Successfully got state from OpenHab: spotify_token_expiry
-- Calling Service: Update
{u'progress_ms': 141323, u'timestamp': 1510079584958, u'repeat_state': u'off', u'shuffle_state': True, u'item': {u'album': {u'album_type': u'album', u'name': u'Yellow Hills', u'external_urls': {u'spotify': u'https://open.spotify.com/album/39CSo60wDA0GznZFJExlFu'}, u'uri': u'spotify:album:39CSo60wDA0GznZFJExlFu', u'href': u'https://api.spotify.com/v1/albums/39CSo60wDA0GznZFJExlFu', u'artists': [{u'name': u'Daniel Kaede', u'external_urls': {u'spotify': u'https://open.spotify.com/artist/6aup7uM4yUHX9NLba0sxmt'}, u'uri': u'spotify:artist:6aup7uM4yUHX9NLba0sxmt', u'href': u'https://api.spotify.com/v1/artists/6aup7uM4yUHX9NLba0sxmt', u'type': u'artist', u'id': u'6aup7uM4yUHX9NLba0sxmt'}], u'images': [{u'url': u'https://i.scdn.co/image/9e368c17ef08c092d95ef30fd68405a7498b0174', u'width': 640, u'height': 640}, {u'url': u'https://i.scdn.co/image/f47e4c781df3e439ed64e8c34f483a6aebb17bfe', u'width': 300, u'height': 300}, {u'url': u'https://i.scdn.co/image/5f18cbf24656817678a38298099a192385c06d99', u'width': 64, u'height': 64}], u'type': u'album', u'id': u'39CSo60wDA0GznZFJExlFu', u'available_markets': [u'AD', u'AR', u'AT', u'AU', u'BE', u'BG', u'BO', u'BR', u'CA', u'CH', u'CL', u'CO', u'CR', u'CY', u'CZ', u'DE', u'DK', u'DO', u'EC', u'EE', u'ES', u'FI', u'FR', u'GB', u'GR', u'GT', u'HK', u'HN', u'HU', u'ID', u'IE', u'IS', u'IT', u'JP', u'LI', u'LT', u'LU', u'LV', u'MC', u'MT', u'MX', u'MY', u'NI', u'NL', u'NO', u'NZ', u'PA', u'PE', u'PH', u'PL', u'PT', u'PY', u'SE', u'SG', u'SK', u'SV', u'TR', u'TW', u'US', u'UY']}, u'name': u'Unspoken Peace', u'uri': u'spotify:track:1aJAjwZXY8z3iJGayp5NIc', u'external_urls': {u'spotify': u'https://open.spotify.com/track/1aJAjwZXY8z3iJGayp5NIc'}, u'popularity': 38, u'explicit': False, u'preview_url': u'https://p.scdn.co/mp3-preview/08c6125eea944b30d1abea87d5f08adec1634424?cid=84cfb01a9ec74483b9930e16f025d4be', u'track_number': 1, u'disc_number': 1, u'href': u'https://api.spotify.com/v1/tracks/1aJAjwZXY8z3iJGayp5NIc', u'artists': [{u'name': u'Daniel Kaede', u'external_urls': {u'spotify': u'https://open.spotify.com/artist/6aup7uM4yUHX9NLba0sxmt'}, u'uri': u'spotify:artist:6aup7uM4yUHX9NLba0sxmt', u'href': u'https://api.spotify.com/v1/artists/6aup7uM4yUHX9NLba0sxmt', u'type': u'artist', u'id': u'6aup7uM4yUHX9NLba0sxmt'}], u'duration_ms': 193421, u'external_ids': {}, u'type': u'track', u'id': u'1aJAjwZXY8z3iJGayp5NIc', u'available_markets': [u'AD', u'AR', u'AT', u'AU', u'BE', u'BG', u'BO', u'BR', u'CA', u'CH', u'CL', u'CO', u'CR', u'CY', u'CZ', u'DE', u'DK', u'DO', u'EC', u'EE', u'ES', u'FI', u'FR', u'GB', u'GR', u'GT', u'HK', u'HN', u'HU', u'ID', u'IE', u'IS', u'IT', u'JP', u'LI', u'LT', u'LU', u'LV', u'MC', u'MT', u'MX', u'MY', u'NI', u'NL', u'NO', u'NZ', u'PA', u'PE', u'PH', u'PL', u'PT', u'PY', u'SE', u'SG', u'SK', u'SV', u'TR', u'TW', u'US', u'UY']}, u'context': {u'href': u'https://api.spotify.com/v1/users/spotify/playlists/37i9dQZEVXcOW89i3DotWz', u'type': u'playlist', u'uri': u'spotify:user:spotify:playlist:37i9dQZEVXcOW89i3DotWz', u'external_urls': {u'spotify': u'https://open.spotify.com/user/spotify/playlist/37i9dQZEVXcOW89i3DotWz'}}, u'device': {u'name': u'Keuken', u'volume_percent': 27, u'is_active': True, u'is_restricted': True, u'type': u'Speaker', u'id': None}, u'is_playing': True}
Successfully posted state to OpenHab: spotify_current_track = Unspoken Peace
Successfully posted state to OpenHab: spotify_current_artist = Daniel Kaede
Successfully posted state to OpenHab: spotify_current_cover = https://i.scdn.co/image/f47e4c781df3e439ed64e8c34f483a6aebb17bfe
Successfully posted state to OpenHab: spotify_current_duration = 193421
Successfully posted state to OpenHab: spotify_current_progress = 141323
Successfully posted state to OpenHab: spotify_current_playing = ON
Successfully posted state to OpenHab: spotify_current_device = Keuken
Successfully posted state to OpenHab: spotify_current_volume = 27
Successfully posted state to OpenHab: spotify_current_context_uri = spotify:user:spotify:playlist:37i9dQZEVXcOW89i3DotWz
Successfully posted state to OpenHab: spotify_current_device_id = NULL
Successfully posted state to OpenHab: spotify_current_progress_percent = 73.06
 -> Success
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-11-07T18:33:07+0000
Done in 0.548756122589 seconds

I guess that limits my “transfer_playback” options, right? Since that function is based on Device ID and not Device.

And I also notices that the list from “get_devices” is always different. Many of my devices only appear in that list if I am playing music via Spotify on that devices (started from the Spotify app). That also implies that the list in “get_devices” is shorter than the list I see via the app.

And there seems to be a small typo in spotify.items: I guess “spotify_forceupadte” should be “spotify_forceupdate”.

The final thing I noticed is… I can’t play a song of my choosing. :slight_smile: I can play/pause/next/previous. But none of these commands seem to do anything. What am I doing wrong?

/usr/bin/python /etc/openhab2/scripts/spotify.py play uri spotify:track:1snNAXmmPXCn0dkF9DaPWw
/usr/bin/python /etc/openhab2/scripts/spotify.py play spotify:track:1snNAXmmPXCn0dkF9DaPWw
/usr/bin/python /etc/openhab2/scripts/spotify.py play uri spotify:track:1snNAXmmPXCn0dkF9DaPWw Livingroom

What is the correct command to play a specific number on a specific device?


(Unparagoned) #136

What devices are you using when you get no volume or deviceid? I had some problems with my Echo and had to restart it and and set it up again, which might be worth trying.

In terms of playing a uri, it should just be

python spotify.py play spotify:user:spotify:playlist:37i9dQZF1Cz3pODEgZPUjE

The spotify webapi doesn’t play tracks uri. Try a playlist URI. In my local version you can also specify the track of the playlist you want to play, I can update my github with the latest version but its not that stable and may destroy your setup.


(Dries) #137

Hi @unparagoned,

Thanks!

I didn’t realize only playlist URI’s can be played. But that’s fine. This works:

/usr/bin/python /etc/openhab2/scripts/spotify.py play spotify:user:myuser:playlist:3XfiXADE66p6PzqfubTGL7

Regarding my other issues. I think it has more to do with the devices that have an incomplete/non-standard integration with Spotify.

My devices:

  • One Amazon Echo Dot. Device ID and volume ID are always shown. The devices is also always displayed in get_devices list. Spotify integration is perfect.
  • A few Chromecasts (regular, Ultra and Audio). Volume is always NULL. Device ID is shown. The device is only displayed in get_devices if I started to play Spotify on that device using the Spotify app. After a while (not playing), it disappears from get_devices and I can’t send any commands anymore (except when re-establishing the connection via the Spotify app). This makes home-automation integration pretty useless. I wanted a device to start playing when I enter a room.
  • I also have two Sonos devices. Integration is even more terrible here. Volume is shown correctly (as other information. However, device ID is missing. I’m also unable to send any commands to my Sonos device. Even when it’s playing Spotify stuff (initiated by the Spotify app).

I’m a bit disappointed in those Chromecasts. I bought two CC Audio devices, with the purpose of controlling them via OpenHAB. Seems like that was not a good idea. I stumbled upon a similar topic on the Home Assistant forum. So that seems to confirm the limitation is on Chromecast level…


(Unparagoned) #138

Yeh, quite a few devices pretty much close spotify after some time, which means the spotify webapi can’t see them since the device is off. Phones seem to turn off spotify instantly, google home after some no use, but my echos seem to keep them on. It makes sense from a device only perspective in terms of saving power, etc, but not from a homeautomation perspective.

One posible solution is to use the python script to send some kind of keep alive command to devices. That should work for say for google home but probably not for the phone. I’ll have a play to see if it works.

With the chromecast can’t you play spotify using the chromecast plugin? That way you can turn on spotify on the chormecast then use the spotify plugin. e.g. for my computer I use an alternative plugin to change the volume rather than through spotify (this is since I use an AVR, so keep everything on the comptuer at 100% and use the AVR to control the volume).

Edit:I rearead your post. Do you really mean the official spotify program and app can see the devices but they don’t show up when running get devices? In my experience if it doesn’t show in with get devices it doesn’t show up in the spotify app. Do you mean Sonos app?


(Dries) #139

Hi @unparagoned,

Yes. I was always referring to the official Spotify app (Android). Although in reality I use the Sonos app to control my Spotify on Sonos, for this analysis I solely used the Spotify app itself. The list in the Spotify app is often much longer than get_devices.

I’m not sure it’s related to power saving. Both my Sonos and Chromecast are always on. E.g. at this very time my Sonos is playing a TuneIn radiostation, and does not show up via “get_devices”.

A.f.a.i.k the ChromeCast binding does not support Spotify URI as input, only sources such as “http://www.something.com/sound.mp3”.

I think the Spotify app interacts with some devices (e.g. Echo) using the Spotify Web API, but also is able to interact with the ChomeCast (using CC API’s) and Sonos (using their API’s). That could explain why the list of devices is longer on the Spotify app than via get_devices.


(Unparagoned) #140

Are you using /usr/bin/python /etc/openhab2/scripts/spotify.py get_devices and looking at the terminal output? I know the habpanel interface doesn’t show variable updates properly.

In thoery if the spotify app knows there is a device so should the webapi, unless it’s connecting directly over the local network. Do you still see the devices if you turn off wifi on your phone?

I’m not really sure on how various devices work if they don’t use the webapi. I know the foobar plugin doesn’t seem to work properly with the webapi which means that there is probably an older legacy api about that isn’t really compatible with the webapi.

In terms of power saving I meant they turn the spotify app off or put it in standby rather than the whole device.


(Dries) #141

Hi,
Yes, I’m checking all input directly via SSH, so I’m pretty sure the output of get_devices is complete.

If I connect via 4G (wifi off), the only device I am seeing is the Amazon Echo. My Sonos/Chromecast are not visible anymore. So I guess Sonos/CC use other API’s…


(salphonso) #142

First off, amazing work on this you all. I am having an issues with playlists and devices. Everything else works great for me. Both generate a 404 response. I’m sure it’s something I have overlooked but I code/setting blind at the moment and can’t find the solution. Any help is greatly appreciated. Below is my ssh output:

root@HAServer:/etc/openhab2# /usr/bin/python /etc/openhab2/scripts/spotify.py devices
Successfully got state from OpenHab: spotify_client_id
Successfully got state from OpenHab: spotify_client_secret
Successfully got state from OpenHab: spotify_access_token
Successfully got state from OpenHab: spotify_refresh_token
Successfully got state from OpenHab: spotify_token_issued
Successfully got state from OpenHab: spotify_token_expiry
-- Calling Service: get devices
devices
https://api.spotify.com/v1/me/player/devices
Error posting state to OpenHab: spotify_devices (HTTP Response 404)
 -> Success
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-11-22T02:30:34+0000
Done in 0.297487974167 seconds
root@HAServer:/etc/openhab2# /usr/bin/python /etc/openhab2/scripts/spotify.py playlists
Successfully got state from OpenHab: spotify_client_id
Successfully got state from OpenHab: spotify_client_secret
Successfully got state from OpenHab: spotify_access_token
Successfully got state from OpenHab: spotify_refresh_token
Successfully got state from OpenHab: spotify_token_issued
Successfully got state from OpenHab: spotify_token_expiry
-- Calling Service: get playlists
playlists
playlists
https://api.spotify.com/v1/me/playlists
Error posting state to OpenHab: spotify_playlists (HTTP Response 404)
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-11-22T02:30:48+0000
Done in 0.611306905746 seconds

(salphonso) #143

Nothing a break and a beer can’t fix. It was a slightly skewed items file messing it up. Updated it accordingly and devices and playlists get a response. Now just need to figure out why they are not populating the dropdown menus.