537 lines
13 KiB
JavaScript
537 lines
13 KiB
JavaScript
let isESP32;
|
|
fetch("/isESP32")
|
|
.then((res) => res.text())
|
|
.then((textResponse) => {
|
|
isESP32 = textResponse;
|
|
if (isESP32 == 0) {
|
|
document.querySelector("#chanGH").style.display = "none";
|
|
}
|
|
});
|
|
fetch("/int")
|
|
.then((res) => res.text())
|
|
.then((textResponse) => {
|
|
document.querySelector("#updInt").innerText = textResponse;
|
|
});
|
|
|
|
let lightbox = document.querySelector("#lightbox");
|
|
const canvasA = document.querySelector("#chartA");
|
|
const canvasB = document.querySelector("#chartB");
|
|
const canvasC = document.querySelector("#chartC");
|
|
const canvasD = document.querySelector("#chartD");
|
|
const canvasE = document.querySelector("#chartE");
|
|
const canvasF = document.querySelector("#chartF");
|
|
const canvasG = document.querySelector("#chartG");
|
|
const canvasH = document.querySelector("#chartH");
|
|
|
|
const chartUpdateInt = document.querySelector("#chartUpd").value;
|
|
document.querySelector("#stopRec").disabled = true;
|
|
let data;
|
|
let record = 0;
|
|
let filename;
|
|
let csvData = [];
|
|
let labelA, labelB, labelC, labelD, labelE, labelF, labelG, labelH;
|
|
|
|
const options = {
|
|
animation: false,
|
|
elements: {
|
|
point: {
|
|
pointStyle: false,
|
|
},
|
|
},
|
|
responsive: true,
|
|
plugins: {
|
|
legend: {
|
|
labels: {
|
|
color: "rgba(250, 250, 250, 1)",
|
|
},
|
|
},
|
|
},
|
|
scales: {
|
|
y: {
|
|
title: {
|
|
display: true,
|
|
text: "Temperature (°C)",
|
|
color: "rgb(250, 250, 250)",
|
|
},
|
|
grid: {
|
|
color: "rgba(250, 250, 250, 0.5)",
|
|
},
|
|
ticks: {
|
|
color: "rgba(250, 250, 250, 0.5)",
|
|
},
|
|
suggestedMin: 0,
|
|
suggestedMax: 50,
|
|
},
|
|
x: {
|
|
title: {
|
|
display: true,
|
|
text: "Time (s)",
|
|
color: "rgb(250, 250, 250)",
|
|
},
|
|
grid: {
|
|
color: "rgba(250, 250, 250, 0.5)",
|
|
},
|
|
ticks: {
|
|
color: "rgba(250, 250, 250, 0.5)",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
document.querySelector("#cupdInt").innerText = chartUpdateInt;
|
|
document.querySelector("#recInfo").style.display = "none";
|
|
const chartA = new Chart(canvasA, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel A temperature",
|
|
backgroundColor: "red",
|
|
borderColor: "red",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
|
|
const chartB = new Chart(canvasB, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel B temperature",
|
|
backgroundColor: "blue",
|
|
borderColor: "blue",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
|
|
const chartC = new Chart(canvasC, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel C temperature",
|
|
backgroundColor: "red",
|
|
borderColor: "red",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
|
|
const chartD = new Chart(canvasD, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel D temperature",
|
|
backgroundColor: "blue",
|
|
borderColor: "blue",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
const chartE = new Chart(canvasE, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel E temperature",
|
|
backgroundColor: "red",
|
|
borderColor: "red",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
|
|
const chartF = new Chart(canvasF, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel F temperature",
|
|
backgroundColor: "blue",
|
|
borderColor: "blue",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
const chartG = new Chart(canvasG, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel G temperature",
|
|
backgroundColor: "red",
|
|
borderColor: "red",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
|
|
const chartH = new Chart(canvasH, {
|
|
type: "line",
|
|
data: {
|
|
labels: [],
|
|
datasets: [
|
|
{
|
|
label: "Channel H temperature",
|
|
backgroundColor: "blue",
|
|
borderColor: "blue",
|
|
data: [],
|
|
},
|
|
],
|
|
},
|
|
options: options,
|
|
});
|
|
|
|
var gateway = `ws://${window.location.hostname}/ws`;
|
|
var websocket;
|
|
// Init web socket when the page loads
|
|
|
|
window.addEventListener("load", onload);
|
|
|
|
function onload(event) {
|
|
initWebSocket();
|
|
}
|
|
|
|
function getReadings() {
|
|
websocket.send("getReadings");
|
|
}
|
|
function setUpdateInterval() {
|
|
let updateInt = document.querySelector("#upd").value;
|
|
websocket.send("u" + updateInt);
|
|
location.reload();
|
|
}
|
|
|
|
function getUpdateInterval() {
|
|
var xhttp = new XMLHttpRequest();
|
|
xhttp.onreadystatechange = function () {
|
|
if (this.readyState == 4 && this.status == 200) {
|
|
document.querySelector("#upd").value = this.responseText;
|
|
}
|
|
};
|
|
xhttp.open("GET", "/int", true);
|
|
xhttp.send();
|
|
}
|
|
|
|
function initWebSocket() {
|
|
console.log("Trying to open a WebSocket connection...");
|
|
websocket = new WebSocket(gateway);
|
|
websocket.onopen = onOpen;
|
|
websocket.onclose = onClose;
|
|
websocket.onmessage = onMessage;
|
|
}
|
|
|
|
// When websocket is established, call the getReadings() function
|
|
function onOpen(event) {
|
|
console.log("Connection opened");
|
|
getReadings();
|
|
}
|
|
|
|
function onClose(event) {
|
|
console.log("Connection closed");
|
|
setTimeout(initWebSocket, 2000);
|
|
csvData.length = 0;
|
|
}
|
|
|
|
function addData(chart, label, data) {
|
|
chart.data.labels.push(label);
|
|
chart.data.datasets.forEach((dataset) => {
|
|
dataset.data.push(data);
|
|
});
|
|
chart.update();
|
|
}
|
|
|
|
function removeFirstData(chart) {
|
|
chart.data.labels.splice(0, 1);
|
|
chart.data.datasets.forEach((dataset) => {
|
|
dataset.data.shift();
|
|
});
|
|
}
|
|
|
|
// Function that receives the message from the ESP32 with the readings
|
|
function onMessage(event) {
|
|
//console.log(event.data);
|
|
data = JSON.parse(event.data);
|
|
let timestamp = new Date();
|
|
document.querySelector("#time").innerHTML = timestamp.getTime();
|
|
data["time"] = timestamp.getTime();
|
|
if (record == 1) {
|
|
csvData.push(createCSV(data));
|
|
}
|
|
}
|
|
|
|
setInterval(function () {
|
|
if (isNaN(data["tempA"])) {
|
|
document.querySelector("#error-tempA").innerHTML =
|
|
"<h3>" + data["tempA"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempA").innerText = "";
|
|
}
|
|
if (isNaN(data["tempB"])) {
|
|
document.querySelector("#error-tempB").innerHTML =
|
|
"<h3>" + data["tempB"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempB").innerText = "";
|
|
}
|
|
if (isNaN(data["tempC"])) {
|
|
document.querySelector("#error-tempC").innerHTML =
|
|
"<h3>" + data["tempC"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempC").innerText = "";
|
|
}
|
|
if (isNaN(data["tempD"])) {
|
|
document.querySelector("#error-tempD").innerHTML =
|
|
"<h3>" + data["tempD"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempD").innerText = "";
|
|
}
|
|
if (isNaN(data["tempE"])) {
|
|
document.querySelector("#error-tempE").innerHTML =
|
|
"<h3>" + data["tempE"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempE").innerText = "";
|
|
}
|
|
if (isNaN(data["tempF"])) {
|
|
document.querySelector("#error-tempF").innerHTML =
|
|
"<h3>" + data["tempF"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempF").innerText = "";
|
|
}
|
|
if (isNaN(data["tempG"])) {
|
|
document.querySelector("#error-tempG").innerHTML =
|
|
"<h3>" + data["tempG"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempG").innerText = "";
|
|
}
|
|
if (isNaN(data["tempH"])) {
|
|
document.querySelector("#error-tempH").innerHTML =
|
|
"<h3>" + data["tempH"] + "</h3>";
|
|
} else {
|
|
document.querySelector("#error-tempH").innerText = "";
|
|
}
|
|
|
|
addData(chartA, data["time"], data["tempA"]);
|
|
addData(chartB, data["time"], data["tempB"]);
|
|
addData(chartC, data["time"], data["tempC"]);
|
|
addData(chartD, data["time"], data["tempD"]);
|
|
addData(chartE, data["time"], data["tempE"]);
|
|
addData(chartF, data["time"], data["tempF"]);
|
|
addData(chartG, data["time"], data["tempG"]);
|
|
addData(chartH, data["time"], data["tempH"]);
|
|
}, chartUpdateInt);
|
|
|
|
function escapeValue(value) {
|
|
var result = "";
|
|
var escape = false;
|
|
|
|
for (var i = 0; i < value.length; ++i) {
|
|
var entry = value[i];
|
|
|
|
result += entry;
|
|
|
|
switch (entry) {
|
|
case '"':
|
|
result += '"';
|
|
case ",":
|
|
escape = true;
|
|
}
|
|
}
|
|
|
|
if (escape) return '"' + result + '"';
|
|
|
|
return result;
|
|
}
|
|
|
|
function createCSV(object) {
|
|
var body = "";
|
|
|
|
for (var column in object) {
|
|
if (object.hasOwnProperty(column)) {
|
|
if (body) body += ",";
|
|
|
|
var value = object[column];
|
|
|
|
if (value == null) continue;
|
|
|
|
body += escapeValue(value.toString());
|
|
}
|
|
}
|
|
|
|
return body;
|
|
}
|
|
|
|
function startRecording() {
|
|
let timedRec = document.querySelector("#timedRec").checked;
|
|
date = new Date();
|
|
let filedate = date.toISOString().slice(0, -5).replaceAll(":", "");
|
|
filename = "therminator-" + filedate + ".csv";
|
|
document.querySelector("#filename").innerText = filename;
|
|
labelA = document.querySelector("#labelA").value;
|
|
labelB = document.querySelector("#labelB").value;
|
|
labelC = document.querySelector("#labelC").value;
|
|
labelD = document.querySelector("#labelD").value;
|
|
labelE = document.querySelector("#labelE").value;
|
|
labelF = document.querySelector("#labelF").value;
|
|
labelG = document.querySelector("#labelG").value;
|
|
labelH = document.querySelector("#labelH").value;
|
|
if (isESP32 == 1) {
|
|
csvData = [
|
|
'time,"' +
|
|
labelA +
|
|
'","' +
|
|
labelB +
|
|
'","' +
|
|
labelC +
|
|
'","' +
|
|
labelD +
|
|
'","' +
|
|
labelE +
|
|
'","' +
|
|
labelF +
|
|
'","' +
|
|
labelG +
|
|
'","' +
|
|
labelH +
|
|
'"',
|
|
];
|
|
} else {
|
|
csvData = [
|
|
'time,"' +
|
|
labelA +
|
|
'","' +
|
|
labelB +
|
|
'","' +
|
|
labelC +
|
|
'","' +
|
|
labelD +
|
|
'","' +
|
|
labelE +
|
|
'","' +
|
|
labelF +
|
|
'"',
|
|
];
|
|
}
|
|
record = 1;
|
|
document.querySelector("#startRec").disabled = true;
|
|
document.querySelector("#stopRec").disabled = false;
|
|
document.querySelector("#recInfo").style.display = "inline-grid";
|
|
document.querySelector("#timedSettings").style.display = "none";
|
|
document.querySelector("#timedCheck").style.display = "none";
|
|
if (timedRec) {
|
|
let timer = document.querySelector("#timer").value;
|
|
if (timer == 0) {
|
|
alert("Recording time must be non-zero");
|
|
return;
|
|
}
|
|
timer = timer * 60000;
|
|
let timeleft = timer / 1000;
|
|
let disp = document.querySelector("#timeLeftCtr");
|
|
document.querySelector("#timeLeft").style.display = "inherit";
|
|
startTimer(timeleft, disp);
|
|
setTimeout(stopRecording, timer);
|
|
}
|
|
}
|
|
function startTimer(duration, display) {
|
|
var timer = duration,
|
|
minutes,
|
|
seconds;
|
|
setInterval(function () {
|
|
minutes = parseInt(timer / 60, 10);
|
|
seconds = parseInt(timer % 60, 10);
|
|
|
|
minutes = minutes < 10 ? "0" + minutes : minutes;
|
|
seconds = seconds < 10 ? "0" + seconds : seconds;
|
|
|
|
display.textContent = minutes + ":" + seconds;
|
|
|
|
if (--timer < 0) {
|
|
timer = duration;
|
|
}
|
|
}, 1000);
|
|
}
|
|
function fancyTimeFormat(e) {
|
|
const h = Math.floor(e / 3600)
|
|
.toString()
|
|
.padStart(2, "0"),
|
|
m = Math.floor((e % 3600) / 60)
|
|
.toString()
|
|
.padStart(2, "0"),
|
|
s = Math.floor(e % 60)
|
|
.toString()
|
|
.padStart(2, "0");
|
|
|
|
return h + ":" + m + ":" + s;
|
|
}
|
|
function stopRecording() {
|
|
record = 0;
|
|
let csvFile = csvData.join("\n");
|
|
const blob = new Blob([csvFile], { type: "text/csv;charset=utf-8," });
|
|
const objUrl = URL.createObjectURL(blob);
|
|
const link = document.createElement("a");
|
|
link.setAttribute("href", objUrl);
|
|
link.setAttribute("download", filename);
|
|
document.querySelector("body").append(link);
|
|
link.click();
|
|
csvData.length = 0;
|
|
document.querySelector("#startRec").disabled = false;
|
|
document.querySelector("#stopRec").disabled = true;
|
|
document.querySelector("#recInfo").style.display = "none";
|
|
document.querySelector("#timedSettings").style.display = "none";
|
|
document.querySelector("#timedCheck").style.display = "inline-block";
|
|
document.querySelector("#timedRec").checked = false;
|
|
document.querySelector("#timeLeft").style.display = "none";
|
|
}
|
|
const beforeUnloadHandler = (event) => {
|
|
// Recommended
|
|
event.preventDefault();
|
|
|
|
// Included for legacy support, e.g. Chrome/Edge < 119
|
|
event.returnValue = true;
|
|
};
|
|
|
|
onbeforeunload = function () {
|
|
if (record) {
|
|
return "You are still recording data! Are you sure you want to leave?";
|
|
}
|
|
};
|
|
|
|
document.querySelector("#timedRec").onchange = function () {
|
|
if (this.checked) {
|
|
document.querySelector("#timedSettings").style.display = "inherit";
|
|
} else {
|
|
document.querySelector("#timedSettings").style.display = "none";
|
|
}
|
|
};
|
|
|
|
function showCredits() {
|
|
lightbox.style.visibility = "visible";
|
|
lightbox.style.opacity = "1"
|
|
}
|
|
function hideCredits() {
|
|
lightbox.style.visibility = "hidden";
|
|
lightbox.style.opacity = "0"
|
|
}
|