Skip to content

Commit 7a3b51c

Browse files
skialpineclaude
andcommitted
feat: allow multiple concurrent WS clients (web UI + app)
The previous middleware returned 503 to any client past the first, which meant opening the on-device web UI prevented a phone/desktop app from connecting to the same scale. Drop the cap and let the library handle multi-client. * include/webserver.h: remove the count-checking middleware so any handshake within the library's DEFAULT_MAX_WS_CLIENTS limit succeeds. * src/hds.ino: call websocket.cleanupClients() with no argument so we inherit the library default (DEFAULT_MAX_WS_CLIENTS, which is 8 on ESP32). Plenty of RAM headroom — ~12-14 KB per client on top of ~240 KB free heap. * src/hds.ino WS_EVT_DISCONNECT: only reset the shared session state (weightWebsocketNotifyInterval, b_websocketEventsEnabled, t_lastWebsocketStatusUpdate) when the LAST client leaves (server->count() == 0). Without this guard, one client disconnecting would wipe rate/events state for any other client still connected. Verified with /tmp/ws_multi.py (5/5): * Two simultaneous handshakes both succeed (was: 2nd got 503). * Both clients receive the weight stream at the negotiated rate (2Hz default, 10Hz after `rate 10`). * Both clients see the periodic status broadcast after `events on`. * Disconnecting client A leaves client B's stream + state intact. Single-client feature regression still 60/60 PASS. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 74d7f0f commit 7a3b51c

2 files changed

Lines changed: 16 additions & 14 deletions

File tree

include/webserver.h

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,10 @@ void startWebServer() {
3939
});
4040
server.addHandler(wifiHandler);
4141

42-
server.addHandler(&websocket).addMiddleware([](AsyncWebServerRequest *request, ArMiddlewareNext next) {
43-
// ws.count() is the current count of WS clients: this one is trying to upgrade its HTTP connection
44-
if (websocket.count() > 0) {
45-
// if we have 1 clients or more, prevent the next one to connect
46-
request->send(503, "text/plain", "Server is busy");
47-
} else {
48-
// process next middleware and at the end the handler
49-
next();
50-
}
51-
});
42+
// Allow multiple concurrent WebSocket clients (e.g. the on-device web UI
43+
// and a separate desktop/phone app at the same time). Per-loop the count
44+
// is bounded by cleanupClients() in src/hds.ino.
45+
server.addHandler(&websocket);
5246

5347
if (!LittleFS.begin()) {
5448
Serial.println("LittleFS mount failed");

src/hds.ino

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -958,9 +958,15 @@ void _wifi_init(void *args) {
958958
client->setCloseClientOnQueueFull(false);
959959
} else if (type == WS_EVT_DISCONNECT) {
960960
Serial.printf("Client %u disconnected\n", client->id());
961-
weightWebsocketNotifyInterval = WEBSOCKET_DEFAULT_NOTIFY_INTERVAL_MS;
962-
b_websocketEventsEnabled = false;
963-
t_lastWebsocketStatusUpdate = 0;
961+
// Only reset shared session state when the LAST client leaves —
962+
// otherwise one client disconnecting would wipe rate/events state
963+
// for any other still-connected clients. server->count() at this
964+
// point excludes the disconnecting client.
965+
if (server->count() == 0) {
966+
weightWebsocketNotifyInterval = WEBSOCKET_DEFAULT_NOTIFY_INTERVAL_MS;
967+
b_websocketEventsEnabled = false;
968+
t_lastWebsocketStatusUpdate = 0;
969+
}
964970
} else if (type == WS_EVT_ERROR) {
965971
Serial.printf("WebSocket error on client %u\n", client->id());
966972
} else if (type == WS_EVT_PONG) {
@@ -1987,7 +1993,9 @@ void loop() {
19871993
}
19881994
}
19891995
if (b_wifiEnabled) {
1990-
websocket.cleanupClients(1);
1996+
// Cap concurrent WS clients at the library default
1997+
// (DEFAULT_MAX_WS_CLIENTS = 8 on ESP32, 4 on ESP8266).
1998+
websocket.cleanupClients();
19911999
ElegantOTA.loop();
19922000
static unsigned long lastUpdate = 0;
19932001
unsigned long current = millis();

0 commit comments

Comments
 (0)