openHAB integration to Spotify Web Connect API (player)

Those having issues on windows may want to look at how the path variable is set up for python. I assume it won’t be /usr/bin/python

Setted the path on windows variables and from win console i can use “python [scriptPath]” without problem, but still not working on openhab console, the problem is the missing of error message :confused:

Hi all,i have this message when test spotify.py,
Successfully got state from OpenHab: spotify_token_expiry
– Calling Service: Update
{
“timestamp” : 1502806217089,
“progress_ms” : 243053,
“is_playing” : true,
“item” : {
“album” : {
“album_type” : “compilation”,
“artists” : [ {
“external_urls” : {
“spotify” : “https://open.spotify.com/artist/711MCceyCBcFnzjGY4Q7Un
},
“href” : “https://api.spotify.com/v1/artists/711MCceyCBcFnzjGY4Q7Un”,
“id” : “711MCceyCBcFnzjGY4Q7Un”,
“name” : “AC/DC”,
“type” : “artist”,
“uri” : “spotify:artist:711MCceyCBcFnzjGY4Q7Un”
} ],
“available_markets” : [ “AD”, “AR”, “AT”, “AU”, “BE”, “BG”, “BO”, “BR”, “CA”, “CH”, “CL”, “CO”, “CR”, “CY”, “CZ”, “DE”, “DK”, “DO”, “EC”, “EE”, “ES”, “FI”, “FR”, “GB”, “GR”, “GT”, “HK”, “HN”, “HU”, “ID”, “IE”, “IS”, “IT”, “JP”, “LI”, “LT”, “LU”, “LV”, “MC”, “MT”, “MX”, “MY”, “NI”, “NL”, “NO”, “NZ”, “PA”, “PE”, “PH”, “PL”, “PT”, “PY”, “SE”, “SG”, “SK”, “SV”, “TR”, “TW”, “US”, “UY” ],
“external_urls” : {
“spotify” : “https://open.spotify.com/album/4ydl8Ci7OsndhI2ALnrpIv
},
“href” : “https://api.spotify.com/v1/albums/4ydl8Ci7OsndhI2ALnrpIv”,
“id” : “4ydl8Ci7OsndhI2ALnrpIv”,
“images” : [ {
“height” : 640,
“url” : “https://i.scdn.co/image/a6d307979309bfc1b8ba9ca64aeae4dc9f51f1ce”,
“width” : 640
}, {
“height” : 300,
“url” : “https://i.scdn.co/image/fed88d1739d842a4b706594ed2af44720634fdd3”,
“width” : 300
}, {
“height” : 64,
“url” : “https://i.scdn.co/image/9b3cc150a0fea3e7fdeb1c18253df9570046ca09”,
“width” : 64
} ],
“name” : “Iron Man 2”,
“type” : “album”,
“uri” : “spotify:album:4ydl8Ci7OsndhI2ALnrpIv”
},
“artists” : [ {
“external_urls” : {
“spotify” : “https://open.spotify.com/artist/711MCceyCBcFnzjGY4Q7Un
},
“href” : “https://api.spotify.com/v1/artists/711MCceyCBcFnzjGY4Q7Un”,
“id” : “711MCceyCBcFnzjGY4Q7Un”,
“name” : “AC/DC”,
“type” : “artist”,
“uri” : “spotify:artist:711MCceyCBcFnzjGY4Q7Un”
} ],
“available_markets” : [ “AD”, “AR”, “AT”, “AU”, “BE”, “BG”, “BO”, “BR”, “CA”, “CH”, “CL”, “CO”, “CR”, “CY”, “CZ”, “DE”, “DK”, “DO”, “EC”, “EE”, “ES”, “FI”, “FR”, “GB”, “GR”, “GT”, “HK”, “HN”, “HU”, “ID”, “IE”, “IS”, “IT”, “JP”, “LI”, “LT”, “LU”, “LV”, “MC”, “MT”, “MX”, “MY”, “NI”, “NL”, “NO”, “NZ”, “PA”, “PE”, “PH”, “PL”, “PT”, “PY”, “SE”, “SG”, “SK”, “SV”, “TR”, “TW”, “US”, “UY” ],
“disc_number” : 1,
“duration_ms” : 273840,
“explicit” : false,
“external_ids” : {
“isrc” : “AUAP07900029”
},
“external_urls” : {
“spotify” : “https://open.spotify.com/track/1V6kRlJnTC4W319N0BvJag
},
“href” : “https://api.spotify.com/v1/tracks/1V6kRlJnTC4W319N0BvJag”,
“id” : “1V6kRlJnTC4W319N0BvJag”,
“name” : “If You Want Blood (You’ve Got It)”,
“popularity” : 61,
“preview_url” : “https://p.scdn.co/mp3-preview/e964a5be5f2f6f13712e81ab02713df08d8421c2?cid=f1fbae74042d42c9816a88e6c04d4098”,
“track_number” : 7,
“type” : “track”,
“uri” : “spotify:track:1V6kRlJnTC4W319N0BvJag”
},
“context” : {
“external_urls” : {
“spotify” : “http://open.spotify.com/user/spotify/playlist/37i9dQZF1DXec50AjHrNTq
},
“href” : “https://api.spotify.com/v1/users/spotify/playlists/37i9dQZF1DXec50AjHrNTq”,
“type” : “playlist”,
“uri” : “spotify:user:spotify:playlist:37i9dQZF1DXec50AjHrNTq”
},
“device” : {
“id” : “13cfd1cda5002a9b87b3302827b77404ffa855bc”,
“is_active” : false,
“is_restricted” : false,
“name” : “Spotify Web Player”,
“type” : “Computer”,
“volume_percent” : 100
},
“repeat_state” : “off”,
“shuffle_state” : false
}
Successfully posted state to OpenHab: spotify_current_track = If You Want Blood (You’ve Got It)
Successfully posted state to OpenHab: spotify_current_artist = AC/DC
Successfully posted state to OpenHab: spotify_current_cover = https://i.scdn.co/image/fed88d1739d842a4b706594ed2af44720634fdd3
Successfully posted state to OpenHab: spotify_current_duration = 273840
Successfully posted state to OpenHab: spotify_current_progress = 243053
Successfully posted state to OpenHab: spotify_current_progress = 243053
Successfully posted state to OpenHab: spotify_current_playing = ON
Successfully posted state to OpenHab: spotify_current_device = Spotify Web Player
Successfully posted state to OpenHab: spotify_current_volume = 100
Successfully posted state to OpenHab: spotify_current_device_id = 13cfd1cda5002a9b87b3302827b77404ffa855bc
-> Success
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-08-15T14:13:49+0000
Done in 1.20426917076 seconds
Why?
thanks

