From 48e0004b34316b622a98d8aa8b77d6662b286345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Ha=C3=9Fel?= Date: Fri, 6 Jun 2025 10:31:11 +0200 Subject: [PATCH] websocket --- src/http.cpp | 44 ++++++++++++++++++++++++++++++++++--------- src/http.h | 4 ++++ src/main.cpp | 1 + src/player.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++-- src/player.h | 2 ++ src/playlist.cpp | 8 ++++++++ src/playlist.h | 4 ++++ 7 files changed, 101 insertions(+), 11 deletions(-) diff --git a/src/http.cpp b/src/http.cpp index 3247bce..5c2910b 100644 --- a/src/http.cpp +++ b/src/http.cpp @@ -1,11 +1,24 @@ #include "http.h" +#include + #include "audio.h" #include "ESPAsyncWebServer.h" #include "player.h" AsyncWebServer server(80); +AsyncWebSocket ws("/ws"); + +void onWebSocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, const AwsEventType type, void *arg, const uint8_t *data, const size_t len) { + if (type == WS_EVT_CONNECT) { + Serial.printf("[WEBSOCKET] Connected: %s\n", client->remoteIP().toString().c_str()); + client->text(stateBuffer); + } else if (type == WS_EVT_DISCONNECT) { + Serial.printf("[WEBSOCKET] Disconnected: %s\n", client->remoteIP().toString().c_str()); + } +} + void httpSetup() { Serial.println("Starting HTTP server"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); @@ -17,41 +30,54 @@ void httpSetup() { request->send(404, "text/plain", "Not Found"); } }); - server.on("/player/stop", [](AsyncWebServerRequest *request) { + server.on("/state", [](AsyncWebServerRequest *request) { + request->send(200, "application/json", stateBuffer); + }); + server.on("/stop", [](AsyncWebServerRequest *request) { playerState = PLAYER_STOP; request->send(200); }); - server.on("/player/play", [](AsyncWebServerRequest *request) { + server.on("/play", [](AsyncWebServerRequest *request) { playerState = PLAYER_PLAY; request->send(200); }); - server.on("/player/pause", [](AsyncWebServerRequest *request) { + server.on("/pause", [](AsyncWebServerRequest *request) { playerState = PLAYER_PAUSE; request->send(200); }); - server.on("/player/mute", [](AsyncWebServerRequest *request) { + server.on("/mute", [](AsyncWebServerRequest *request) { audioMute = true; request->send(200); }); - server.on("/player/unmute", [](AsyncWebServerRequest *request) { + server.on("/unmute", [](AsyncWebServerRequest *request) { audioMute = false; request->send(200); }); - server.on("/player/up", [](AsyncWebServerRequest *request) { + server.on("/up", [](AsyncWebServerRequest *request) { audioVolume = max(0.0f, min(audioVolume + 0.05f, 1.0f)); request->send(200); }); - server.on("/player/down", [](AsyncWebServerRequest *request) { + server.on("/down", [](AsyncWebServerRequest *request) { audioVolume = max(0.0f, min(audioVolume - 0.05f, 1.0f)); request->send(200); }); - server.on("/player/next", [](AsyncWebServerRequest *request) { + server.on("/next", [](AsyncWebServerRequest *request) { playerSkip += 1; request->send(200); }); - server.on("/player/back", [](AsyncWebServerRequest *request) { + server.on("/back", [](AsyncWebServerRequest *request) { playerSkip -= 1; request->send(200); }); + ws.onEvent(onWebSocketEvent); + server.addHandler(&ws); server.begin(); } + +void httpLoop() { + ws.cleanupClients(); +} + +void websocketSendAll() { + ws.textAll(stateBuffer); +} diff --git a/src/http.h b/src/http.h index abcba1f..3699b12 100644 --- a/src/http.h +++ b/src/http.h @@ -3,4 +3,8 @@ void httpSetup(); +void httpLoop(); + +void websocketSendAll(); + #endif diff --git a/src/main.cpp b/src/main.cpp index af25438..5b4195f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -24,4 +24,5 @@ void setup() { void loop() { wifiLoop(); playerLoop(); + httpLoop(); } diff --git a/src/player.cpp b/src/player.cpp index db6debc..c00deb8 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -1,8 +1,9 @@ #include "player.h" -#include +#include #include "audio.h" +#include "http.h" #include "playlist.h" #define DELAY_MS_ADD 250UL @@ -16,11 +17,13 @@ int playerSkip = 0; PlayerState playerState = PLAYER_STOP; +void updateStateBuffer(); + void playerSetup() { audioSetup(); } -void playerPlay(const Entry entry) { +void playerPlay(const Entry &entry) { if (audioPlay(entry)) { errorMs = 0; delayMs = 0; @@ -36,6 +39,7 @@ void playerLoop() { const auto entry = playlistNext(playerSkip); playerPlay(entry); playerSkip = 0; + updateStateBuffer(); } if (audioLoop()) { errorMs = 0; @@ -46,4 +50,45 @@ void playerLoop() { } const auto entry = playlistNextOrRepeatOneIfEnabled(); playerPlay(entry); + updateStateBuffer(); +} + +char stateBuffer0[200] = "{}"; + +char stateBuffer1[200]; + +char *stateBuffer = stateBuffer0; + +const char *getPlayerStateString() { + switch (playerState) { + case PLAYER_STOP: + return "STOP"; + case PLAYER_PLAY: + return "PLAY"; + case PLAYER_PAUSE: + return "PAUSE"; + default: return "[???]"; + } + +} + +void updateStateBuffer() { + auto json = JsonDocument(); + const auto entry = playlistCurrent(); + json["state"] = getPlayerStateString(); + json["entry"]["type"] = entry.type; + json["entry"]["url"] = entry.url; + json["entry"]["title"] = entry.title; + json["volume"] = audioVolume; + json["mute"] = audioMute; + json["playlist"]["count"] = playlistGetCount(); + json["playlist"]["index"] = playlistGetIndex(); + if (stateBuffer == stateBuffer0) { + serializeJson(json, stateBuffer1, sizeof(stateBuffer1)); + stateBuffer = stateBuffer1; + } else { + serializeJson(json, stateBuffer0, sizeof(stateBuffer0)); + stateBuffer = stateBuffer0; + } + websocketSendAll(); } diff --git a/src/player.h b/src/player.h index f3d2a6a..bc6673a 100644 --- a/src/player.h +++ b/src/player.h @@ -11,6 +11,8 @@ extern PlayerState playerState; extern int playerSkip; +extern char *stateBuffer; + void playerSetup(); void playerLoop(); diff --git a/src/playlist.cpp b/src/playlist.cpp index e7ab8f0..5fe2702 100644 --- a/src/playlist.cpp +++ b/src/playlist.cpp @@ -127,3 +127,11 @@ Entry playlistBack() { } return playlistSet(playlistIndex - 1); } + +size_t playlistGetCount() { + return playlistEntries.size(); +} + +size_t playlistGetIndex() { + return playlistIndex; +} diff --git a/src/playlist.h b/src/playlist.h index 67f52f0..a12d62f 100644 --- a/src/playlist.h +++ b/src/playlist.h @@ -17,4 +17,8 @@ Entry playlistNextOrRepeatOneIfEnabled(); Entry playlistBack(); +size_t playlistGetCount(); + +size_t playlistGetIndex(); + #endif