fetch("/isESP32")
.then((res) => res.text())
.then((textResponse) => {
let isESP32 = textResponse;
});
fetch("/int")
.then((res) => res.text())
.then((textResponse) => {
document.querySelector("#updInt").innerText = textResponse;
});
const canvasA = document.querySelector("#chartA");
const canvasB = document.querySelector("#chartB");
const chartUpdateInt = document.querySelector("#chartUpd").value;
document.querySelector("#stopRec").disabled = true;
let data;
let record = 0;
let filename;
let csvData;
let labelA, labelB;
const chartAdata = {
data: {
labels: [],
datasets: [
{
label: "Channel A temperature",
backgroundColor: "red",
borderColor: "red",
data: [],
},
],
},
};
const chartBdata = {
data: {
labels: [],
datasets: [
{
label: "Channel B temperature",
backgroundColor: "blue",
borderColor: "blue",
data: [],
},
],
},
};
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,
});
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 =
"
" + data["tempA"] + "
";
} else {
document.querySelector("#error-tempA").innerText = "";
}
if (isNaN(data["tempB"])) {
document.querySelector("#error-tempB").innerHTML =
"" + data["tempB"] + "
";
} else {
document.querySelector("#error-tempB").innerText = "";
}
addData(chartA, data["time"], data["tempA"]);
addData(chartB, data["time"], data["tempB"]);
}, 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;
csvData = ['time,"' + labelA + '","' + labelB + '"'];
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("#timeLeft");
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";
}
};