Files
audio_project_hub/src/services/web_service.cpp
T

250 lines
5.2 KiB
C++

#include "web_service.h"
WebService::WebService(DashboardState& state, DiagnosticsState& diag_state)
:
Service("Web", 10),
dashboardState(state),
diagnosticsState(diag_state),
server(80),
webSocket(81)
{
}
String formatUptime() {
unsigned long seconds = millis() / 1000;
unsigned long days = seconds / 86400;
seconds %= 86400;
unsigned long hours = seconds / 3600;
seconds %= 3600;
unsigned long minutes = seconds / 60;
seconds %= 60;
char buffer[64];
snprintf(buffer, sizeof(buffer),
"%lu days %02lu:%02lu:%02lu",
days, hours, minutes, seconds);
return String(buffer);
}
String ROOT_HTML = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ESP32 Dashboard</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
margin-top: 50px;
background: #111;
color: white;
}
.card {
background: #222;
padding: 25px;
margin: auto;
width: 80%;
max-width: 400px;
border-radius: 15px;
}
h1 {
color: #00ff99;
}
#uptime {
font-size: 28px;
margin-top: 20px;
}
</style>
<script>
let socket;
function connectWebSocket() {
socket = new WebSocket(
"ws://" + window.location.hostname + ":81/"
);
socket.onopen = function() {
console.log("WebSocket connected");
};
socket.onmessage = function(event) {
const data = JSON.parse(event.data);
document.getElementById("uptime").innerHTML = data.system.uptime;
document.getElementById("firmware_version").innerHTML = data.system.version;
document.getElementById("free_heap").innerHTML = data.diagnostics.free_heap;
document.getElementById("minimum_free_heap").innerHTML = data.diagnostics.minimum_free_heap;
document.getElementById("cpu_frequency").innerHTML = data.diagnostics.cpu_frequency;
};
socket.onclose = function() {
console.log("WebSocket disconnected");
setTimeout(connectWebSocket, 2000);
};
}
window.onload = connectWebSocket;
</script>
</head>
<body>
<div class="card">
<h1>ESP32 Dashboard OTA</h1>
<p>Device uptime:</p>
<div id="uptime">Loading...</div>
</div>
<div class="card">
<h1>Hub Diagnostics:</h1>
<p>Free heap:</p>
<div id=free_heap>Loading...</div>
<p>Minimum free heap:</p>
<div id=minimum_free_heap>Loading...</div>
<p>CPU Frequency:</p>
<div id=cpu_frequency>Loading...</div>
</div>
</body>
<footer>
Firmware Version: <div id="firmware_version">Loading...</div>
</footer>
</html>
)rawliteral";
void WebService::broadcastState()
{
DiagnosticSample diagnostics = diagnosticsState.getCurrent();
Serial.println(diagnostics.freeHeap);
String json = "{";
// Opening system tag:
json += "\"system\":{";
json += "\"uptime\":\"";
json += dashboardState.uptime;
json += "\",";
json += "\"version\":\"";
json += dashboardState.firmwareVersion;
json += "\"";
json += "},"; // Close system tag
// Opening diagnostic tag:
json += "\"diagnostics\":{";
json += "\"free_heap\":\"";
json += diagnostics.freeHeap;
//json += ESP.getFreeHeap();
json += "\",";
json += "\"minimum_free_heap\":\"";
json += diagnostics.minimumFreeHeap;
json += "\",";
json += "\"cpu_frequency\":\"";
json += diagnostics.cpuFrequency;
json += "\"";
json += "}"; // Clost diagnostic tag
// Final close bracket
json += "}";
//Serial.println(json);
webSocket.broadcastTXT(json);
}
void WebService::begin() {
// Root path
server.on("/", [this](){
server.send(
200,
"text/html",
ROOT_HTML
);
});
#ifdef DEBUGGING
// Prints out paths that are requested but not found.
server.onNotFound([this]() {
Serial.print("HTTP not found: ");
Serial.println(server.uri());
server.send(404, "text/plain", "Not found");
});
#endif
server.begin();
webSocket.begin();
// Manage web socket connections
webSocket.onEvent(
[this](uint8_t clientNum,
WStype_t type,
uint8_t *payload,
size_t length)
{
if (type == WStype_TEXT) {
handleWebSocketMessage(
clientNum,
payload,
length
);
}
if (type == WStype_CONNECTED) {
Serial.println("WebSocket client connected");
broadcastState();
}
}
);
Serial.println("Web server started");
}
void WebService::handleWebSocketMessage(uint8_t clientNum, uint8_t *payload, size_t length) {
Serial.println("Client number: " + clientNum);
Serial.println("Sent a message of length: " + length);
Serial.print("Saying: ");
for (int ii = 0; ii < length; ii ++) {
Serial.print(payload[ii]);
}
Serial.print("\n\n\n");
}
void WebService::update()
{
dashboardState.update();
server.handleClient();
webSocket.loop();
// Brodcast updates once per second
static unsigned long lastUpdate = 0;
if (millis() - lastUpdate >= 1000)
{
lastUpdate = millis();
broadcastState();
}
}