openHAB integration to Spotify Web Connect API (player)

Has anyone seen the spotify unofficial binding? Wondering if this binding is “aware”?

I wanted to ask the same question. I see some interaction on this forum on the spotify.py solution, but not on the Spotify Binding. How do both compare? From an architectural perspective, I prefer a binding instead of a py-script. But the py-script seems to be more mature (and more used).

Anyone else cares to share their experience?

Hi!
I am making some progress!
It now works really nice but i am still not able to send commands.
Is this even possible?
The commands are labeled with “current” -> current playing for instance.
Can i fire play/pause?
If yes, how? :slight_smile:
Thank you!!

@Jonas88, the best way to learn this spotify integration is to look at the code of the custom ground floor widget in the matching matrix theme. It’s also from @pmpkk (you should load the widget and then use habpanel’s build in widget code editor to examine the relevant code.)

If you do not want to use a custom widget but directly take habpanel widgets you would have to use a “button” widget and set it to fire (alternating) events to item spotify_action. See this image:

However I would suggest that to use a custom widget, for example the Music Control Widget, and connect it to the right items (spotify_action, etc.).

hi!
I’ll look at the code, thank you :slight_smile:
however - i can’t see your snapshot.

Ok, i am feeling dumb right now. i just didn’t find it.
For the other guys:
just send commands to the spotify_action item like:
play pause etc … you don’t even need to code, you can just use a button widget for example.

Thank you very much! :slight_smile:

Only “problem” i got now is that my log is growing like crazy because i call the script quite frequently … i did manage to get rid of the status update but if spotify is running the item change (current time) is getting mad. i tried to find a solution to exclude a single item from the log but it doesn’t seem to be that easy …

You could remove the print statements in the python scripts to reduce the log output.

Hey pmpkk, i already did that. i got rid of the “status-update” but the thing changes are handled outside of the script (at least i think so) :wink:

I see “John’e echo” in your config.
Does this mean you can select a spotify song on the weg UI and stream it through Amazon echo.
Or is this about something totally different?

Yes, that’s definitely possible.

Sounds great. Thanks.
I will try to get it to work.

Hi,

I tried that way, but did not succeed to get the Spotify part tot work (on my screen all information is scattered around the whole widget.

Could you please post the spotify part only of the groudfloor widget?
I guess I would be able to handle the rest - fitting it into my screen.

Is is possible to run it without the matrix theme?
Thanks in advance.

I tried recreating the bug you talked about. It was easiest to rename my echo to Jem’s Echo which should work unless something more exotic with character sets and encoding is going on. I wasn’t able to recreate the problem. Maybe I accidently patched it at some point and you have an old version.

All the following worked.
python spotify.py play Jem
python spotify.py play "Jem’s"
python spotify.py play “Jem’s Echo”

I’ll update github later today, then try that

NCO Who’s code are you running? You should probably be using pmpkk’s version since it seems like he’s backported the key features. But if you are using mine then…

I have mine setup so I can play on any device I like. It allows me to use voice controls on my Echo and home without it changing playback device or I can use my Google Home to play music on my Amazon Echo. At the moment if you want to specify what an album you need to have the spotify uri. I tried using the uri of a song but it seems like the webapi doesn’t like that.

You can do
python spotify.py play spotify:album:4DEZVbAxlZPRXWCHUV5wF3 “Jem’s Echo”

Here is my music widget

<div class="section">
	<div class="thing"></div>
	  
	<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">{{itemValue('spotify_current_progress') / 1000 | number:0}}</div>
          <div class="playbackBar"><div class="playbackBarDone" ng-style="{'width': itemValue('spotify_current_duration') }"></div></div>
          <div class="playbackTime">{{itemValue('spotify_current_duration') / 1000 | number:0}}</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#pause"></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#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_set_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_set_volume', 'volume_down')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#down-arrow-2"></use></svg></div>
      	<div class="control on" ng-if="itemValue('spotify_current_volume')=='0'" ng-click="sendCmd('spotify_set_volume', 'mute')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#volume-close"></use></svg></div>
				<div class="control" ng-if="itemValue('spotify_current_volume')!='0'" ng-click="sendCmd('spotify_set_volume', 'mute')"><svg viewBox="0 0 80 80"><use xlink:href="/static/matrix-theme/squidink.svg#volume"></use></svg></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="nameGroup"><div class="name">Update</div></div>
      <div class="valueGroup"><div class="value">{{itemValue('spotify_lastConnectionDateTime') | date:'MMM d, HH:mm:ss'}}</div></div>	
    </div>  
    
    <div class="widget" >
      <div class="icon off" ng-click="sendCmd('spotify_device_update', 'ON')"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#double-arrow"></use></svg></div>
      <div class="nameGroup"><div class="name">Devices</div></div>
      <div class="btn-group" dropdown-append-to-body="true" uib-dropdown>            
        <button id="single-button" type="button" class="btn btn-primary" uib-dropdown-toggle>
          {{itemValue('spotify_current_device')}} <span class="caret"></span>
        </button>
        <ul class="dropdown-menu"  uib-dropdown-menu role="menu" aria-labelledby="single-button">
          <div ng-init="devices=itemValue('spotify_devices')"></div>
          <div ng-repeat="item in $eval(devices).devices" ng-if="item.state!='NULL'">
            <li role="menuitem"><a ng-click='sendCmd("spotify_action", "play \"" + item.id + "\"")'>{{item.name}}</a></li>
          </div>
        </ul>
      </div>
    </div>

    <div class="widget">
      <div class="icon off" ng-click="sendCmd('spotify_action', 'playlists')"><svg viewBox="0 0 48 48"><use xlink:href="/static/matrix-theme/squidink.svg#double-arrow"></use></svg></div>
      <div class="nameGroup"><div class="name">Play Lists </div></div>
      <div class="btn-group" dropdown-append-to-body="true" uib-dropdown>            
        <button id="single-button" type="button" class="btn btn-primary" uib-dropdown-toggle>
          Select <span class="caret"></span>
        </button>
        <ul class="dropdown-menu" uib-dropdown-menu role="menu" style="overflow: auto; max-height:300px; overflow-x:hidden" aria-labelledby="single-button">
          <div ng-init="playlists=itemValue('spotify_playlists')"></div>
          <div ng-repeat="item in $eval(playlists).items" ng-if="item.state!='NULL'">
            <li role="menuitem"><a ng-click='sendCmd("spotify_action", "play \"" + item.uri + "\"")'>{{item.name}}</a></li>
          </div>         
        </ul>
      </div>
    </div>
    
	</div>   
</div>

Hi,

The bug only appears if the echo with the apostrophe appears earlier in the
list than the one you are after.

So assuming g the first item return from your api is Jem’s echo -if you try
migrate to any of your other devices, you’ll see the prob.
If Jem’s echo is last in the list, then the bug won’t appear.

Also, make sure that after the echo rename, the name with an apostrophe
does appear in your returned list from the API as having an apostrophe.

I still can’t replicate the problem. Are you sure you sure you are using my fork? Maybe you are using the main version that pmpkk created?

Here is an example where the first and last device both have apostrophes in them. Maybe Echos’ have better encoding than iphones’ but I’m not sure.The API results have apostrophes as they should.

1 Device : Jem’s Echo
2 Device : Norman
3 Device : John
4 Device : Phone
5 Device : Entrail Echo’s

I can play any device using the following examples

    python spotify.py play John
    python spotify.py play "Jem’s"
    python spotify.py play Entrail
    python spotify.py play [deviceid]

Hey,

I set up everything according to your GitHub instruction, but with the last step I keep getting an Error 400 from the API. Do you have an idea why this happens?

/usr/bin/python /etc/openhab2/scripts/spotify.py
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'error': {u'status': 400, u'message': u'invalid id'}}
 -> Item node missing from response :(
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-10-16T08:54:18+0000
Done in 0.840596914291 seconds

@lukkigi

Did you copy all spotify items or the file itself from the github?

Could you post spotify.items file?

It seems like it stopped when it tried to update the item ‘spotify_current_track’, because openhab wasn’t able to retrieve the item with this specific name.

Similar issue here but fails on get 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 Token Refresh Service
{‘Content-Length’: ‘69’, ‘Keep-Alive’: ‘timeout=600’, ‘Server’: ‘nginx’, ‘Connection’: ‘keep-alive’, ‘Date’: ‘Sun, 15 Oct 2017 19:30:44 GMT’, ‘Content-Type’: ‘application/json’}
{u’error_description’: u’Invalid refresh token’, u’error’: u’invalid_grant’}
Successfully got state from OpenHab: spotify_auth_code
– Calling Token Service for the first time
{‘Content-Length’: ‘63’, ‘Keep-Alive’: ‘timeout=600’, ‘Server’: ‘nginx’, ‘Connection’: ‘keep-alive’, ‘Date’: ‘Sun, 15 Oct 2017 19:30:44 GMT’, ‘Content-Type’: ‘application/json’}
{u’error_description’: u’Invalid client’, u’error’: u’invalid_client’}
– Calling Service: Get Devices
-> Device List Failure: <type ‘exceptions.KeyError’>
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2017-10-15T19:30:44+0000
Done in 0.762307882309 seconds