Added volume up, down, mute, get options
This commit is contained in:
@@ -17,6 +17,7 @@ For more information, please refer to <http://unlicense.org/>
|
||||
#include "SD.h" // https://github.com/espressif/arduino-esp32/tree/master/libraries/SD/src
|
||||
#include "FS.h" // https://github.com/espressif/arduino-esp32/tree/master/libraries/FS/src
|
||||
#include <WebServer.h> // https://github.com/espressif/arduino-esp32/tree/master/libraries/WebServer
|
||||
#include <uri/UriBraces.h> // https://github.com/espressif/arduino-esp32/blob/master/libraries/WebServer
|
||||
|
||||
|
||||
// define all constants
|
||||
@@ -47,7 +48,7 @@ const String apSSID = version; // ssid of access point open
|
||||
const String apPSK = "aA16161Aa"; // pre-shared-key of access point opened when not able to connect to wifi
|
||||
|
||||
// create all needed variables
|
||||
int currentVolume = 21; // variable where current volume (0...21) is stored
|
||||
int currentVolume = 20; // variable where current volume (0...20) is stored
|
||||
String currentSongPath; // path to currently playing song
|
||||
bool audioPlaying = true; // play song or not?
|
||||
Audio audio; // Audio object (for playing audio, decoding mp3, ...)
|
||||
@@ -94,8 +95,8 @@ void loop() {
|
||||
if (operation_mode == 0) { // things only need to be done if in interconnected mode
|
||||
setupWiFi(); // if connection was lost
|
||||
if (audioPlaying) audio.loop(); // play audio if not paused
|
||||
if(esp_timer_get_time()%100 == 0) { // REALLY NEEDED; audio playing won't work else!
|
||||
loopServer(); // listen on http ports all 100 ms
|
||||
if (esp_timer_get_time() % 50 == 0) { // REALLY NEEDED; audio playing won't work else!
|
||||
loopServer(); // listen on http ports all 50 ms
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,7 @@ For more information, please refer to <http://unlicense.org/>
|
||||
|
||||
void setupAudio() {
|
||||
audio.setPinout(I2S_BLCK, I2S_LRC, I2S_DOUT); // tell the audio library what output pins to use
|
||||
audio.setVolumeSteps(20);
|
||||
Serial.printf("[SETUP] Set up audio card successfully (Pins: BLCK %d | LRC %d | DOUT %d)\n", I2S_BLCK, I2S_LRC, I2S_DOUT);
|
||||
}
|
||||
|
||||
@@ -73,11 +74,11 @@ void backwardButtonHandler() {
|
||||
}
|
||||
|
||||
void setAudioVolume() {
|
||||
int newCurrentVolume = analogRead(audioVolumePin) / 195; // read voltage from audioVolumePin and divide by 195 (min. volume is 0, max. 21; 21 fits 195 times into 4095 (maximum input))
|
||||
int newCurrentVolume = analogRead(audioVolumePin) / 204.75; // read voltage from audioVolumePin and divide by 204.75 (min. volume is 0, max. 20; 20 fits 204.75 times into 4095 (maximum input))
|
||||
if(currentVolume != newCurrentVolume) { // just do it if the volume changed
|
||||
currentVolume = newCurrentVolume;
|
||||
audio.setVolume(currentVolume); // set volume
|
||||
Serial.printf("[INFO] Set volume to %d/21!\n", currentVolume);
|
||||
Serial.printf("[INFO] Set volume to %d/20!\n", currentVolume);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -65,6 +65,7 @@ String getWiFiPSK() {
|
||||
return getWiFiPSK(wifiConfigPath);
|
||||
}
|
||||
|
||||
|
||||
bool createPlaylistFromDirectory(String folderpath) { // create a .m3u playlist from all directory contents (the directory 'folderpath' is used)
|
||||
File folder;
|
||||
File playlist;
|
||||
@@ -111,7 +112,7 @@ String getSongFromPlaylist(String path, int position) {
|
||||
song = (char)playlist.read(); // read character...
|
||||
while (playlist.available()) {
|
||||
currentChar = (char)playlist.read();
|
||||
if (currentChar != '\n') {
|
||||
if (currentChar != '\n' && currentChar != '\r') {
|
||||
song += currentChar; // ... except if and as long as a newline hits
|
||||
} else {
|
||||
break; // exit while loop
|
||||
|
@@ -11,12 +11,38 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
||||
For more information, please refer to <http://unlicense.org/>
|
||||
*/
|
||||
|
||||
String generate_api_json(bool success, String content, bool plain) {
|
||||
String currentResourcePlaying = getSongFromPlaylist(currentPlaylist, currentPlaylistPosition);
|
||||
|
||||
String json = "{\"success\": "; // success
|
||||
json += success ? "true" : "false";
|
||||
json += ", ";
|
||||
json += "\"state\": \""; // playing or paused?
|
||||
json += audioPlaying ? "playing" : "paused";
|
||||
json += "\", ";
|
||||
json += "\"currentResource\": \"" + currentResourcePlaying + "\""; // current playing resource
|
||||
if (!plain) {
|
||||
json += ", ";
|
||||
json += content;
|
||||
}
|
||||
json += "}";
|
||||
|
||||
return json;
|
||||
}
|
||||
String generate_api_json(bool success) { // if you just want the basic json frame with the basic info
|
||||
return generate_api_json(success, "", true);
|
||||
}
|
||||
String generate_api_json(bool success, String content) { // when info is to be embedded
|
||||
return generate_api_json(success, content, false);
|
||||
}
|
||||
|
||||
|
||||
void configRoot() {
|
||||
Serial.println("[HTTP] [Config] 200 - GET '/'");
|
||||
|
||||
String html = "<html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>";
|
||||
String html = "<html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Configuration | ";
|
||||
html += version;
|
||||
html += "configuration</title></head><body><div style='text-align:center;'><br><br><p>Configuration of your</p><h3>NetSpeaker</h3><br><hr><br><p>Work in progress!</p></div></body></html>";
|
||||
html += "</title></head><body><div style='text-align:center;'><br><br><p>Configuration of your</p><h3>NetSpeaker</h3><br><hr><br><p>Work in progress!</p></div></body></html>";
|
||||
|
||||
conf_server.send(200, "text/html", html);
|
||||
}
|
||||
@@ -24,24 +50,20 @@ void configRoot() {
|
||||
void apiRoot() {
|
||||
Serial.println("[HTTP] [API] 200 - GET '/'");
|
||||
|
||||
String html = "<html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>";
|
||||
String html = "<html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>API | ";
|
||||
html += version;
|
||||
html += "configuration</title></head><body><div style='text-align:center;'><br><br><p>API of your</p><br><h3>NetSpeaker</h3><br><hr><br><p>Work in progress!</p></div></body></html>";
|
||||
html += "</title></head><body><div style='text-align:center;'><br><br><p>API of your</p><br><h3>NetSpeaker</h3><br><hr><br><p>Work in progress!</p></div></body></html>";
|
||||
|
||||
api_server.send(200, "text/html", html);
|
||||
}
|
||||
|
||||
void api_v1_playback_toggle() {
|
||||
Serial.println("[HTTP] [API] 200 - GET '/_api/v1/playback/toggle'");
|
||||
Serial.println("[HTTP] [API] 200 - GET '/api/v1/playback/toggle'");
|
||||
|
||||
audioPlaying = !audioPlaying;
|
||||
Serial.printf("[INFO] Playback has switched: %s\n", audioPlaying ? "Playing" : "Paused");
|
||||
|
||||
String json = "{'success': true, 'state': '";
|
||||
json += audioPlaying ? "playing" : "paused";
|
||||
json += "'}";
|
||||
|
||||
api_server.send(200, "application/json", json);
|
||||
api_server.send(200, "application/json", generate_api_json(true));
|
||||
}
|
||||
|
||||
void api_v1_playback_play() {
|
||||
@@ -50,46 +72,99 @@ void api_v1_playback_play() {
|
||||
audioPlaying = true;
|
||||
Serial.printf("[INFO] Playback has switched: Playing\n");
|
||||
|
||||
String json = "{'success': true, 'state': 'playing'}";
|
||||
api_server.send(200, "application/json", json);
|
||||
api_server.send(200, "application/json", generate_api_json(true));
|
||||
}
|
||||
|
||||
void api_v1_playback_pause() {
|
||||
Serial.println("[HTTP] [API] 200 - GET '/_api/v1/playback/pause'");
|
||||
Serial.println("[HTTP] [API] 200 - GET '/api/v1/playback/pause'");
|
||||
|
||||
audioPlaying = false;
|
||||
Serial.printf("[INFO] Playback has switched: Paused\n");
|
||||
|
||||
String json = "{'success': true, 'state': 'paused'}";
|
||||
api_server.send(200, "application/json", json);
|
||||
api_server.send(200, "application/json", generate_api_json(true));
|
||||
}
|
||||
|
||||
void api_v1_playback_next() {
|
||||
Serial.println("[HTTP] [API] 200 - GET '/_api/v1/playback/next'");
|
||||
Serial.println("[HTTP] [API] 200 - GET '/api/v1/playback/next'");
|
||||
|
||||
String resourcePath = nextAudio();
|
||||
nextAudio();
|
||||
|
||||
String json = "{'success': true, 'state': '";
|
||||
json += audioPlaying ? "playing" : "paused";
|
||||
json += "', 'currentResource': '";
|
||||
json += resourcePath;
|
||||
json += "'}";
|
||||
|
||||
api_server.send(200, "application/json", json);
|
||||
api_server.send(200, "application/json", generate_api_json(true));
|
||||
}
|
||||
|
||||
void api_v1_playback_previous() {
|
||||
Serial.println("[HTTP] [API] 200 - GET '/_api/v1/playback/previous'");
|
||||
Serial.println("[HTTP] [API] 200 - GET '/api/v1/playback/previous'");
|
||||
|
||||
String resourcePath = previousAudio();
|
||||
previousAudio();
|
||||
|
||||
String json = "{'success': true, 'state': '";
|
||||
json += audioPlaying ? "playing" : "paused";
|
||||
json += "', 'currentResource': '";
|
||||
json += resourcePath;
|
||||
json += "'}";
|
||||
api_server.send(200, "application/json", generate_api_json(true));
|
||||
}
|
||||
|
||||
api_server.send(200, "application/json", json);
|
||||
void api_v1_playback_volume() {
|
||||
String option = api_server.pathArg(0);
|
||||
bool success = true;
|
||||
Serial.printf("[HTTP] [API] 200 - GET '/api/v1/volume/%s'\n", option);
|
||||
|
||||
if (option == "up") {
|
||||
currentVolume++;
|
||||
if (currentVolume > 20) currentVolume = 20;
|
||||
} else if (option == "down") {
|
||||
currentVolume--;
|
||||
if (currentVolume < 0) currentVolume = 0;
|
||||
} else if (option == "mute") {
|
||||
currentVolume = 0; // TODO: remember the previous volume and just mute it; unmute has to be implemented then
|
||||
} else if (option == "get") {
|
||||
// just here that no 'success: false' is sent
|
||||
} else if (option == "0") {
|
||||
currentVolume = 0;
|
||||
} else if (option == "1") {
|
||||
currentVolume = 1;
|
||||
} else if (option == "2") {
|
||||
currentVolume = 2;
|
||||
} else if (option == "3") {
|
||||
currentVolume = 3;
|
||||
} else if (option == "4") {
|
||||
currentVolume = 4;
|
||||
} else if (option == "5") {
|
||||
currentVolume = 5;
|
||||
} else if (option == "6") {
|
||||
currentVolume = 6;
|
||||
} else if (option == "7") {
|
||||
currentVolume = 7;
|
||||
} else if (option == "8") {
|
||||
currentVolume = 8;
|
||||
} else if (option == "9") {
|
||||
currentVolume = 9;
|
||||
} else if (option == "10") {
|
||||
currentVolume = 10;
|
||||
} else if (option == "11") {
|
||||
currentVolume = 11;
|
||||
} else if (option == "12") {
|
||||
currentVolume = 12;
|
||||
} else if (option == "13") {
|
||||
currentVolume = 13;
|
||||
} else if (option == "14") {
|
||||
currentVolume = 14;
|
||||
} else if (option == "15") {
|
||||
currentVolume = 15;
|
||||
} else if (option == "16") {
|
||||
currentVolume = 16;
|
||||
} else if (option == "17") {
|
||||
currentVolume = 17;
|
||||
} else if (option == "18") {
|
||||
currentVolume = 18;
|
||||
} else if (option == "19") {
|
||||
currentVolume = 19;
|
||||
} else if (option == "20") {
|
||||
currentVolume = 20;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
audio.setVolume(currentVolume); // set volume
|
||||
String content = "\"volume\": "; // prepare the http response
|
||||
content += String(currentVolume);
|
||||
api_server.send(200, "application/json", generate_api_json(success, content)); // generate json and send it
|
||||
}
|
||||
|
||||
|
||||
@@ -113,11 +188,12 @@ void setupApiWeb() {
|
||||
api_server.send(404, "text/html", "<html><head><title>Not Found</title></head><body><h1>Not Found</h1><p>This resource does not exist on this server.</p></body></html>");
|
||||
});
|
||||
api_server.on("/", apiRoot);
|
||||
api_server.on("/_api/v1/playback/toggle", api_v1_playback_toggle);
|
||||
api_server.on("/_api/v1/playback/play", api_v1_playback_play);
|
||||
api_server.on("/_api/v1/playback/pause", api_v1_playback_pause);
|
||||
api_server.on("/_api/v1/playback/next", api_v1_playback_next);
|
||||
api_server.on("/_api/v1/playback/previous", api_v1_playback_previous);
|
||||
api_server.on("/api/v1/playback/toggle", api_v1_playback_toggle);
|
||||
api_server.on("/api/v1/playback/play", api_v1_playback_play);
|
||||
api_server.on("/api/v1/playback/pause", api_v1_playback_pause);
|
||||
api_server.on("/api/v1/playback/next", api_v1_playback_next);
|
||||
api_server.on("/api/v1/playback/previous", api_v1_playback_previous);
|
||||
api_server.on(UriBraces("/api/v1/volume/{}"), api_v1_playback_volume);
|
||||
|
||||
Serial.println("[HTTP] [API] Starting API server (http) on port " + String(webport_api));
|
||||
api_server.begin();
|
||||
|
@@ -36,7 +36,7 @@ void setupWiFi() {
|
||||
WiFi.mode(WIFI_AP_STA);
|
||||
WiFi.begin(WiFiSSID, WiFiPSK);
|
||||
// wait for 10 seconds for wifi to connect
|
||||
int start_timer = millis(); while(WiFi.status() != WL_CONNECTED) { if((millis()-start_timer) > 10000) break; }
|
||||
int start_timer = millis(); while(WiFi.status() != WL_CONNECTED) { if((millis()-start_timer) > 20000) break; }
|
||||
if(WiFi.status() != WL_CONNECTED) {
|
||||
currentWiFiMode = 1;
|
||||
Serial.printf("[WiFi] Unable to connect to %s\n", WiFiSSID);
|
||||
@@ -58,5 +58,4 @@ void setupWiFi() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user