itender/src/web/WebHandler.ts
Tobias Hopp c81713cd23 update
Took 15 hours 7 minutes
2022-11-17 00:46:19 +01:00

595 lines
24 KiB
TypeScript

import {WebSocketPayload} from "../WebSocketPayload";
import {IDrink} from "../database/IDrink";
import {Modal} from "./Modal";
import {ButtonType} from "./ButtonType";
import {Pane} from "./Pane";
import {setup} from "rpi-gpio";
export class WebHandler {
private static containers = [];
public static onDrinkUpdate(payload: WebSocketPayload) {
if (!payload.data) return;
let drinks: IDrink[] = payload.data;
const main = document.getElementById("main");
if (!main) return;
main.style.gridTemplateRows = `repeat(${Math.round(drinks.length / 3)}, calc(90%/2))`;
main.innerHTML = "";
for (let drink of drinks) {
let drinkEle = document.createElement("div");
drinkEle.classList.add("drink");
let drinkImg = document.createElement("img");
drinkImg.classList.add("thumbnail");
drinkEle.append(drinkImg);
let drinkName = document.createElement("p");
drinkName.classList.add("drinkName");
drinkEle.append(drinkName);
drinkImg.alt = "Foto von " + drink.name;
drinkImg.src = "/images/" + drink.name + ".png";
drinkName.innerText = drink.name;
/*
let ingredients = "<ul style='list-style-type: disc;'>";
for (let i of drink.ingredients) {
ingredients += "<li>" + i.amount + "ml " + i.type.name + "</li>";
}
ingredients += "</ul>"
drinkEle.onclick = () => {
let modal = new Modal("drink", drink.name);
modal.content = `<strong>Zutaten</strong><br>
${ingredients}`*/ //todo
//modal.leftCentered = true;
// modal.open();
//};
//main.append(drinkEle);
}
}
public static onContainerUpdate(payload: WebSocketPayload) {
}
static async openSetup() {
// new
this.openPane(Pane.SETUP);
let menuBtn = document.getElementById("menuBtn") as HTMLButtonElement;
let setupContainers = document.getElementById("setupContainers") as HTMLDivElement;
menuBtn.disabled = true;
const containerAddBtn = document.getElementById("containerAddBtn") as HTMLButtonElement;
containerAddBtn.onclick = () => {
let con = document.createElement("div");
let containerName = document.createElement("p");
containerName.innerText = "Behälter " + (setupContainers.getElementsByTagName("div").length + 1);
con.classList.add("setupContainer");
con.append(containerName);
let sensorTypeLabel = document.createElement("label");
sensorTypeLabel.innerText = "Art des Sensors ";
con.append(sensorTypeLabel);
let sensorType = document.createElement("select");
sensorType.classList.add("input");
let sensorTypeNone = document.createElement("option") as HTMLOptionElement;
sensorTypeNone.innerText = "Keiner";
sensorTypeNone.value = "0";
sensorType.append(sensorTypeNone);
let sensorTypeUltrasound = document.createElement("option") as HTMLOptionElement;
sensorTypeUltrasound.innerText = "Ultraschall";
sensorTypeUltrasound.value = "1";
sensorType.append(sensorTypeUltrasound);
let sensorTypeScale = document.createElement("option") as HTMLOptionElement;
sensorTypeScale.innerText = "Wägezelle";
sensorTypeScale.value = "2";
sensorType.append(sensorTypeScale);
con.append(sensorType);
con.append(document.createElement("br"));
let selectPin = document.createElement("select");
selectPin.style.display = "none";
selectPin.classList.add("input");
selectPin.style.display = "inline";
let noSel = document.createElement("option") as HTMLOptionElement;
noSel.innerText = "Bitte wählen";
noSel.value = "-1";
noSel.disabled = true;
selectPin.append(noSel.cloneNode(true));
selectPin.selectedIndex = 0;
const pins = [3, 5, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40];
for (let pin of pins) {
let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + pin;
pinEle.value = "" + pin;
selectPin.append(pinEle);
}
let pumpLabel = document.createElement("label");
pumpLabel.innerText = "Pumpen Pin";
con.append(pumpLabel);
con.append(selectPin.cloneNode(true));
con.append(document.createElement("br"));
let sensor1Label = document.createElement("label");
sensor1Label.innerText = "Sensor 1 Pin";
con.append(sensor1Label);
con.append(selectPin.cloneNode(true));
con.append(document.createElement("br"));
let sensor2Label = document.createElement("label");
sensor2Label.innerText = "Sensor 2 Pin";
con.append(sensor2Label);
con.append(selectPin.cloneNode(true));
con.append(document.createElement("br"));
let removeBtn = document.createElement("button");
removeBtn.classList.add("btn", "btn-danger");
removeBtn.onclick = () => {
con.classList.add("removeSlowly");
setTimeout(() => {
con.remove();
let i = 1;
for (let elementsByTagNameElement of setupContainers.getElementsByTagName("div")) {
let e = elementsByTagNameElement.getElementsByTagName("p")[0] as HTMLParagraphElement;
e.innerText = "Behälter " + i;
i++;
}
}, 750);
}
removeBtn.style.float = "right";
removeBtn.innerText = "Entfernen";
con.append(removeBtn);
setupContainers.append(con);
};
return;
// old
Modal.close();
let modal = new Modal("setup", "Setup 1/2");
let containers: { container: HTMLDivElement, slot: number, pumpPin: HTMLSelectElement, sensorType: HTMLSelectElement, sensorPin1: HTMLSelectElement, sensorPin2: HTMLSelectElement, volume: HTMLSelectElement }[] = [];
let onchange = () => {
let containerEle = document.getElementById("setup_containers") as HTMLDivElement;
let containerNumber = document.getElementById("setup_slots") as HTMLInputElement;
if (!containerEle || !containerNumber) return;
let i = 1;
let oldElements = containerEle.getElementsByTagName("div");
for (let e of oldElements) {
if (i > containerNumber.valueAsNumber) {
e.remove();
containers.pop();
}
i++;
}
for (let i = containerEle.getElementsByTagName("div").length; i < containerNumber.valueAsNumber; i++) {
let con = document.createElement("div");
let thisContainer = {};
thisContainer["container"] = con;
con.classList.add("setupContainer");
let containerName = document.createElement("p");
containerName.innerText = "Container " + (i + 1);
thisContainer["slot"] = i + 1;
con.append(containerName);
let sensorTypeLabel = document.createElement("label");
sensorTypeLabel.innerText = "Art des Sensors ";
con.append(sensorTypeLabel);
let sensorType = document.createElement("select");
sensorType.classList.add("input");
let sensorTypeNone = document.createElement("option") as HTMLOptionElement;
sensorTypeNone.innerText = "Keiner";
sensorTypeNone.value = "0";
sensorType.append(sensorTypeNone);
let sensorTypeUltrasound = document.createElement("option") as HTMLOptionElement;
sensorTypeUltrasound.innerText = "Ultraschall";
sensorTypeUltrasound.value = "1";
sensorType.append(sensorTypeUltrasound);
let sensorTypeScale = document.createElement("option") as HTMLOptionElement;
sensorTypeScale.innerText = "Wägezelle";
sensorTypeScale.value = "2";
sensorType.append(sensorTypeScale);
con.append(sensorType);
thisContainer["sensorType"] = sensorType;
con.append(document.createElement("br"));
let changeWhenTypeOfSensor: HTMLElement[] = [];
let list = ["Pumpen Port ", "Sensor 1 ", "Sensor 2 "];
for (let t of list) {
let labelElement = document.createElement("label");
labelElement.innerText = t;
changeWhenTypeOfSensor.push(labelElement);
con.append(labelElement);
let selectElement = document.createElement("select");
labelElement.style.display = "none";
selectElement.style.display = "none";
selectElement.classList.add("input");
if (t == "Sensor 1 ") {
thisContainer["sensorPin1"] = selectElement;
} else if (t == "Sensor 2 ") {
thisContainer["sensorPin2"] = selectElement;
} else {
thisContainer["pumpPin"] = selectElement;
labelElement.style.display = "inline";
selectElement.style.display = "inline";
}
let noSel = document.createElement("option") as HTMLOptionElement;
noSel.innerText = "Bitte wählen";
noSel.value = "-1";
noSel.disabled = true;
selectElement.append(noSel); //loveyou
selectElement.selectedIndex = 0;
const pins = [3, 5, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40];
for (let pin of pins) {
let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + pin;
pinEle.value = "" + pin;
selectElement.append(pinEle);
}
con.append(selectElement);
let br = document.createElement("br");
con.append(br);
}
sensorType.onchange = () => {
// 0 => ultrasound; 1 => scale
if (sensorType.value == "1") {
thisContainer["sensorPin1"].style.display = "inline";
thisContainer["sensorPin2"].style.display = "inline";
changeWhenTypeOfSensor[1].style.display = "inline";
changeWhenTypeOfSensor[2].style.display = "inline";
changeWhenTypeOfSensor[1].innerText = "Trigger Pin ";
changeWhenTypeOfSensor[2].innerText = "Echo Pin ";
} else if (sensorType.value == "2") {
thisContainer["sensorPin1"].style.display = "inline";
thisContainer["sensorPin2"].style.display = "inline";
changeWhenTypeOfSensor[1].style.display = "inline";
changeWhenTypeOfSensor[2].style.display = "inline";
changeWhenTypeOfSensor[1].innerText = "Clock Pin ";
changeWhenTypeOfSensor[2].innerText = "Data Pin ";
} else {
thisContainer["sensorPin1"].style.display = "none";
thisContainer["sensorPin2"].style.display = "none";
changeWhenTypeOfSensor[1].style.display = "none";
changeWhenTypeOfSensor[2].style.display = "none";
changeWhenTypeOfSensor[1].innerText = "Sensor 1 ";
changeWhenTypeOfSensor[2].innerText = "Sensor 2 ";
}
};
let labelElement = document.createElement("label");
labelElement.innerText = "Gesamtvolumen (ml) ";
con.append(labelElement);
let selectElement = document.createElement("select");
selectElement.classList.add("input");
const mls = [50, 100, 200, 250, 300, 330, 500, 750, 1000, 1250, 1500, 2000, 2500, 5000, 10000];
for (let ml of mls) {
let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + ml;
pinEle.value = "" + ml;
selectElement.append(pinEle);
thisContainer["volume"] = selectElement;
}
selectElement.selectedIndex = 7;
con.append(selectElement);
let br = document.createElement("br");
con.append(br);
containerEle.append(con);
let cast = thisContainer as { container: HTMLDivElement, slot: number, pumpPin: HTMLSelectElement, sensorType: HTMLSelectElement, sensorPin1: HTMLSelectElement, sensorPin2: HTMLSelectElement, volume: HTMLSelectElement };
containers.push(cast);
console.log(cast);
}
};
let div1 = document.createElement("div");
div1.style.marginBottom = "2%";
modal.addContent(div1);
let labelElement = document.createElement("label");
labelElement.innerText = "Anzahl Slots";
div1.append(labelElement);
let numberInputElement = document.createElement("input") as HTMLInputElement;
numberInputElement.type = "number";
numberInputElement.id = "setup_slots";
numberInputElement.classList.add("input");
numberInputElement.style.width = "20%;"
numberInputElement.value = "0";
numberInputElement.min = "0";
numberInputElement.max = "30";
numberInputElement.onchange = () => {
onchange();
};
div1.append(numberInputElement);
let divContainers = document.createElement("div");
divContainers.id = "setup_containers";
modal.addContent(divContainers);
let status = document.createElement("p");
status.style.color = "black";
status.innerHTML = "Drücke 'Weiter' zum Speichern";
modal.addContent(status);
modal.addButton(ButtonType.SUCCESS, "Weiter", () => {
status.innerHTML = "...";
status.style.color = "gray";
if (numberInputElement.valueAsNumber < 0 || numberInputElement.valueAsNumber > 30) {
numberInputElement.value = "0";
status.style.color = "black";
status.innerHTML = "Automatische Änderungen überprüfen!";
return;
}
// Check
if (numberInputElement.valueAsNumber != containers.length) {
onchange();
status.style.color = "black";
status.innerHTML = "Automatische Änderungen überprüfen!";
return;
}
if (containers.length == 0) {
status.style.color = "red";
status.innerHTML = "Es muss mindestens ein Container hinzugefügt werden!";
return;
}
let newContainers: { slot: number, pumpPin: number, sensorPin1: number, sensorPin2: number, volume: number }[] = [];
let ok = true;
for (let c of containers) {
for (let c2 of containers) {
if (c.slot == c.slot) continue;
let pins = [c.sensorPin1.value, c.sensorPin2.value, c.pumpPin.value, c2.sensorPin1.value, c2.sensorPin2.value, c2.pumpPin.value];
let i = 0;
for (let pin of pins) {
let j = 0;
if (pin == "-1") {
console.log("Skip ", pin);
continue;
}
for (let pin2 of pins) {
// Wenn index derselbe ist, ignorieren
if (j == i) {
console.log("Index skip ", pin);
continue;
}
if (pin2 == "-1") {
console.log("Skip ", pin);
continue;
}
if (pin == pin2) {
console.log("Pin same error", pin, pin2, c, c2)
ok = false;
c.container.classList.add("error");
c2.container.classList.add("error");
setTimeout(() => {
c.container.classList.remove("error");
c2.container.classList.remove("error");
}, 2000);
break;
}
j++;
}
i++;
if (!ok) break;
}
if (!ok) break;
/*console.log(c, c2);
console.log(c.sensorPin2.value == c2.sensorPin2.value);
if (
c.pumpPin.value == c2.pumpPin.value ||
(c.sensorType.value != "0" && (
(c.sensorPin1.value == c2.sensorPin1.value)
|| (c.sensorPin2.value == c2.sensorPin2.value)
|| (c.sensorPin1.value == c2.sensorPin2.value)
|| (c.sensorPin2.value == c2.sensorPin1.value)))
) {
console.log("Check not ok")
ok = false;
c.container.classList.add("error");
c2.container.classList.add("error");
setTimeout(() => {
c.container.classList.remove("error");
c2.container.classList.remove("error");
}, 2000);
break;
}*/
}
if (!ok) break;
if (c.pumpPin.value == "-1" || (c.sensorType.value != "0" && (c.sensorPin1.value == "-1" || c.sensorPin2.value == "-1"))) {
console.log("Local check invalid", c);
ok = false;
c.container.classList.add("error");
setTimeout(() => {
c.container.classList.remove("error");
}, 1000);
}
let pins = [c.sensorPin1.value, c.sensorPin2.value, c.pumpPin.value];
let i = 0;
for (let pin of pins) {
let j = 0;
if (pin == "-1") {
console.log("Skip ", pin);
continue;
}
for (let pin2 of pins) {
// Wenn index derselbe ist, ignorieren
if (j == i) {
console.log("Index skip ", pin);
continue;
}
if (pin2 == "-1") {
console.log("Skip ", pin);
continue;
}
if (pin == pin2) {
console.log("Pin same error", pin, pin2, c)
ok = false;
c.container.classList.add("error");
setTimeout(() => {
c.container.classList.remove("error");
}, 2000);
break;
}
j++;
}
i++;
}
/*if (c.pumpPin.value == c.sensorPin1.value || c.pumpPin.value == c.sensorPin2.value || c.sensorPin1.value == c.sensorPin2.value) {
ok = false;
c.container.classList.add("error");
setTimeout(() => {
c.container.classList.remove("error");
}, 1000);
break;
}*/
newContainers.push({
slot: c.slot,
sensorPin1: parseInt(c.sensorPin1.value),
sensorPin2: parseInt(c.sensorPin2.value),
pumpPin: parseInt(c.pumpPin.value),
volume: parseInt(c.volume.value)
});
}
if (!ok) {
status.style.color = "red";
status.innerHTML = "Problem erkannt<br>Bitte überprüfen, ob alle benötigten Felder gesetzt sind<br>und ob Pins nicht mehrfach belegt sind!"
return;
}
// todo Hier konfiguration an Server senden und speichern
// zurück und hinsenden mittels function die hier in der WebHandler.ts gespeichert wird maybe?
status.style.color = "green";
status.innerHTML = "Konfiguration gespeichert!";
let tareModal = new Modal("setup", "Setup 2/2");
let container = document.createElement("div");
tareModal.addContent(container);
let txt = document.createElement("p");
txt.innerHTML = `Um das Setup abzuschließen, müssen die Sensoren eingestellt werden.<br>
Bitte zunächst jegliche Behälter von/unter den Sensoren entfernen.<br>Zum fortfahren "Messen"-Schaltfläche berühren.<br>`;
tareModal.addContent(txt);
let btn = tareModal.addButton(ButtonType.SUCCESS, "Messen", () => {
txt.innerHTML = "<strong>Messung läuft...</strong><br><span style='text-decoration: underline'>Gerät nicht berühren!</span><br><div class=\"lds-ellipsis\">\n" +
" <div></div><div></div><div></div><div></div>\n" +
"</div>";
btn.disabled = true;
btn.innerText = "Bitte warten";
});
// todo send messung to server to start
tareModal.open();
});
//await modal.open();
let setupNumber = document.getElementById("setup_slots") as HTMLInputElement;
setupNumber.focus();
}
public static openPane(pane: Pane): void {
let mainPanel = document.getElementById("main") as HTMLDivElement;
let setupPanel = document.getElementById("setup") as HTMLDivElement;
let menuPanel = document.getElementById("menu") as HTMLDivElement;
let settingsPanel = document.getElementById("settings") as HTMLDivElement;
mainPanel.classList.add("hiddenPane");
setupPanel.classList.add("hiddenPane");
menuPanel.classList.add("hiddenPane");
settingsPanel.classList.add("hiddenPane");
switch (pane) {
case Pane.MAIN: {
mainPanel.classList.remove("hiddenPane");
break;
}
case Pane.MENU: {
menuPanel.classList.remove("hiddenPane");
break;
}
case Pane.SETUP: {
setupPanel.classList.remove("hiddenPane");
break;
}
case Pane.SETTINGS: {
settingsPanel.classList.remove("hiddenPane");
break;
}
}
let title = document.getElementById("title") as HTMLTitleElement;
title.innerText = pane.toString();
}
}