Took 1 hour 28 minutes
This commit is contained in:
Tobias Hopp 2022-11-20 18:50:10 +01:00
parent 9d839328f8
commit a4ac8d083b
8 changed files with 98 additions and 52 deletions

View File

@ -27,8 +27,6 @@ export class Settings {
this._json = JSON.parse(file.toString("utf8")); this._json = JSON.parse(file.toString("utf8"));
this._setupDone = this._json["setupDone"]; this._setupDone = this._json["setupDone"];
this._setupDone = false;
} }
public static saveSettings() { public static saveSettings() {

View File

@ -4,5 +4,6 @@ export enum WebSocketEvent {
CONTAINERS = "CONTAINERS", CONTAINERS = "CONTAINERS",
CONFIG = "CONFIG", CONFIG = "CONFIG",
TARE = "TARE", TARE = "TARE",
SETUP = "SETUP" SETUP = "SETUP",
REQUEST = "REQUEST"
} }

View File

@ -69,35 +69,30 @@ export class iTender {
log("Measuring containers..."); log("Measuring containers...");
return new Promise(async resolve => { return new Promise(async resolve => {
for (let c of (await Container.find({enabled: true}))) { for (let c of (await Container.find({}))) {
try { try {
if (!c.sensorFilledMax || c.sensorFilledMin) {
c.enabled = false;
await c.save();
continue;
}
let rand = Math.random() * 5; let rand = Math.random() * 5;
if (c.sensorType == SensorType.ULTRASOUND) { if (c.sensorType == SensorType.ULTRASOUND) {
let sensor = new HCSR04(c.sensorPin1, c.sensorPin2); let sensor = new HCSR04(c.sensorPin1, c.sensorPin2);
c.rawData = sensor.distance(); c.rawData = sensor.distance();
c.rawData = rand; c.rawData = rand;
c.filled = c.rawData * c.sensorFilledMin / 100;
} else if (c.sensorType == SensorType.LOADCELL) { } else if (c.sensorType == SensorType.LOADCELL) {
let sensor = new HX711(c.sensorPin1, c.sensorPin2); let sensor = new HX711(c.sensorPin1, c.sensorPin2);
c.rawData = sensor.measure(); c.rawData = sensor.measure();
c.rawData = rand; c.rawData = rand;
}
if (c.sensorFilledMax && c.sensorFilledMin) {
c.filled = c.rawData * c.sensorFilledMax / 100; c.filled = c.rawData * c.sensorFilledMax / 100;
} }
} catch (e) { } catch (e) {
c.filled = -1; c.filled = -1;
c.rawData = 0; c.rawData = 0;
} }
console.log(c);
await c.save(); await c.save();
} }
log("Containers measured!"); log("Containers measured!");

View File

@ -84,11 +84,11 @@ router.ws('/', async (ws, req, next) => {
} else { } else {
if (Settings.setupDone) { if (Settings.setupDone) {
iTender.setStatus(iTenderStatus.READY); iTender.setStatus(iTenderStatus.READY);
await WebSocketHandler.sendContainers();
await WebSocketHandler.sendRunningConfig(); await WebSocketHandler.sendRunningConfig();
} }
} }
await WebSocketHandler.sendContainers();
} }
} }
}); });

View File

@ -3,5 +3,6 @@ export enum Pane {
MENU = "MENU", MENU = "MENU",
SETTINGS = "SETTINGS", SETTINGS = "SETTINGS",
SETUP = "SETUP", SETUP = "SETUP",
NONE = "NONE" NONE = "NONE",
CONTAINERS = "CONTAINERS",
} }

View File

@ -30,14 +30,13 @@ export class Setup {
} }
(document.getElementById("setup_cancelBtn") as HTMLButtonElement).disabled = !payload.data["setupDone"]; (document.getElementById("setup_cancelBtn") as HTMLButtonElement).disabled = !payload.data["setupDone"];
if( !payload.data["setupDone"] ) if (!payload.data["setupDone"]) {
{
let modal = new Modal("setup", "Willkommen!"); let modal = new Modal("setup", "Willkommen!");
let txt = document.createElement("p"); let txt = document.createElement("p");
txt.innerHTML = `Dieser iTender ist noch nicht eingerichtet.<br>Um ihn zu nutzen, ist eine Grund-Konfiguration (Setup) nötig.<br><br>Das Setup lässt sich später auch jederzeit aus dem Menü erneut aufrufen.<br>Um die Einrichtung des Gerätes abzuschließen, muss mindestens ein Behälter mit Pumpe (optional auch Sensor) hinzugefügt werden.<br><br>`; txt.innerHTML = `Dieser iTender ist noch nicht eingerichtet.<br>Um ihn zu nutzen, ist eine Grund-Konfiguration (Setup) nötig.<br><br>Das Setup lässt sich später auch jederzeit aus dem Menü erneut aufrufen.<br>Um die Einrichtung des Gerätes abzuschließen, muss mindestens ein Behälter mit Pumpe (optional auch Sensor) hinzugefügt werden.<br><br>`;
modal.addContent(txt); modal.addContent(txt);
let btn = document.createElement("button"); let btn = document.createElement("button");
btn.classList.add("btn","btn-primary"); btn.classList.add("btn", "btn-primary");
btn.innerText = "Weiter"; btn.innerText = "Weiter";
btn.onclick = () => { btn.onclick = () => {
txt.innerHTML = `Auf der folgenden Seite können nun verschiedene Module eingerichtet werden.<br><br> txt.innerHTML = `Auf der folgenden Seite können nun verschiedene Module eingerichtet werden.<br><br>
@ -48,7 +47,9 @@ Hier lässt sich konfigurieren, ob die Nutzung der Remote-Bedienung erlaubt ist,
<strong>Behälter-Modul</strong><br> <strong>Behälter-Modul</strong><br>
Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>Dort müssen GPIO-Pins der Pumpe, etwaige Sensoren-Typen und Pins definiert werden.<br>Außerdem wird das Volumen eingestellt.<br><br>`; Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>Dort müssen GPIO-Pins der Pumpe, etwaige Sensoren-Typen und Pins definiert werden.<br>Außerdem wird das Volumen eingestellt.<br><br>`;
btn.innerText = "Einrichtung starten"; btn.innerText = "Einrichtung starten";
btn.onclick= () => {modal.close();} btn.onclick = () => {
modal.close();
}
} }
modal.addContent(btn); modal.addContent(btn);
modal.open(); modal.open();
@ -189,7 +190,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
let tareModal = new Modal("tare", "Einmessung Sensoren"); let tareModal = new Modal("tare", "Einmessung Sensoren");
let txt = document.createElement("p"); let txt = document.createElement("p");
txt.innerHTML = `Damit alle Sensoren korrekte Werte liefern, sollte eine Einmessung durchgeführt werden.<br> txt.innerHTML = `Damit alle Sensoren korrekte Werte liefern, sollte eine Einmessung durchgeführt werden.<br>
Während der Einmessung müssen die Behälter je nachdem geleert, gefüllt oder komplett entnommen werden.<br><br>`; Während der Einmessung müssen die Behälter einmal geleert und gefüllt werden.<br><br>`;
tareModal.addContent(txt); tareModal.addContent(txt);
tareModal.addButton(ButtonType.PRIMARY, "Später", () => { tareModal.addButton(ButtonType.PRIMARY, "Später", () => {
@ -205,7 +206,7 @@ Während der Einmessung müssen die Behälter je nachdem geleert, gefüllt oder
let txt = document.createElement("p"); let txt = document.createElement("p");
txt.innerHTML = `Messung Teil 1<br> txt.innerHTML = `Messung Teil 1<br>
Bitte alle <strong>Behälter entfernen</strong> und Sensoren freilegen.<br> Bitte den <strong>Inhalt der Behälter entfernen</strong><br>
Die Gewichtssensoren werden beim Bestätigen austariert<br><br>Zum fortfahren Tarieren drücken.<br>`; Die Gewichtssensoren werden beim Bestätigen austariert<br><br>Zum fortfahren Tarieren drücken.<br>`;
modal.addContent(txt); modal.addContent(txt);
@ -221,27 +222,12 @@ Die Gewichtssensoren werden beim Bestätigen austariert<br><br>Zum fortfahren Ta
WebWebSocketHandler.send(payload); WebWebSocketHandler.send(payload);
txt.innerHTML = `Messung Teil 2<br> txt.innerHTML = `Messung Teil 2<br>
Bitte nun alle <strong>Behälter ohne Inhalt</strong> einsetzen.<br> Bitte nun alle <strong>Behälter mit Inhalt füllen</strong> und wieder einsetzen.<br>
Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren Tarieren drücken.<br>`; Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren Tarieren drücken.<br>`;
btn.onclick = () => { btn.onclick = () => {
let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 1}); let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 1});
WebWebSocketHandler.send(payload); WebWebSocketHandler.send(payload);
txt.innerHTML = `Messung Teil 3<br>
Bitte nun alle <strong>Behälter mit vollständigem Inhalt</strong> einsetzen.<br>
Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren Tarieren drücken.<br>`;
btn.onclick = () => {
let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 2});
WebWebSocketHandler.send(payload);
payload = new WebSocketPayload(WebSocketEvent.TARE, false, {state: false});
WebWebSocketHandler.send(payload);
txt.innerHTML = `Alle Werte wurden erfolgreich gespeichert.<br>Die Einmessung kann jederzeit über die Speichern-Navigation wiederholt werden.<br><br>Das Einmessen sollte nach mehrfachem Benutzen wiederholt werden.<br>`;
btn.innerText = "Schließen";
btn.onclick = () => modal.close(); btn.onclick = () => modal.close();
}
}; };
}; };
@ -252,7 +238,7 @@ Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren T
tareModal.open(); tareModal.open();
WebWebSocketHandler.tareContainerUpdates = (payload: WebSocketPayload) => { WebWebSocketHandler.registerForEvent(WebSocketEvent.CONTAINERS, (payload: WebSocketPayload) => {
if (!ul) return; if (!ul) return;
ul.innerHTML = ""; ul.innerHTML = "";
@ -261,10 +247,10 @@ Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren T
if (c.sensorType == SensorType.NONE) continue; if (c.sensorType == SensorType.NONE) continue;
let li = document.createElement("li"); let li = document.createElement("li");
li.innerText = `Behälter ${c.slot}: ${c.rawData} [${c.sensorType}]`; li.innerText = `Behälter ${c.slot}: ${c.rawData.toFixed(3)} [${c.sensorType}]`;
ul.append(li); ul.append(li);
} }
} });
} }
public static addSetupContainer() { public static addSetupContainer() {
@ -290,7 +276,7 @@ Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren T
selectPin.append(noSel.cloneNode(true)); selectPin.append(noSel.cloneNode(true));
selectPin.selectedIndex = 0; selectPin.selectedIndex = 0;
// 3,5,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26,29,31,32,33,35,36,37,38,40 // 3,5,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26,29,31,32,33,35,36,37,38,40
const pins = [3,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26,29,31,32,33,35,36,37,38]; const pins = [3, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 35, 36, 37, 38];
for (let pin of pins) { for (let pin of pins) {
let pinEle = document.createElement("option") as HTMLOptionElement; let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + pin; pinEle.innerText = "" + pin;

View File

@ -11,6 +11,7 @@ export class WebWebSocketHandler {
private static socket: WebSocket; private static socket: WebSocket;
private static url = (window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005"; private static url = (window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005";
public static tareContainerUpdates: (payload: WebSocketPayload) => void; public static tareContainerUpdates: (payload: WebSocketPayload) => void;
private static eventRegister: { event: WebSocketEvent, fn: (payload: WebSocketPayload) => void }[] = [];
constructor() { constructor() {
@ -21,6 +22,10 @@ export class WebWebSocketHandler {
WebWebSocketHandler.socket.onmessage = this.onMessage; WebWebSocketHandler.socket.onmessage = this.onMessage;
} }
public static registerForEvent(event: WebSocketEvent, fn: (payload: WebSocketPayload) => void) {
WebWebSocketHandler.eventRegister.push({event: event, fn: fn});
}
private onMessage(msgEvent: MessageEvent) { private onMessage(msgEvent: MessageEvent) {
let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data); let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data);
if (!payload) { if (!payload) {
@ -29,6 +34,11 @@ export class WebWebSocketHandler {
} }
console.log("[WS] Received " + payload.event + " Event", payload); console.log("[WS] Received " + payload.event + " Event", payload);
for (let evReg of WebWebSocketHandler.eventRegister) {
if (evReg.event == payload.event)
evReg.fn(payload);
}
switch (payload.event) { switch (payload.event) {
case WebSocketEvent.CONFIG: { case WebSocketEvent.CONFIG: {
// Incoming WebSocketStatus // Incoming WebSocketStatus
@ -82,14 +92,6 @@ export class WebWebSocketHandler {
WebHandler.onDrinkUpdate(payload); WebHandler.onDrinkUpdate(payload);
break; break;
} }
case WebSocketEvent.CONTAINERS: {
WebHandler.onContainerUpdate(payload);
if (WebWebSocketHandler.tareContainerUpdates != undefined) {
WebWebSocketHandler.tareContainerUpdates(payload);
}
break;
}
} }
} }
@ -170,7 +172,7 @@ export class WebWebSocketHandler {
} }
public static send(payload: WebSocketPayload): Promise<void> { public static send(payload: WebSocketPayload): Promise<void> {
console.log("[WS] Sending " + payload.event + " Event",payload); console.log("[WS] Sending " + payload.event + " Event", payload);
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
if (this.socket && this.socket.readyState == 1) { if (this.socket && this.socket.readyState == 1) {

View File

@ -2,6 +2,9 @@ import {WebWebSocketHandler} from "./WebWebSocketHandler";
import {Modal} from "./Modal"; import {Modal} from "./Modal";
import {WebHandler} from "./WebHandler"; import {WebHandler} from "./WebHandler";
import {Pane} from "./Pane"; import {Pane} from "./Pane";
import {WebSocketPayload} from "../WebSocketPayload";
import {WebSocketEvent} from "../WebSocketEvent";
import {ButtonType} from "./ButtonType";
const main = document.getElementById("main"); const main = document.getElementById("main");
const time = document.getElementById("right"); const time = document.getElementById("right");
@ -23,6 +26,7 @@ document.addEventListener("DOMContentLoaded", () => {
}); });
function setupOnClickEvents() { function setupOnClickEvents() {
// Menu BTN
const menuBtn = document.getElementById("menuBtn") as HTMLButtonElement; const menuBtn = document.getElementById("menuBtn") as HTMLButtonElement;
menuBtn.disabled = true; menuBtn.disabled = true;
@ -37,6 +41,65 @@ function setupOnClickEvents() {
} }
menuBtn.onclick = doMenu; menuBtn.onclick = doMenu;
// Menu buttons
const menuContainersBtn = document.getElementById("menu_containers") as HTMLButtonElement;
const menuStatsBtn = document.getElementById("menu_stats") as HTMLButtonElement;
menuContainersBtn.onclick = () => WebHandler.openPane(Pane.CONTAINERS);
menuStatsBtn.onclick = async () => {
let statsModal = new Modal("stats", "Statistiken");
let txt = document.createElement("p");
txt.innerHTML = `Folgende Statistiken wurden erfasst.`;
statsModal.addContent(txt);
let div = document.createElement("div");
div.style.textAlign = "left";
statsModal.addContent(div);
let list = document.createElement("ul");
div.append(list);
statsModal.addContent(document.createElement("br"));
statsModal.addButton(ButtonType.PRIMARY, "Schließen", () => statsModal.close());
WebWebSocketHandler.registerForEvent(WebSocketEvent.REQUEST, (payload) => {
if (payload.data["event"] == "stats") {
let li = document.createElement("li");
li.innerText = "Cocktails ausgegeben: " + payload.data["content"]["drinks_finished"];
list.append(li);
li = document.createElement("li");
li.innerText = "Häufigster Cocktail: " + payload.data["content"]["drink_most"];
list.append(li);
li = document.createElement("li");
li.innerText = "Anzahl Ingredients: " + payload.data["content"]["count_ingredients"];
list.append(li);
li = document.createElement("li");
li.innerText = "Anzahl Cocktails: " + payload.data["content"]["count_cocktails"];
list.append(li);
}
});
let payload = new WebSocketPayload(WebSocketEvent.REQUEST, false, {type: "stats"});
await WebWebSocketHandler.send(payload);
await statsModal.open();
};
const menuSettingsBtn = document.getElementById("menu_settings") as HTMLButtonElement;
const menuSetupBtn = document.getElementById("menu_setup") as HTMLButtonElement;
menuSettingsBtn.onclick = () => WebHandler.openPane(Pane.SETTINGS);
menuSetupBtn.onclick = () => {
let payload = new WebSocketPayload(WebSocketEvent.SETUP, false, true );
WebWebSocketHandler.send(payload);
}
} }
function load() { function load() {