openHAB integration to Spotify Web Connect API (player)

@Dries I have the same issue with devices .

I have a LINN DS player on my LAN, it has proper spotfiy connect intergration but only shows in HABPanel when i click play or use it in the Official App

Did you sort this out?

Ideally I should get a list of devices I can choose but I dont

@tr1cks relevant for you

Unfortunately not

Hi!

I tried to keep lists as json in String item. It working well, but only when I open page first time. After refresh they vanish. May be it’s related to ng-init. It’s hard to say for me, because I am almost not familiar with Angular. What can be wrong?

<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);sendCmd('spotify_action', 'transfer_playback')">
            {{device.name}}
        </div>
    </div>
</div>

I had some issues with the devices and playlists not updating. My current setup works well but it’s a branch and I think the way devices is different to the main branch so you may need to adapt it. There is a refresh button which updates devices, and then I make sure the interface has the latest set of devices with a mouseover function.

Note: The way devices works may be different in the main branch. 

      <div class="widget" ng-init="devices=$eval(itemValue('spotify_devices')).devices">
        <div class="icon off" ng-click="sendCmd('spotify_device_update', 'ON'); devices=$eval(itemValue('spotify_devices')).devices"><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  ng-click="devices=$eval(itemValue('spotify_devices')).devices" ng-mouseover="devices=$eval(itemValue('spotify_devices')).devices">
            {{itemValue('spotify_current_device')}} <span class="caret"></span>
          </button>
          <ul class="mydropdown-menu" uib-dropdown-menu role="menu" style="overflow: auto; max-height:300px; overflow-x:hidden" aria-labelledby="single-button" >   
            <div ng-repeat="dev in devices" ng-if="dev.state!='NULL'" >
              <li role="menuitem"><a ng-click='sendCmd("spotify_action", "play \"" + dev.id + "\"")'>{{dev.name}}</a></li>
            </div>
          </ul>
        </div>
      </div>

How does that look visiually @unparagoned

It’s a circle arrow for refresh and a drop-down to select devices. There is a picture here Matrix Theme for HABPanel

Just for mention. https://api.spotify.com/v1/me/player/ can return 204 with empty body. It will lead to exception on r.json() and error “Failure: <type ‘exceptions.ValueError’>” in log.

1 Like

Have somebody problems lately like “Invalid client Id” or “Invalid refresh token”?

1 Like

@Edwin_de_Boer did you fix this? I have the same issue now

Do you have an actual problem or do you just want to make the logs look clean?

An actual problem @unparagoned

I switched off my receiver thats used for spotify and all of a sudden when I reauth, which works fine, I see the logs showing token issues.

Nothing had changed. Looking in influx, I cant see it storing the token either.

