Last active
July 16, 2020 07:09
-
-
Save witnessmenow/063dcd4b4407aa51afb4f6a0a442b5af to your computer and use it in GitHub Desktop.
Spotify TJpg POC - a demo of displaying album art on a matrix
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
/*************************************************************************************** | |
** Function name: listSPIFFS | |
** Description: Listing SPIFFS files | |
***************************************************************************************/ | |
#ifdef ESP8266 | |
void listSPIFFS(void) { | |
Serial.println(F("\r\nListing SPIFFS files:")); | |
fs::Dir dir = SPIFFS.openDir("/"); // Root directory | |
static const char line[] PROGMEM = "================================================="; | |
Serial.println(FPSTR(line)); | |
Serial.println(F(" File name Size")); | |
Serial.println(FPSTR(line)); | |
while (dir.next()) { | |
String fileName = dir.fileName(); | |
Serial.print(fileName); | |
int spaces = 33 - fileName.length(); // Tabulate nicely | |
if (spaces < 1) spaces = 1; | |
while (spaces--) Serial.print(" "); | |
fs::File f = dir.openFile("r"); | |
String fileSize = (String) f.size(); | |
spaces = 10 - fileSize.length(); // Tabulate nicely | |
if (spaces < 1) spaces = 1; | |
while (spaces--) Serial.print(" "); | |
Serial.println(fileSize + " bytes"); | |
} | |
Serial.println(FPSTR(line)); | |
Serial.println(); | |
delay(1000); | |
} | |
//==================================================================================== | |
#elif defined ESP32 | |
void listSPIFFS(void) { | |
Serial.println(F("\r\nListing SPIFFS files:")); | |
static const char line[] PROGMEM = "================================================="; | |
Serial.println(FPSTR(line)); | |
Serial.println(F(" File name Size")); | |
Serial.println(FPSTR(line)); | |
fs::File root = SPIFFS.open("/"); | |
if (!root) { | |
Serial.println(F("Failed to open directory")); | |
return; | |
} | |
if (!root.isDirectory()) { | |
Serial.println(F("Not a directory")); | |
return; | |
} | |
fs::File file = root.openNextFile(); | |
while (file) { | |
if (file.isDirectory()) { | |
Serial.print("DIR : "); | |
String fileName = file.name(); | |
Serial.print(fileName); | |
} else { | |
String fileName = file.name(); | |
Serial.print(" " + fileName); | |
// File path can be 31 characters maximum in SPIFFS | |
int spaces = 33 - fileName.length(); // Tabulate nicely | |
if (spaces < 1) spaces = 1; | |
while (spaces--) Serial.print(" "); | |
String fileSize = (String) file.size(); | |
spaces = 10 - fileSize.length(); // Tabulate nicely | |
if (spaces < 1) spaces = 1; | |
while (spaces--) Serial.print(" "); | |
Serial.println(fileSize + " bytes"); | |
} | |
file = root.openNextFile(); | |
} | |
Serial.println(FPSTR(line)); | |
Serial.println(); | |
delay(1000); | |
} | |
#endif |
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
// Fetch a file from the URL given and save it in SPIFFS | |
// Return 1 if a web fetch was needed or 0 if file already exists | |
bool getFile(String url, String filename) { | |
// If it exists then no need to fetch it | |
if (SPIFFS.exists(filename) == true) { | |
Serial.println("Found " + filename); | |
return 0; | |
} | |
Serial.println("Downloading " + filename + " from " + url); | |
WiFiClientSecure *client = new WiFiClientSecure; | |
if (client) { | |
client -> setCACert(spotify_server_cert); | |
{ | |
// Check WiFi connection | |
if ((WiFi.status() == WL_CONNECTED)) { | |
HTTPClient http; | |
Serial.print("[HTTP] begin...\n"); | |
// Configure server and url | |
http.begin(*client, url); | |
Serial.print("[HTTP] GET...\n"); | |
// Start connection and send HTTP header | |
int httpCode = http.GET(); | |
if (httpCode > 0) { | |
fs::File f = SPIFFS.open(filename, "w+"); | |
if (!f) { | |
Serial.println("file open failed"); | |
return 0; | |
} | |
// HTTP header has been send and Server response header has been handled | |
Serial.printf("[HTTP] GET... code: %d\n", httpCode); | |
// File found at server | |
if (httpCode == HTTP_CODE_OK) { | |
// Get length of document (is -1 when Server sends no Content-Length header) | |
int total = http.getSize(); | |
int len = total; | |
// Create buffer for read | |
uint8_t buff[128] = { 0 }; | |
// Get tcp stream | |
WiFiClient * stream = http.getStreamPtr(); | |
// Read all data from server | |
while (http.connected() && (len > 0 || len == -1)) { | |
// Get available data size | |
size_t size = stream->available(); | |
if (size) { | |
// Read up to 128 bytes | |
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size)); | |
// Write it to file | |
f.write(buff, c); | |
// Calculate remaining bytes | |
if (len > 0) { | |
len -= c; | |
} | |
} | |
yield(); | |
} | |
Serial.println(); | |
Serial.print("[HTTP] connection closed or file end.\n"); | |
} | |
f.close(); | |
} | |
else { | |
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str()); | |
} | |
http.end(); | |
} | |
} | |
delete client; | |
} else { | |
Serial.println("Unable to create client"); | |
return -1; | |
} | |
return 1; // File was fetched from web | |
} |
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
/******************************************************************* | |
Display an image from Spotify on a matrix display | |
This is a rough proof of concept | |
This is a mashup of two examples from the TJpg_Decoder library, | |
further modified to add support for HTTPS | |
Parts: | |
ESP32 D1 Mini * - https://s.click.aliexpress.com/e/_dSi824B | |
ESP32 I2S Matrix Shield (From my Tindie) = https://www.tindie.com/products/brianlough/esp32-i2s-matrix-shield/ | |
* * = 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 | |
*******************************************************************/ | |
// Example for library: | |
// https://github.com/Bodmer/TJpg_Decoder | |
// This example is for an ESP8266 or ESP32, it fetches a Jpeg file | |
// from the web and saves it in a SPIFFS file. You must have SPIFFS | |
// space allocated in the IDE. | |
// Chenge next 2 lines to suit your WiFi network | |
#define WIFI_SSID "wifi" | |
#define PASSWORD "pass" | |
#define ALBUM_ART "/album.jpg" | |
// Include the jpeg decoder library | |
#include <TJpg_Decoder.h> | |
// https://github.com/Bodmer/TJpg_Decoder | |
// Include SPIFFS | |
#define FS_NO_GLOBALS | |
#include <FS.h> | |
// Include WiFi and http client | |
#ifdef ESP8266 | |
#include <ESP8266WiFi.h> | |
#include <ESP8266HTTPClient.h> | |
#include <WiFiClientSecure.h> | |
#else | |
#include "SPIFFS.h" // Required for ESP32 only | |
#include <WiFi.h> | |
#include <HTTPClient.h> | |
#include <WiFiClientSecure.h> | |
#endif | |
#include <ArduinoSpotifyCert.h> | |
// Load tabs attached to this sketch | |
#include "List_SPIFFS.h" | |
#include "Web_Fetch.h" | |
#include <ESP32-RGB64x32MatrixPanel-I2S-DMA.h> | |
RGB64x32MatrixPanel_I2S_DMA dma_display; | |
// This next function will be called during decoding of the jpeg file to | |
// render each block to the TFT. If you use a different TFT library | |
// you will need to adapt this function to suit. | |
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) | |
{ | |
// Stop further decoding as image is running off bottom of screen | |
if ( y >= dma_display.height() ) return 0; | |
dma_display.drawRGBBitmap(x, y, bitmap, w, h); | |
// Return 1 to decode next block | |
return 1; | |
} | |
void setup() | |
{ | |
Serial.begin(115200); | |
Serial.println("\n\n Testing TJpg_Decoder library"); | |
// Initialise SPIFFS | |
if (!SPIFFS.begin(true)) { | |
Serial.println("SPIFFS initialisation failed!"); | |
while (1) yield(); // Stay here twiddling thumbs waiting | |
} | |
Serial.println("\r\nInitialisation done."); | |
// Initialise the TFT | |
dma_display.begin(); | |
dma_display.fillScreen(dma_display.color565(0, 0, 0)); | |
// The jpeg image can be scaled by a factor of 1, 2, 4, or 8 | |
TJpgDec.setJpgScale(1); | |
// The decoder must be given the exact name of the rendering function above | |
TJpgDec.setCallback(tft_output); | |
// The byte order can be swapped (set true for TFT_eSPI) | |
//TJpgDec.setSwapBytes(true); | |
WiFi.begin(WIFI_SSID, PASSWORD); | |
while (WiFi.status() != WL_CONNECTED) { | |
delay(1000); | |
Serial.print("."); | |
} | |
Serial.println(); | |
// This is for demoe purposes only so that file is fetched each time this is run | |
if (SPIFFS.exists(ALBUM_ART) == true) { | |
Serial.println("For test only, removing file"); | |
SPIFFS.remove(ALBUM_ART); | |
//SPIFSS.remove("/F35.jpg"); | |
} | |
} | |
void loop() | |
{ | |
// List files stored in SPIFFS | |
listSPIFFS(); | |
// Time recorded for test purposes | |
uint32_t t = millis(); | |
// Fetch the jpg file from the specified URL, examples only, from imgur | |
bool loaded_ok = getFile("https://i.scdn.co/image/ab67616d00004851d72fb5571087bca0a2fed008", ALBUM_ART); // Note name preceded with "/" | |
//bool loaded_ok = downloadFile("http://i.imgur.com/OnW2qOO.jpg", "/F35.jpg"); | |
t = millis() - t; | |
if (loaded_ok) { Serial.print(t); Serial.println(" ms to download"); } | |
// List files stored in SPIFFS, should have the file now | |
listSPIFFS(); | |
t = millis(); | |
// Now draw the SPIFFS file | |
TJpgDec.drawFsJpg(0, 0, ALBUM_ART); | |
//TJpgDec.drawFsJpg(0, 0, "/F35.jpg"); | |
t = millis() - t; | |
Serial.print(t); Serial.println(" ms to draw to TFT"); | |
// Wait forever | |
while(1) yield(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment