527 lines
21 KiB
TypeScript
527 lines
21 KiB
TypeScript
import {WebSocketPayload} from "../WebSocketPayload";
|
|
import {IDrink} from "../database/IDrink";
|
|
import {Modal} from "./Modal";
|
|
import {ButtonType} from "./ButtonType";
|
|
import {Pane} from "./Pane";
|
|
import {IContainer} from "../database/IContainer";
|
|
import {Setup} from "./Setup";
|
|
import * as Events from "events";
|
|
import {SensorType} from "../SensorType";
|
|
|
|
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) {
|
|
let containerDiv = document.getElementById("setupContainers") as HTMLDivElement;
|
|
containerDiv.innerHTML = "";
|
|
|
|
let containers = payload.data as IContainer[];
|
|
for (let c of containers) {
|
|
Setup.addSetupContainer();
|
|
}
|
|
|
|
let i = 0;
|
|
let list = containerDiv.getElementsByTagName("div");
|
|
for (let c of containers) {
|
|
let current = list[i] as HTMLDivElement;
|
|
let selects = current.getElementsByTagName("select");
|
|
|
|
(selects[0] as HTMLSelectElement).value = c.pumpPin.toString();
|
|
let type;
|
|
if( c.sensorType == SensorType.NONE )
|
|
type = "-1";
|
|
else if( c.sensorType == SensorType.ULTRASOUND )
|
|
type = "0";
|
|
else
|
|
type = "1";
|
|
(selects[1] as HTMLSelectElement).value = type;
|
|
(selects[2] as HTMLSelectElement).value = c.sensorPin1.toString();
|
|
(selects[3] as HTMLSelectElement).value = c.sensorPin2.toString();
|
|
(selects[4] as HTMLSelectElement).value = c.volume.toString();
|
|
let event = new Event('change', { bubbles: true });
|
|
selects[1].dispatchEvent( event );
|
|
|
|
i++;
|
|
}
|
|
|
|
}
|
|
|
|
static async openSetup() {
|
|
|
|
|
|
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();
|
|
}
|
|
} |