Add graphing and data acquisition options
This commit is contained in:
parent
6f21e47efa
commit
37736012d4
|
@ -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>
|
||||||
|
|
|
@ -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
20
data/style.css
Normal 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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
32
src/main.cpp
32
src/main.cpp
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue