Last active
November 9, 2020 17:54
-
-
Save witnessmenow/9115234bf9dceb316b57b76d66a0e199 to your computer and use it in GitHub Desktop.
HTTPS not working
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************* | |
Displays Album Art on a ST7789 | |
This example could easily be adapted to any Adafruit GFX | |
based screen. | |
NOTE: You need to get a Refresh token to use this example | |
Use the getRefreshToken example to get it. | |
Parts: | |
D1 Mini ESP8266 * - http://s.click.aliexpress.com/e/uzFUnIe | |
ST7789 TFT Screen | |
* * = Affilate | |
If you find what I do useful and would like to support me, | |
please consider becoming a sponsor on Github | |
https://github.com/sponsors/witnessmenow/ | |
Written by Brian Lough | |
YouTube: https://www.youtube.com/brianlough | |
Tindie: https://www.tindie.com/stores/brianlough/ | |
Twitter: https://twitter.com/witnessmenow | |
*******************************************************************/ | |
// ---------------------------- | |
// Standard Libraries | |
// ---------------------------- | |
#include <ESP8266WiFi.h> | |
#include <WiFiClientSecure.h> | |
#define FS_NO_GLOBALS | |
#include <FS.h> | |
#include <LittleFS.h> | |
#include <SPI.h> | |
// ---------------------------- | |
// Additional Libraries - each one of these will need to be installed. | |
// ---------------------------- | |
#include <TFT_eSPI.h> | |
// Graphics and font library for ST7789 driver chip | |
// Can be installed from the library manager (Search for "eSPI") | |
// https://github.com/Bodmer/TFT_eSPI | |
#include <ArduinoSpotify.h> | |
// Library for connecting to the Spotify API | |
// Install from Github | |
// https://github.com/witnessmenow/arduino-spotify-api | |
#include <ArduinoJson.h> | |
// Library used for parsing Json from the API responses | |
// Search for "Arduino Json" in the Arduino Library manager | |
// https://github.com/bblanchon/ArduinoJson | |
#include <JPEGDEC.h> | |
// Library for decoding Jpegs from the API responses | |
// Search for "JPEGDEC" in the Arduino Library manager | |
// https://github.com/bitbank2/JPEGDEC/ | |
//------- Replace the following! ------ | |
char ssid[] = ""; // your network SSID (name) | |
char password[] = ""; // your network password | |
char clientId[] = ""; // Your client ID of your spotify APP | |
char clientSecret[] = ""; // Your client Secret of your spotify APP (Do Not share this!) | |
// Country code, including this is advisable | |
#define SPOTIFY_MARKET "IE" | |
#define SPOTIFY_REFRESH_TOKEN "" | |
//------- ---------------------- ------ | |
// file name for where to save the image. | |
#define ALBUM_ART "/album.jpg" | |
// so we can compare and not download the same image if we already have it. | |
String lastAlbumArtUrl; | |
WiFiClientSecure client; | |
ArduinoSpotify spotify(client, clientId, clientSecret, SPOTIFY_REFRESH_TOKEN); | |
// You might want to make this much smaller, so it will update responsively | |
unsigned long delayBetweenRequests = 30000; // Time between requests (30 seconds) | |
unsigned long requestDueTime; //time when request due | |
TFT_eSPI tft = TFT_eSPI(); | |
JPEGDEC jpeg; | |
// This next function will be called during decoding of the jpeg file to | |
// render each block to the Display. If you use a different display | |
// you will need to adapt this function to suit. | |
void JPEGDraw(JPEGDRAW *pDraw) | |
{ | |
// Stop further decoding as image is running off bottom of screen | |
if ( pDraw->y >= tft.height() ) return; | |
// This function will clip the image block rendering automatically at the TFT boundaries | |
tft.pushImage(pDraw->x, pDraw->y, pDraw->iWidth, pDraw->iHeight, pDraw->pPixels); | |
} | |
void setup() { | |
Serial.begin(115200); | |
// Initialise LittleFS, if this fails try .begin(true) | |
// NOTE: I believe this formats it though it will erase everything on | |
// LittleFS already! In this example that is not a problem. | |
// I have found once I used the true flag once, I could use it | |
// without the true flag after that. | |
if (!LittleFS.begin()) { | |
Serial.println("LittleFS initialisation failed!"); | |
while (1) yield(); // Stay here twiddling thumbs waiting | |
} | |
Serial.println("\r\nInitialisation done."); | |
// Initialise the TFT | |
tft.begin(); | |
tft.setTextColor(0xFFFF, 0x0000); | |
tft.fillScreen(TFT_BLACK); | |
tft.setSwapBytes(true); // We need to swap the colour bytes (endianess) | |
// Set WiFi to station mode and disconnect from an AP if it was Previously | |
// connected | |
WiFi.mode(WIFI_STA); | |
WiFi.disconnect(); | |
delay(100); | |
// Attempt to connect to Wifi network: | |
Serial.print("Connecting Wifi: "); | |
Serial.println(ssid); | |
WiFi.begin(ssid, password); | |
while (WiFi.status() != WL_CONNECTED) | |
{ | |
Serial.print("."); | |
delay(500); | |
} | |
Serial.println(""); | |
Serial.println("WiFi connected"); | |
Serial.println("IP address: "); | |
IPAddress ip = WiFi.localIP(); | |
Serial.println(ip); | |
// Only avaible in ESP8266 V2.5 RC1 and above | |
client.setFingerprint(SPOTIFY_FINGERPRINT); | |
//client.setInsecure(); | |
// If you want to enable some extra debugging | |
// uncomment the "#define SPOTIFY_DEBUG" in ArduinoSpotify.h | |
delay(100); | |
Serial.println("Refreshing Access Tokens"); | |
Serial.print("Free Heap: "); | |
Serial.println(ESP.getFreeHeap()); | |
if (!spotify.refreshAccessToken()) { | |
Serial.println("Failed to get access tokens"); | |
} | |
} | |
File myfile; | |
void * myOpen(const char *filename, int32_t *size) { | |
myfile = LittleFS.open(filename, "w+"); | |
*size = myfile.size(); | |
return &myfile; | |
} | |
void myClose(void *handle) { | |
if (myfile) myfile.close(); | |
} | |
int32_t myRead(JPEGFILE *handle, uint8_t *buffer, int32_t length) { | |
if (!myfile) return 0; | |
return myfile.read(buffer, length); | |
} | |
int32_t mySeek(JPEGFILE *handle, int32_t position) { | |
if (!myfile) return 0; | |
return myfile.seek(position); | |
} | |
int displayImage(char *albumArtUrl) { | |
// In this example I reuse the same filename | |
// over and over, maybe saving the art using | |
// the album URI as the name would be better | |
// as you could save having to download them each | |
// time, but this seems to work fine. | |
if (LittleFS.exists(ALBUM_ART) == true) { | |
Serial.println("Removing existing image"); | |
LittleFS.remove(ALBUM_ART); | |
} | |
File f = LittleFS.open(ALBUM_ART, "w+"); | |
if (!f) { | |
Serial.println("file open failed"); | |
return -1; | |
} | |
unsigned long lTime = millis(); | |
bool gotImage = spotify.getImage(albumArtUrl, &f); | |
Serial.print("Time taken to get Image (ms): "); | |
Serial.println(millis() - lTime); | |
// | |
// Make sure to close the file! | |
f.close(); | |
// | |
if (gotImage) { | |
lTime = millis(); | |
// jpeg.open((char *)ALBUM_ART, myOpen, myClose, myRead, mySeek, JPEGDraw); | |
// jpeg.decode(0, 0, 0); | |
// jpeg.close(); | |
Serial.print("Time taken to decode and display Image (ms): "); | |
Serial.println(millis() - lTime); | |
return 0; | |
} else { | |
return -2; | |
} | |
// | |
// return 0; | |
} | |
void printCurrentlyPlayingToSerial(CurrentlyPlaying currentlyPlaying) | |
{ | |
if (!currentlyPlaying.error) | |
{ | |
Serial.println("--------- Currently Playing ---------"); | |
Serial.print("Is Playing: "); | |
if (currentlyPlaying.isPlaying) | |
{ | |
Serial.println("Yes"); | |
} else { | |
Serial.println("No"); | |
} | |
Serial.print("Track: "); | |
Serial.println(currentlyPlaying.trackName); | |
Serial.print("Track URI: "); | |
Serial.println(currentlyPlaying.trackUri); | |
Serial.println(); | |
Serial.print("Artist: "); | |
Serial.println(currentlyPlaying.firstArtistName); | |
Serial.print("Artist URI: "); | |
Serial.println(currentlyPlaying.firstArtistUri); | |
Serial.println(); | |
Serial.print("Album: "); | |
Serial.println(currentlyPlaying.albumName); | |
Serial.print("Album URI: "); | |
Serial.println(currentlyPlaying.albumUri); | |
Serial.println(); | |
// will be in order of widest to narrowest | |
// currentlyPlaying.numImages is the number of images that | |
// are stored | |
for (int i = 0; i < currentlyPlaying.numImages; i++) { | |
Serial.println("------------------------"); | |
Serial.print("Album Image: "); | |
Serial.println(currentlyPlaying.albumImages[i].url); | |
Serial.print("Dimensions: "); | |
Serial.print(currentlyPlaying.albumImages[i].width); | |
Serial.print(" x "); | |
Serial.print(currentlyPlaying.albumImages[i].height); | |
Serial.println(); | |
} | |
Serial.println("------------------------"); | |
} | |
} | |
void loop() { | |
if (millis() > requestDueTime) | |
{ | |
Serial.print("Free Heap: "); | |
Serial.println(ESP.getFreeHeap()); | |
Serial.println("getting currently playing song:"); | |
// Market can be excluded if you want e.g. spotify.getCurrentlyPlaying() | |
CurrentlyPlaying currentlyPlaying = spotify.getCurrentlyPlaying(SPOTIFY_MARKET); | |
if (!currentlyPlaying.error) | |
{ | |
printCurrentlyPlayingToSerial(currentlyPlaying); | |
// Smallest (narrowest) image will always be last. | |
SpotifyImage smallestImage = currentlyPlaying.albumImages[currentlyPlaying.numImages - 1]; | |
String newAlbum = String(smallestImage.url); | |
if (newAlbum != lastAlbumArtUrl) { | |
Serial.println("Updating Art"); | |
int displayImageResult = displayImage(smallestImage.url); | |
if (displayImageResult == 0) { | |
lastAlbumArtUrl = newAlbum; | |
} else { | |
Serial.print("failed to display image: "); | |
Serial.println(displayImageResult); | |
} | |
} | |
} | |
requestDueTime = millis() + delayBetweenRequests; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment