add files
This commit is contained in:
1 parent
3eaff3a647
commit
e76a9c1e9b
9 files changed
+752
No files matched your search
@@ -0,0 +1,119 @@
|
||||
// =====================================================================
|
||||
// WebServerManager.cpp
|
||||
// =====================================================================
|
||||
#include "WebServerManager.h"
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
WebServerManager::WebServerManager(ZoneManager &zoneManager)
|
||||
: _zoneManager(zoneManager), _server(80), _ws("/ws") {
|
||||
}
|
||||
|
||||
void WebServerManager::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
|
||||
AwsEventType type, void *arg, uint8_t *data, size_t len) {
|
||||
if (type == WS_EVT_CONNECT) {
|
||||
Serial.printf("[WS] client #%u connected from %s\n", client->id(),
|
||||
client->remoteIP().toString().c_str());
|
||||
} else if (type == WS_EVT_DISCONNECT) {
|
||||
Serial.printf("[WS] client #%u disconnected\n", client->id());
|
||||
}
|
||||
}
|
||||
|
||||
void WebServerManager::setupRoutes() {
|
||||
_ws.onEvent(onWsEvent);
|
||||
_server.addHandler(&_ws);
|
||||
|
||||
// GET /zones -> current zone definitions + occupancy
|
||||
_server.on("/zones", HTTP_GET, [this](AsyncWebServerRequest *request) {
|
||||
request->send(200, "application/json", _zoneManager.zonesToJson());
|
||||
});
|
||||
|
||||
// POST /updateZones -> replace zone definitions (partial updates
|
||||
// allowed; see ZoneManager::zonesFromJson)
|
||||
_server.on(
|
||||
"/updateZones", HTTP_POST, [](AsyncWebServerRequest *request) {},
|
||||
nullptr,
|
||||
[this](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
|
||||
if (_zoneManager.zonesFromJson(data, len)) {
|
||||
request->send(200, "application/json",
|
||||
"{\"status\":\"success\",\"message\":\"Zones updated\"}");
|
||||
} else {
|
||||
request->send(400, "application/json",
|
||||
"{\"status\":\"error\",\"message\":\"Invalid JSON\"}");
|
||||
}
|
||||
});
|
||||
|
||||
// Basic health check, handy when bringing up a new node in the
|
||||
// future multi-radar setup.
|
||||
_server.on("/status", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
StaticJsonDocument<128> doc;
|
||||
doc["status"] = "ok";
|
||||
doc["uptime_ms"] = millis();
|
||||
String out;
|
||||
serializeJson(doc, out);
|
||||
request->send(200, "application/json", out);
|
||||
});
|
||||
}
|
||||
|
||||
void WebServerManager::begin(const char *ssid, const char *password) {
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(ssid);
|
||||
WiFi.begin(ssid, password);
|
||||
|
||||
// Matches the original project's blocking connect-on-boot
|
||||
// behavior. This only runs once at startup, not in the main
|
||||
// loop, so it doesn't violate the "no long delay() in the
|
||||
// acquisition path" requirement — radar acquisition hasn't
|
||||
// started yet at this point in setup().
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.println();
|
||||
Serial.print("WiFi connected, IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
setupRoutes();
|
||||
_server.begin();
|
||||
Serial.println("HTTP server started.");
|
||||
}
|
||||
|
||||
void WebServerManager::loop() {
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
// Non-blocking reconnect kick. We don't retry-loop with
|
||||
// delay() here (unlike begin()) so radar acquisition in the
|
||||
// main loop is never stalled by a flaky network.
|
||||
static uint32_t lastAttempt = 0;
|
||||
uint32_t now = millis();
|
||||
if (now - lastAttempt > 5000) {
|
||||
Serial.println("WiFi disconnected, retrying...");
|
||||
WiFi.reconnect();
|
||||
lastAttempt = now;
|
||||
}
|
||||
}
|
||||
_ws.cleanupClients();
|
||||
}
|
||||
|
||||
void WebServerManager::broadcastFrame(const RadarFrame &frame) {
|
||||
if (_ws.count() == 0) return; // skip serialization work if nobody's listening
|
||||
|
||||
StaticJsonDocument<512> doc;
|
||||
doc["sensor"] = "LD2453";
|
||||
doc["node_id"] = frame.node_id;
|
||||
doc["sequence"] = frame.sequence_number;
|
||||
doc["timestamp"] = frame.timestamp_ms;
|
||||
|
||||
JsonArray targets = doc.createNestedArray("targets");
|
||||
for (uint8_t i = 0; i < frame.targetCount && i < 3; i++) {
|
||||
const RadarTarget &t = frame.targets[i];
|
||||
JsonObject jt = targets.createNestedObject();
|
||||
jt["id"] = i + 1; // radar slot index, NOT a persistent person ID
|
||||
jt["valid"] = t.valid;
|
||||
jt["x"] = t.x_mm;
|
||||
jt["y"] = t.y_mm;
|
||||
jt["speed"] = t.speed;
|
||||
}
|
||||
|
||||
String out;
|
||||
serializeJson(doc, out);
|
||||
_ws.textAll(out);
|
||||
}
|
||||
Reference in new issue
Block a user