Documentation Index
Fetch the complete documentation index at: https://mintlify.com/benz206/SpotifyMacroBoard/llms.txt
Use this file to discover all available pages before exploring further.
Base URL
All endpoints are accessed via HTTPS on your personal server:Replace
benzhou.tech with your own domain when setting up your personal server.Authentication
All endpoints use password-based authentication via URL parameter:SampleCredentials.h and validated by the server before processing requests.
Endpoints
Manage playback state
Controls Spotify playback by executing various actions.Authentication password matching server configuration
Action to perform. Must be one of:
playPause, skip, back, loop, vdec, vinc, shuffleActions
Toggle play/pause state. Mapped from pause/play button (GPIO 25).Source: src/src.ino:366-369
Skip to next track. Mapped from skip button (GPIO 26).Source: src/src.ino:371-375
Go to previous track or restart current track. Mapped from back button (GPIO 14).Source: src/src.ino:361-364
Toggle repeat/loop mode. Mapped from loop button (GPIO 13).Source: src/src.ino:359
Decrease volume. Mapped from volume decrease button (GPIO 5).Source: src/src.ino:349-352
Increase volume. Mapped from volume increase button (GPIO 12).Source: src/src.ino:354-357
Toggle shuffle mode. Mapped from shuffle button (GPIO 4).Source: src/src.ino:347
Request example
Response
The server should return an HTTP 200 status on success. The ESP32 does not parse the response body for this endpoint.Get current playback
Retrieves the current playback state including track information, progress, and album art color.Authentication password matching server configuration
Request example
Response
Returns JSON with current playback information:Current track title. Displayed on OLED screen (line 2-3).Example:
"Bohemian Rhapsody"Extracted at: src/src.ino:248Artist name. Displayed on OLED screen (line 4).Example:
"Queen"Extracted at: src/src.ino:249Album name. Stored but not displayed on screen due to space constraints.Example:
"A Night at the Opera"Extracted at: src/src.ino:250Track duration in seconds.Example:
354 (5:54)Extracted at: src/src.ino:251, 259Current playback position in seconds. Used to render progress bar.Example:
120 (2:00)Extracted at: src/src.ino:252, 260Whether playback is currently paused. When true, progress counter stops incrementing.Example:
falseExtracted at: src/src.ino:253, 256Current volume level (0-100). Displayed as icon in top-right corner.Example:
75Icon mapping (src/src.ino:140-148):- 67-100: volume_3 (full)
- 34-66: volume_2 (medium)
- 1-33: volume_1 (low)
- 0: volume_0 (muted)
RGB color array The color is faded smoothly over 256 steps when the track changes (src/src.ino:292-304).
[R, G, B] extracted from album artwork. Each value is 0-255.Example: [45, 52, 71]Used to set RGB LED strip color for ambient lighting that matches the album art.Extracted at: src/src.ino:263-276Response example
Response parsing
The ESP32 uses a custom JSON parser to extract values:Polling intervals
The ESP32 polls endpoints at different intervals:| Endpoint | Interval | Constant | Source |
|---|---|---|---|
/api/getCurrent | 5 seconds | currentDelay = 5000 | src/src.ino:25, 395-398 |
| RSSI check | 10 seconds | RSSIDelay = 10000 | src/src.ino:24, 389-393 |
| Progress update | 1 second | timeDelay = 1000 | src/src.ino:26, 400-406 |
| LED fade step | 4 ms | fadeDelay = 4 | src/src.ino:27, 408-411 |
Connection handling
The ESP32 maintains a persistent HTTPS connection using HTTP Keep-Alive:- Protocol: HTTPS (TLS/SSL)
- Port: 443
- Host: benzhou.tech (configurable)
- Keep-Alive: Enabled for connection reuse
- Timeout: 5000ms for response (src/src.ino:222-229)
Error responses
The ESP32 provides visual feedback for errors using the RGB LED strip:| Error condition | LED color | Source |
|---|---|---|
| Connection failed | Red | src/src.ino:196-198 |
| Response timeout (>5s) | Yellow | src/src.ino:225-228 |
| Invalid response format | Orange | src/src.ino:234-237 |
| WiFi connecting | Pulsing white | src/src.ino:79-87 |
| WiFi connected | Fade to green | src/src.ino:89-95 |
Timeout handling
Button mapping
Buttons are mapped to actions in the following order:| GPIO | Function | Action | API call |
|---|---|---|---|
| 4 | Shuffle | Toggle shuffle | /api/manageState/{password}/shuffle |
| 5 | Volume - | Decrease volume | /api/manageState/{password}/vdec |
| 12 | Volume + | Increase volume | /api/manageState/{password}/vinc |
| 13 | Loop | Toggle repeat | /api/manageState/{password}/loop |
| 14 | Back | Previous track | /api/manageState/{password}/back |
| 25 | Play/Pause | Toggle playback | /api/manageState/{password}/playPause |
| 26 | Skip | Next track | /api/manageState/{password}/skip |
INPUT_PULLUP, meaning they read LOW when pressed:
Implementation notes
Why GET instead of POST?
The ESP32 uses GET requests for simplicity. The WiFiClientSecure library makes GET requests straightforward, and since the password is sent over HTTPS, itβs encrypted in transit.Why custom JSON parsing?
The ESP32 has limited RAM (320KB). Using a full JSON library like ArduinoJson would consume significant memory. The customextractValue() function is lightweight and sufficient for the simple JSON structure.
Why Keep-Alive?
TLS handshakes are computationally expensive on the ESP32. By maintaining a persistent connection, the device avoids repeated handshakes, significantly improving response time and reducing power consumption.Next steps
Server setup
Set up your personal proxy server
Hardware assembly
Assemble the MacroBoard hardware