I think you have the Debug flag turned on. Otherwise it looks like it’s doing what it is supposed to.

The JSON in the log is the API response. When debug is off, it is not output.

Thanks

I have played around a bit with this now and I have an improvement suggestion.

How about adding some config variables at the very top of the py script?
(I am not so familiar with python but this should be possible i think?!)

In my case Volume up by 10% was a bit too much for the yamaha device i was running the playback,
so i changed the volume up and down buttons to 5% in the .py file.
Some config values for senseful thiings would be really nice.

What do you think about this?

That’s a good idea! I won’t have time over the next few weeks but I will try to implement some in September!

Thanks!

1 Like

Any answer, I’m lost here, too. Thx

There is a auth HTML page which can handle that for you in the repo included. Just call that page in your browser.

I am on mobile now, but can make a screenshot later.

im new un openhab and I can’t found the “PUT”

But I solved

Rest API -> items -> PUT Items Status -> itemName= Spotify_client_id and the body is your Spotify Clien Id

Peace.

@Michael_Stjerna

[ Moving the convo to this thread ]

I uploaded a new version of the spotify.py script to github.

Two changes:

  1. You can get a list of all devices by calling “get_devices”. This stores a json array into a new item called “spotify_device_list”. You can use this in habpanel to generate a drop down or selector.
  2. Then set the item “spotify_current_device_id” to the id you want.
  3. Call the play command. It now passes in the device id, if present.

Does that give you what you need?

1 Like

Done! :slight_smile:

1 Like

Hey!

I’m in the process of merging your changes into the main code. Quick question:

I noticed that the API doesn’t allow you to change the device while playback is active. Do you see the same thing?

Hi @pmpkk

Thanks for the updated script
How do you change the device from the spotify.pl?
I can get a list of the devices now

