task refactoring working, sometimes misses events, check priorities

This commit is contained in:
2026-04-12 01:45:32 +02:00
parent fdba6d5ad5
commit 095aa59f36
8 changed files with 202 additions and 52 deletions

View File

@@ -37,7 +37,7 @@ public:
struct color_t struct color_t
{ {
uint8_t a, g, r, b; uint8_t a, r, g, b;
}; };
union color_u union color_u

View File

@@ -64,7 +64,7 @@ build_flags =
-DARDUINO_USB_MODE=0 -DARDUINO_USB_MODE=0
-DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000 -DCONFIG_ASYNC_TCP_MAX_ACK_TIME=5000
-DCONFIG_ASYNC_TCP_PRIORITY=21 -DCONFIG_ASYNC_TCP_PRIORITY=21
-DCONFIG_ASYNC_TCP_QUEUE_SIZE=64 -DCONFIG_ASYNC_TCP_QUEUE_SIZE=128
-DCONFIG_ASYNC_TCP_RUNNING_CORE=1 -DCONFIG_ASYNC_TCP_RUNNING_CORE=1
-DCONFIG_ASYNC_TCP_STACK_SIZE=4096 -DCONFIG_ASYNC_TCP_STACK_SIZE=8192
-fstack-protector-all -fstack-protector-all

View File