I recreated the app in Spotify Dev console, entered in the new secret/client id and auth works. But the token part is failing and ive no idea why. This worked fine before.

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
{‘client_secret’: ‘XXXXXXXX’, ‘redirect_uri’: ‘http://192.168.0.3:8080/static/spotify-auth.html’, ‘client_id’: ‘CCCCC518’, ‘refresh_token’: ‘NULL’, ‘grant_type’: ‘refresh_token’}
{‘Content-Length’: ‘69’, ‘Keep-Alive’: ‘timeout=600’, ‘Server’: ‘nginx’, ‘Connection’: ‘keep-alive’, ‘Date’: ‘Thu, 05 Jul 2018 00:31:34 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’: ‘68’, ‘Keep-Alive’: ‘timeout=600’, ‘Server’: ‘nginx’, ‘Connection’: ‘keep-alive’, ‘Date’: ‘Thu, 05 Jul 2018 00:31:34 GMT’, ‘Content-Type’: ‘application/json’}
{u’error_description’: u’Invalid redirect URI’, u’error’: u’invalid_grant’}
– Calling Service: Play
Successfully got state from OpenHab: spotify_current_device_id
401
– Calling Service: Update
{u’error’: {u’status’: 401, u’message’: u’Invalid access token’}}
-> Item node missing from response :frowning:
– Calling Service: Get Devices
-> Device List Failure: <type ‘exceptions.KeyError’>
– Calling Service: Get Playlists
{u’error’: {u’status’: 401, u’message’: u’Invalid access token’}}
-> Playlist List Failure: <type ‘exceptions.KeyError’>
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2018-07-05T00:31:36.000+0000
Done in 3.3187558651 seconds

What do you mean reauth? The way it should work is you auth once, then the script will handle all the authorisation and getting new keys in the background.

Make sure you go through the instructions thoroughly and it should work.

If you are still struggling you can try a widget to made, it should cover the main instruction on setting up authorisation.

image

Remember to change the clientid, secret, openhab name/ip:port then you should be good to go.

<div class="section" ng-init="new_client_id='clientid';new_client_secret='secret'">
  <widget>
    <div class="title">Spotify Creds</div>
    <div class="name"> Sign up to spotify to develop your own app to get a client ID and client secret <a href="https://developers.spotify.com/my-application/">developers.spotify.com/my-application/</a> then add http://openhabian:8080/static/spotify-auth.html to the redirect uri and save changes. Complete id and secret below and click buttons to update them. then click authenticate link and authenticate</div>

    <div class="name">Current ID: {{itemValue('spotify_client_id')}} </div> &#13; <div class="name">  Enter new spotify_client_id <input style="color: black;" ng-model="new_client_id"  size="35"  />
    <button ng-click="sendCmd('spotify_client_id', new_client_id)">Update Client ID</button></div>
    <div class="name">Current secret: {{itemValue('spotify_client_secret')}}</div> &#13; <div class="name"> Enter new spotify_client_secret <input style="color: black;" ng-model="new_client_secret" size="35" />
    <button ng-click="sendCmd('spotify_client_secret', new_client_secret)">Update Client Secret</button></div>
    <div class="title">&#10;<a href="http://openhabian:8080/static/spotify-auth.html" target="_blank">Click open authenication link!</a></div>
    <div class="controlGroup">
      <div class="heading">&#10;Blow clears other creds credential- DANGEROUS</div>
      <div class="name" ng-init="display=0">Click below to see and reset auth codes</div>
      <div class="name" ng-click="display=1">ENABLE RESET - DANGER</div>
      <div class="nameGroup" ng-if="display==1">
        <button ng-click="sendCmd('spotify_auth_code','NULL')">Reset</button><div> {{itemValue('spotify_auth_code')}}</div>
        <button ng-click="sendCmd('spotify_access_token','NULL')">Reset</button><div> {{itemValue('spotify_access_token')}}</div>
        <button ng-click="sendCmd('spotify_refresh_token','NULL')">Reset</button><div> {{itemValue('spotify_refresh_token')}}</div>
        <button ng-click="sendCmd('spotify_token_expiry','NULL')">Reset</button><div> {{itemValue('spotify_token_expiry')}}</div>
      </div>
    </div>
  </widget>
</div>

There is nothing wrong with the widget, as mentioned this was working fine before.

I use the widget to enter the client id and secret, it authenticates correctly. But when I go back into the Open Auth link, it seems its not authenticated.

I also cannot see the token and so on being stored in Influx DB

Its not saving the token it seems.

This was working perfectly before.

The static/spotify-auth.html page will not be clear that it has been authorised. But once you done it once you should never need to do it again. Here mine is fully authorised and work and this is what the auth link looks like.

image

If it is a persistence issue then try this setup.

Mapdb for persistence

mapdb.persist in the persistence folder

Strategies {
		everyHour : "0 0 * * * ?"
    	everyDay  : "0 0 0 * * ?"
		default = everyUpdate
}

Items {
		* : strategy = everyChange, everyDay, restoreOnStartup
}

I reinstalled influx db persistance from Paperui.

I used the Widget

11:53:38.399 [INFO ] [smarthome.event.ItemCommandEvent ] - Item ‘spotify_client_id’ received command 5c80fa9aebb74b41a6eefe36631de518
11:53:38.415 [INFO ] [smarthome.event.ItemStateChangedEvent] - spotify_client_id changed from NULL to 5c80fa9aebb74b41a6eefe36631de518
11:53:47.371 [INFO ] [smarthome.event.ItemCommandEvent ] - Item ‘spotify_client_secret’ received command 3dd797838ff540a5b0319a7dc6a5e71c
11:53:47.380 [INFO ] [smarthome.event.ItemStateChangedEvent] - spotify_client_secret changed from NULL to 3dd797838ff540a5b0319a7dc6a5e71c
11:53:53.592 [INFO ] [smarthome.event.ItemStateChangedEvent] - spotify_auth_code changed from NULL to AQAkpr66g43p1f9hY0jBpl7sh8Xm1_p-t7l1MmKO_qTN0DOjjrne6LdsNM2HO_6rBhsi9aHkj0k6UuAADRjTL3wRzKveTfIKTYoaz9FD36l5XMLUtJPPlHaQlvMf7wvqGchUCVv7L4a8VsqzBKivtl4hTQfeppEk1PgBQ3KH8yHpRtE1xOZlViMYDPeMwtmNZIFB8D1YKnVXibUIMeUhNPcsBxhRZq8Lk3etiUK96bEhg9lyGy3ajXasTHbIt6QeHo-XfBmw_ECncgkEGYlIx2jd4Zxi4dIbjdPd1R7pyw-oHWk

Problem remains:

Successfully got state from OpenHab: spotify_token_expiry
-- Calling Token Refresh Service
{'client_secret': 'XXX', 'redirect_uri': 'http://192.168.0.3:8080/static/spotify-auth.html', 'client_id': 'XX', 'refresh_token': 'NULL', 'grant_type': 'refresh_token'}
{'Content-Length': '69', 'Keep-Alive': 'timeout=600', 'Server': 'nginx', 'Connection': 'keep-alive', 'Date': 'Thu, 05 Jul 2018 01:57:25 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': '68', 'Keep-Alive': 'timeout=600', 'Server': 'nginx', 'Connection': 'keep-alive', 'Date': 'Thu, 05 Jul 2018 01:57:26 GMT', 'Content-Type': 'application/json'}
{u'error_description': u'Invalid redirect URI', u'error': u'invalid_grant'}
-- Calling Service: Play
Successfully got state from OpenHab: spotify_current_device_id
401
-- Calling Service: Update
{u'error': {u'status': 401, u'message': u'Invalid access token'}}
 -> Item node missing from response :(
-- Calling Service: Get Devices
 -> Device List Failure:  <type 'exceptions.KeyError'>
-- Calling Service: Get Playlists
{u'error': {u'status': 401, u'message': u'Invalid access token'}}
 -> Playlist List Failure:  <type 'exceptions.KeyError'>
Successfully posted state to OpenHab: spotify_lastConnectionDateTime = 2018-07-05T01:57:28.000+0000
Done in 2.9642021656 seconds

I fixed the issue, found an article on Stackoverflow.

Your URI must match in the spotify script and the Web Dev console. I had my private, internal IP address in the script but my external dns name in the Web dev.

Both variants was tried. Internal IP was the first option. Or you ended put it in the Web Dev console at the end?

I did web dev before also. I also emptied the states

Does anyone know how to stop the huge amount of information in the Log file re: Spotify Updates?

There are logInfo(“Spotify”, resp) statements in the spotify.rule file that I’m sure I can remove but then I may miss information.

One rule in in particular generates a whole page off stuff!