Giter Club home page Giter Club logo

spotify-api-arduino's Introduction

spotify-api-arduino

Travis CI status License Release stable
Arduino library for integrating with a subset of the Spotify Web-API (Does not play music)

Work in progress library - expect changes!

Supported Boards:

ESP32

Working well

ESP8266

Working well

Other boards - Arduino Wifi Nina (Nano IOT etc)

Should in theory work, but I have no tested it on them and will not be able to provide support for them.

Help support what I do!

I have put a lot of effort into creating Arduino libraries that I hope people can make use of. If you enjoy my work, please consider becoming a Github sponsor!

Library Features:

The Library supports the following features:

  • Get Authentication Tokens
  • Getting your currently playing track
  • Player Controls:
    • Next
    • Previous
    • Seek
    • Play (basic version, basically resumes a paused track)
    • Play Advanced (play given song, album, artist)
    • Pause
    • Set Volume (doesn't seem to work on my phone, works on desktop though)
    • Set Repeat Modes
    • Toggle Shuffle
  • Get Devices
  • Search Spotify Library

What needs to be added:

  • Better instructions for how to set up your refresh token.
  • Example where refresh token and full operation are handled in same sketch.

Setup Instructions

Spotify Account

  • Sign into the Spotify Developer page
  • Create a new application. (name it whatever you want)
  • You will need to use the "client ID" and "client secret" from this page in your sketches
  • You will also need to add a callback URI for authentication process by clicking "Edit Settings", what URI to add will be mentioned in further instructions

Getting Your Refresh Token

Spotify's Authentication flow requires a webserver to complete, but it's only needed once to get your refresh token. Your refresh token can then be used in all future sketches to authenticate.

Because the webserver is only needed once, I decided to seperate the logic for getting the Refresh token to it's own example.

Follow the instructions in the getRefreshToken example to get your token.

Note: Once you have a refresh token, you can use it on either platform in your sketches, it is not tied to any particular device.

Running

Take one of the included examples and update it with your WiFi creds, Client ID, Client Secret and the refresh token you just generated.

Scopes

By default the getRefreshToken examples will include the required scopes, but if you want change them the following info might be useful.

put a %20 between the ones you need.

Feature Required Scope
Current Playing Song Info user-read-playback-state
Player Controls user-modify-playback-state

Installation

Download zip from Github and install to the Arduino IDE using that.

Dependancies

  • V6 of Arduino JSON - can be installed through the Arduino Library manager.

Compile flag configuration

There are some flags that you can set in the SpotifyArduino.h that can help with debugging


#define SPOTIFY_DEBUG 1
// Enables extra debug messages on the serial.
// Will be disabled by default when library is released.
// NOTE: Do not use this option on live-streams, it will reveal your private tokens!

#define SPOTIFY_SERIAL_OUTPUT 1
// Comment out if you want to disable any serial output from this library
// (also comment out DEBUG and PRINT_JSON_PARSE)

//#define SPOTIFY_PRINT_JSON_PARSE 1
// Prints the JSON received to serial (only use for debugging as it will be slow)
// Requires the installation of ArduinoStreamUtils (https://github.com/bblanchon/ArduinoStreamUtils)

spotify-api-arduino's People

Contributors

bolukan avatar christianfemia avatar danielrcoates avatar dennisnon avatar fabquenneville avatar gabe-h avatar j4cko avatar mirageofmage avatar om-hb avatar paulskpt avatar witnessmenow avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

spotify-api-arduino's Issues

Control playback

Hello Brian,
Very nice library! Deserves support.
Looking at the examples, i.e. playback control.ino. Is it possible to add for example a hardware button to a command?

Best,
Rodney

Getting a "could not parse error" info. Not displaying refresh token

I have used this library for about 6 months and then suddenly I'm constantly getting a could not parse error and connection failed. When I try to get my new refresh token, it is not prompting it and again i get could not parse error on my serial monitor. Please help :((

Crashes when it's time to Refresh the Access Token

This the the Serial Monitor

/v1/me/player/currently-playing?market=NO
Status Code: 200
Closing client
[ #1 ][SPOTIFY][LOOP] triggered!
[ #2 ][SPOTIFY][CHECK][ISPLAYING] True
[ #3 ][SPOTIFY][SET][CURRENTLYPLAYING] The Real Slim Shady

/v1/me/player/currently-playing?market=NO
Status Code: 200
Closing client
[ #1 ][SPOTIFY][LOOP] triggered!
[ #2 ][SPOTIFY][CHECK][ISPLAYING] True
[ #3 ][SPOTIFY][SET][CURRENTLYPLAYING] The Real Slim Shady

/v1/me/player/currently-playing?market=NO
Status Code: 200
Closing client
[ #1 ][SPOTIFY][LOOP] triggered!
[ #2 ][SPOTIFY][CHECK][ISPLAYING] True
[ #3 ][SPOTIFY][SET][CURRENTLYPLAYING] The Real Slim Shady

/v1/me/player/currently-playing?market=NO
Refresh of the Access token is due, doing that now.

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x400014e8  PS      : 0x00060230  A0      : 0x800f3200  A1      : 0x3ffb1590  
A2      : 0x00496972  A3      : 0x00496970  A4      : 0x000000ff  A5      : 0x0000ff00
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x462d4100  A9      : 0x3ffb1860  
A10     : 0x00000003  A11     : 0x00060223  A12     : 0x00060220  A13     : 0x00000000  
A14     : 0x00000000  A15     : 0x00000000  SAR     : 0x0000000a  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00496970  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

ELF file SHA256: 0000000000000000

Backtrace: 0x400014e8:0x3ffb1590 0x400f31fd:0x3ffb15a0 0x400f1349:0x3ffb18b0 0x400d1bca:0x3ffb1970 0x400d1d2d:0x3ffb1db0 0x400d1dad:0x3ffb1dd0 0x400d258b:0x3ffb1f10 0x400d25fa:0x3ffb1f80 0x400d71b8:0x3ffb1fb0 0x4008992a:0x3ffb1fd0
  #0  0x400014e8:0x3ffb1590 in ?? ??:0
  #1  0x400f31fd:0x3ffb15a0 in _svfprintf_r at /Users/ivan/e/newlib_xtensa-2.2.0-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/stdio/../../../.././newlib/libc/stdio/vfprintf.c:1529
  #2  0x400f1349:0x3ffb18b0 in sprintf at /Users/ivan/e/newlib_xtensa-2.2.0-bin/newlib_xtensa-2.2.0/xtensa-esp32-elf/newlib/libc/stdio/../../../.././newlib/libc/stdio/sprintf.c:644
  #3  0x400d1bca:0x3ffb1970 in ArduinoSpotify::refreshAccessToken() at src/ArduinoSpotify.cpp:247
  #4  0x400d1d2d:0x3ffb1db0 in ArduinoSpotify::checkAndRefreshAccessToken() at src/ArduinoSpotify.cpp:247
  #5  0x400d1dad:0x3ffb1dd0 in ArduinoSpotify::getCurrentlyPlaying(char const*) at src/ArduinoSpotify.cpp:247
  #6  0x400d258b:0x3ffb1f10 in Spotify::loop() at include/mySpotify.h:102
  #7  0x400d25fa:0x3ffb1f80 in loop() at src/main.cpp:31
  #8  0x400d71b8:0x3ffb1fb0 in loopTask(void*) at C:\users\krist\.platformio\packages\framework-arduinoespressif32\cores\esp32/main.cpp:23
  #9  0x4008992a:0x3ffb1fd0 in vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c:355 (discriminator 1)

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8
*** ESP32-HUB75-MatrixPanel-I2S-DMA: Memory Allocations Complete ***
Total memory that was reserved: 14 kB.
... of which was used for the DMA Linked List(s): 6 kB.
Heap Memory Available: 313896 bytes total. Largest free block: 113792 bytes.
General RAM Available: 245556 bytes total. Largest free block: 113792 bytes.
[WIFI][STATUS] Connecting to WiFi..
[WIFI][STATUS] Connecting to WiFi..
[WIFI][STATUS] Connecting to WiFi..
[WIFI][STATUS] Connecting to WiFi..
[WIFI][STATUS] Connecting to WiFi..
[WIFI][STATUS] Connected
[DNS][NAME] Matrix16x32
grant_type=refresh_token&refresh_token=AQDEDjdcfKXdlEbipT96ipLNUd7Z5POAsIZCmT_xxGs_LlSp1cbvKiwLDYxAoCfgSJKVyKzOe5hYZ9ROE9I5djTvGMD4Kj36NiaAtsKomNnopM8y5yF7zXYHGiGvp99BVg4&client_id=02a6ad0c66434cf5b5cd792f59aeee0f&client_secret=dbf2688de2c147c695564070cc4dc30a
Status Code: 200
status Code200
Closing client
/v1/me/player/currently-playing?market=NO
Status Code: 200
Closing client
[ #1 ][SPOTIFY][LOOP] triggered!
[ #2 ][SPOTIFY][CHECK][ISPLAYING] True
[ #3 ][SPOTIFY][SET][CURRENTLYPLAYING] The Real Slim Shady
[ #4 ][SPOTIFY][CHECK][NEWSONG][OR][SAMESONG] False/True
/v1/me/player/currently-playing?market=NO
Status Code: 200
Closing client

And this is what my main loop looks like

void loop()
{
  if (millis() > requestDueTime)
  {
    Spotify::loop();

    if (Spotify::isPlaying() == true)
    {

      #ifdef SPOTIFY_DEBUG
          Serial.println("[ #2 ][SPOTIFY][CHECK][ISPLAYING] True");
      #endif

      String currentlyPlaying = String(Spotify::currentlyPlaying.trackName);

      #ifdef SPOTIFY_DEBUG
          Serial.print("[ #3 ][SPOTIFY][SET][CURRENTLYPLAYING] ");
          Serial.println(currentlyPlaying);
      #endif

      if (currentlyPlaying != Spotify::lastPlayedSong || Spotify::SpotifyPaused == true)
      {

        #ifdef SPOTIFY_DEBUG
            Serial.println("[ #4 ][SPOTIFY][CHECK][NEWSONG][OR][SAMESONG] False/True");
        #endif

        Matrix::clear();
        Matrix::drawSpotifyLogo();
        Matrix::writeText(18, 0, dma_display->color444(0,0,15), Spotify::currentlyPlaying.firstArtistName);
        Matrix::writeText(18, 8, dma_display->color444(0,15,0), Spotify::currentlyPlaying.trackName);
        Spotify::lastPlayedSong = currentlyPlaying;
        Spotify::SpotifyPaused = false;
      }
      Matrix::drawOnce = false;
    }
    else
    {
      if (Matrix::drawOnce == false)
      {

        #ifdef SPOTIFY_DEBUG
            Serial.println("[ #5 ][SPOTIFY][CHECK][ISPLAYING] False");
        #endif

        Matrix::clear();
        Matrix::drawSpotifyLogo();
        Matrix::writeText(18, 0, dma_display->color444(15,0,0), (char *)"Spotify is not playing!");
        Matrix::writeText(18, 8, dma_display->color444(15,15,15), (char *)"Time 4 silent party!");
        Matrix::drawOnce = true;
        Spotify::SpotifyPaused = true;
      }
    }
    requestDueTime = millis() + delayBetweenRequests;
  }
}

Status: HTTP/1.0 403 Forbidden

Hi,
when I try playerControls.ino it does not work, i get Status: HTTP/1.0 403 Forbidden.

Serial monitor:
Posnetek zaslona 2021-09-05 135325

but if i try getCurrentlyPlaying.ino, it works. I tried diferent scopes (user-modify-playback-state and user-read-playback-state) but problem persist.

Is that happening because I don't have premium or is something else?

PS: @witnessmenow Love you work, you are brilliant! <3

Strange behaviour of player controls function

Hi I am new to C++ language and this library. So far this library works for my project, however, the spotify.play() function will always fail with the following message.

/v1/me/player/play
api.spotify.com
[ 11307][E][ssl_client.cpp:37] _handle_error(): [send_ssl_data():382]: (-80) UNKNOWN ERROR CODE (0050)
Failed to send request

The strange thing is, the request was actually sent successfully, and my music was played as intended.

Additional Info:

  • I have a Spotify premium account
  • The function was only called once

Super long access token

22:06:48.440 -> Free Heap: 209044
22:06:48.440 -> getting currently playing song:
22:06:48.440 -> /v1/me/player/currently-playing?additional_types=episode&market=US
22:06:48.440 -> stack size -1070511967
22:06:48.440 -> Refresh of the Access token is due, doing that now.
22:06:48.440 -> grant_type=refresh_token&refresh_token (hidden)
22:06:48.440 -> stack size -1070511455
22:06:48.440 -> accounts.spotify.com
22:06:49.044 -> Status: HTTP/1.0 200 OK
22:06:49.044 -> HTTP Version: HTTP/1.0
22:06:49.044 -> Status Code: 200
22:06:49.044 -> status Code200
22:06:49.044 -> No JSON error, dealing with response
22:06:49.044 -> Problem with access_token (too long or null): 582 character token was here
22:06:49.652 -> Failed to send request
22:06:49.652 -> Status Code: -2
22:06:49.652 -> stack size -1070511967
22:06:49.652 -> Error: -2

This is what my output looks like. Code worked fine until a few days ago, ran the token refresh but that was broke. Updated library and still didn't fix the issue. Used a different program to get the refresh token and now the output is what I get. It's trying to use an absurdly long 582 character access token

Update documentation regarding the getRefreshToken

Hi Brian, yesterday I managed to run the getRefreshToken successfully, but only after performing some steps that I did not read in the documentation. Beside opening a Developers account on Spotify and creating a 'first application', I discovered that, only after performing two other steps, the getRefreshToken procedure was executing successfully. The two extra steps are these:

  1. in your Spotify Developers Dashboard. Click on the icon (big green square) of your first application. Then click on the button "Settings". In the item "Rederict URIs" add the "http://<your_local_ip_address>/callback/", e.g. "http://192.168.1.114/callback/". Then click on the button "ADD". This white-lists the given address to rederict to after authentication success OR failure.
  2. Next, back in the dashboard of your first app, click on the button "USERS AND ACCESS". In the next page click left down on the button "+ ADD NEW USER". There you will be asked to enter the full name and his/hers Spotify Account e-mail address of the user to add. I added myself as first user. One can add 25 users for each app (or ask Spotify for an 'extension').
    After this all has been done you can leave the Spotify Developer site. Next run the getRefreshToken sketch in the Arduino IDE. Have the Arduino IDE Monitor window open When you see that the sketch is running go inside a webbrowser. Go to http:// (e.g. "http://192.168.1.114"); press . On the next page that shows only a short link in the upper left of the window, click on that link; watch the Monitor Window. There will be output of exchange of authentication protocol. When things proceed OK, there will pop up a window in your webbrowser, in top the Spotify logo, below it the name you gave to your first app and a text with three items you must AGREE upon (you give consent that users of your app can view your Spotify account data; view your activity on Spotify; Take actions in Spotify on your behalf. This page also informs you how to remove your authorization to users of your app. After I clicked the AGREE button, immediately arrived the RefreshToken on the webbrowser page as in the dialogue printed onto the IDE's Monitor window.
    I'll add some screenshots.

Final note: In the getRefreshToken.ino sketch, I un-commented the line 96 (#define USE_IP_ADDRESS 1", to use the MDNS option. I modifed line 104 to contain the IP-addres (192.168.1.114) instead of "arduino.local".

2021-10-20_23h44_Redirect_callback_URI_white-listed_img0

2021-10-20_20h35_Spotify_Developer_Dashboard_1stt_app_1st_user_added_v2

2021-10-20_23h16_Authorization_given_for_users_of_my_1st_app_

Add way to get device Ids

Is there an easy way to get the device ids available in my account? I couldn't find anything on this in the examples/code.

Using albumArtMatrix with a ICND2153 64x64 matrix

Hi,

I'm happily using the albumArtMatrix example with one om my matrices. However, I would like to use it with my new matrix that uses the ICND21153 IC. I am using the following library to control it: https://github.com/LAutour/ESP32-HUB75-MatrixPanel-DMA-ICN2053

When I plugged it in, this did not compile: dma_display->fillScreen(dma_display->color565(0, 0, 0));

Furthermore, when I commented the problematic rows out, the code compiled but the album art does not show up. I have previously modified the code to work with this library: https://github.com/mrfaptastic/ESP32-HUB75-MatrixPanel-DMA
I suspect that there is something that needs to be changed in the following function now:

// This next function will be called during decoding of the jpeg file to
// render each block to the Matrix. If you use a different display
// you will need to adapt this function to suit.

int JPEGDraw(JPEGDRAW *pDraw) {
// Stop further decoding as image is running off bottom of screen
if ( pDraw->y >= dma_display->height() ) return 1;

dma_display->drawRGBBitmap(pDraw->x, pDraw->y, pDraw->pPixels, pDraw->iWidth, pDraw->iHeight);
return 1;
}

I would be very thankful if anyone could point me in the right direction to make this work. Thanks!

Certificate issue

Hi,

I get the following error when using the code:

[ 71666][E][ssl_client.cpp:37] _handle_error(): [start_ssl_client():273]: (-9984) X509 - Certificate verification failed, e.g. CRL, CA or signature check failed
[ 71669][E][WiFiClientSecure.cpp:144] connect(): start_ssl_client: -9984

I have tried to get the new certificate from *.spotify.com and replaced the one in SpotifyArduinoCert.h but it does not solve the problem. Does anyone know how to fix this?

Can't get access token on ESP8266 status Code -1?

What the title says basically . I' can't really get my access token. It worked fine like 2 days ago, and yesterday I was unable to refresh it, so I went to generate a new, and I can't even get one.
Is there any fix for this?

Serial output:

WiFi connected
IP address: 
192.168.0.21
MDNS responder started
HTTP server started
File Not Found

URI: /favicon.ico
Method: GET
Arguments: 0
grant_type=authorization_code&code=AQDM7SVuLkCdS5UQjXNcxMeaBLRMLol8_YMaoTqsFcA3oB04fKJ9juLIbJj9PVxfsFsfT6r9ya3WlM6mGXdjwWlwLUnBKDYjFoMBM8QnUh4F45cu2Cm9eSpq_JoB9fh0zZlOhvtKZZnlE5Qs4BO_LZesAv1Vjjk41Jcl_RcqZ_wOWRXtAQYono9tcEiE4JztdHeIqiVuAIc2jkbL9BuCFoeI6vzCRGfi4EnCuGbpd4aUIIZsj9bV_g&redirect_uri=http%3A%2F%2Farduino.local%2Fcallback%2F&client_id=(my correct clientid)&client_secret=(my corret client secret)
Connection failed
status Code-1

Edit: Also Here's my code for the rpoject so far

#pragma region PINEK
#define ROTARY_PINA D2
#define ROTARY_PINB D1
#define GOMB_PIN D3
#define MIN 0 //rotary min ertek
#define MAX 25 //rotary max ertek
#define TFT_CS 15
#define TFT_RST 0
#define TFT_DC 2
#pragma endregion

#pragma region KONYVTARAK
//ESP8266hoz
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <HttpClient.h>

//A kep letoltesehez
//#include <ESPDownload.h>
#include "FS.h"

//kijelzohoz
#include <Adafruit_GFX.h>
#include <Adafruit_ST7735.h>

//Rotary encoderhez
#include <ClickEncoder.h>
#define CLIK_PER_LEPES 4 //Rotary encoderhez alapertelmezett ertek

//Spotifyhez
#include <ArduinoJson.h>
#include <ArduinoSpotify.h>
#pragma endregion

#pragma region PRIVATADATOK
char ssid[] = "ssid";   // SSID
char jelszo[] = "password"; // Jelszo

char clientId[] = "myclientid"; // Spotify ClientID
char clientSecret[] = "myclientpassword"; // Spotify ClientSecret

#define SPOTIFY_MARKET "HU"
#define SPOTIFY_REFRESH_TOKEN "AQAZjXFmjhjU0_5P-sksQJcV32WqIZj2t70FBiRuTJsebfmUf6zDyyTx15Tk9aloEqN68fmvCPJBPpDnZ3VXJqA8QEnRhumt4x3HJX7hS2JExcaf4-0hxCKeS5Ds_9gVjmB_sL0Ry-FwjwKWjbwXtjsjDeOp1i8rRwtA4-ZjJu63hQ"
#pragma endregion

#pragma region objektumok
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

ClickEncoder encoder = ClickEncoder(ROTARY_PINA,ROTARY_PINB,GOMB_PIN,CLIK_PER_LEPES);

WiFiClientSecure wificlient;

ArduinoSpotify *spotify;

//ESPDownload downloader = ESPDownload();
#pragma endregion

#pragma region kijelzo tisztitas
//letisztitja a kijelzot
void clearScreen(){
  tft.fillScreen(ST77XX_BLACK);
}
#pragma endregion

#pragma region startup
//csatlakozik a wifihez
void csatlakozasWifihez(){
  WiFi.mode(WIFI_STA); // station-mód
  WiFi.disconnect();
  delay(100);
  
  Serial.print("Csatlakozas WIFI-hez: "); // csatlakozas wifihez
  Serial.println(ssid);
  WiFi.begin(ssid, jelszo);
  while (WiFi.status() != WL_CONNECTED) // amig nem csatlakozik
  {
    Serial.print(".");
    delay(1000);
  }
  Serial.println("");
  Serial.println("Csatlakozva!");
  Serial.println("IP cim: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
}


//spotify alapbeallitasai
void spotifyAlap(){
  //wificlient.setFingerprint(SPOTIFY_FINGERPRINT); // ssl fingerprint beallitasa
  Serial.println(
      "Access Tokenek frissitese"); // ez altal ferunk hozza a Spotify API-hoz
  /*if (!spotify->refreshAccessToken()) {
    Serial.println("Nem sikerült lekerdezni az Access Tokeneket");
  }*/
}

//encoder alapbeallitasait
void encoderAlap(){
  encoder.setDoubleClickEnabled(true);
  encoder.setAccelerationEnabled(false);
}

//kijelzo alapbeallitasai
void kijelzoAlap(){
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(2);
  tft.setTextWrap(false);
  tft.setTextColor(ST77XX_WHITE);
  clearScreen();
  printBar(0);
}
#pragma endregion

#pragma region Spotify lekerdezes es kiiras
//kiirja hogy jelenleg hol tart a zene
void printProgress(CurrentlyPlaying jelenlegJatszott){
  float eltelt = jelenlegJatszott.progressMs;
  float idotartam = jelenlegJatszott.duraitonMs;
  float szazalek = (eltelt / idotartam) * 100;
  int egeszszazalek = (int)szazalek;
  tft.fillRect(14, 152, 99, 6, ST77XX_BLACK);
  tft.fillRect(14, 152, egeszszazalek, 6, ST77XX_WHITE);
}

//itt tarolodik a zene es az eloado neve
char* zeneneve= "Burning Bridges / Long Day (feat. IDK)";
char* eloadoneve= "King Gizzard and The Lizard Wizard";

//lekerdezi az eloado es a zene nevet
void getArtistandMusic(CurrentlyPlaying jelenlegJatszott){
  eloadoneve = jelenlegJatszott.firstArtistName;
  zeneneve= jelenlegJatszott.trackName;
}

//kiirja az eloadot es a zene nevet
void printArtistandMusic(){
  tft.fillRect(13, 107, 115, 20, ST77XX_BLACK);
  tft.setCursor(13, 107);
  tft.print(eloadoneve); //dinamikusan megjelenítendő
  tft.setCursor(13, 117);
  tft.print(zeneneve); //dinamikusan megjelenítendő
}

//attol fuggoen hogy jelenleg jatszodik e le zene rajzol ki egy szimbolumot
void printPlayPause(CurrentlyPlaying jelenlegJatszott){
  tft.fillRect(56, 145, 16, -16, ST77XX_BLACK);
  if(jelenlegJatszott.isPlaying){
    tft.fillRect(58, 145, 4, -14, ST77XX_WHITE);
    tft.fillRect(66, 145, 4, -14, ST77XX_WHITE);
  }
  else{
    tft.fillTriangle(58, 145, 58, 131, 69, 138, ST77XX_WHITE);
  }
}
#pragma endregion

#pragma region Iranyito menu
//valtozok a menuk iranyitasahoz
int menuszam = 0;
int kivalasztottelem = 0;

//a visszalepo gomb kiirasa
void printBack(int kivalasztottelem){
  if (kivalasztottelem == 0){
    tft.fillRect(17, 14, -7, 4, ST77XX_GREEN);
    tft.fillTriangle(10, 20, 10, 12, 6, 16, ST77XX_GREEN);
  }
  else {
    tft.fillRect(17, 14, -7, 4, ST77XX_WHITE);
    tft.fillTriangle(10, 20, 10, 12, 6, 16, ST77XX_WHITE);
  }
}

//Ismetlodes be van e kapcsolva
//0 - off
//1 - album/playlist ismetles
//2 - zene ismetlese
int repeatcounter = 0;

//ismetles gomb kiirasa
void printRepeat(int kivalasztottelem){
  if (kivalasztottelem == 1){
    if (repeatcounter == 0){
      tft.drawCircle(112, 48, 5, ST77XX_GREEN);
    }
    else if (repeatcounter == 1){
      tft.fillCircle(112, 48, 5, ST77XX_GREEN);
    }
    else{
      tft.drawCircle(112, 48, 5, ST77XX_GREEN);
      tft.drawChar(110, 45, '1', ST77XX_GREEN, ST77XX_BLACK, 1);
    }
  }
  else{
    if (repeatcounter == 0){
      tft.drawCircle(112, 48, 5, ST77XX_WHITE);
    }
    else if (repeatcounter == 1){
      tft.fillCircle(112, 48, 5, ST77XX_WHITE);
    }
    else{
      tft.drawCircle(112, 48, 5, ST77XX_WHITE);
      tft.drawChar(110, 45, '1', ST77XX_WHITE, ST77XX_BLACK, 1);
    }
  }
}

//shuffle be van e kapcsolva
bool shuffletoggle = false;

//shuffle gomb kiirasa
void printShuffle(int kivalasztottelem){
  if (kivalasztottelem == 2){
    if (!shuffletoggle) tft.drawChar(110, 61, 'S', ST77XX_GREEN, ST77XX_BLACK, 1);
    else tft.drawChar(110, 61, 'S', ST77XX_RED, ST77XX_BLACK, 1);
  }
  else{
    if (!shuffletoggle) tft.drawChar(110, 61, 'S', ST77XX_WHITE, ST77XX_BLACK, 1);
    else tft.drawChar(110, 61, 'S', ST77XX_GREEN, ST77XX_BLACK, 1);
  }
}

//elozo zene gomb kiirasa
void printBackward(int kivalasztottelem){
  if (kivalasztottelem == 3){
    tft.fillTriangle(34, 145, 34, 131, 23, 138, ST77XX_GREEN);
    tft.fillTriangle(29, 145, 29, 131, 18, 138, ST77XX_GREEN);
  }
  else{
    tft.fillTriangle(34, 145, 34, 131, 23, 138, ST77XX_WHITE);
    tft.fillTriangle(29, 145, 29, 131, 18, 138, ST77XX_WHITE);
  }
}

//szunet gomb kiirasa
void printPause(int kivalasztottelem){
  if (kivalasztottelem == 4){
    tft.fillRect(46, 145, 4, -14, ST77XX_GREEN);
    tft.fillRect(54, 145, 4, -14, ST77XX_GREEN);
  }
  else{
    tft.fillRect(46, 145, 4, -14, ST77XX_WHITE);
    tft.fillRect(54, 145, 4, -14, ST77XX_WHITE);
  }
}

//lejatszas gomb kiirasa
void printPlay(int kivalasztottelem){
  if (kivalasztottelem == 5){
    tft.fillTriangle(72, 145, 72, 131, 81, 138, ST77XX_GREEN);
  }
  else{
    tft.fillTriangle(72, 145, 72, 131, 81, 138, ST77XX_WHITE);
  }
}

//kovetkezo zene gomb kiirasa
void printForward(int kivalasztottelem){
  if (kivalasztottelem == 6){
    tft.fillTriangle(94, 145, 94, 131, 105, 138, ST77XX_GREEN);
    tft.fillTriangle(99, 145, 99, 131, 110, 138, ST77XX_GREEN);
  }
  else{
    tft.fillTriangle(94, 145, 94, 131, 105, 138, ST77XX_WHITE);
    tft.fillTriangle(99, 145, 99, 131, 110, 138, ST77XX_WHITE);
  }
}

//az also progressbar/hangerosav kiirasa
void printBar(int menuszam){
  if (kivalasztottelem == 7){
    tft.drawRect(14, 151, 101, 8, ST77XX_GREEN);
  }
  else tft.drawRect(14, 151, 101, 8, ST77XX_WHITE);
}

//a hangerot kiirja a hangerosavra
void printVolume(int vol){
  tft.fillRect(14, 152, vol, 6, ST77XX_WHITE);
  tft.fillRect(114, 152, -(100-vol), 6, ST77XX_BLACK);
}

#pragma endregion

#pragma region setup
void setup() {
  Serial.begin(115200);
  spotify = new ArduinoSpotify(wificlient, clientId, clientSecret, SPOTIFY_REFRESH_TOKEN); 
  csatlakozasWifihez();
  spotifyAlap();
  encoderAlap();
  kijelzoAlap();
}
#pragma endregion

#pragma region loop valtozok
//Spotify jelenleg lejatszott zene
CurrentlyPlaying jelenlegJatszott;

//Jelenleg lejatszott zene URL-je
String jelenlegikepUrl = "";

//seged valtozo a belso menuhoz
bool kiirtamar = false;

//Spotify lekeresek kozotti ido
unsigned long kesleltetes = 2000; // Lekeres kozotti kesleltetesi ido
unsigned long kesleltetesseged;

//Nem kell ide magyarazat
int hangero = 100;
int newhangero = 100;
#pragma endregion

#pragma region loop
void loop() { 
  static uint32_t lastService = 0;
  if (lastService + 1000 < micros()) {
    lastService = micros();                
    encoder.service();  
  }
  
  static int16_t last, value;
  value += encoder.getValue();
  if (value != last) {
    last = value;
    if (menuszam == 2){
      newhangero = abs((last*5) % 101);
      Serial.println(newhangero);
    }
    else if (menuszam == 1){
      kivalasztottelem = abs(last % 8);
      Serial.println(kivalasztottelem);
    }
  }



  ClickEncoder::Button b = encoder.getButton();
  if (b != ClickEncoder::Open) {
    Serial.print("Button: ");
    switch (b) {
      case(ClickEncoder::Clicked): 
        if(menuszam == 0) {
          menuszam = 1; 
          clearScreen();
          printBar(0);
          kiirtamar = false;
        } 
        else if (menuszam == 1) {
          if(kivalasztottelem == 0){
            menuszam = 0;
            clearScreen();
            printBar(0);
          }
          else if(kivalasztottelem == 1){
            repeatcounter++;
            if (repeatcounter > 2) repeatcounter = 0;
            tft.fillRect(107, 43, 10, 10, ST77XX_BLACK);
            /*if (repeatcounter == 0) spotify->setRepeatMode(repeat_off);
            else if (repeatcounter == 1) spotify->setRepeatMode(repeat_context);
            else spotify->setRepeatMode(repeat_track);*/
          }
          else if(kivalasztottelem == 2){
            if (!shuffletoggle) shuffletoggle = true;
            else shuffletoggle = false;
            //spotify->toggleShuffle(shuffletoggle);
          }
          else if(kivalasztottelem == 3){
           // spotify->previousTrack();
          }
          else if(kivalasztottelem == 4){
           // spotify->pause();
          }
          else if(kivalasztottelem == 5){
            //spotify->play();
          }
          else if(kivalasztottelem == 6){
            //spotify->nextTrack();
          }
          else if(kivalasztottelem == 7){
            tft.fillRect(14, 152, 99, 6, ST77XX_BLACK);
            menuszam = 2;
          }
        }
        else if (menuszam == 2){
          if (newhangero != hangero){
            //spotify->setVolume(newhangero);
            hangero = newhangero;
          }
          value = 7;
          menuszam = 1;
        } 
        break;
      case(ClickEncoder::DoubleClicked): break; 
      default: break;
    }
  }    
  if (millis() > kesleltetesseged) {
    
    /*String curHREF = jelenlegJatszott.albumImages[2].url;
    curHREF.replace("https", "http");
    if (curHREF != jelenlegikepUrl){
      
    }*/
    if(menuszam == 0){
      jelenlegJatszott = spotify->getCurrentlyPlaying(SPOTIFY_MARKET);
      printProgress(jelenlegJatszott);
      //getArtistandMusic(jelenlegJatszott);
      printArtistandMusic(); 
      printPlayPause(jelenlegJatszott);
    }
    kesleltetesseged = millis() + kesleltetes;
  }
  if (menuszam == 1){
    printForward(kivalasztottelem);
    printBackward(kivalasztottelem);
    printPause(kivalasztottelem);
    printPlay(kivalasztottelem);
    printBack(kivalasztottelem);
    printBar(kivalasztottelem);
    printRepeat(kivalasztottelem);
    printShuffle(kivalasztottelem);
    if(!kiirtamar){
      printArtistandMusic();
      kiirtamar = true;
    }
  }
  if (menuszam == 2){
    printBar(7);
    printVolume(newhangero);
  }
}
#pragma endregion

Request time

When making a request to check if a song is playing it takes about 900ms to 1000ms to make the request, which causes the rest of my program to freeze.
Is there a way to speed that up?
This is part of my sketch:

void loop(){
    if (millis() > requestDueTime) {
       int status = spotify.getCurrentlyPlaying(updatePlaying, SPOTIFY_MARKET);
      requestDueTime = millis() + delayBetweenRequests;
    }

 }
void updatePlaying(CurrentlyPlaying currentlyPlaying) {
   isPlaying = currentlyPlaying.isPlaying;
}

Should not use sprintf with the same source and buffer

From Boulkan on Discord:

sprintf(command, command, position);

@brian L You tested it, so it works. But I doubt this is fool-proof for all C-implementations. @bitbank 💾Mr. Optimization any 2 cents?

citation: "However, the standards explicitly note that the results are undefined if source and destination buffers overlap"

But this is pointed to the overlap between the destination buffer (first command) and the variable (position). And the format is constant, so.... Just wondering.

Outdated Spotify Fingerprint

I believe the Spotify Fingerprint changed recently and it should be: 9F 3F 7B C6 26 4C 97 06 A2 D4 D7 B2 35 45 D9 AA 8D BD CD 4D

(would make a pull request but I'm not familiar enough with Github)

ESPmDNS not working solution

In the getRefreshToken.ino file
Add following line in declarations
const char* mdnsName = "ESPotify"; // Domain name for the mDNS responder

replace:
if (MDNS.begin("esp32")) {
Serial.println("MDNS responder started");
}
with:
if (MDNS.begin(mdnsName)) { // start the multicast domain name server
Serial.print("mDNS responder started: http://");
Serial.print(mdnsName);
Serial.println(".local");
}

And of course change the myDashboard in the spotify for developers page

Failing to get access token

Hello,

Everything was working up until a rain storm and power was cutoff my house, so my router reset and attributed a new IP address to the esp8266. I thought this was fine, so I went and tried to get a new refresh token by correcting the new IP address in the spotify App. I then uploaded the getRefreshToken sketch and when I clicked on the authentication, it went to the address with a completely blank page:

https://192.168.1.204/callback/?code=AQAn8o7M7ouo5wkRI2ys1prpPP44g6XXwPp8KBkvaLAXca6zLhSETLVnPO3RHqZH04HVO5p2bM5JphRqzXOkoW6PvRSQpEmIsAK6i5n-cn1UXW2pMwz13RAP5SDfP5zFEwgRHv9wBLT6v10VuRscKFv7BLkoVo5wxEDMkj0feiyy5ScNTpxndceLqPe47D3ZHOPHcDndm205zQgwp3-PMj83EuDY8yHRj2VxvvqEGGUrCw8gsn_0_Q

The refresh token was not printed on screen like last time I did this. So I tried using this (larger) string in the URL after '?code=' , but with no luck.

Could you help me figure out what is wrong? Thanks

Return -1 when using with ESPAsyncWebServer

When adding a basic async web server to my esp32 I get this error from the Spotify library (with and without multithreading):
/v1/me/player/currently-playing?additional_types=episode&market=DE
stack size -1073601487
Status Code: -1
My project has gotten quite large so I am not able to send the entire code.
Without the web server the stack size is about the same but it does not throw the error -1.

Method for setting access keys/bearer token needed

Hi, is there a reason there's no method to set access keys / _bearerToken (along with the time they were acquired)?

I'm using the ESP-32 Deep Sleep 'RTC_DATA_ATTR' variables, and that has a limit of 8kb ram as it is persistent through deep sleep. My problem is that I would rather not refresh the access key every time the ESP-32 wakes up from deep sleep if I can avoid it, as it causes the ESP32 to draw more power and creates some unnecessary requests. I could store the whole instance of the class in the 'RTC_DATA_ATTR' ram but that might be too much for it and it's not very efficient.

I was wondering whether or not I have missed something and if this was an intentional decision, otherwise I can make a PR to add this!

invalid conversion from 'const char*' to 'char*' [-fpermissive]

Hi, the new Version doesn't compile for me.
Did I do something wrong?

Arduino: 1.8.13 (Windows 10), Board: "WeMos D1 R1, 80 MHz, Flash, Disabled (new can abort), All SSL ciphers (most compatible), 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600"

C:\Users\eiers\Desktop\arduino-spotify-api-master\examples\esp8266\getRefreshToken\getRefreshToken.ino: In function 'void handleCallback()':

getRefreshToken:112:83: error: invalid conversion from 'const char*' to 'char*' [-fpermissive]

       refreshToken = spotify.requestAccessTokens((char*) code.c_str(), callbackURI);


exit status 1

invalid conversion from 'const char*' to 'char*' [-fpermissive]

Add support and examples for displaying images.

Various image sizes come back in the currently playing track endpoint. It would be cool to have ability to display them on screens

Need to also test what happens if you are playing a song that doesn't have an album

Estimated needed size of Heap?

Hey there, this is not really an issue, but a question,
do you know how much free dynamic Space the ESP8266 needs in order to process the JSON from Spotify?
Your example code works fine for me, but when Im merging it into my project, I get a Stack overflow and the ESP crashes.
I currently have 26752Bytes left for local Variables, which seems like to little?

Publish to PlatformIO & Arduino registries

While revisiting our old https://github.com/ThingPulse/esp8266-spotify-remote (maybe not even my fix/bssl-memory branch works with ESP8266 Ardunino Core 3.x) I thought that surely someone must have created a Spotify Arduino library in the meantime. That's how I ended up here. Thanks Brian!

Do you have any plans to publish to PlatformIO & Arduino registries? Considering that you've already got library.json and library.properties in place, you're nearly there 😄

Not Library related

Hi Brian, first thank you for your work.
I have implemented your Spotify api in order to show current track name and artist on a rgb matrix display (single 64x32 module with esp32 hub75 / Mrfaptastic library ).

Although in principle it works correctly, I can't show the name of the artist with dma_display->print(currentlyPlaying.artists[i].artistName);
I get compiling error with this funtion on RGB matrix display (on serial monitor is just fine)ç

Another help that I would like to ask you, is if it is possible to make the text scroll since there is not space for so much information in a simple panel.

Thanks in advance

`// ----------------------------
// Standard Libraries
// ----------------------------

#if defined(ESP8266)
#include <ESP8266WiFi.h>
#elif defined(ESP32)
#include <WiFi.h>
#endif
#include <Adafruit_GFX.h>
#include <Adafruit_GrayOLED.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>

#include <Arduino.h>

#include "Fonts/FreeSansBold9pt7b.h"
#include "Fonts/FreeSansBold12pt7b.h"
#include "Fonts/FreeSansBold18pt7b.h"
#include "Fonts/Picopixel.h"
#include "Fonts/FreeSerif9pt7b.h"
#include "Fonts/FreeSerif12pt7b.h"
#include "Fonts/FreeSerif18pt7b.h"
//#include "Fonts/FreeSerif12pt7b.h"

#include <WiFiClientSecure.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>

// ----------------------------
// Additional Libraries - each one of these will need to be installed.
// ----------------------------

#include <SpotifyArduino.h>
// Library for connecting to the Spotify API

// Install from Github
// https://github.com/witnessmenow/spotify-api-arduino

// including a "spotify_server_cert" variable
// header is included as part of the SpotifyArduino libary
#include <SpotifyArduinoCert.h>

#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

//------- Replace the following! ------

char ssid[] = "MiFibra-XXXX"; // your network SSID (name)
char password[] = "XXXXXXX"; // your network password
char clientId[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // Your client ID of your spotify APP
char clientSecret[] = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; // 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 "AQBn5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx--D4oPfCCMaXZAnQqBcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxaO4"

//------- ---------------------- ------
// -------------------------------------
// ------- Matrix Config ------
// -------------------------------------

const int panelResX = 64; // Number of pixels wide of each INDIVIDUAL panel module.
const int panelResY = 32; // Number of pixels tall of each INDIVIDUAL panel module.
const int panel_chain = 1; // Total number of panels chained one to another

#define ENABLE_DOUBLE_BUFFER 1 // This is a good example to show the difference the //estaba quitado originalmente
// double buffer makes, it doesn't flash as much
// comment this out to test without it

// See the "displaySetup" method for more display config options

//------------------------------------------------------------------------------------------------------------------

MatrixPanel_I2S_DMA *dma_display = nullptr;

WiFiClientSecure secured_client;

uint16_t myBLACK = dma_display->color565(0, 0, 0);
uint16_t myWHITE = dma_display->color565(255, 255, 255);
uint16_t myRED = dma_display->color565(255, 0, 0);
uint16_t myGREEN = dma_display->color565(0, 255, 0);
uint16_t myBLUE = dma_display->color565(0, 0, 255);
uint16_t myPINK = dma_display->color565(227, 28, 121);
uint16_t myYELLOW = dma_display->color565(255, 255, 0);
uint16_t myPURPLE = dma_display->color565(199, 36, 177);

void displaySetup() {
HUB75_I2S_CFG mxconfig(
panelResX, // module width
panelResY, // module height
panel_chain // Chain length
);

#ifdef ENABLE_DOUBLE_BUFFER
// This is how you enable the double buffer.
// Double buffer can help with animation heavy projects
mxconfig.double_buff = false;
#endif

mxconfig.clkphase = false;

dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
}

TaskHandle_t Task1;

WiFiClientSecure client;
SpotifyArduino spotify(client, clientId, clientSecret, SPOTIFY_REFRESH_TOKEN);

unsigned long delayBetweenRequests = 6000; // Time between requests (1 minute)
unsigned long requestDueTime; //time when request due

void setup()
{

Serial.begin(115200);

displaySetup();

dma_display->fillScreen(myBLACK);
dma_display->setFont(&FreeSansBold9pt7b);
dma_display->setCursor(0,20);
dma_display->setTextSize(1); // size 2 == 16 pixels high
dma_display->setTextWrap(false); // N.B!! Don't wrap at end of line
dma_display->setTextColor(myWHITE);
#ifdef ENABLE_DOUBLE_BUFFER
dma_display->flipDMABuffer();

#endif

WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED)
{
    delay(500);
    Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());





// Handle HTTPS Verification

#if defined(ESP8266)
client.setFingerprint(SPOTIFY_FINGERPRINT); // These expire every few months
#elif defined(ESP32)
client.setCACert(spotify_server_cert);
#endif

Serial.println("Refreshing Access Tokens");
if (!spotify.refreshAccessToken())
{
    Serial.println("Failed to get access tokens");
}

}

void printCurrentlyPlayingToSerial(CurrentlyPlaying currentlyPlaying)
{
Serial.print("Track: ");
Serial.println(currentlyPlaying.trackName);

dma_display->fillScreen(myBLACK);
dma_display->setCursor(0,20); 
dma_display->print(currentlyPlaying.trackName);

Serial.println("Artist: ");
for (int i = 0; i < currentlyPlaying.numArtists; i++)
{
    Serial.print("Name: ");
    Serial.println(currentlyPlaying.artists[i].artistName);
    //Serial.print("Artist URI: ");
    //Serial.println(currentlyPlaying.artists[i].artistUri);
    Serial.println();
}

}

void loop()
{

#ifdef ENABLE_DOUBLE_BUFFER
dma_display->flipDMABuffer();
#endif
if (millis() > requestDueTime)
{

    Serial.println("getting currently playing song:");
    // Market can be excluded if you want e.g. spotify.getCurrentlyPlaying()
    int status = spotify.getCurrentlyPlaying(printCurrentlyPlayingToSerial, SPOTIFY_MARKET);
    if (status == 200)
    {
        Serial.println("Successfully got currently playing");
    }
    else if (status == 204)
    {
        Serial.println("Doesn't seem to be anything playing");
    }
    else
    {
        Serial.print("Error: ");
        Serial.println(status);
    }
    requestDueTime = millis() + delayBetweenRequests;
}

}`

NoMemory crash for searchForSong()

Is the searchForSong() function tested OK for the esp8266?
When using the Arduino IDE on a NodeMCU clone the getSearchResults example fails with serial output

Free Heap: 39104
Making Search Request:
/v1/search
stack size -1073740928
Status: HTTP/1.0 200 OK
HTTP Version: HTTP/1.0
Status Code: 200
Status Code: 200
deserializeJson() failed with code NoMemory
Closing client

So is it the negative stack size or the free heap size that's causing the problems?

Warnings on Arduino IDE

I am getting many warnings on arduino IDE.
warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]
The small program below shows where these come from.
You can find one for instance on line 104 of the ArduinoSpotify.h file.
ArduinoSpotify(Client &client, char *clientId, char *clientSecret, char *refreshToken = "");
char *refreshToken = "" this part gives the warning as illustrated below
You can remove the warning by adding (char *) as shown below but not sure program then still works as intended

char refreshToken1 [] = ""; //Is Ok
char *refreshToken2 = (char *)""; //Is OK
char *refreshToken3 = ""; // gives above warning
void setup() {
}
void loop() {
}

Update documentation that some endpoints require premium

The API client is working great so far on an ESP32 TTGO T-Display. But there is one problem:

All API functions, that use the /v1/me/player endpoint fail with the following error message

Skipping to next track.../v1/me/player/next
api.spotify.com
[E][ssl_client.cpp:36] _handle_error(): [send_ssl_data():301]: (-80) UNKNOWN ERROR CODE (0050)
Failed to send request

I have tested it with my own code, but also the example at https://github.com/witnessmenow/spotify-api-arduino/blob/master/examples/esp32/playerControls/playerControls.ino.
Is this a bug or am I doing something wrong?

Get currently-playing needs to be extended to have support for Podcasts

The current implementation of get currently playing does not support podcasts

Changes required:

  1. And additional param needs to be added to the URL https://api.spotify.com/v1/me/player/currently-playing?additional_types=episode

  2. The JSON response is different for podcasts, so both the JSON filter and what is parsed needs to be adapted.

  3. The data needs to be presented back to the user somehow. Its possible to maybe shoehorn the podcast details into the currentPlaying if we take some liberties with the naming :)

404 Response with getRefreshToken

While using the getRefreshToken example for esp8266 Spotify returns the 404 code causing the check serial monitor message to be posted and the serial monitor doesn't give any additional information.

Refresh without client_secret // device flow and PKCE support

Hi @witnessmenow,
nice library! 👍

I saw that currently the token refresh calls are depending on client_secret:

const char *refreshAccessTokensBody =
R"(grant_type=refresh_token&refresh_token=%s&client_id=%s&client_secret=%s)";

However, there are some flows where the client_secret is not needed - it is not needed when the refresh_token was obtained using the device flow, and I see it is also not needed when the PKCE flow was followed.

Would you be open to have changes in your library where the client_secret is optional so that the refresh_token can be fetched using the client_id only?

Parse error when using the get refresh token

Hi,

I had this running smooth for a couple years already, but now I had a persistent connection error. I plugged the ESP32 to my computer and tried to run the get refresh token routine, but I get this:

13:43:16.423 -> MDNS responder started
13:43:16.423 -> HTTP server started
13:43:22.755 -> grant_type=authorization_code&code=AQBrOGhJAHCDyNpYZ[... lots more,,,]
13:43:22.755 -> accounts.spotify.com
13:43:25.841 -> Connection failed
13:43:25.841 -> status Code-1
13:43:27.838 -> Could not parse errorgrant_type=authorization_code&code=AQBrOGhJAHCDyNpYZ-[... lots more,,,]
13:43:48.826 -> accounts.spotify.com
13:43:48.921 -> Connection failed
13:43:48.921 -> status Code-1
13:43:50.898 -> Could not parse error

I created another app in the Spotify dashboard, and I got to see Spotify allowing me to verify that app, but then the ESP error occurred again.

Could you please help me out on this one?

Many thanks in advance!

I am attempting to get a refresh token in the same project as getting a current song

This is not an issue, it is more so a question. I have been using(and loving) your API. Individually, both of these examples work great. I am currently trying to use your API to complete both tasks in one project.

In the setup I first use:

WiFiClientSecure client; ArduinoSpotify spotify(client, clientId, clientSecret);

To initialize and get refreshtokens, then I use:

spotify.setRefreshToken(refreshToken);

To add the refresh token. I have been running into a problem, however, where every time I attempt to use:

spotify.refreshAccessTokens()

I get a no exception wdt reset. When I do not get the wdt reset, the code instead gives me a connection failed response when connecting to spotify. I was wondering if you might now how I could alter the code either in the cpp or my own code to prevent the wdt timeout. Thank you for your help, I love everything you have done on this API so far!

Issue on ESP32 getCurrentlyPlaying

Hi, I am trying the getCurrentlyPlaying, with a refresh_token got from the getRefreshToken example; and it always brings up the same error:

Connected to haifisch
IP address: 192.168.1.137
Refreshing Access Tokens
grant_type=refresh_token&refresh_token=AQB_zX3KKxiYsogl26g4LNqXvyHJ5iR2pdT1Cc8p2uxQKEC2QybHZinD7-GF47VbXc4_c612bkVmWtjQKE4VYx8amK3m25DAv2NdEjk3NA3iM29noOn3YGwpHigM-WXSrqA&client_id=f8aeea367669458dac14b17261ff61ea&client_secret=12b50f86299943a6b7b1152eb343420d
stack size -1073421775
accounts.spotify.com
Status Code: 200
status Code200
Closing client
Free Heap: 278432
getting currently playing song:
/v1/me/player/currently-playing?market=ES
stack size -1073421711
Status Code: -1
stack size -1073421711
Closing client

Connection error unless setInsecure(); is used

Hi,

I get the following error:

Trying to refresh access tokens
grant_type=refre.... [I cut this]
stack size -1073741152
accounts.spotify.com
Connection failed
status Code-1
Could not parse errorFailed to get access tokens

But if i set client.setInsecure(); the code works.
I read in another issue this has something to do with the fingerprint? I am not really into this topic but using grc.com/fingerprints for accounts.spotify.com I get the very same hash i find in SpotifyArduino.h so is there something else wrong?

I use an ESP 8266 if that is important

BTW thanks a lot for the Code, I am using it for a physical skip Button in my room, love it!

Memory Leaks

The current version is exposing internal memory areas of the ArduionJSON as part of the return values which might lead to "funny" behaviour.

I created a minial example show the issue:

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <ArduinoSpotify.h>
#include <ArduinoJson.h>

char ssid[] = "aa";
char password[] = "aa";

char clientId[] = "aaa";
char clientSecret[] = "aaa";

#define SPOTIFY_MARKET "DE"
#define SPOTIFY_REFRESH_TOKEN "aaa"

#include <ArduinoSpotifyCert.h>

WiFiClientSecure client;
ArduinoSpotify spotify(client, clientId, clientSecret, SPOTIFY_REFRESH_TOKEN);

void setup() {
    Serial.begin(115200);

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println();

    client.setCACert(spotify_server_cert);

    if(!spotify.refreshAccessToken()){
        Serial.println("Failed to get access tokens");
    }

    CurrentlyPlaying currentlyPlaying = (spotify.getCurrentlyPlaying(SPOTIFY_MARKET));

    while(1) {
        Serial.println(currentlyPlaying.firstArtistName);
        delay(1000);
        spotify.getCurrentlyPlaying(SPOTIFY_MARKET);
        yield();
    }
}

void loop() {
}

This should print the same artist name (the one that was running when the programm started) every second, but with the current version the output usually turns into rubish after the first iteration. Issue is address by #15 (at the cost of high stack usage)

Spotify set device?

Will there ever be a way to set a specific output device as example when i press play my ESP32 choses the device "My Computer" and starts playing on this device. Becouse after like 1h of not playing anything Spotify "forgets" the last output device and if i press play nothing happens until i manualy set "My Computer" as output and then the Arduino works again. Just wondering becouse i am building a Volume controller for my PC with integrated Spotify Controlls.

no matching function for call to 'SpotifyArduino::getCurrentlyPlaying()'

Hi Brian,
hope this finds you well!

thanks for sharing your projects with us,

please your help, i'm very new in arduino, and i'm trying the "albumnArtMatrix" and i keep getting the same error :
no matching function for call to 'SpotifyArduino::getCurrentlyPlaying()'

Serial.println("getting currently playing song:");
// Market can be excluded if you want e.g. spotify.getCurrentlyPlaying()
int currentlyPlayingNr = spotify.getCurrentlyPlaying();
if (currentlyPlayingNr >= 0){ // was: if (!currentlyPlaying.error) which causes a compiler error 'struct CurrentlyPlaying' has no member named 'error'
{
printCurrentlyPlayingToSerial(currentlyPlaying);

and the other error i'm getting is: Compilation error: expected primary-expression before '.' token

Serial.print("Artist: ");
Serial.println(SpotifyArtist.artistName);
Serial.print("Artist URI: ");
Serial.println(SpotifyArtist.artistUri);
Serial.println();

Thanks so much for your help
greetings from Chile!

Rename library

Arduino do not want libraries starting with "arduino", as they want to reserve it for official libraries

Audio playing

i am building a project in which i am able able to authorize with spotify and receive token thus getting music information, but i wish to play music and recieve the mp3 audio info ? can we do that ? I yes how?
I am using Esp32

Refresh Token update error

To start I'm currently on an ESP32-S2 metro, here's my steps to produce this error:

  • Get refresh token: use the example template, got refresh code:
    AQXXX-XXXX...
  • Open get current playing track example, change ssid, password, clientId, clientSecret, and spotify_refresh_token
  • flash board
  • Now in serial it shows the following error:

Free Heap: 133608
getting currently playing song:
/v1/me/player/currently-playing?additional_types=episode&market=CA
stack size -1073573279
Refresh of the Access token is due, doing that now.
grant_type=refresh_token&refresh_token=AQXXXXXXXXXXXXXXXX&client_id=cb4XXXXXXXXXX&client_secret=3d9XXXXXXXXXXX
stack size -1073572751
accounts.spotify.com
Status: HTTP/1.0 200 OK
HTTP Version: HTTP/1.0
Status Code: 200
status Code200
No JSON error, dealing with response
Problem with access_token (too long or null): BQDXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Failed to send request
Status Code: -2
stack size -1073573279
Error: -2

also noticed that the "updated" token is ~30 characters longer

Connection failed in examples

Hi, I have some troubles running the examples. I know I got the examples running last year, but unsure if the "connection failed" is due to a Spotify API change or not. The response from all examples are:

stack size -1073423839
accounts.spotify.com
Status: HTTP/1.0 200 OK
HTTP Version: HTTP/1.0
Status Code: 200
status Code200
No JSON error, dealing with response
Free Heap: 266652
Getting devices:
/v1/me/player/devices
stack size -1073424191
Connection failed
Status Code: -1

Get Access Token "Not found: /" Error

I am uploading the code required to get Refresh Token, and after the connection is established, when I go to the IP address, I encounter the error message "Not found: /". What should I do?
Ekran Görüntüsü (387)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.