@@ -17,7 +17,7 @@
#define CORE_0 0 #define CORE_0 0
#define CORE_1 1 #define CORE_1 1
#define RT_TASK_STACK 2048 // in words #define RT_TASK_STACK 2048 // in words
#define RT_TASK_PRIORITY (configMAX_PRIORITIES - 6) // highest priority after wifi tasks #define RT_TASK_PRIORITY (configMAX_PRIORITIES - 5) // highest priority after wifi tasks
struct isrParams struct isrParams
{ {

View File

@@ -31,7 +31,7 @@ void setup()
// Setup Logger // Setup Logger
LOG_ATTACH_SERIAL(Serial); LOG_ATTACH_SERIAL(Serial);
LOG_SET_LEVEL(DebugLogLevel::LVL_INFO); LOG_SET_LEVEL(DebugLogLevel::LVL_DEBUG);
// Print Processor Info // Print Processor Info
LOG_DEBUG("ESP32 Chip:", ESP.getChipModel()); LOG_DEBUG("ESP32 Chip:", ESP.getChipModel());
@@ -82,19 +82,20 @@ void loop()
led.setStatus(RGBled::LedStatus::INIT); led.setStatus(RGBled::LedStatus::INIT);
bool running = true; bool running = true;
std::mutex fs_mutex; std::mutex fs_mutex;
LITTLEFSGuard fsGuard;
//////// INIT SPI PORTS //////// //////// INIT SPI PORTS ////////
bool spiA_ok = true; bool spiA_ok = true;
bool spiB_ok = true; bool spiB_ok = true;
// Init 2 SPI interfaces // Init 2 SPI interfaces
SPIClass SPI_A(FSPI); // SPIClass SPI_A(FSPI);
spiA_ok = SPI_A.begin(SPI_A_SCK, SPI_A_MISO, SPI_A_MOSI); // spiA_ok = SPI_A.begin(SPI_A_SCK, SPI_A_MISO, SPI_A_MOSI);
SPI_A.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1 // SPI_A.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1
#ifdef CH_B_ENABLE // #ifdef CH_B_ENABLE
SPIClass SPI_B(HSPI); // SPIClass SPI_B(HSPI);
spiB_ok = SPI_B.begin(SPI_B_SCK, SPI_B_MISO, SPI_B_MOSI); // spiB_ok = SPI_B.begin(SPI_B_SCK, SPI_B_MISO, SPI_B_MOSI);
SPI_B.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1 // SPI_B.setDataMode(SPI_MODE1); // ADS1256 requires SPI mode 1
#endif // #endif
if (!spiA_ok || !spiB_ok) if (!spiA_ok || !spiB_ok)
{ {
LOG_ERROR("Unable to Initialize SPI Busses"); LOG_ERROR("Unable to Initialize SPI Busses");
@@ -106,20 +107,20 @@ void loop()
// Resources Initialization // Resources Initialization
std::shared_ptr<Devices> dev = std::make_shared<Devices>(); std::shared_ptr<Devices> dev = std::make_shared<Devices>();
dev->m_spi_a = std::make_unique<SPIClass>(SPI_A); // dev->m_spi_a = std::make_unique<SPIClass>(SPI_A);
dev->m_spi_b = std::make_unique<SPIClass>(SPI_B); // dev->m_spi_b = std::make_unique<SPIClass>(SPI_B);
// Init ADC_A // // Init ADC_A
dev->m_adc_a = std::make_unique<ADS1256>(ADC_A_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_A_CS, 2.5, &SPI_A); // dev->m_adc_a = std::make_unique<ADS1256>(ADC_A_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_A_CS, 2.5, &SPI_A);
dev->m_adc_b = std::make_unique<ADS1256>(ADC_B_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_B_CS, 2.5, &SPI_B); // dev->m_adc_b = std::make_unique<ADS1256>(ADC_B_DRDY, ADS1256::PIN_UNUSED, ADS1256::PIN_UNUSED, ADC_B_CS, 2.5, &SPI_B);
dev->m_adc_a->InitializeADC(); // dev->m_adc_a->InitializeADC();
dev->m_adc_a->setPGA(PGA_1); // dev->m_adc_a->setPGA(PGA_1);
dev->m_adc_a->setDRATE(DRATE_7500SPS); // dev->m_adc_a->setDRATE(DRATE_7500SPS);
dev->m_adc_b->InitializeADC(); // dev->m_adc_b->InitializeADC();
dev->m_adc_b->setPGA(PGA_1); // dev->m_adc_b->setPGA(PGA_1);
dev->m_adc_b->setDRATE(DRATE_7500SPS); // dev->m_adc_b->setDRATE(DRATE_7500SPS);
const rtIgnitionTask::rtTaskParams taskA_params{ const rtIgnitionTask::rtTaskParams taskA_params{
.rt_running = true, .rt_running = true,
@@ -183,8 +184,9 @@ void loop()
.rt_queue = nullptr, .rt_queue = nullptr,
.dev = dev}; .dev = dev};
auto task_A = rtIgnitionTask(taskA_params, 1024, 128, CORE_0, fs_mutex); auto task_A = rtIgnitionTask(taskA_params, 4096, 256, CORE_1, fs_mutex);
auto task_B = rtIgnitionTask(taskA_params, 1024, 128, CORE_1, fs_mutex); delay(50);
auto task_B = rtIgnitionTask(taskB_params, 4096, 256, CORE_1, fs_mutex);
// Ignition A on Core 0 // Ignition A on Core 0
auto ignA_task_success = task_A.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL; auto ignA_task_success = task_A.getStatus() == rtIgnitionTask::OK ? pdPASS : pdFAIL;
@@ -197,23 +199,43 @@ void loop()
esp_restart(); esp_restart();
} }
const bool tasK_A_rt = task_A.start();
delay(50);
const bool task_B_rt = task_B.start();
if (tasK_A_rt != true || task_B_rt != true)
{
led.setStatus(RGBled::LedStatus::ERROR);
LOG_ERROR("Unable to start realtime tasks");
} else
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);
LITTLEFSGuard fsGuard;
WebPage webPage(80, LittleFS); // Initialize webserver and Websocket WebPage webPage(80, LittleFS); // Initialize webserver and Websocket
task_A.onMessage([&webPage](ignitionBoxStatusFiltered sts){
ArduinoJson::JsonDocument doc;
doc["box_a"] = sts.toJson();
doc["box_b"] = ArduinoJson::JsonDocument();
webPage.sendWsData(doc.as<String>());
});
task_B.onMessage([&webPage](ignitionBoxStatusFiltered sts){
ArduinoJson::JsonDocument doc;
doc["box_a"] = ArduinoJson::JsonDocument();
doc["box_b"] = sts.toJson();
webPage.sendWsData(doc.as<String>());
});
task_A.enableSave(true, "ignitionA_test.csv");
task_B.enableSave(true, "ignitionB_test.csv");
uint32_t last_loop = millis(); uint32_t last_loop = millis();
//////////////// INNER LOOP ///////////////////// //////////////// INNER LOOP /////////////////////
while (running) while (running)
{ {
led.setStatus(RGBled::LedStatus::IDLE); if ((millis() - last_loop) > 2000)
delay(100);
if ((millis() - last_loop) > 1000)
{ {
clearScreen(); clearScreen();
Serial.println();
printRunningTasksMod(Serial); printRunningTasksMod(Serial);
last_loop = millis(); last_loop = millis();
} }

View File

@@ -296,20 +296,22 @@ rtIgnitionTask::rtIgnitionTask(const rtTaskParams params, const uint32_t history
m_params.rt_queue = m_queue; m_params.rt_queue = m_queue;
// create PSram history vectors // create PSram history vectors
m_history_0.resize(history_size); m_history_0 = PSHistory(history_size);
m_history_1.resize(history_size); m_history_1 = PSHistory(history_size);
// assing active and writable history // assing active and writable history
m_active_history = std::unique_ptr<PSHistory>(&m_history_0); m_active_history = std::unique_ptr<PSHistory>(&m_history_0);
m_save_history = std::unique_ptr<PSHistory>(&m_history_1); m_save_history = std::unique_ptr<PSHistory>(&m_history_1);
LOG_WARN("Starting Manager for [", m_params.name.c_str(), "]"); LOG_WARN("Starting Manager for [", m_params.name.c_str(), "]");
auto task_success = xTaskCreate( // auto task_success = pdPASS;
auto task_success = xTaskCreatePinnedToCore(
rtIgnitionTask_manager, rtIgnitionTask_manager,
(std::string("man_") + m_params.name).c_str(), (std::string("man_") + m_params.name).c_str(),
m_params.rt_stack_size, 8192,
(void *)this, (void *)this,
1, m_params.rt_priority >> 2,
&m_manager_handle); &m_manager_handle,
m_core);
if (task_success != pdPASS) if (task_success != pdPASS)
{ {
@@ -341,10 +343,12 @@ void rtIgnitionTask::run()
if (new_data == pdPASS) if (new_data == pdPASS)
{ {
m_last_data = millis();
m_manager_status = rtTaskStatus::RUNNING; m_manager_status = rtTaskStatus::RUNNING;
// if history buffer is full swap buffers and if enabled save history buffer // if history buffer is full swap buffers and if enabled save history buffer
if (m_counter_status >= m_active_history->size()) if (m_counter_status >= m_active_history->size())
{ {
LOG_DEBUG("Save for Buffer Full: ", m_counter_status);
m_counter_status = 0; m_counter_status = 0;
m_partial_save = false; // reset partial save flag on new data cycle m_partial_save = false; // reset partial save flag on new data cycle
std::swap(m_active_history, m_save_history); std::swap(m_active_history, m_save_history);
@@ -356,13 +360,21 @@ void rtIgnitionTask::run()
m_info_filtered.update(m_last_status); m_info_filtered.update(m_last_status);
(*m_active_history)[m_counter_status] = m_last_status; (*m_active_history)[m_counter_status] = m_last_status;
if (m_on_message_cb && m_counter_status % 10)
{
m_on_message_cb(m_info_filtered);
}
// update data counter // update data counter
m_counter_status++; m_counter_status++;
} }
else else
{ {
if (millis() - m_last_data > c_idle_time){ if (millis() - m_last_data > c_idle_time)
if (m_counter_status > 0 && !m_partial_save){ {
if (m_counter_status > 0 && !m_partial_save)
{
LOG_DEBUG("Save Partial: ", m_counter_status);
m_active_history->resize(m_counter_status); m_active_history->resize(m_counter_status);
saveHistory(*m_active_history, m_history_path); saveHistory(*m_active_history, m_history_path);
m_active_history->resize(m_max_history); m_active_history->resize(m_max_history);
@@ -434,13 +446,18 @@ void rtIgnitionTask::enableSave(const bool enable, const std::filesystem::path f
} }
} }
void rtIgnitionTask::onMessage(std::function<void(ignitionBoxStatusFiltered)> callaback)
{
m_on_message_cb = callaback;
}
void rtIgnitionTask::saveHistory(const rtIgnitionTask::PSHistory &history, const std::filesystem::path &file_name) void rtIgnitionTask::saveHistory(const rtIgnitionTask::PSHistory &history, const std::filesystem::path &file_name)
{ {
// Lock filesystem mutex to avoid concurrent access // Lock filesystem mutex to avoid concurrent access
std::lock_guard<std::mutex> fs_lock(m_fs_mutex); std::lock_guard<std::mutex> fs_lock(m_fs_mutex);
// Check for free space // Check for free space
if (LittleFS.totalBytes() - LittleFS.usedBytes() < history.size() * sizeof(ignitionBoxStatus) * 200) // check if at least 1MB is free for saving history if (LittleFS.totalBytes() - LittleFS.usedBytes() < history.size() * sizeof(ignitionBoxStatus)) // check if at least 1MB is free for saving history
{ {
LOG_ERROR("Not enough space in SPIFFS to save history"); LOG_ERROR("Not enough space in SPIFFS to save history");
return; return;
@@ -454,9 +471,8 @@ void rtIgnitionTask::saveHistory(const rtIgnitionTask::PSHistory &history, const
// if firt save remove old file and create new // if firt save remove old file and create new
auto save_flags = std::ios::out; auto save_flags = std::ios::out;
if (m_first_save && m_filesystem.exists(file_path.c_str())) if (m_first_save)
{ {
m_first_save = false;
save_flags |= std::ios::trunc; // overwrite existing file save_flags |= std::ios::trunc; // overwrite existing file
m_filesystem.remove(file_path.c_str()); // ensure file is removed before saving to avoid issues with appending to existing file in SPIFFS m_filesystem.remove(file_path.c_str()); // ensure file is removed before saving to avoid issues with appending to existing file in SPIFFS
LOG_INFO("Saving history to Flash, new file:", file_path.c_str()); LOG_INFO("Saving history to Flash, new file:", file_path.c_str());
@@ -477,12 +493,12 @@ void rtIgnitionTask::saveHistory(const rtIgnitionTask::PSHistory &history, const
// write csv header // write csv header
if (m_first_save) if (m_first_save)
{ {
ofs << "TS,\ ofs << "TS,EVENTS_12,DLY_12,STAT_12,V_12_1,V_12_2,V_12_3,V_12_4,IGNITION_MODE_12,"
EVENTS_12,DLY_12,STAT_12,V_12_1,V_12_2,V_12_3,V_12_4,IGNITION_MODE_12,\ << "EVENTS_34,DLY_34,STAT_34,V_34_1,V_34_2,V_34_3,V_34_4,IGNITION_MODE_34,"
EVENTS_34,DLY_34,STAT_34,V_34_1,V_34_2,V_34_3,V_34_4,IGNITION_MODE_34,\ << "ENGINE_RPM,ADC_READTIME,N_QUEUE_ERRORS"
ENGINE_RPM,ADC_READTIME,N_QUEUE_ERRORS"
<< std::endl; << std::endl;
ofs.flush(); ofs.flush();
m_first_save = false;
} }
for (const auto &entry : history) for (const auto &entry : history)

View File

@@ -14,6 +14,7 @@
#include <FS.h> #include <FS.h>
#include <LittleFS.h> #include <LittleFS.h>
#include <datasave.h> #include <datasave.h>
#include <functional>
// ISR // ISR
#include "isr.h" #include "isr.h"
@@ -111,6 +112,8 @@ public:
void enableSave(const bool enable, const std::filesystem::path filename); void enableSave(const bool enable, const std::filesystem::path filename);
void onMessage(std::function<void(ignitionBoxStatusFiltered)> callaback);
private: private:
void saveHistory(const rtIgnitionTask::PSHistory &history, const std::filesystem::path &file_name); void saveHistory(const rtIgnitionTask::PSHistory &history, const std::filesystem::path &file_name);
@@ -147,7 +150,9 @@ private:
ignitionBoxStatus m_last_status; ignitionBoxStatus m_last_status;
ignitionBoxStatusFiltered m_info_filtered; ignitionBoxStatusFiltered m_info_filtered;
static const uint32_t c_idle_time = 2000; // in mS std::function<void(ignitionBoxStatusFiltered)> m_on_message_cb = nullptr;
static const uint32_t c_idle_time = 10000; // in mS
static const uint32_t c_spark_timeout_max = 500; // uS static const uint32_t c_spark_timeout_max = 500; // uS
static const uint8_t c_adc_time = 4; // in mS static const uint8_t c_adc_time = 4; // in mS
static const uint8_t c_io_time = 2; // in mS static const uint8_t c_io_time = 2; // in mS

View File

@@ -5,25 +5,69 @@
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/portable.h" #include "freertos/portable.h"
#include "esp_heap_caps.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_partition.h"
#include "LittleFS.h"
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#define FREERTOS_TASK_NUMBER_MAX_NUM 256 // RunTime stats for how many Tasks to be stored #define FREERTOS_TASK_NUMBER_MAX_NUM 256 // RunTime stats for how many Tasks to be stored
std::string printBits(uint32_t value) { std::string printBits(uint32_t value)
{
std::string result; std::string result;
for (int i = 31; i >= 0; i--) { for (int i = 31; i >= 0; i--)
{
// ottieni il singolo bit // ottieni il singolo bit
result += ((value >> i) & 1) ? '1' : '0'; result += ((value >> i) & 1) ? '1' : '0';
// aggiungi uno spazio ogni 8 bit, tranne dopo l'ultimo // aggiungi uno spazio ogni 8 bit, tranne dopo l'ultimo
if (i % 8 == 0 && i != 0) { if (i % 8 == 0 && i != 0)
{
result += ' '; result += ' ';
} }
} }
return result; return result;
} }
// ANSI colors
#define BAR_WIDTH 30
#define COLOR_RESET "\033[0m"
#define COLOR_RED "\033[31m"
#define COLOR_GREEN "\033[32m"
#define COLOR_BLUE "\033[34m"
#define COLOR_MAGENTA "\033[35m"
#define COLOR_CYAN "\033[36m"
#define COLOR_YELLOW "\033[33m"
#define COLOR_WHITE "\033[37m"
#define COLOR_LBLUE "\033[94m"
void printBar(Print &printer, const char *label, size_t used, size_t total, const char *color)
{
float perc = total > 0 ? ((float)used / total) : 0;
int filled = perc * BAR_WIDTH;
printer.printf("%s%-12s [" COLOR_RESET, color, label);
for (int i = 0; i < BAR_WIDTH; i++)
{
if (i < filled)
printer.printf("%s#%s", color, COLOR_RESET);
else
printer.printf("-");
}
printer.printf("] %s%6.2f%%%s (%5.3f/%5.3f)MB\n",
color,
perc * 100.0,
COLOR_RESET,
(used / 1024.0f / 1024.0f),
(total / 1024.0f / 1024.0f));
}
void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t &a, const TaskStatus_t &b)> orderBy) void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t &a, const TaskStatus_t &b)> orderBy)
{ {
static const char *taskStates[] = {"Running", "Ready", "Blocked", "Suspended", "Deleted", "Invalid"}; static const char *taskStates[] = {"Running", "Ready", "Blocked", "Suspended", "Deleted", "Invalid"};
@@ -53,6 +97,68 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
ulCurrentRunTime = ulTotalRunTime - ulLastRunTime; ulCurrentRunTime = ulTotalRunTime - ulLastRunTime;
ulLastRunTime = ulTotalRunTime; ulLastRunTime = ulTotalRunTime;
// PRINT MEMORY INFO
printer.printf("\033[H");
printer.printf(COLOR_LBLUE "=================== ESP32 SYSTEM MONITOR ===================\n\n" COLOR_RESET);
// ===== HEAP =====
size_t freeHeap = esp_get_free_heap_size();
size_t totalHeap = heap_caps_get_total_size(MALLOC_CAP_DEFAULT);
printBar(printer, "HEAP", totalHeap - freeHeap, totalHeap, COLOR_GREEN);
// ===== RAM INTERNA =====
size_t freeInternal = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
size_t totalInternal = heap_caps_get_total_size(MALLOC_CAP_INTERNAL);
printBar(printer, "INTERNAL", totalInternal - freeInternal, totalInternal, COLOR_BLUE);
// ===== PSRAM =====
size_t totalPsram = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
if (totalPsram > 0)
{
size_t freePsram = heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
printBar(printer, "PSRAM", totalPsram - freePsram, totalPsram, COLOR_MAGENTA);
}
printer.printf("\n");
// ===== FLASH APP (approssimato) =====
const esp_partition_t *app_partition =
esp_partition_find_first(ESP_PARTITION_TYPE_APP,
ESP_PARTITION_SUBTYPE_APP_FACTORY,
NULL);
if (app_partition)
{
size_t totalAPP = app_partition->size; // dimensione reale partizione
size_t sketchSize = ESP.getSketchSize();
printBar(printer, "FLASH APP", sketchSize, totalAPP, COLOR_CYAN);
}
else
{
printer.printf(COLOR_YELLOW "%-12s [NOT FOUND]\n" COLOR_RESET, "FLASH APP");
}
// ===== LITTLEFS (corretto con partition table) =====
const esp_partition_t *fs_partition =
esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
ESP_PARTITION_SUBTYPE_DATA_LITTLEFS,
"littlefs");
if (fs_partition)
{
size_t totalFS = fs_partition->size; // dimensione reale partizione
size_t usedFS = LittleFS.usedBytes(); // spazio usato reale
printBar(printer, "LITTLEFS", usedFS, totalFS, COLOR_YELLOW);
}
else
{
printer.printf(COLOR_YELLOW "%-12s [NOT FOUND]\n" COLOR_RESET, "LITTLEFS");
}
// ===== MIN HEAP =====
size_t minHeap = esp_get_minimum_free_heap_size();
printer.printf("%s\nMin Heap Ever:%s %u KB\n\n", COLOR_RED, COLOR_RESET, minHeap / 1024);
// Print Runtime Information // Print Runtime Information
printer.printf("Tasks: %u, Runtime: %lus, Period: %luus\r\n", uxArraySize, ulTotalRunTime / 1000000, ulCurrentRunTime); printer.printf("Tasks: %u, Runtime: %lus, Period: %luus\r\n", uxArraySize, ulTotalRunTime / 1000000, ulCurrentRunTime);
@@ -79,4 +185,3 @@ void printRunningTasksMod(Print &printer, std::function<bool(const TaskStatus_t
} }
printer.println(); printer.println();
} }

View File

@@ -2,6 +2,7 @@
WebPage::WebPage(const uint8_t port, fs::FS &filesystem) : m_port(port), m_webserver(AsyncWebServer(port)), m_websocket(AsyncWebSocket("/ws")), m_filesystem(filesystem) WebPage::WebPage(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");
m_websocket.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client, m_websocket.onEvent([this](AsyncWebSocket *server, AsyncWebSocketClient *client,
AwsEventType type, void *arg, uint8_t *data, size_t len) AwsEventType type, void *arg, uint8_t *data, size_t len)
{ onWsEvent(server, client, type, arg, data, len); }); { onWsEvent(server, client, type, arg, data, len); });
@@ -17,6 +18,7 @@ WebPage::WebPage(const uint8_t port, fs::FS &filesystem) : m_port(port), m_webse
); );
m_webserver.begin(); m_webserver.begin();
LOG_DEBUG("Webserver Init OK");
} }
WebPage::~WebPage() WebPage::~WebPage()