diff --git a/data/index.html b/data/index.html
index c120efb..9859fb4 100644
--- a/data/index.html
+++ b/data/index.html
@@ -13,6 +13,7 @@
+
diff --git a/data/status.js b/data/status.js
index de00373..ca42350 100644
--- a/data/status.js
+++ b/data/status.js
@@ -1,4 +1,5 @@
import { data } from "./load-data.js";
+import { initWebSocket, registerCallback } from "./websocket.js";
const statusDialog = document.querySelector(".dialog-status");
const expandButton = document.querySelector(".expand-status");
@@ -7,24 +8,8 @@ expandButton.addEventListener("click", () => {
statusDialog.showModal();
});
-async function loadStatus() {
- try {
- const res = await fetch("/status");
- if (!res.ok) {
- throw new Error(
- `Response status: ${res.status}\n${await res.text()}`
- );
- }
-
- const data = await res.json();
- console.log(data);
-
- return data;
- } catch (e) {
- console.error(e);
- return null;
- }
-}
+registerCallback("status", setStatus);
+initWebSocket();
function setStatus(status) {
setValue("model", status.chip.model);
@@ -70,7 +55,6 @@ function setValue(className, value) {
function parseDuration(ms) {
const date = new Date(ms);
- console.log(date);
const time =
date.getUTCHours().toString().padStart(2, "0") +
":" +
@@ -126,5 +110,3 @@ function selectConnectionIcon(signalStrength) {
}
return "signal1.svg";
}
-
-setStatus(await loadStatus());
diff --git a/data/websocket.js b/data/websocket.js
new file mode 100644
index 0000000..268d69e
--- /dev/null
+++ b/data/websocket.js
@@ -0,0 +1,37 @@
+const gateway = `ws://${window.location.hostname}/ws`;
+let ws;
+
+let callbacks = {};
+
+export function initWebSocket() {
+ if (ws) return;
+
+ ws = new WebSocket(gateway);
+
+ ws.onopen = () => {
+ console.info("WebSocket connection opened");
+ };
+
+ ws.onclose = (event) => {
+ console.info("WebSocket connection closed, reason:", event.reason);
+ ws = null;
+ };
+
+ ws.onerror = (event) => {
+ console.warn("WebSocket encountered error, closing socket.", event);
+ ws.close();
+ ws = null;
+ };
+
+ ws.onmessage = (event) => {
+ const message = JSON.parse(event.data);
+ console.log("received websocket data", message);
+ if (message.type in callbacks) {
+ callbacks[message.type](message.data);
+ }
+ };
+}
+
+export function registerCallback(type, callback) {
+ callbacks[type] = callback;
+}
diff --git a/src/main.cpp b/src/main.cpp
index 5ec2d45..08cd9e6 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,6 +21,7 @@
#include
#include
+#include "websocket.h"
#include "routes/config.h"
#include "routes/networks.h"
#include "routes/status.h"
@@ -418,9 +419,6 @@ void setup()
server.on("/networks", HTTP_GET, [](AsyncWebServerRequest *request)
{ onGetNetworks(request); });
- server.on("/status", HTTP_GET, [](AsyncWebServerRequest *request)
- { onGetStatus(request); });
-
server.onRequestBody([](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total)
{
if (request->url() == "/config" && request->method() == HTTP_PUT) {
@@ -429,7 +427,8 @@ void setup()
ESP.restart();
} });
- delay(1000);
+ initWebSocket(&server);
+
server.begin();
Serial.println("Server started!");
@@ -501,4 +500,6 @@ void loop()
{
transmitDmxToArtnet(dmx2, dmx2_data, universe2);
}
+
+ webSocketLoop();
}
diff --git a/src/routes/status.cpp b/src/routes/status.cpp
index e25d21a..44af29b 100644
--- a/src/routes/status.cpp
+++ b/src/routes/status.cpp
@@ -19,7 +19,7 @@ int8_t getWiFiStrength()
}
}
-void onGetStatus(AsyncWebServerRequest *request)
+JsonDocument buildStatusJson()
{
JsonDocument doc;
@@ -39,7 +39,5 @@ void onGetStatus(AsyncWebServerRequest *request)
doc["psram"]["total"] = ESP.getPsramSize();
doc["connection"]["signalStrength"] = getWiFiStrength();
- String jsonString;
- serializeJson(doc, jsonString);
- request->send(200, "application/json", jsonString);
+ return doc;
}
\ No newline at end of file
diff --git a/src/routes/status.h b/src/routes/status.h
index 03e821b..9df7ac2 100644
--- a/src/routes/status.h
+++ b/src/routes/status.h
@@ -2,4 +2,4 @@
#include
#include
-void onGetStatus(AsyncWebServerRequest *request);
\ No newline at end of file
+JsonDocument buildStatusJson();
diff --git a/src/websocket.cpp b/src/websocket.cpp
new file mode 100644
index 0000000..0bb8d1a
--- /dev/null
+++ b/src/websocket.cpp
@@ -0,0 +1,52 @@
+#include "websocket.h"
+
+AsyncWebSocket ws("/ws");
+
+long webSocketLastUpdate = 0;
+const int WS_UPDATE_INTERVAL = 10 * 1000; // 10 seconds
+
+String buildStatusString()
+{
+ JsonDocument doc;
+ doc["type"] = "status";
+ doc["data"] = buildStatusJson();
+
+ String jsonString = "";
+ serializeJson(doc, jsonString);
+ return jsonString;
+}
+
+void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
+{
+ switch (type)
+ {
+ case WS_EVT_CONNECT:
+ Serial.printf("[WS] Client %u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
+ // directly send status to client
+ ws.text(client->id(), buildStatusString());
+ break;
+ case WS_EVT_DISCONNECT:
+ Serial.printf("[WS] Client %u disconnected\n", client->id());
+ break;
+ case WS_EVT_DATA:
+ Serial.printf("[WS] Data received from client %u: %s\n", client->id(), (char *)data);
+ break;
+ default:
+ break;
+ }
+}
+
+void webSocketLoop()
+{
+ if (millis() - webSocketLastUpdate > WS_UPDATE_INTERVAL)
+ {
+ ws.textAll(buildStatusString());
+ webSocketLastUpdate = millis();
+ }
+}
+
+void initWebSocket(AsyncWebServer *server)
+{
+ ws.onEvent(onEvent);
+ server->addHandler(&ws);
+}
diff --git a/src/websocket.h b/src/websocket.h
new file mode 100644
index 0000000..05d1144
--- /dev/null
+++ b/src/websocket.h
@@ -0,0 +1,11 @@
+#include
+#include "routes/status.h"
+
+#ifndef WEBSOCKET_H
+#define WEBSOCKET_H
+
+void initWebSocket(AsyncWebServer *server);
+
+void webSocketLoop();
+
+#endif