Currently playing Spotify song on Photon and OLED display
We've got a little party coming up where the music is provided through a Spotify playlist. The list is maintained by 5 people and currently contains 825 songs, which is well over 60 hours of music. That makes it kinda hard to answer the expected questions at the party like "He! I know this song, who are they?"
In order to give a swift answer to those questions I thought it would be nice to provide the guests with an easy interface: an up to date oled screen that holds the artist and title of the current song.
Currently playing Spotify song
First hurdle is to get the current Spotify song. Even though Spotify said well over a year ago that they would put it in their API, it is still not there. Luckily there is a workaround. If you connect your Spotify account to last.fm, the current song is available via their API.
Second thing to consider is the actual hardware. As I had an OLED screen lying around as well as a Particle Photon, I choose these to be the tools of choise. Mind that my OLED screen has 4 connectors (VCC, GND, SDA and SCL), while others around usually have more connections.
Now for the actual work. First thing I needed was the last.fm part. A few minutes after applying for an API key I received it, meanwhile I had found the user.getRecentTracks method on their API site. The first check with curl and jq looked very promising:
read -p 'Last.fm user name: ' user read -p 'Last.fm API key: ' api_key curl \ --silent \ -d method=user.getrecenttracks \ -d user=${user} \ -d api_key=${api_key} \ -d format=json \ -d limit=1 \ http://ws.audioscrobbler.com/2.0/ |\ jq '.recenttracks.track[0].artist."#text", .recenttracks.track[0].name'
This provided me with:
"Monkey3" "Icarus"
My first thought now was to write a .ino file, perform the request to last.fm from there, parse the JSON within the .ino file and publish the text to the OLED.
Webhooks
As I thought a little more about that, I figured I might as well use the webhooks that Particle provides. This saves me the trouble of parsing the JSON data and only leaving very little data to be transfered to the Photon.
The webhook works with mustache as a templating/filtering engine, so I needed to rewrite the jq syntax to mustache. At first this was a bit of trial and error and, after reading the docs a bit better, was not that hard. The mustache template to get the artist and track is {{#recenttracks}}{{#track}}{{#@attr.nowplaying}}{{artist.#text}} - {{name}}{{/@attr.nowplaying}}{{/track}}{{/recenttracks}}.
The condition wether or not the song is now playing made the mustache solution even better than the original jq one.
I've put this in a jsfiddle if you want to play with this.
So the hook responses with something like:
hook-response/lastfm_currenttrack/0, data: traumahelikopter - Down In the City
I've created the webhook itself with the following json file (replacing the username and api_key with the proper values):
{ "eventName": "lastfm_currenttrack", "name": "lastfm_hook", "url": "http://ws.audioscrobbler.com/2.0/", "requestType": "GET", "headers": null, "query": { "method": "user.getrecenttracks", "format": "json", "user": "LASTFMUSER", "api_key": "LASTFMAPIKEY", "limit": 1 }, "responseTemplate": "{{#recenttracks}}{{#track}}{{#@attr.nowplaying}}{{artist.#text}} - {{name}}{{/@attr.nowplaying}}{{/track}}{{/recenttracks}}", "json": null, "auth": null, "mydevices": true }
Saving this to file lastfm_hook.json and running the code: particle webhook create lastfm_hook.json.
Getting the data to the OLED display
This part was kinda straight-forward as well. I quickly found the required library via https://community.particle.io/t/adafruit-ssd1306-library-ported/3505/36, connected the wires (VCC, GND, SDA to D0 and SCL to D1) and wrote the lastfm_playing.ino file. Compiled it all with Particle Dev and it worked in one go.
The webhook is called every ten seconds, which leaves some overlap in songs, but that does not annoy me. I don't want to hammer the API's if it is not needed. Another thing to notice is that the artist and song might be a bit more text than fits on the display (but that does not bother me either).
I've forked the Adafruit_SSD1306 code in steviethecat/Adafruit_SSD1306, adding the example lastfm_* files.
All I need to do now is put the lot in a nice enclosure, perhaps modify the screen layout a bit more and wait for the party to get started!















