diff --git a/ToDo.md b/ToDo.md index 1348114..24dba1b 100644 --- a/ToDo.md +++ b/ToDo.md @@ -28,4 +28,5 @@ - [ ] Bei Container erstellung kann optional "Arduino Proxy" angewählt werden - Danach werden die Daten dieses Containers über den Arduino bezogen - [ ] Behälter Menü neu designen -- [ ] In den ganzen messfn checken ob überhaupt eingestellt ist, den proxy zu nutzen \ No newline at end of file +- [ ] In den ganzen messFn checken ob überhaupt eingestellt ist, den proxy zu nutzen +- [ ] Slot mit in Container senden nehmen \ No newline at end of file diff --git a/public/stylesheets/setup.css b/public/stylesheets/setup.css index 1db1fe2..43136f4 100644 --- a/public/stylesheets/setup.css +++ b/public/stylesheets/setup.css @@ -95,4 +95,4 @@ #setupContainers .setupContainer select { margin-bottom: 2%; -} \ No newline at end of file +} diff --git a/src/ArduinoProxy.ts b/src/ArduinoProxy.ts index 438ac4c..b4fc67b 100644 --- a/src/ArduinoProxy.ts +++ b/src/ArduinoProxy.ts @@ -37,7 +37,7 @@ export class ArduinoProxy { return ele.manufacturer == "Arduino"; }); if (!arduino) { - return reject("No arduino found"); + return reject("No arduino found. Is it plugged in?"); } // @ts-ignore @@ -51,7 +51,7 @@ export class ArduinoProxy { if (err) { log("Error whilst connecting to proxy (open serial-connection)"); log(err.name + "\n" + err.message + "\n" + err.stack); - return reject(err.name); + return reject("Could not open serial connection to arduino"); } // @ts-ignore diff --git a/src/WebSocketHandler.ts b/src/WebSocketHandler.ts index ec3bf3a..b1cc46e 100644 --- a/src/WebSocketHandler.ts +++ b/src/WebSocketHandler.ts @@ -28,6 +28,7 @@ export class WebSocketHandler { try { if (this.ws && this.ws.readyState == 1) { log("Sending " + payload.event); + await this.ws.send(payload.toString()); resolve(); } @@ -38,7 +39,8 @@ export class WebSocketHandler { } public static answerRequest(type: RequestType, content: any) { - WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.RESPONSE, {type: type, content: content})); + + WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.RESPONSE, {type: type, data: content})); log("Answered " + type + " request"); } diff --git a/src/database/Database.ts b/src/database/Database.ts index 10f3a19..5e0ce28 100644 --- a/src/database/Database.ts +++ b/src/database/Database.ts @@ -3,6 +3,7 @@ import debug from "debug"; import Ingredient from "./Ingredient"; import Drink from "./Drink"; import Container from "./Container"; +import mongoose from "mongoose"; // create a namespace for logging const log = debug("itender:server"); @@ -13,6 +14,7 @@ export class Database { return new Promise(async (resolve, reject) => { try { //connect to mongodb using mongoose + mongoose.set("strictQuery", false); await Mongoose.connect("mongodb://127.0.0.1:27017/iTender?retryWrites=true"); log("Connected to Database"); // Preload the schema for Ingredient, Drink and Container diff --git a/src/routes/ws/websocketRoute.ts b/src/routes/ws/websocketRoute.ts index 8480f97..75c4cd2 100644 --- a/src/routes/ws/websocketRoute.ts +++ b/src/routes/ws/websocketRoute.ts @@ -13,6 +13,7 @@ import {IJob} from "../../database/IJob"; import {SensorHelper} from "../../SensorHelper"; import {IContainer} from "../../database/IContainer"; import {Mixer} from "../../Mixer"; +import {ArduinoProxy} from "../../ArduinoProxy"; const express = require('express'); const router = express.Router(); @@ -168,32 +169,44 @@ router.ws('/', async (ws, req, next) => { "ambient_color": string } - await SensorHelper.clearAllRawMeasurements(); - let content: { error: boolean, msg: string } = { - error: false, - msg: "" + let content: { success: boolean, msg: string } = { + success: true, + msg: "Prüfung erfolgreich." }; // Check config /// Check Proxy - if (Settings.get("arduino_proxy_enabled") == true) { - + if (conf["arduino_proxy_enabled"]) { + try { + await ArduinoProxy.connect(); + } catch (e) { + content.success = false; + content.msg = "Bei der Kommunikation mit dem Arduino Proxy ist ein Fehler aufgetreten.
Technische Details: " + e; + return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content); + } } // Check measurements - await SensorHelper.measureAllRaw(); + try { + await SensorHelper.measureAllRaw(); + } catch (e) { + content.success = false; + content.msg = e + "
Überprüfe die Einstellungen der Sensoren-Pins."; + return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content); + } + for (let c of await Container.find()) { if (c.sensorType != SensorType.NONE && c.rawData == -1) { - content.error = true; + content.success = false; content.msg = "Container " + (c.slot + 1) + " weist Fehler im Sensor auf.
Überprüfe die Einstellungen der Sensoren-Pins."; return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content); } } - + return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content); break; } case RequestType.TARE: { @@ -208,6 +221,8 @@ router.ws('/', async (ws, req, next) => { } } + let timeouts: NodeJS.Timer[] = []; + async function measureAndSafe() { try { await SensorHelper.measureAllRaw(); @@ -220,13 +235,15 @@ router.ws('/', async (ws, req, next) => { // { success: boolean, msg: string } WebSocketHandler.answerRequest(type, {success: false, msg: e}); success = false; + for (let t of timeouts) + clearTimeout(t); } } - setTimeout(measureAndSafe, 500); - setTimeout(measureAndSafe, 1000); - setTimeout(measureAndSafe, 2000); - setTimeout(measureAndSafe, 3000); + timeouts.push(setTimeout(measureAndSafe, 500)); + timeouts.push(setTimeout(measureAndSafe, 1000)); + timeouts.push(setTimeout(measureAndSafe, 2000)); + timeouts.push(setTimeout(measureAndSafe, 3000)); setTimeout(async () => { if (success) { diff --git a/src/web/Containers.ts b/src/web/Containers.ts index e9fcc45..01fd1b0 100644 --- a/src/web/Containers.ts +++ b/src/web/Containers.ts @@ -111,7 +111,7 @@ export class Containers { WebWebSocketHandler.request(RequestType.CONTAINERS).then((payload) => { - for (let container of (payload.data["content"] as IContainer[])) { + for (let container of (payload.data as IContainer[])) { containerVolumes[container._id] = container.volume; let option = document.createElement("option"); option.value = container._id; @@ -119,10 +119,10 @@ export class Containers { selectContainer.append(option); containers[container._id] = container; } - //containers = payload.data["content"] as IContainer[]; + //containers = payload.data as IContainer[]; }); WebWebSocketHandler.request(RequestType.INGREDIENTS).then((payload) => { - for (let ingredient of (payload.data["content"] as IIngredient[])) { + for (let ingredient of (payload.data as IIngredient[])) { let option = document.createElement("option"); option.value = ingredient._id; option.innerText = ingredient.name; diff --git a/src/web/Fill.ts b/src/web/Fill.ts index e750927..0fdb8f1 100644 --- a/src/web/Fill.ts +++ b/src/web/Fill.ts @@ -64,7 +64,7 @@ export class Fill { modal.open().then(() => { WebWebSocketHandler.request(RequestType.JOB).then((payload) => { let minus = 0; - let job = payload.data.content as IJob; + let job = payload.data as IJob; ml.innerText = Math.floor((job.completeAmount / job.estimatedTime) * minus) + "ml"; waterAnimDiv.style.setProperty("--fillTime", job.estimatedTime + "s"); waterAnimDiv.style.backgroundImage = `url("/images/${job.drink._id}.png")`; diff --git a/src/web/Setup.ts b/src/web/Setup.ts index d45c737..49430c2 100644 --- a/src/web/Setup.ts +++ b/src/web/Setup.ts @@ -29,6 +29,22 @@ export class Setup { const proxyCheckbox = document.getElementById("proxyCheckbox") as HTMLInputElement; proxyCheckbox.checked = !!payload.data["arduino_proxy_enabled"]; + this.usingProxy = proxyCheckbox.checked; + proxyCheckbox.onchange = () => { + this.usingProxy = proxyCheckbox.checked; + for (let checkbox of this.arduinoProxyCheckboxes) { + checkbox.disabled = !proxyCheckbox.checked; + if( !proxyCheckbox.checked ) + { + checkbox.checked = false; + let event = new Event('change', {bubbles: true}); + checkbox.dispatchEvent(event); // Trigger virtual onChange event + + } + console.log(checkbox.disabled ? "Disabled" : "Enabled", checkbox); + } + } + ledCheckbox.checked = !!payload.data["led_enabled"]; allowRemoteCheckbox.checked = !!payload.data["remote_enabled"]; hotspotCheckbox.checked = !!payload.data["hotspot_enabled"]; @@ -80,6 +96,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D const cancelBtn = document.getElementById("setup_cancelBtn") as HTMLButtonElement; cancelBtn.onclick = () => { let payload = new WebSocketPayload(WebSocketEvent.SETUP, false); + menuBtn.disabled = false; WebWebSocketHandler.send(payload); } @@ -147,8 +164,6 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D setupSaveBtn.disabled = true; - - const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement; const ledGPIO = document.getElementById("ledGPIO") as HTMLInputElement; const ambientColor = document.getElementById("ambientColor") as HTMLInputElement; @@ -188,8 +203,8 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D // Check let answer = await WebWebSocketHandler.request(RequestType.CHECK, newConf); - if( !(answer.data["success"] as boolean) ) - { + + if (!(answer.data as boolean)) { ele.innerHTML = `Die Konfiguration weist Fehler auf!
${answer.data["msg"]}`; await errorModal.open(); return; @@ -214,6 +229,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D setTimeout(() => { saveModal.close(); + this.startTare(); }, 1000); @@ -223,8 +239,6 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D }); - menuBtn.disabled = false; - } } @@ -236,6 +250,12 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D tareModal.addButton(ButtonType.PRIMARY, "Nein", () => { tareModal.close(); + // Needs to be after selectPin.append because noSel-Pin should always be at pos 0 + let event = new Event('click', {bubbles: true}); + let btn = document.getElementById("setup_cancelBtn"); + if(btn ) + btn.dispatchEvent(event); + }); let ul; @@ -275,6 +295,10 @@ Alle Sensoren wurden erfolgreich kalibriert.
`; btn.onclick = () => { modal.close(); clearInterval(tareInterval); + let event = new Event('click', {bubbles: true}); + let btn = document.getElementById("setup_cancelBtn"); + if(btn ) + btn.dispatchEvent(event); }; } else { btn.innerText = "Erneut versuchen"; @@ -321,19 +345,24 @@ Mindestens ein Sensor konnte nicht kalibriert werden.
${data.msg}
`; // Proxy Label let proxyLabel = document.createElement("label"); - proxyLabel.innerText = "Pumpen Pin"; + proxyLabel.innerText = "Arduino als Proxy"; + proxyLabel.style.display = "block"; + proxyLabel.style.marginBottom = "1%"; containerDiv.append(proxyLabel); // Proxy checkbox let proxyCheckbox = document.createElement("input"); proxyCheckbox.type = "checkbox"; + proxyCheckbox.classList.add("input"); + proxyCheckbox.style.marginLeft = "3%"; proxyCheckbox.checked = !!(Setup.usingProxy && container?.useProxy); // Auto Check proxyCheckbox.disabled = !(Setup.usingProxy); this.arduinoProxyCheckboxes.push(proxyCheckbox); - containerDiv.append(proxyCheckbox); + proxyLabel.append(proxyCheckbox); + containerDiv.append(document.createElement("br")); // Pump Pin Selector let pumpPinSelect; @@ -343,7 +372,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.
${data.msg}
`; pumpPinSelect = selectPin.cloneNode(true); pumpPinSelect.onchange = () => Setup.checkContainers(); pumpPinSelect.selectedIndex = 0; - containerDiv.append(pumpPinSelect); + pumpLabel.append(pumpPinSelect); containerDiv.append(document.createElement("br")); @@ -369,7 +398,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.
${data.msg}
`; sensorTypeScale.innerText = "Wägezelle"; sensorTypeScale.value = "1"; sensorType.append(sensorTypeScale); - containerDiv.append(sensorType); + sensorTypeLabel.append(sensorType); containerDiv.append(document.createElement("br")); @@ -429,7 +458,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.
${data.msg}
`; pumpPinSelect.append(noSel.cloneNode(true)); sensor1Select.append(noSel.cloneNode(true)); sensor2Select.append(noSel.cloneNode(true)); - selectPin.selectedIndex = 0; + pumpPinSelect.selectedIndex = 0; sensor1Select.selectedIndex = 0; sensor2Select.selectedIndex = 0; // Add pins @@ -483,7 +512,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.
${data.msg}
`; let containerDiv = document.getElementById("setupContainers") as HTMLDivElement; containerDiv.innerHTML = ""; - let containers = payload.data["content"] as IContainer[]; + let containers = payload.data as IContainer[]; for (let c of containers) { Setup.addSetupContainer(c); } diff --git a/src/web/WebHandler.ts b/src/web/WebHandler.ts index cf0372e..be55bd0 100644 --- a/src/web/WebHandler.ts +++ b/src/web/WebHandler.ts @@ -46,7 +46,7 @@ export class WebHandler { drinkEle.onclick = () => { WebWebSocketHandler.request(RequestType.STARTFILL, {drink: drink}).then((payload) => { - let data = payload.data.content as { success: boolean, job?: IJob }; + let data = payload.data as { success: boolean, job?: IJob }; if (!data.success) { let modal = new Modal("fill", "Oh nein!"); diff --git a/src/web/WebWebSocketHandler.ts b/src/web/WebWebSocketHandler.ts index 1fa238a..b454d46 100644 --- a/src/web/WebWebSocketHandler.ts +++ b/src/web/WebWebSocketHandler.ts @@ -219,7 +219,7 @@ export class WebWebSocketHandler { return new Promise(resolve => { WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => { if ((payload.data["type"] as RequestType) == type) { - resolve(payload); + resolve(payload.data); } }); WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, { diff --git a/src/web/main.ts b/src/web/main.ts index cbe4774..f716c7a 100644 --- a/src/web/main.ts +++ b/src/web/main.ts @@ -77,19 +77,19 @@ function setupOnClickEvents() { WebWebSocketHandler.request(RequestType.STATS).then((payload) => { let li = document.createElement("li"); - li.innerText = "Cocktails ausgegeben: " + payload.data["content"]["drinks_finished"]; + li.innerText = "Cocktails ausgegeben: " + payload.data["drinks_finished"]; list.append(li); li = document.createElement("li"); - li.innerText = "Häufigster Cocktail: " + payload.data["content"]["drink_most"]; + li.innerText = "Häufigster Cocktail: " + payload.data["drink_most"]; list.append(li); li = document.createElement("li"); - li.innerText = "Anzahl Ingredients: " + payload.data["content"]["count_ingredients"]; + li.innerText = "Anzahl Ingredients: " + payload.data["count_ingredients"]; list.append(li); li = document.createElement("li"); - li.innerText = "Anzahl Cocktails: " + payload.data["content"]["count_cocktails"]; + li.innerText = "Anzahl Cocktails: " + payload.data["count_cocktails"]; list.append(li); }); diff --git a/views/index.pug b/views/index.pug index 5a524a5..e1395b7 100644 --- a/views/index.pug +++ b/views/index.pug @@ -22,7 +22,7 @@ block setup label(onclick="document.getElementById('hotspotCheckbox').checked = !document.getElementById('hotspotCheckbox').checked;") Ohne WiFi Hotspot aktivieren input#hotspotCheckbox.input(type="checkbox") div.inputGroup - label(onclick="document.getElementById('proxyCheckbox').checked = !document.getElementById('proxyCheckbox').checked;") Arduino Mega als Proxy erlauben + label() Arduino Mega als Proxy erlauben input#proxyCheckbox.input(type="checkbox")