inkplate-6-arduino-library/examples/Projects/Spotify_api_example/Spotify_api_example.ino

240 lines
6.5 KiB
Arduino
Raw Normal View History

2020-09-24 10:43:08 +02:00
/*
Spotify_api_example for e-radionica.com Inkplate 6
For this example you will need only USB cable and Inkplate 6.
Select "Inkplate 6(ESP32)" from Tools -> Board menu.
Don't have "Inkplate 6(ESP32)" option? Follow our tutorial and add it:
https://e-radionica.com/en/blog/add-inkplate-6-to-arduino-ide/
This project shows you how Inkplate 6 can be used to display
your spotify real time activity.
To get this working, see https://inkplate.readthedocs.io/en/latest/examples.html#spotify-api
It is quite complicated, but were sure you'll get it working!
Want to learn more about Inkplate? Visit www.inkplate.io
Looking to get support? Write on our forums: http://forum.e-radionica.com/en/
3 August 2020 by e-radionica.com
*/
2020-09-23 14:55:41 +02:00
#include "Inkplate.h"
#include <ArduinoJson.h>
#include <ArduinoSpotify.h>
#include <ArduinoSpotifyCert.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
2020-09-23 15:11:48 +02:00
// Include auto generated UI code
2020-09-23 14:55:41 +02:00
#include "generatedUI.h"
2020-09-23 15:11:48 +02:00
// Declare our Inkplate object
2020-09-23 14:55:41 +02:00
Inkplate display(INKPLATE_1BIT);
2020-09-23 15:11:48 +02:00
// Fill these with your credentials
2020-09-23 14:55:41 +02:00
char ssid[] = "";
char password[] = "";
char clientId[] = "";
char clientSecret[] = "";
#define SPOTIFY_REFRESH_TOKEN ""
#define SPOTIFY_MARKET "IE"
2020-09-23 15:11:48 +02:00
// --------------------------------
2020-09-23 14:55:41 +02:00
2020-09-23 15:11:48 +02:00
// Variables for storing data to be rendered to screen
2020-09-23 14:55:41 +02:00
char name[128];
char title[128];
char album[128];
char url[128];
int imgW;
bool playing;
int elapsedTime = 0;
int totalTime = 0;
float elapsed = 0;
2020-09-23 15:11:48 +02:00
// Define how often to do a full screen refresh
2020-09-23 14:55:41 +02:00
#define FULLREFRESH 10
int cnt = 0;
2020-09-23 15:11:48 +02:00
// Adjust these for your timezone
2020-09-23 14:55:41 +02:00
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
2020-09-23 15:11:48 +02:00
// Initiate Spotify API wrapper object
2020-09-23 14:55:41 +02:00
WiFiClientSecure client;
ArduinoSpotify spotify(client, clientId, clientSecret, SPOTIFY_REFRESH_TOKEN);
2020-09-23 15:11:48 +02:00
// Time between requests to Spotify API
unsigned long delayBetweenRequests = 100;
2020-09-23 14:55:41 +02:00
void setup()
{
2020-09-23 15:11:48 +02:00
// Initialise serial and display objects
2020-09-23 14:55:41 +02:00
Serial.begin(115200);
display.begin();
2020-09-23 15:11:48 +02:00
// Connect to WiFi
2020-09-23 14:55:41 +02:00
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting...");
// Wait for connection
int cnt = 0;
Serial.print(F("Waiting for WiFi to connect..."));
while ((WiFi.status() != WL_CONNECTED))
{
Serial.print(F("."));
delay(1000);
++cnt;
if (cnt == 20)
{
Serial.println("Can't connect to WIFI, restarting");
delay(100);
ESP.restart();
}
}
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
2020-09-23 15:11:48 +02:00
// Set Spotify certificate
2020-09-23 14:55:41 +02:00
client.setCACert(spotify_server_cert);
Serial.println("Refreshing Access Tokens");
if (!spotify.refreshAccessToken())
{
Serial.println("Failed to get access tokens");
}
2020-09-23 15:11:48 +02:00
// Get time from internet
2020-09-23 14:55:41 +02:00
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
2020-09-23 15:11:48 +02:00
// Display blank screen
2020-09-23 14:55:41 +02:00
display.display();
}
void loop()
{
2020-09-23 15:11:48 +02:00
// If Inkplate disconnected form WiFi try reconnecting and if that fails reset
2020-09-23 14:55:41 +02:00
if (!display.isConnected())
{
Serial.println("Reconnecting...");
delay(100);
if (!display.joinAP(ssid, password))
ESP.restart();
}
2020-09-23 15:11:48 +02:00
// Get currently playing track info
2020-09-23 14:55:41 +02:00
CurrentlyPlaying currentlyPlaying = spotify.getCurrentlyPlaying(SPOTIFY_MARKET);
2020-09-23 15:11:48 +02:00
// If all went well display to screen
2020-09-23 14:55:41 +02:00
if (!currentlyPlaying.error)
{
parsePlayingData(currentlyPlaying);
updateScreenContent();
}
delay(delayBetweenRequests);
}
void parsePlayingData(CurrentlyPlaying currentlyPlaying)
{
2020-09-23 15:11:48 +02:00
// Copy data to global variables
2020-09-23 14:55:41 +02:00
strcpy(name, currentlyPlaying.firstArtistName);
strcpy(title, currentlyPlaying.trackName);
strcpy(album, currentlyPlaying.albumName);
playing = currentlyPlaying.isPlaying;
2020-09-23 15:11:48 +02:00
// Find image whose dimensions are closest to 300 by 300
2020-09-23 14:55:41 +02:00
int mn = 0;
for (int i = 1; i < currentlyPlaying.numImages; i++)
if (abs(currentlyPlaying.albumImages[i].width - 300) + abs(currentlyPlaying.albumImages[i].width - 300) <
abs(currentlyPlaying.albumImages[mn].width - 300) + abs(currentlyPlaying.albumImages[mn].width - 300))
mn = i;
2020-09-23 15:11:48 +02:00
// Copy data to global variables
2020-09-23 14:55:41 +02:00
imgW = currentlyPlaying.albumImages[mn].width;
strcpy(url, currentlyPlaying.albumImages[mn].url);
2020-09-23 15:11:48 +02:00
// Copy data to global variables
2020-09-23 14:55:41 +02:00
elapsed = (float)currentlyPlaying.progressMs / (float)currentlyPlaying.duraitonMs;
elapsedTime = currentlyPlaying.progressMs / 1000;
totalTime = currentlyPlaying.duraitonMs / 1000;
}
void updateScreenContent()
{
2020-09-23 15:11:48 +02:00
// Initally clear the INkplate buffer
2020-09-23 14:55:41 +02:00
display.clearDisplay();
2020-09-23 15:11:48 +02:00
// Display playing info
2020-09-23 14:55:41 +02:00
line1_color = line2_color = playing;
triangle2_color = !playing;
2020-09-23 15:11:48 +02:00
// Limit text to 35 chars and add ... if needed
2020-09-23 14:55:41 +02:00
strncpy(text1_content, name, min((int)35, (int)strlen(name)));
strncpy(text2_content, title, min((int)35, (int)strlen(title)));
strncpy(text3_content, album, min((int)35, (int)strlen(album)));
text1_content[min((int)35, (int)strlen(name))] = 0;
text2_content[min((int)35, (int)strlen(title))] = 0;
text3_content[min((int)35, (int)strlen(album))] = 0;
if (strlen(name) >= 35)
strcat(text1_content, "...");
if (strlen(title) >= 35)
strcat(text2_content, "...");
if (strlen(album) >= 35)
strcat(text3_content, "...");
2020-09-23 15:11:48 +02:00
// Functions to center text and image
2020-09-23 14:55:41 +02:00
int16_t x1 = 0, y1 = 0;
uint16_t w = 0, h = 0;
display.setFont(text1_font);
display.getTextBounds(text1_content, 0, 200, &x1, &y1, &w, &h);
text1_cursor_x = 400 - w / 2;
display.setFont(text2_font);
display.getTextBounds(text2_content, 0, 200, &x1, &y1, &w, &h);
text2_cursor_x = 400 - w / 2;
display.setFont(text3_font);
display.getTextBounds(text3_content, 0, 200, &x1, &y1, &w, &h);
text3_cursor_x = 400 - w / 2;
display.drawJpegFromWeb(url, 400 - imgW / 2, 103, 1);
circle2_center_x = elapsed * (730 - 70) + 70;
2020-09-23 15:11:48 +02:00
// Display time
2020-09-23 14:55:41 +02:00
digital_clock2_h = elapsedTime / 60;
digital_clock2_m = elapsedTime % 60;
digital_clock5_h = totalTime / 60;
digital_clock5_m = totalTime % 60;
struct tm timeinfo;
if (getLocalTime(&timeinfo))
{
digital_clock4_h = timeinfo.tm_hour;
digital_clock4_m = timeinfo.tm_min;
}
2020-09-23 15:11:48 +02:00
// Draw all rest auto generated UI
2020-09-23 14:55:41 +02:00
mainDraw();
2020-09-23 15:11:48 +02:00
// Every FULLREFRESH do a full refresh
2020-09-23 14:55:41 +02:00
if (cnt++ % FULLREFRESH == 0)
display.display();
else
display.partialUpdate();
}