Done in 0.470010042191 seconds
[15:18:20] openhabian@openHABianPi:/etc/openhab2/scripts$ /usr/bin/python /etc/openhab2/scripts/spotify.py device_id "94827c523b0cfc3f1ef78a281ea01b7ba6f0d284"
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" : [ {
    "id" : "fa33ff0eb346a1aadc2f8b895b858974a2955109",
    "is_active" : true,
    "is_restricted" : false,
    "name" : "WL000296",
    "type" : "Computer",
    "volume_percent" : 52
  }, {
    "id" : "e5e1881cc55d0c6563b70b4b355d4e993b0329ed",
    "is_active" : false,
    "is_restricted" : false,
    "name" : "Kök",
    "type" : "Unknown",
    "volume_percent" : 50
  }, {
    "id" : "f5002b5076c0ac07ca486bdb77b78e1916794545",
    "is_active" : false,
    "is_restricted" : false,
    "name" : "SHIELD",
    "type" : "TV",
    "volume_percent" : 100
  }, {
    "id" : "94827c523b0cfc3f1ef78a281ea01b7ba6f0d284",
    "is_active" : false,
    "is_restricted" : false,
    "name" : "Landet heos1 + Landet Vardagsrum",
    "type" : "Unknown",
    "volume_percent" : 8
  }, {
    "id" : "6a423f7a7f4b1f34b6e82bf7f50aa580c6006106",
    "is_active" : false,
    "is_restricted" : false,
    "name" : "Denon AVR-X4300H",
    "type" : "Unknown",
    "volume_percent" : 37
  } ]
}
Successfully posted state to OpenHab: spotify_devices = {"devices": [{"name": "WL000296", "volume_percent": 52, "is_active": true, "is_restricted": false, "type": "Computer", "id": "fa33ff0eb346a1aadc2f8b895b858974a2955109"}, {"name": "K\u00f6k", "volume_percent": 50, "is_active": false, "is_restricted": false, "type": "Unknown", "id": "e5e1881cc55d0c6563b70b4b355d4e993b0329ed"}, {"name": "SHIELD", "volume_percent": 100, "is_active": false, "is_restricted": false, "type": "TV", "id": "f5002b5076c0ac07ca486bdb77b78e1916794545"}, {"name": "Landet heos1 + Landet Vardagsrum", "volume_percent": 8, "is_active": false, "is_restricted": false, "type": "Unknown", "id": "94827c523b0cfc3f1ef78a281ea01b7ba6f0d284"}, {"name": "Denon AVR-X4300H", "volume_percent": 37, "is_active": false, "is_restricted": false, "type": "Unknown", "id": "6a423f7a7f4b1f34b6e82bf7f50aa580c6006106"}]}
Match : None  or  94827c523b0cfc3f1ef78a281ea01b7ba6f0d284 index:  -1
None
null
1 Device :  WL000296 id : fa33ff0eb346a1aadc2f8b895b858974a2955109
2 Device :  Kök id : e5e1881cc55d0c6563b70b4b355d4e993b0329ed
3 Device :  SHIELD id : f5002b5076c0ac07ca486bdb77b78e1916794545
4 Device :  Landet heos1 + Landet Vardagsrum id : 94827c523b0cfc3f1ef78a281ea01b7ba6f0d284
Successfully posted state to OpenHab: spotify_device_name = Landet heos1 + Landet Vardagsrum
Successfully posted state to OpenHab: spotify_device_id = 94827c523b0cfc3f1ef78a281ea01b7ba6f0d284
Successfully posted state to OpenHab: spotify_device_index = 4
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-08-31T13:18:25+0000
Done in 0.492110013962 seconds

The next thing would be to update your web-widget with a dropdown for the devices so the selection can be easaly changed.

I will play more with it later today or tomorrow.

//Michael

Hi

Then new version of the script don’t allow me to use the playlist item anymore :frowning:

It works for me. What exactly are you trying to do with the playlist?

Ok, that problem is solved :slight_smile:
Was missing some items…

Do you have any instructions for how to change the output device?
Idealy I would like to have a drop down to select output device from the custom widget.

Did you manage to change the device from the script? I saw some comments of issues while playing?
Would it be possible to do a “Stop-play”, “change device” and “start play” solution when a new device is selected.

Br
Michael Stjerna

I adapted my HapPanel theme like this. Are you using my theme?

Yes, please share :slight_smile:

Here you go:

You’ll need to get the latest versions from github for:

matrix-theme.css
spotify.py
spotify.items

<div class="section">

	<div class="sectionIconContainer"><div class="sectionIcon"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#line-visuals"></use></svg></div></div>
	<div class="title">Music</div>
	<div class="controls">
    
		<div class="widget">
			<div class="icon off"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#line-visuals"></use></svg></div>
			<div class="name">Track</div>
			<div class="appLogo"><svg viewBox="0 0 440 100"><use xlink:href="/static/matrix-theme/AppIcons.svg#spotify"></use></svg></div>        
			<div class="valueGroup">
				<div class="value">{{itemValue('spotify_current_track')}}</div>
				<div class="value">{{itemValue('spotify_current_artist')}}</div>
			</div>

			<div class="music">
				<div class="cover" ng-style="{'background-image': 'url(' + itemValue('spotify_current_cover') + ')'}"></div>
				<div class="playback">
					<div class="playbackTime">{{ 946684800000 + itemValue('spotify_current_progress')*1 | date:'mm:ss'}}</div>
					<div class="playbackBar"><div class="playbackBarDone" ng-style="{'width': itemValue('spotify_current_progress_percent') + '%'}"></div></div>
					<div class="playbackTime">{{ 946684800000 + itemValue('spotify_current_duration')*1 | date:'mm:ss'}}</div>
				</div>
				<div class="controlGroup">
					<div class="control" ng-click="sendCmd('spotify_action', 'next')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#right-arrow-2"></use></svg></div>
					<div class="control" ng-click="sendCmd('spotify_action', 'play')" ng-if="itemValue('spotify_current_playing')!='ON'"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#right-play"></use></svg></div>
					<div class="control" ng-click="sendCmd('spotify_action', 'pause')" ng-if="itemValue('spotify_current_playing')=='ON'"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#stop_1_"></use></svg></div>
					<div class="control" ng-click="sendCmd('spotify_action', 'previous')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#left-arrow-2"></use></svg></div>
				</div>
			</div>      
		</div>
    
		<div class="widget">
			<div class="icon off"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#line-visuals"></use></svg></div>
			<div class="name">Play Lists</div>
			<div class="sceneGroup">
				<div class="scene" ng-class="{true:'on', false:''}[itemValue('spotify_current_context_uri')=='spotify:user:spotify:playlist:37i9dQZF1DX5OepaGriAIm']" ng-click="sendCmd('spotify_action', 'play spotify:user:spotify:playlist:37i9dQZF1DX5OepaGriAIm')">Women of Jazz</div>
				<div class="scene" ng-class="{true:'on', false:''}[itemValue('spotify_current_context_uri')=='spotify:user:spotify:playlist:37i9dQZF1DWSJHnPb1f0X3']" ng-click="sendCmd('spotify_action', 'play spotify:user:spotify:playlist:37i9dQZF1DWSJHnPb1f0X3')">Cardio</div>        
			</div>
		</div>

		<div class="widget">
			<div class="icon off"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#volume"></use></svg></div>
			<div class="name">Volume<div class="value">{{itemValue('spotify_current_volume')}}</div></div>
			<div class="controlGroup">
				<div class="control" ng-click="sendCmd('spotify_action', 'volume_up')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#top-arrow-2"></use></svg></div>
				<div class="control" ng-click="sendCmd('spotify_action', 'volume_down')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#down-arrow-2"></use></svg></div>
			</div>
		</div>

 		<div class="widget">
			<div class="icon off"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#box"></use></svg></div>
			<div class="name">Devices</div>
			<div class="sceneGroup" ng-init="deviceList = $eval(itemValue('spotify_device_list'))">
				<div class="scene" ng-class="{true:'on', false:''}[itemValue('spotify_current_device_id')==device.id]" ng-repeat="device in deviceList" ng-click="sendCmd('spotify_current_device_id', device.id)">{{device.name}}</div>
			</div>
		</div>

		<div class="widget" ng-click="sendCmd('spotify_forceupadte', 'ON')">
			<div class="icon off"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#double-arrow"></use></svg></div>
			<div class="name">Update</div>
     	<div class="valueGroup">
        <div class="value">{{itemValue('spotify_lastConnectionDateTime') | date:'MMM d, HH:mm:ss'}}</div>
      </div>			
		</div>

  </div>

</div>
2 Likes