Add graphing and data acquisition options

This commit is contained in:
huskee 2023-12-16 00:15:54 +02:00
parent 6f21e47efa
commit 37736012d4
5 changed files with 123 additions and 31 deletions

View file

@ -2,17 +2,42 @@
<html> <html>
<head> <head>
<title>therminator</title> <title>therminator</title>
<link rel="stylesheet" type="text/css" href="/style.css" />
</head> </head>
<body> <body>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script> <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<p class="reading">A: <span id="tempA"></span></p> <h1>/* therminator */</h1>
<p class="reading">B: <span id="tempB"></span></p> <p>last sensor update: <span id="time"></span></p>
<p>time: <span id="time"></span></p> <div id="options">
<div <div id="mv">
class="chart-container" <p>
style="position: relative; height: 40vh; width: 80vw" max data points:
> <select id="maxVals" onchange="location.reload()">
<option>15</option>
<option>20</option>
<option>30</option>
<option>50</option>
<option>100</option>
</select>
</p>
</div>
<div id="ui">
<p>
update interval (ms):
<select id="updateInterval" onchange="changeUpdateInterval()">
<option>500</option>
<option>1000</option>
<option>3000</option>
</select>
</p>
</div>
</div>
<div class="chart-container">
<h2>Channel A:</h2>
<div id="error-tempA"></div>
<canvas id="chartA"></canvas> <canvas id="chartA"></canvas>
<h2>Channel B:</h2>
<div id="error-tempB"></div>
<canvas id="chartB"></canvas> <canvas id="chartB"></canvas>
</div> </div>
<script src="script.js"></script> <script src="script.js"></script>

View file

@ -1,10 +1,34 @@
const maxVals = 15;
const canvasA = document.getElementById("chartA"); const canvasA = document.getElementById("chartA");
const canvasB = document.getElementById("chartB"); const canvasB = document.getElementById("chartB");
const maxValsSelect = document.getElementById("maxVals");
let maxVals = maxValsSelect.options[maxValsSelect.selectedIndex].text;
const options = { const options = {
suggestedMin: 0, plugins: {
suggestedMax: 50, legend: {
} labels: {
color: "rgba(250, 250, 250, 1)",
},
},
},
scales: {
y: {
grid: {
color: "rgba(250, 250, 250, 0.5)",
},
ticks: {
color: "rgba(250, 250, 250, 0.5)",
},
},
x: {
grid: {
color: "rgba(250, 250, 250, 0.5)",
},
ticks: {
color: "rgba(250, 250, 250, 0.5)",
},
},
},
};
const chartA = new Chart(canvasA, { const chartA = new Chart(canvasA, {
type: "line", type: "line",
data: { data: {
@ -81,16 +105,18 @@ function removeFirstData(chart) {
dataset.data.shift(); dataset.data.shift();
}); });
} }
function changeUpdateInterval() {
const updateSelect = document.getElementById("updateInterval");
let updateInt = updateSelect.options[updateSelect.selectedIndex].text;
websocket.send("u" + updateInt);
location.reload();
}
// Function that receives the message from the ESP32 with the readings // Function that receives the message from the ESP32 with the readings
function onMessage(event) { function onMessage(event) {
console.log(event.data); console.log(event.data);
var data = JSON.parse(event.data); var data = JSON.parse(event.data);
var keys = Object.keys(data);
for (var i = 0; i < keys.length - 1; i++) {
var key = keys[i];
document.getElementById(key).innerHTML = data[key];
}
var today = new Date(); var today = new Date();
var date = var date =
today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate(); today.getFullYear() + "-" + (today.getMonth() + 1) + "-" + today.getDate();
@ -104,6 +130,18 @@ function onMessage(event) {
if (chartB.data.labels.length > maxVals) { if (chartB.data.labels.length > maxVals) {
removeFirstData(chartB); removeFirstData(chartB);
} }
addData(chartA, dateTime, data["tempA"]); if (isNaN(data["tempA"])) {
addData(chartB, dateTime, data["tempB"]); document.getElementById("error-tempA").innerHTML =
"<h3>" + data["tempA"] + "</h3>";
} else {
document.getElementById("error-tempA").innerText = "";
}
if (isNaN(data["tempB"])) {
document.getElementById("error-tempB").innerHTML =
"<h3>" + data["tempB"] + "</h3>";
} else {
document.getElementById("error-tempB").innerText = "";
}
addData(chartA, data["time"] / 1000, data["tempA"]);
addData(chartB, data["time"] / 1000, data["tempB"]);
} }

20
data/style.css Normal file
View file

@ -0,0 +1,20 @@
@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:ital,wght@0,400;0,500;0,700;1,400;1,500;1,700&display=swap");
body {
background-color: rgb(50, 50, 50);
color: white;
font-family: "IBM Plex Mono", monospace;
white-space: nowrap;
padding: 1rem 2rem;
}
#mv, #ui, #chartA, #chartB {
display: inline-block;
}
#error-tempA, #error-tempB {
color: red !important;
}
.chart-container {
position: relative;
height: 40vh;
width: 80vw;
}

View file

@ -19,4 +19,5 @@ lib_deps =
ESPAsyncTCP ESPAsyncTCP
zeed/ESP Async WebServer zeed/ESP Async WebServer
Arduino_JSON Arduino_JSON
ESPAsyncWiFiManager
monitor_filters = esp8266_exception_decoder, colorize monitor_filters = esp8266_exception_decoder, colorize

View file

@ -9,6 +9,7 @@
#define CS_A D2 #define CS_A D2
#define CS_B D3 #define CS_B D3
Adafruit_MAX31855 thermocoupleA(CS_A); Adafruit_MAX31855 thermocoupleA(CS_A);
Adafruit_MAX31855 thermocoupleB(CS_B); Adafruit_MAX31855 thermocoupleB(CS_B);
@ -18,7 +19,7 @@ AsyncWebSocket ws("/ws");
JSONVar readings; JSONVar readings;
unsigned long int lastTime = 0; unsigned long int lastTime = 0;
unsigned long int timerDelay = 3000; unsigned long int timerDelay = 500;
String checkSensor(Adafruit_MAX31855 &sensor) { String checkSensor(Adafruit_MAX31855 &sensor) {
if (isnan(sensor.readCelsius())) { if (isnan(sensor.readCelsius())) {
uint8_t err = sensor.readError(); uint8_t err = sensor.readError();
@ -42,22 +43,29 @@ String getSensorReadings() {
return jsonString; return jsonString;
} }
void notifyClients(String sensorReadings) { void notifyClients(String text) {
ws.textAll(sensorReadings); ws.textAll(text);
} }
void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) { void handleWebSocketMessage(void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo *)arg; AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) { if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) {
// data[len] = 0; data[len] = 0;
// String message = (char*)data; String message = (char *)data;
// Check if the message is "getReadings" // Check if the message is "getReadings"
// if (strcmp((char*)data, "getReadings") == 0) { if (strcmp((char *)data, "getReadings") == 0) {
// if it is, send current sensor readings // if it is, send current sensor readings
String sensorReadings = getSensorReadings(); String sensorReadings = getSensorReadings();
Serial.print(sensorReadings); Serial.print(sensorReadings);
notifyClients(sensorReadings); notifyClients(sensorReadings);
//} }
if (message.startsWith("u")) {
String uVal = (message.substring(message.indexOf("u") + 1, message.length()));
int uInt = uVal.toInt();
timerDelay = uInt;
Serial.printf("update interval changed to %d\n", uInt);
notifyClients("update interval changed to " + uVal);
}
} }
} }