Set time from browser
This commit is contained in:
@@ -38,6 +38,11 @@ function connectWS() {
|
|||||||
console.log("WebSocket connesso");
|
console.log("WebSocket connesso");
|
||||||
lastMessageTimestamp = Date.now();
|
lastMessageTimestamp = Date.now();
|
||||||
setLoadingIndicator(false);
|
setLoadingIndicator(false);
|
||||||
|
|
||||||
|
ws.send(JSON.stringify({
|
||||||
|
cmd: "setTime",
|
||||||
|
time: Math.floor(Date.now() / 1000)
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
ws.onclose = () => {
|
ws.onclose = () => {
|
||||||
@@ -142,7 +147,7 @@ function updateChart(data) {
|
|||||||
const boxA = data.box_a;
|
const boxA = data.box_a;
|
||||||
const coils12A = boxA.coils12 || {};
|
const coils12A = boxA.coils12 || {};
|
||||||
const coils34A = boxA.coils34 || {};
|
const coils34A = boxA.coils34 || {};
|
||||||
chartData.datasets[0].data.push(boxA.eng_rpm/10);
|
chartData.datasets[0].data.push(boxA.eng_rpm / 10);
|
||||||
chartData.datasets[2].data.push(coils12A.spark_delay);
|
chartData.datasets[2].data.push(coils12A.spark_delay);
|
||||||
chartData.datasets[3].data.push(coils34A.spark_delay);
|
chartData.datasets[3].data.push(coils34A.spark_delay);
|
||||||
}
|
}
|
||||||
@@ -151,7 +156,7 @@ function updateChart(data) {
|
|||||||
const boxB = data.box_b;
|
const boxB = data.box_b;
|
||||||
const coils12B = boxB.coils12 || {};
|
const coils12B = boxB.coils12 || {};
|
||||||
const coils34B = boxB.coils34 || {};
|
const coils34B = boxB.coils34 || {};
|
||||||
chartData.datasets[1].data.push(boxB.eng_rpm/10);
|
chartData.datasets[1].data.push(boxB.eng_rpm / 10);
|
||||||
chartData.datasets[4].data.push(coils12B.spark_delay);
|
chartData.datasets[4].data.push(coils12B.spark_delay);
|
||||||
chartData.datasets[5].data.push(coils34B.spark_delay);
|
chartData.datasets[5].data.push(coils34B.spark_delay);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ void loop()
|
|||||||
LOG_DEBUG("Real Time Tasks A & B initialized");
|
LOG_DEBUG("Real Time Tasks A & B initialized");
|
||||||
led.setStatus(RGBled::LedStatus::OK);
|
led.setStatus(RGBled::LedStatus::OK);
|
||||||
|
|
||||||
WebPage webPage(80, LittleFS); // Initialize webserver and Websocket
|
AstroWebServer webPage(80, LittleFS); // Initialize webserver and Websocket
|
||||||
|
|
||||||
task_A.onMessage([&webPage](ignitionBoxStatusFiltered sts){
|
task_A.onMessage([&webPage](ignitionBoxStatusFiltered sts){
|
||||||
ArduinoJson::JsonDocument doc;
|
ArduinoJson::JsonDocument doc;
|
||||||
@@ -237,6 +237,7 @@ void loop()
|
|||||||
{
|
{
|
||||||
clearScreen();
|
clearScreen();
|
||||||
printRunningTasksMod(Serial);
|
printRunningTasksMod(Serial);
|
||||||
|
delay(100);
|
||||||
last_loop = millis();
|
last_loop = millis();
|
||||||
}
|
}
|
||||||
} //////////////// INNER LOOP /////////////////////
|
} //////////////// INNER LOOP /////////////////////
|
||||||
|
|||||||
@@ -99,7 +99,14 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
|
|||||||
|
|
||||||
// PRINT MEMORY INFO
|
// PRINT MEMORY INFO
|
||||||
printer.printf("\033[H");
|
printer.printf("\033[H");
|
||||||
printer.printf(COLOR_LBLUE "=================== ESP32 SYSTEM MONITOR ===================\n\n" COLOR_RESET);
|
printer.printf(COLOR_LBLUE "=================== ESP32 SYSTEM MONITOR ===================\n" COLOR_RESET);
|
||||||
|
|
||||||
|
std::string buffer;
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
struct tm *t = localtime(&now);
|
||||||
|
buffer.resize(64);
|
||||||
|
strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
|
||||||
|
printer.printf(COLOR_YELLOW "=============== Datetime: %s ===============\n\n" COLOR_RESET, buffer.c_str());
|
||||||
|
|
||||||
// ===== HEAP =====
|
// ===== HEAP =====
|
||||||
size_t freeHeap = esp_get_free_heap_size();
|
size_t freeHeap = esp_get_free_heap_size();
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
#include <webserver.h>
|
#include <webserver.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
WebPage::WebPage(const uint8_t port, fs::FS &filesystem) : m_port(port), m_webserver(AsyncWebServer(port)), m_websocket(AsyncWebSocket("/ws")), m_filesystem(filesystem)
|
static const std::map<const std::string, AstroWebServer::c_commandEnum> s_webserverCommands = {
|
||||||
|
{"setTime", AstroWebServer::SET_TIME},
|
||||||
|
};
|
||||||
|
|
||||||
|
AstroWebServer::AstroWebServer(const uint8_t port, fs::FS &filesystem) : m_port(port), m_webserver(AsyncWebServer(port)), m_websocket(AsyncWebSocket("/ws")), m_filesystem(filesystem)
|
||||||
{
|
{
|
||||||
LOG_DEBUG("Initializing Web Server");
|
LOG_DEBUG("Initializing Web Server");
|
||||||
m_websocket.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client,
|
m_websocket.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client,
|
||||||
@@ -10,62 +15,107 @@ WebPage::WebPage(const uint8_t port, fs::FS &filesystem) : m_port(port), m_webse
|
|||||||
m_webserver.addHandler(&m_websocket);
|
m_webserver.addHandler(&m_websocket);
|
||||||
m_webserver.serveStatic("/", m_filesystem, "/").setDefaultFile("index.html");
|
m_webserver.serveStatic("/", m_filesystem, "/").setDefaultFile("index.html");
|
||||||
|
|
||||||
m_webserver.on("/upload", HTTP_POST,
|
m_webserver.on("/upload", HTTP_POST, [this](AsyncWebServerRequest *request)
|
||||||
[this](AsyncWebServerRequest *request)
|
{ onUploadRequest(request); }, [this](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
||||||
{ onUploadRequest(request); },
|
{ onUploadHandler(request, filename, index, data, len, final); });
|
||||||
[this](AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
|
||||||
{ onUploadHandler(request, filename, index, data, len, final); }
|
|
||||||
);
|
|
||||||
|
|
||||||
m_webserver.begin();
|
m_webserver.begin();
|
||||||
LOG_DEBUG("Webserver Init OK");
|
LOG_DEBUG("Webserver Init OK");
|
||||||
}
|
}
|
||||||
|
|
||||||
WebPage::~WebPage()
|
AstroWebServer::~AstroWebServer()
|
||||||
{
|
{
|
||||||
m_webserver.removeHandler(&m_websocket);
|
m_webserver.removeHandler(&m_websocket);
|
||||||
m_webserver.end();
|
m_webserver.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::sendWsData(const String &data){
|
void AstroWebServer::sendWsData(const String &data)
|
||||||
if (m_websocket.count()){
|
{
|
||||||
|
if (m_websocket.count())
|
||||||
|
{
|
||||||
m_websocket.textAll(data);
|
m_websocket.textAll(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
|
void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case WS_EVT_CONNECT:
|
case WS_EVT_CONNECT:
|
||||||
Serial.printf("WS client IP[%s]-ID[%u] CONNECTED\r\n", client->remoteIP().toString().c_str(), client->id());
|
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] CONNECTED");
|
||||||
break;
|
break;
|
||||||
case WS_EVT_DISCONNECT:
|
case WS_EVT_DISCONNECT:
|
||||||
Serial.printf("WS client ID[%u] DISCONNECTED\r\n", client->remoteIP().toString().c_str(), client->id());
|
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] DISCONNECTED");
|
||||||
break;
|
break;
|
||||||
|
case WS_EVT_DATA:
|
||||||
|
{
|
||||||
|
AwsFrameInfo *info = (AwsFrameInfo *)arg;
|
||||||
|
if (info->final && info->index == 0 && info->len == len)
|
||||||
|
{
|
||||||
|
std::string data_str((char *)data, len);
|
||||||
|
ArduinoJson::JsonDocument doc;
|
||||||
|
if (auto rv = ArduinoJson::deserializeJson(doc, data_str) != ArduinoJson::DeserializationError::Ok)
|
||||||
|
{
|
||||||
|
LOG_ERROR("WS Client unable to deserialize Json");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!doc["cmd"].is<std::string>() || !s_webserverCommands.contains(doc["cmd"]))
|
||||||
|
{
|
||||||
|
LOG_WARN("WS Client Invalid Json command [", doc["cmd"].as<std::string>().c_str(), "]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string buffer;
|
||||||
|
switch (s_webserverCommands.at(doc["cmd"]))
|
||||||
|
{
|
||||||
|
case SET_TIME:
|
||||||
|
{
|
||||||
|
auto epoch = doc["time"].as<time_t>();
|
||||||
|
timeval te{
|
||||||
|
.tv_sec = epoch,
|
||||||
|
.tv_usec = 0,
|
||||||
|
};
|
||||||
|
timezone tz{
|
||||||
|
.tz_minuteswest = 0,
|
||||||
|
.tz_dsttime = DST_MET,
|
||||||
|
};
|
||||||
|
settimeofday(&te, &tz);
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
struct tm *t = localtime(&now);
|
||||||
|
buffer.resize(64);
|
||||||
|
strftime(buffer.data(), sizeof(buffer), "%Y-%m-%d %H:%M:%S", t);
|
||||||
|
LOG_DEBUG("WS Client set Datetime to: ", buffer.c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
// call external command callback
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::onUploadRequest(AsyncWebServerRequest *request)
|
void AstroWebServer::onUploadRequest(AsyncWebServerRequest *request)
|
||||||
{
|
{
|
||||||
if (m_upload_failed)
|
if (m_uploadFailed)
|
||||||
request->send(500, "text/plain", "Upload failed");
|
request->send(500, "text/plain", "Upload failed");
|
||||||
else
|
else
|
||||||
request->send(200, "text/plain", "Upload successful");
|
request->send(200, "text/plain", "Upload successful");
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebPage::onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
void AstroWebServer::onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final)
|
||||||
{
|
{
|
||||||
if (index == 0) // only on first iteration to open file
|
if (index == 0) // only on first iteration to open file
|
||||||
{
|
{
|
||||||
m_upload_failed = false;
|
m_uploadFailed = false;
|
||||||
String safeName = filename;
|
String safeName = filename;
|
||||||
int slashIndex = safeName.lastIndexOf('/');
|
int slashIndex = safeName.lastIndexOf('/');
|
||||||
if (slashIndex >= 0)
|
if (slashIndex >= 0)
|
||||||
safeName = safeName.substring(slashIndex + 1);
|
safeName = safeName.substring(slashIndex + 1);
|
||||||
if (safeName.length() == 0)
|
if (safeName.length() == 0)
|
||||||
{
|
{
|
||||||
m_upload_failed = true;
|
m_uploadFailed = true;
|
||||||
LOG_ERROR("Invalid file name");
|
LOG_ERROR("Invalid file name");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -74,27 +124,27 @@ void WebPage::onUploadHandler(AsyncWebServerRequest *request, const String &file
|
|||||||
if (m_filesystem.exists(filePath.c_str()))
|
if (m_filesystem.exists(filePath.c_str()))
|
||||||
m_filesystem.remove(filePath.c_str());
|
m_filesystem.remove(filePath.c_str());
|
||||||
|
|
||||||
m_upload_file = m_filesystem.open(filePath.c_str(), FILE_WRITE);
|
m_uploadFile = m_filesystem.open(filePath.c_str(), FILE_WRITE);
|
||||||
if (!m_upload_file)
|
if (!m_uploadFile)
|
||||||
{
|
{
|
||||||
m_upload_failed = true;
|
m_uploadFailed = true;
|
||||||
LOG_ERROR("Failed to open upload file:", filePath.c_str());
|
LOG_ERROR("Failed to open upload file:", filePath.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actual write of file data
|
// Actual write of file data
|
||||||
if (!m_upload_failed && m_upload_file)
|
if (!m_uploadFailed && m_uploadFile)
|
||||||
{
|
{
|
||||||
if (m_upload_file.write(data, len) != len)
|
if (m_uploadFile.write(data, len) != len)
|
||||||
m_upload_failed = true;
|
m_uploadFailed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// close the file and save on final call
|
// close the file and save on final call
|
||||||
if (final && m_upload_file)
|
if (final && m_uploadFile)
|
||||||
{
|
{
|
||||||
m_upload_file.close();
|
m_uploadFile.close();
|
||||||
if (!m_upload_failed)
|
if (!m_uploadFailed)
|
||||||
LOG_INFO("Uploaded file to LittleFS:", filename.c_str());
|
LOG_INFO("Uploaded file to LittleFS:", filename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#define DEBUGLOG_DEFAULT_LOG_LEVEL_INFO
|
#define DEBUGLOG_DEFAULT_LOG_LEVEL_DEBUG
|
||||||
|
|
||||||
// System includes
|
// System includes
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
@@ -7,26 +7,22 @@
|
|||||||
#include <ESPAsyncWebServer.h>
|
#include <ESPAsyncWebServer.h>
|
||||||
#include <AsyncTCP.h>
|
#include <AsyncTCP.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
||||||
class WebPage
|
class AstroWebServer
|
||||||
{
|
{
|
||||||
const uint8_t m_port = 80;
|
|
||||||
fs::FS &m_filesystem;
|
|
||||||
AsyncWebServer m_webserver;
|
|
||||||
AsyncWebSocket m_websocket;
|
|
||||||
bool m_upload_failed = false;
|
|
||||||
fs::File m_upload_file;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebPage(const uint8_t port, fs::FS &filesystem);
|
AstroWebServer(const uint8_t port, fs::FS &filesystem);
|
||||||
~WebPage();
|
~AstroWebServer();
|
||||||
|
|
||||||
void sendWsData(const String &data);
|
void sendWsData(const String &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
|
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client,
|
||||||
AwsEventType type, void *arg, uint8_t *data, size_t len);
|
AwsEventType type, void *arg, uint8_t *data, size_t len);
|
||||||
|
|
||||||
void onUploadRequest(AsyncWebServerRequest *request);
|
void onUploadRequest(AsyncWebServerRequest *request);
|
||||||
void onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
|
void onUploadHandler(AsyncWebServerRequest *request, const String &filename, size_t index, uint8_t *data, size_t len, bool final);
|
||||||
@@ -35,4 +31,17 @@ private:
|
|||||||
void onStop(AsyncWebServerRequest *request);
|
void onStop(AsyncWebServerRequest *request);
|
||||||
void onDownload(AsyncWebServerRequest *request);
|
void onDownload(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const uint8_t m_port = 80;
|
||||||
|
fs::FS &m_filesystem;
|
||||||
|
AsyncWebServer m_webserver;
|
||||||
|
AsyncWebSocket m_websocket;
|
||||||
|
bool m_uploadFailed = false;
|
||||||
|
fs::File m_uploadFile;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum c_commandEnum
|
||||||
|
{
|
||||||
|
SET_TIME
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user