websocket

This commit is contained in:
Patrick Haßel 2025-06-06 10:31:11 +02:00
parent dc4c3bf33a
commit 48e0004b34
7 changed files with 101 additions and 11 deletions

View File

@ -1,11 +1,24 @@
#include "http.h" #include "http.h"
#include <ArduinoJson.h>
#include "audio.h" #include "audio.h"
#include "ESPAsyncWebServer.h" #include "ESPAsyncWebServer.h"
#include "player.h" #include "player.h"
AsyncWebServer server(80); 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() { void httpSetup() {
Serial.println("Starting HTTP server"); Serial.println("Starting HTTP server");
DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*"); DefaultHeaders::Instance().addHeader("Access-Control-Allow-Origin", "*");
@ -17,41 +30,54 @@ void httpSetup() {
request->send(404, "text/plain", "Not Found"); 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; playerState = PLAYER_STOP;
request->send(200); request->send(200);
}); });
server.on("/player/play", [](AsyncWebServerRequest *request) { server.on("/play", [](AsyncWebServerRequest *request) {
playerState = PLAYER_PLAY; playerState = PLAYER_PLAY;
request->send(200); request->send(200);
}); });
server.on("/player/pause", [](AsyncWebServerRequest *request) { server.on("/pause", [](AsyncWebServerRequest *request) {
playerState = PLAYER_PAUSE; playerState = PLAYER_PAUSE;
request->send(200); request->send(200);
}); });
server.on("/player/mute", [](AsyncWebServerRequest *request) { server.on("/mute", [](AsyncWebServerRequest *request) {
audioMute = true; audioMute = true;
request->send(200); request->send(200);
}); });
server.on("/player/unmute", [](AsyncWebServerRequest *request) { server.on("/unmute", [](AsyncWebServerRequest *request) {
audioMute = false; audioMute = false;
request->send(200); request->send(200);
}); });
server.on("/player/up", [](AsyncWebServerRequest *request) { server.on("/up", [](AsyncWebServerRequest *request) {
audioVolume = max(0.0f, min(audioVolume + 0.05f, 1.0f)); audioVolume = max(0.0f, min(audioVolume + 0.05f, 1.0f));
request->send(200); request->send(200);
}); });
server.on("/player/down", [](AsyncWebServerRequest *request) { server.on("/down", [](AsyncWebServerRequest *request) {
audioVolume = max(0.0f, min(audioVolume - 0.05f, 1.0f)); audioVolume = max(0.0f, min(audioVolume - 0.05f, 1.0f));
request->send(200); request->send(200);
}); });
server.on("/player/next", [](AsyncWebServerRequest *request) { server.on("/next", [](AsyncWebServerRequest *request) {
playerSkip += 1; playerSkip += 1;
request->send(200); request->send(200);
}); });
server.on("/player/back", [](AsyncWebServerRequest *request) { server.on("/back", [](AsyncWebServerRequest *request) {
playerSkip -= 1; playerSkip -= 1;
request->send(200); request->send(200);
}); });
ws.onEvent(onWebSocketEvent);
server.addHandler(&ws);
server.begin(); server.begin();
} }
void httpLoop() {
ws.cleanupClients();
}
void websocketSendAll() {
ws.textAll(stateBuffer);
}

View File

@ -3,4 +3,8 @@
void httpSetup(); void httpSetup();
void httpLoop();
void websocketSendAll();
#endif #endif

View File

@ -24,4 +24,5 @@ void setup() {
void loop() { void loop() {
wifiLoop(); wifiLoop();
playerLoop(); playerLoop();
httpLoop();
} }

View File

@ -1,8 +1,9 @@
#include "player.h" #include "player.h"
#include <Arduino.h> #include <ArduinoJson.h>
#include "audio.h" #include "audio.h"
#include "http.h"
#include "playlist.h" #include "playlist.h"
#define DELAY_MS_ADD 250UL #define DELAY_MS_ADD 250UL
@ -16,11 +17,13 @@ int playerSkip = 0;
PlayerState playerState = PLAYER_STOP; PlayerState playerState = PLAYER_STOP;
void updateStateBuffer();
void playerSetup() { void playerSetup() {
audioSetup(); audioSetup();
} }
void playerPlay(const Entry entry) { void playerPlay(const Entry &entry) {
if (audioPlay(entry)) { if (audioPlay(entry)) {
errorMs = 0; errorMs = 0;
delayMs = 0; delayMs = 0;
@ -36,6 +39,7 @@ void playerLoop() {
const auto entry = playlistNext(playerSkip); const auto entry = playlistNext(playerSkip);
playerPlay(entry); playerPlay(entry);
playerSkip = 0; playerSkip = 0;
updateStateBuffer();
} }
if (audioLoop()) { if (audioLoop()) {
errorMs = 0; errorMs = 0;
@ -46,4 +50,45 @@ void playerLoop() {
} }
const auto entry = playlistNextOrRepeatOneIfEnabled(); const auto entry = playlistNextOrRepeatOneIfEnabled();
playerPlay(entry); 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();
} }

View File

@ -11,6 +11,8 @@ extern PlayerState playerState;
extern int playerSkip; extern int playerSkip;
extern char *stateBuffer;
void playerSetup(); void playerSetup();
void playerLoop(); void playerLoop();

View File

@ -127,3 +127,11 @@ Entry playlistBack() {
} }
return playlistSet(playlistIndex - 1); return playlistSet(playlistIndex - 1);
} }
size_t playlistGetCount() {
return playlistEntries.size();
}
size_t playlistGetIndex() {
return playlistIndex;
}

View File

@ -17,4 +17,8 @@ Entry playlistNextOrRepeatOneIfEnabled();
Entry playlistBack(); Entry playlistBack();
size_t playlistGetCount();
size_t playlistGetIndex();
#endif #endif