updated and fixed charts

This commit is contained in:
Emanuele Trabattoni
2026-04-13 10:26:55 +02:00
parent f8c3c69e80
commit 212b37c95f
7 changed files with 132 additions and 65 deletions

View File

@@ -185,11 +185,17 @@
<!-- TAB 2 (grafico) -->
<div id="tab2" class="tab-content">
<canvas id="chart" height="100"></canvas>
<div class="chart-container">
<h3>Box A</h3>
<canvas id="chartA" height="100"></canvas>
</div>
<div class="chart-container">
<h3>Box B</h3>
<canvas id="chartB" height="100"></canvas>
</div>
</div>
<script src="chart.js"></script>
<script src="script.js"></script>
</body>
<div class="upload-section">
@@ -200,7 +206,7 @@
<div id="uploadStatus" class="upload-status">No file uploaded yet.</div>
</div>
<script src="chart.js"></script>
<script src="script.js"></script>
</body>
</html>

View File

@@ -3,16 +3,23 @@ let lastMessageTimestamp = 0;
const IDLE_THRESHOLD_MS = 1000;
const loadingIndicator = document.getElementById("loadingIndicator");
let chart;
let chartData = {
let chartA, chartB;
let dataA = {
labels: [],
datasets: [
{ label: "BoxA RPM", data: [] },
{ label: "BoxB RPM", data: [] },
{ label: "Coils12A Delay", data: [] },
{ label: "Coils34A Delay", data: [] },
{ label: "Coils12B Delay", data: [] },
{ label: "Coils34B Delay", data: [] }
{ label: "RPM", data: [] },
{ label: "Coils12 Delay", data: [] },
{ label: "Coils34 Delay", data: [] }
]
};
let dataB = {
labels: [],
datasets: [
{ label: "RPM", data: [] },
{ label: "Coils12 Delay", data: [] },
{ label: "Coils34 Delay", data: [] }
]
};
@@ -64,7 +71,7 @@ function connectWS() {
lastMessageTimestamp = Date.now();
setLoadingIndicator(false);
updateChart(data)
updateCharts(data)
// Update Box_A
if (data.box_a) {
@@ -138,42 +145,49 @@ function connectWS() {
};
}
function updateChart(data) {
const time = new Date().toLocaleTimeString();
function updateCharts(data) {
chartData.labels.push(time);
const t = new Date().toLocaleTimeString();
// ===== BOX A =====
dataA.labels.push(t);
if (data.box_a) {
const boxA = data.box_a;
const coils12A = boxA.coils12 || {};
const coils34A = boxA.coils34 || {};
chartData.datasets[0].data.push(boxA.eng_rpm / 10);
chartData.datasets[2].data.push(coils12A.spark_delay);
chartData.datasets[3].data.push(coils34A.spark_delay);
chartData.datasets[1].data.push(0);
chartData.datasets[4].data.push(0);
chartData.datasets[5].data.push(0);
dataA.datasets[0].data.push(data.box_a.eng_rpm / 10);
dataA.datasets[1].data.push(data.box_a.coils12.spark_delay);
dataA.datasets[2].data.push(data.box_a.coils34.spark_delay);
} else {
dataA.datasets[0].data.push(undefined);
dataA.datasets[1].data.push(undefined);
dataA.datasets[2].data.push(undefined);
}
// ===== BOX B =====
dataB.labels.push(t);
if (data.box_b) {
const boxB = data.box_b;
const coils12B = boxB.coils12 || {};
const coils34B = boxB.coils34 || {};
chartData.datasets[1].data.push(boxB.eng_rpm / 10);
chartData.datasets[4].data.push(coils12B.spark_delay);
chartData.datasets[5].data.push(coils34B.spark_delay);
chartData.datasets[0].data.push(0);
chartData.datasets[2].data.push(0);
chartData.datasets[3].data.push(0);
dataB.datasets[0].data.push(data.box_b.eng_rpm / 10);
dataB.datasets[1].data.push(data.box_b.coils12.spark_delay);
dataB.datasets[2].data.push(data.box_b.coils34.spark_delay);
} else {
dataB.datasets[0].data.push(undefined);
dataB.datasets[1].data.push(undefined);
dataB.datasets[2].data.push(undefined);
}
// limite punti (tipo buffer)
if (chartData.labels.length > 100) {
chartData.labels.shift();
chartData.datasets.forEach(d => d.data.shift());
// limite buffer
const maxPoints = 100;
if (dataA.labels.length > maxPoints) {
dataA.labels.shift();
dataA.datasets.forEach(d => d.data.shift());
}
chart.update();
if (dataB.labels.length > maxPoints) {
dataB.labels.shift();
dataB.datasets.forEach(d => d.data.shift());
}
chartA.update();
chartB.update();
}
function start() {
@@ -232,12 +246,29 @@ function openTab(tabId) {
event.target.classList.add('active');
}
function initChart() {
const ctx = document.getElementById('chart').getContext('2d');
function initCharts() {
const ctxA = document.getElementById('chartA').getContext('2d');
const ctxB = document.getElementById('chartB').getContext('2d');
chart = new Chart(ctx, {
chartA = new Chart(ctxA, {
type: 'line',
data: chartData,
data: dataA,
options: {
animation: false,
responsive: true,
scales: {
x: {
display: true
},
y: {
beginAtZero: true
}
}
}
});
chartB = new Chart(ctxB, {
type: 'line',
data: dataB,
options: {
animation: false,
responsive: true,
@@ -254,7 +285,7 @@ function initChart() {
}
window.onload = () => {
initChart();
initCharts();
};
setInterval(updateLoadingState, 200);

View File

@@ -248,3 +248,12 @@ span {
.tab-content.active {
display: block;
}
.chart-container {
max-width: 1000px;
margin: 20px auto;
background: white;
padding: 20px;
border-radius: 6px;
box-shadow: 0 1px 3px rgba(0,0,0,0.08);
}

View File

@@ -52,7 +52,7 @@ void setup()
IPAddress gateway(10, 11, 12, 1);
IPAddress subnet(255, 255, 255, 0);
WiFi.softAPConfig(local_IP, gateway, subnet);
WiFi.setTxPower(WIFI_POWER_5dBm); // reduce wifi power
WiFi.setTxPower(WIFI_POWER_13dBm); // reduce wifi power
if (WiFi.softAP(WIFI_SSID, WIFI_PASSWORD))
{
LOG_INFO("WiFi AP Mode Started");
@@ -184,7 +184,7 @@ void loop()
.rt_queue = nullptr,
.dev = dev};
auto task_A = rtIgnitionTask(taskA_params, 4096, 256, CORE_1, fs_mutex);
auto task_A = rtIgnitionTask(taskA_params, 4096, 256, CORE_0, fs_mutex);
delay(50);
auto task_B = rtIgnitionTask(taskB_params, 4096, 256, CORE_1, fs_mutex);
@@ -211,34 +211,38 @@ void loop()
led.setStatus(RGBled::LedStatus::OK);
AstroWebServer 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>());
ArduinoJson::JsonDocument json_data;
bool data_a, data_b;
task_A.onMessage([&webPage, &json_data, &data_a](ignitionBoxStatusFiltered sts){
json_data["box_a"] = sts.toJson();
data_a = true;
});
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_B.onMessage([&webPage, &json_data, &data_b](ignitionBoxStatusFiltered sts){
json_data["box_b"] = sts.toJson();
data_b = true;
});
task_A.enableSave(true, "ignitionA_test.csv");
task_B.enableSave(true, "ignitionB_test.csv");
// task_A.enableSave(true, "ignitionA_test.csv");
// task_B.enableSave(true, "ignitionB_test.csv");
uint32_t last_loop = millis();
uint32_t monitor_loop = millis();
uint32_t data_loop = monitor_loop;
//////////////// INNER LOOP /////////////////////
while (running)
{
if ((millis() - last_loop) > 2000)
uint32_t this_loop = millis();
if (this_loop - monitor_loop > 2000)
{
clearScreen();
printRunningTasksMod(Serial);
delay(100);
last_loop = millis();
monitor_loop = millis();
}
if ((data_a && data_b) || (this_loop - data_loop > 500)) {
webPage.sendWsData(json_data.as<String>());
json_data.clear();
data_a = data_b = false;
data_loop = millis();
}
} //////////////// INNER LOOP /////////////////////

View File

@@ -360,7 +360,7 @@ void rtIgnitionTask::run()
m_info_filtered.update(m_last_status);
(*m_active_history)[m_counter_status] = m_last_status;
if (m_on_message_cb && m_counter_status % 10)
if (m_on_message_cb && m_counter_status % 10 == 0)
{
m_on_message_cb(m_info_filtered);
}

View File

@@ -1,10 +1,19 @@
#include <webserver.h>
#include <ArduinoJson.h>
static const std::map<const std::string, AstroWebServer::c_commandEnum> s_webserverCommands = {
static std::map<const std::string, AstroWebServer::c_commandEnum> s_webserverCommands = {
{"setTime", AstroWebServer::SET_TIME},
};
void on_ping(TimerHandle_t xTimer)
{
if (!xTimer)
return;
auto ws = (AsyncWebSocket *)pvTimerGetTimerID(xTimer);
ws->pingAll();
ws->cleanupClients();
}
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");
@@ -20,11 +29,15 @@ AstroWebServer::AstroWebServer(const uint8_t port, fs::FS &filesystem) : m_port(
{ onUploadHandler(request, filename, index, data, len, final); });
m_webserver.begin();
m_websocket.enable(true);
m_pingTimer = xTimerCreate("wsPingTimer", pdMS_TO_TICKS(2000), pdTRUE, (void *)&m_websocket, on_ping);
LOG_DEBUG("Webserver Init OK");
}
AstroWebServer::~AstroWebServer()
{
xTimerDelete(m_pingTimer, pdMS_TO_TICKS(10));
m_webserver.removeHandler(&m_websocket);
m_webserver.end();
}
@@ -47,6 +60,9 @@ void AstroWebServer::onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *cli
case WS_EVT_DISCONNECT:
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] DISCONNECTED");
break;
case WS_EVT_PONG:
LOG_DEBUG("WS client IP[", client->remoteIP().toString().c_str(), "]-ID[", client->id(), "] PONG");
break;
case WS_EVT_DATA:
{
AwsFrameInfo *info = (AwsFrameInfo *)arg;

View File

@@ -38,6 +38,7 @@ private:
AsyncWebSocket m_websocket;
bool m_uploadFailed = false;
fs::File m_uploadFile;
TimerHandle_t m_pingTimer = NULL;
public:
enum c_commandEnum