Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e05938457 | |||
| caccf91b7e | |||
| bd582c0d81 | |||
| e593c3fed9 | |||
| 5b6b810efd | |||
| b782867c69 |
+6
-4
@@ -12,9 +12,11 @@
|
|||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
framework = arduino
|
framework = arduino
|
||||||
;lib_deps =
|
lib_deps =
|
||||||
;; esp32async/ESPAsyncWebServer@^3.12.0
|
WebSockets
|
||||||
|
;board_build.f_cpu = 160000000L
|
||||||
|
;build_type = debug
|
||||||
|
|
||||||
; upload via OTA
|
; upload via OTA
|
||||||
upload_protocol = espota
|
;upload_protocol = espota
|
||||||
upload_port = 192.168.4.1
|
;upload_port = 192.168.4.1
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
// Contains configuration constants:
|
// Contains configuration constants:
|
||||||
|
|
||||||
#define FIRMWARE_VERSION "1.0.2"
|
#define FIRMWARE_VERSION "1.0.6"
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
#include "diagnostics_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
void DiagnosticsState::update()
|
||||||
|
{
|
||||||
|
current.timestamp = millis();
|
||||||
|
current.freeHeap =
|
||||||
|
ESP.getFreeHeap();
|
||||||
|
|
||||||
|
current.minimumFreeHeap =
|
||||||
|
ESP.getMinFreeHeap();
|
||||||
|
|
||||||
|
current.cpuFrequency =
|
||||||
|
ESP.getCpuFreqMHz();
|
||||||
|
|
||||||
|
Serial.print("#update: ");
|
||||||
|
Serial.println(current.freeHeap);
|
||||||
|
Serial.println("Calling current from update");
|
||||||
|
getCurrent();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DiagnosticSample DiagnosticsState::getCurrent()
|
||||||
|
{
|
||||||
|
DiagnosticSample sample;
|
||||||
|
sample.timestamp = current.timestamp;
|
||||||
|
sample.freeHeap = current.freeHeap;
|
||||||
|
sample.minimumFreeHeap = current.minimumFreeHeap;
|
||||||
|
sample.cpuFrequency = current.cpuFrequency;
|
||||||
|
|
||||||
|
Serial.print("#getCurrent: ");
|
||||||
|
Serial.println(sample.freeHeap);
|
||||||
|
Serial.println(sample.timestamp);
|
||||||
|
return sample;
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define DIAGNOSTIC_HISTORY_SIZE 60
|
||||||
|
|
||||||
|
|
||||||
|
struct DiagnosticSample
|
||||||
|
{
|
||||||
|
uint32_t timestamp;
|
||||||
|
uint32_t freeHeap;
|
||||||
|
uint32_t minimumFreeHeap;
|
||||||
|
uint32_t cpuFrequency;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class DiagnosticsState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void update();
|
||||||
|
|
||||||
|
|
||||||
|
DiagnosticSample getCurrent();
|
||||||
|
//DiagnosticSample getHistory(uint8_t index);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
volatile DiagnosticSample current;
|
||||||
|
//DiagnosticSample history[DIAGNOSTIC_HISTORY_SIZE];
|
||||||
|
//uint8_t historyIndex = 0;
|
||||||
|
};
|
||||||
+8
-4
@@ -4,6 +4,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
#include "core/dashboard_state.h"
|
#include "core/dashboard_state.h"
|
||||||
|
#include "core/diagnostics_state.h"
|
||||||
|
|
||||||
#include "services/service_manager.h"
|
#include "services/service_manager.h"
|
||||||
#include "services/wifi_service.h"
|
#include "services/wifi_service.h"
|
||||||
@@ -11,22 +12,24 @@
|
|||||||
#include "services/web_service.h"
|
#include "services/web_service.h"
|
||||||
|
|
||||||
#include "tasks/system_task.h"
|
#include "tasks/system_task.h"
|
||||||
|
#include "tasks/diagnostics_task.h"
|
||||||
|
|
||||||
|
|
||||||
DashboardState dashboardState;
|
DashboardState dashboardState;
|
||||||
|
DiagnosticsState diagnosticsState;
|
||||||
|
|
||||||
|
// Simple service scheduler nice for grouping tasks
|
||||||
ServiceManager services;
|
ServiceManager services;
|
||||||
|
|
||||||
|
|
||||||
WiFiService wifi;
|
WiFiService wifi;
|
||||||
OTAService ota;
|
OTAService ota;
|
||||||
WebService web(dashboardState);
|
WebService web(dashboardState, diagnosticsState);
|
||||||
|
|
||||||
|
|
||||||
|
// Actual FreeRTOS tasks that are scheduled
|
||||||
SystemTask systemTask(services);
|
SystemTask systemTask(services);
|
||||||
|
|
||||||
|
DiagnosticsTask diagnosticsTask(diagnosticsState);
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
@@ -38,6 +41,7 @@ void setup()
|
|||||||
|
|
||||||
|
|
||||||
systemTask.start();
|
systemTask.start();
|
||||||
|
diagnosticsTask.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+143
-55
@@ -1,10 +1,12 @@
|
|||||||
#include "web_service.h"
|
#include "web_service.h"
|
||||||
|
|
||||||
WebService::WebService(DashboardState& state)
|
WebService::WebService(DashboardState& state, DiagnosticsState& diag_state)
|
||||||
:
|
:
|
||||||
Service("Web", 10),
|
Service("Web", 10),
|
||||||
dashboardState(state),
|
dashboardState(state),
|
||||||
server(80)
|
diagnosticsState(diag_state),
|
||||||
|
server(80),
|
||||||
|
webSocket(81)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,31 +67,38 @@ h1 {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
function updateUptime() {
|
|
||||||
fetch('/uptime')
|
let socket;
|
||||||
.then(response => response.text())
|
|
||||||
.then(data => {
|
function connectWebSocket() {
|
||||||
document.getElementById("uptime").innerHTML = data;
|
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);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(updateUptime, 1000);
|
window.onload = connectWebSocket;
|
||||||
window.onload = updateUptime;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
|
||||||
function getVersion() {
|
|
||||||
fetch('/version')
|
|
||||||
.then(response => response.text())
|
|
||||||
.then(data => {
|
|
||||||
document.getElementById("firmware_version").innerHTML = data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
window.onload = getVersion;
|
|
||||||
</script>
|
|
||||||
|
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -98,25 +107,69 @@ window.onload = getVersion;
|
|||||||
<p>Device uptime:</p>
|
<p>Device uptime:</p>
|
||||||
<div id="uptime">Loading...</div>
|
<div id="uptime">Loading...</div>
|
||||||
</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>
|
<footer>
|
||||||
Firmware Version: <div id="firmware_version">Loading...</div>
|
Firmware Version: <div id="firmware_version">Loading...</div>
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
)rawliteral";
|
)rawliteral";
|
||||||
|
|
||||||
|
void WebService::broadcastState()
|
||||||
// server.send(200, "text/html", html);
|
{
|
||||||
// }
|
DiagnosticSample diagnostics = diagnosticsState.getCurrent();
|
||||||
//
|
Serial.println(diagnostics.freeHeap);
|
||||||
// void handleUptime() {
|
String json = "{";
|
||||||
// server.send(200, "text/plain", formatUptime());
|
|
||||||
// }
|
// Opening system tag:
|
||||||
//
|
json += "\"system\":{";
|
||||||
// void handleVersion() {
|
|
||||||
// server.send(200, "text/plain", FIRMWARE_VERSION);
|
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() {
|
void WebService::begin() {
|
||||||
// Root path
|
// Root path
|
||||||
@@ -128,34 +181,69 @@ void WebService::begin() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Version path
|
#ifdef DEBUGGING
|
||||||
server.on("/version", [this](){
|
// Prints out paths that are requested but not found.
|
||||||
server.send(
|
server.onNotFound([this]() {
|
||||||
200,
|
Serial.print("HTTP not found: ");
|
||||||
"text/plain",
|
Serial.println(server.uri());
|
||||||
dashboardState.firmwareVersion
|
|
||||||
);
|
server.send(404, "text/plain", "Not found");
|
||||||
});
|
});
|
||||||
|
#endif
|
||||||
// Uptime path
|
|
||||||
server.on("/uptime", [this]() {
|
|
||||||
server.send(
|
|
||||||
200,
|
|
||||||
"text/plain",
|
|
||||||
dashboardState.uptime
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
server.begin();
|
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");
|
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()
|
void WebService::update()
|
||||||
{
|
{
|
||||||
dashboardState.update();
|
dashboardState.update();
|
||||||
|
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
|
webSocket.loop();
|
||||||
|
|
||||||
|
// Brodcast updates once per second
|
||||||
|
static unsigned long lastUpdate = 0;
|
||||||
|
|
||||||
|
if (millis() - lastUpdate >= 1000)
|
||||||
|
{
|
||||||
|
lastUpdate = millis();
|
||||||
|
broadcastState();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "service.h"
|
|
||||||
#include "../core/dashboard_state.h"
|
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
|
#include <WebSocketsServer.h>
|
||||||
|
|
||||||
|
#include "service.h"
|
||||||
|
|
||||||
|
#include "../core/dashboard_state.h"
|
||||||
|
#include "../core/diagnostics_state.h"
|
||||||
|
|
||||||
class WebService : public Service {
|
class WebService : public Service {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WebService(DashboardState& state);
|
WebService(DashboardState& state, DiagnosticsState& diag_state);
|
||||||
|
|
||||||
void begin() override;
|
void begin() override;
|
||||||
void update() override;
|
void update() override;
|
||||||
@@ -17,5 +20,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
WebServer server;
|
WebServer server;
|
||||||
DashboardState dashboardState;
|
WebSocketsServer webSocket;
|
||||||
|
|
||||||
|
DashboardState& dashboardState;
|
||||||
|
DiagnosticsState& diagnosticsState;
|
||||||
|
|
||||||
|
void handleWebSocketMessage(uint8_t clientNum, uint8_t *payload, size_t length);
|
||||||
|
void broadcastState();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
#include "diagnostics_task.h"
|
||||||
|
|
||||||
|
DiagnosticsTask::DiagnosticsTask(
|
||||||
|
DiagnosticsState& state
|
||||||
|
)
|
||||||
|
:
|
||||||
|
diagnostics(state)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DiagnosticsTask::start()
|
||||||
|
{
|
||||||
|
|
||||||
|
xTaskCreatePinnedToCore(
|
||||||
|
taskEntry,
|
||||||
|
"DiagnosticsTask",
|
||||||
|
4096,
|
||||||
|
this,
|
||||||
|
1,
|
||||||
|
&taskHandle,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DiagnosticsTask::taskEntry(void* parameter)
|
||||||
|
{
|
||||||
|
|
||||||
|
DiagnosticsTask* task =
|
||||||
|
static_cast<DiagnosticsTask*>(parameter);
|
||||||
|
|
||||||
|
|
||||||
|
task->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DiagnosticsTask::run()
|
||||||
|
{
|
||||||
|
|
||||||
|
TickType_t lastWake =
|
||||||
|
xTaskGetTickCount();
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
diagnostics.update();
|
||||||
|
|
||||||
|
vTaskDelayUntil(
|
||||||
|
&lastWake,
|
||||||
|
pdMS_TO_TICKS(1000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#include "../core/diagnostics_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
class DiagnosticsTask
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DiagnosticsTask(
|
||||||
|
DiagnosticsState& state
|
||||||
|
);
|
||||||
|
|
||||||
|
void start();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static void taskEntry(void* parameter);
|
||||||
|
void run();
|
||||||
|
|
||||||
|
DiagnosticsState& diagnostics;
|
||||||
|
|
||||||
|
TaskHandle_t taskHandle = nullptr;
|
||||||
|
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user