From 937f825e8270a6dd48c74d96c559a373fc908f6c Mon Sep 17 00:00:00 2001 From: Tobias Hopp Date: Thu, 2 Feb 2023 14:28:09 +0100 Subject: [PATCH] add and close #12 Took 1 hour 46 minutes --- package.json | 2 +- public/stylesheets/modal.css | 4 +- src/Settings.ts | 4 +- src/iTender.ts | 2 +- src/main.ts | 17 ++++++- src/routes/ws/websocketRoute.ts | 38 ++++++++++---- src/web/Containers.ts | 3 +- src/web/Modal.ts | 2 +- src/web/Settings.ts | 38 ++++++++++---- src/web/Setup.ts | 11 ++-- src/web/main.ts | 89 ++++++++++++++------------------- update.sh | 2 + views/index.pug | 12 +++-- 13 files changed, 135 insertions(+), 89 deletions(-) diff --git a/package.json b/package.json index bf367d6..30e50b3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "itender", - "version": "1.0.2", + "version": "2.2.8", "private": true, "author": "Tobias Hopp ", "license": "UNLICENSED", diff --git a/public/stylesheets/modal.css b/public/stylesheets/modal.css index 3e3ee83..bd58611 100644 --- a/public/stylesheets/modal.css +++ b/public/stylesheets/modal.css @@ -63,12 +63,12 @@ .modalBlendIn { - animation: modalBlendIn 0.5s forwards; + animation: modalBlendIn 0.4s forwards; } .modalBlendOut { - animation: modalBlendOut 0.8s forwards; + animation: modalBlendOut 0.4s forwards; } diff --git a/src/Settings.ts b/src/Settings.ts index 3b61876..e748b29 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -30,10 +30,10 @@ export class Settings { } public static saveSettings() { - fs.writeFileSync(path.join(__dirname, "../config.json"), JSON.stringify(this._json)); + fs.writeFileSync(path.join(__dirname, "../config.json"), JSON.stringify(this._json, null, 1)); } - public static get(key: string): any { + public static get(key: "setupDone"|"secondsPer100ml"|"arduino_proxy_enabled"|"led_enabled"|"remote_enabled"|"hotspot_enabled"|"led_gpio"|"ambient_color"): any { return this._json[key]; } diff --git a/src/iTender.ts b/src/iTender.ts index eac7ab9..60bec0b 100644 --- a/src/iTender.ts +++ b/src/iTender.ts @@ -33,7 +33,7 @@ export class iTender { * How many seconds it takes to fill 100ml * @private */ - static secondsPer100ml: number = 35.3335; + static secondsPer100ml: number = 19.3335; // 35.3335 /** * Sensitivity-Factor of the hx711 scales diff --git a/src/main.ts b/src/main.ts index d1d0e2c..a2efc59 100644 --- a/src/main.ts +++ b/src/main.ts @@ -10,6 +10,7 @@ import Drink from "./database/Drink"; import {MyGPIO} from "./MyGPIO"; import {ContainerHelper} from "./ContainerHelper"; import {Mixer} from "./Mixer"; +import {ArduinoProxy} from "./ArduinoProxy"; const log = debug("itender:server"); @@ -20,11 +21,25 @@ const wsApp = new WebsocketApp(); (async () => { try { log("Starting..."); + Settings.loadSettings(); + + await Database.connect(); + if( Settings.get("arduino_proxy_enabled") as boolean ) + { + try { + await ArduinoProxy.connect(); + } catch( e ) + { + Settings.set("arduino_proxy_enabled",false); + Settings.setupDone = false; + log("Force iTender to setup, because proxy not connected!"); + } + } //await test(); await app.listen(); await wsApp.listen(); - Settings.loadSettings(); + iTender.setStatus(iTenderStatus.STARTING); await Utils.sleep(2000); diff --git a/src/routes/ws/websocketRoute.ts b/src/routes/ws/websocketRoute.ts index 1e4c1a2..4be084a 100644 --- a/src/routes/ws/websocketRoute.ts +++ b/src/routes/ws/websocketRoute.ts @@ -77,6 +77,17 @@ router.ws('/', async (ws, req, next) => { await container.save(); i++; } + + let containers : IContainer[] = await Container.find(); + for( let c of containers ) + { + let find = data.find( (e) => { + return c._id == e.id; + } ); + if( !find ) + await Container.deleteOne({_id: c._id }); + } + break; } @@ -211,7 +222,7 @@ router.ws('/', async (ws, req, next) => { } catch (e) { log("Checkup failed"); content.success = false; - content.msg = "Bei der Kommunikation mit dem Arduino Proxy ist ein Fehler aufgetreten.
Technische Details: " + e; + 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); } } @@ -288,13 +299,20 @@ router.ws('/', async (ws, req, next) => { } case RequestType.UPDATE: { - /* - - git pull - - yarn install - - yarn run compile - - (arduino update?) - - reboot - */ + if( !iTender.internetConnection ) + return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, false); + WebSocketHandler.answerRequest(msg.data["type"] as RequestType, true); + + + try { + let result = await exec("/home/itender/itender/update.sh"); + if( result.stderr ) + await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Der iTender konnte das Update nicht installieren.
Möglicherweise ist die Internetverbindung nicht ausreichend oder das Update enthält Fehler.
")); + } catch( e ) + { + await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Der iTender konnte das Update nicht installieren.
Möglicherweise ist die Internetverbindung nicht ausreichend oder das Update enthält Fehler.
")); + } + break; } @@ -321,7 +339,9 @@ router.ws('/', async (ws, req, next) => { "ip": ipAddr, "network": wifi.substring(wifi.indexOf('"')+1,wifi.length-2), "uptime": (await exec("uptime -p")).stdout.substring(3), - "version": packageJson.version + "version": packageJson.version, + "author": "Tobias Hopp", + "contact": "tobi@gaminggeneration.de" } return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, data); diff --git a/src/web/Containers.ts b/src/web/Containers.ts index 01807e7..8d3741a 100644 --- a/src/web/Containers.ts +++ b/src/web/Containers.ts @@ -82,7 +82,7 @@ export class Containers { let selectIngredient = document.createElement("select"); selectIngredient.classList.add("hidden"); selectIngredient.classList.add("input"); - selectIngredient.style.width = "50%" + selectIngredient.style.width = "35%" // When ingredient is changed selectIngredient.onchange = () => { @@ -189,6 +189,7 @@ export class Containers { selectContainer.dispatchEvent(event); selectIngredient.dispatchEvent(event); }); + modal.close(); }; modal.open(); diff --git a/src/web/Modal.ts b/src/web/Modal.ts index 924dbfd..e89998c 100644 --- a/src/web/Modal.ts +++ b/src/web/Modal.ts @@ -177,7 +177,7 @@ export class Modal { modalContent.classList.remove("modalBlendOut"); modal.classList.remove("modalBlendOut"); this.modalInClose = false; - }, 800); + }, 402); this.currentModalId = undefined; } diff --git a/src/web/Settings.ts b/src/web/Settings.ts index 555337a..f82d67e 100644 --- a/src/web/Settings.ts +++ b/src/web/Settings.ts @@ -13,6 +13,9 @@ export class Settings { const reload = document.getElementById("settings_reload") as HTMLButtonElement; reload.onclick = () => window.location.reload(); + + const update = document.getElementById("settings_update") as HTMLButtonElement; + update.onclick = () => this.update(); } private static onClickRefreshDrinks() { @@ -41,32 +44,47 @@ export class Settings { th.append(tdTh1, tdTh2); - let x = [["internet","Internet-Konnektivität"], ["ip","IP-Adresse"], ["network","WiFi-Netzwerk"], ["uptime","Gerät aktiv seit"], ["version", "Version"]]; - for( let y of x ) - { + let x = [["internet", "Internet-Konnektivität"], ["ip", "IP-Adresse"], ["network", "WiFi-Netzwerk"], ["uptime", "Gerät aktiv seit"], ["version", "Version"], ["author", "Entwickler"], ["contact", "Support-Adresse"]]; + for (let y of x) { let tr = document.createElement("tr"); let td1 = document.createElement("td"); let td2 = document.createElement("td"); td1.innerText = y[1]; td1.style.fontWeight = "bold"; - if( payload.data[y[0]] === true || payload.data[y[0]] === false ) - { + if (payload.data[y[0]] === true || payload.data[y[0]] === false) { td2.innerText = payload.data[y[0]] == true ? "Verbunden" : "Getrennt"; - } - else - { + } else { td2.innerText = payload.data[y[0]]; } - tr.append(td1,td2); + tr.append(td1, td2); table.append(tr); } modal.addContent(table); modal.addBR(); - modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close() ); + modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close()); + modal.open(); + }); + } + + private static update() { + WebWebSocketHandler.request(RequestType.UPDATE, null).then((payload) => { + let modal = new Modal("info", "System-Update"); + let txt = document.createElement("p"); + if (payload.data as boolean) { + + txt.innerHTML = `Der iTender wird nun aktualisiert!

+Sobald das Update installiert ist, wird das System neu gestartet.
Die dadurch hergehende Verbindungswarnung kann ignoriert werden.
Der iTender stellt die Verbindung automatisch wieder her.

Schalten Sie das System nicht aus und entfernen Sie nicht das Netzkabel!`; + modal.addContent(txt); + modal.loader = true; + } else { + txt.innerHTML = `Das System kann nicht aktualisiert werden.
iTender hat keine Internet-Konnektivität fest gestellt.
Versuchen Sie es zu einem späteren Zeitpunkt erneut.`; + modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close()); + } + modal.open(); }); } diff --git a/src/web/Setup.ts b/src/web/Setup.ts index 505035a..cd4dfa5 100644 --- a/src/web/Setup.ts +++ b/src/web/Setup.ts @@ -199,9 +199,9 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.
D // Check let answer = await WebWebSocketHandler.request(RequestType.CHECK, newConf); - console.log(answer); + if (!(answer.data["success"] as boolean)) { - ele.innerHTML = `Die Konfiguration weist Fehler auf!
${answer.data["msg"]}`; + ele.innerHTML = `Die Überprüfung schlug fehl!
${answer.data["msg"]}`; await errorModal.open(); return; } @@ -552,8 +552,11 @@ Mindestens ein Sensor konnte nicht kalibriert werden.
${data.msg}
`; setTimeout(() => { c.classList.remove("error"); c2.classList.remove("error"); - sel.classList.remove("error"); - sel2.classList.remove("error"); + setTimeout( () => { + sel.classList.remove("error"); + sel2.classList.remove("error"); + }, 1500 ); + }, 2200); returner = false; } diff --git a/src/web/main.ts b/src/web/main.ts index b448727..16ef03e 100644 --- a/src/web/main.ts +++ b/src/web/main.ts @@ -31,7 +31,7 @@ document.addEventListener("DOMContentLoaded", async () => { setInterval(() => { - if(!time ) return; + if (!time) return; let currentDate = new Date(); time.innerText = "" + (currentDate.getHours() < 10 ? "0" + currentDate.getHours() : currentDate.getHours()) + ":" + (currentDate.getMinutes() < 10 ? "0" + currentDate.getMinutes() : currentDate.getMinutes()); @@ -39,29 +39,28 @@ document.addEventListener("DOMContentLoaded", async () => { WebWebSocketHandler.registerForEvent(WebSocketEvent.CONTAINERS, (payload) => { console.log("Updating container list...") - let container : IContainer; + let container: IContainer; let bottomContainers = document.getElementById("menuContainers") as HTMLDivElement; bottomContainers.innerHTML = ""; - for( container of payload.data ) - { + for (container of payload.data) { let containerDiv = document.createElement("div") as HTMLDivElement; containerDiv.classList.add("container"); let span = document.createElement("span") as HTMLSpanElement; - let pcnt = Math.round( container.filled * 100 / container.volume ); - if( !container.content ) + let pcnt = Math.round(container.filled * 100 / container.volume); + if (!container.content) span.innerText = "-"; - else if( isNaN(pcnt) ) + else if (isNaN(pcnt)) span.innerText = "?%"; else span.innerText = pcnt + "%"; - if( pcnt < 5 ) + if (pcnt < 5) containerDiv.style.backgroundColor = "red"; - else if ( pcnt < 15 ) - containerDiv.style.backgroundColor = "#ef4f00"; - else if ( pcnt < 30 ) - containerDiv.style.backgroundColor = "#ff5400"; + else if (pcnt < 15) + containerDiv.style.backgroundColor = "#EF4F00"; + else if (pcnt < 30) + containerDiv.style.backgroundColor = "#FF5400"; containerDiv.append(span); @@ -75,18 +74,6 @@ function setupOnClickEvents() { const menuBtn = document.getElementById("menuBtn") as HTMLButtonElement; menuBtn.disabled = true; - let timer = 0; - function mouseDown() { - timer = Date.now(); - } - function mouseUp() { - if( ( Date.now() - timer ) / 1000 > 5 ) - window.location.reload(); - } - menuBtn.onmousedown = mouseDown; - menuBtn.ontouchstart = mouseDown; - menuBtn.onmouseup = mouseUp; - menuBtn.ontouchend = mouseUp; function doMenu() { if (WebHandler.currentPane != Pane.MENU) { @@ -107,43 +94,43 @@ function setupOnClickEvents() { menuStatsBtn.onclick = async () => { - let statsModal = new Modal("stats", "Statistiken"); + let modal = new Modal("stats", "Statistiken"); - let txt = document.createElement("p"); - txt.innerHTML = `Folgende Statistiken wurden erfasst.`; - statsModal.addContent(txt); + let table = document.createElement("table"); + table.style.marginLeft = "auto"; + table.style.marginRight = "auto"; - let div = document.createElement("div"); - div.style.textAlign = "left"; - statsModal.addContent(div); + let th = document.createElement("th"); + table.append(th); - let list = document.createElement("ul"); - div.append(list); + let tdTh1 = document.createElement("td"); + tdTh1.innerText = ""; + let tdTh2 = document.createElement("td"); + tdTh2.innerText = ""; - statsModal.addContent(document.createElement("br")); - statsModal.addButton(ButtonType.PRIMARY, "Schließen", () => statsModal.close()); + th.append(tdTh1, tdTh2); WebWebSocketHandler.request(RequestType.STATS).then((payload) => { - let li = document.createElement("li"); - console.log(payload); - li.innerText = "Cocktails ausgegeben: " + payload.data["drinks_finished"]; - list.append(li); + let x = [["drinks_finished", "Ausgegebene Cocktails"], ["drink_most", "Beliebtester Cocktail"], ["count_cocktails", "Anzahl an Cocktails"], ["count_ingredients", "Anzahl an Zutaten"]]; + for (let y of x) { + let tr = document.createElement("tr"); + let td1 = document.createElement("td"); + let td2 = document.createElement("td"); - li = document.createElement("li"); - li.innerText = "Häufigster Cocktail: " + payload.data["drink_most"]; - list.append(li); + td1.innerText = y[1]; + td1.style.fontWeight = "bold"; + td2.innerText = payload.data[y[0]]; + tr.append(td1, td2); - li = document.createElement("li"); - li.innerText = "Anzahl Ingredients: " + payload.data["count_ingredients"]; - list.append(li); - - li = document.createElement("li"); - li.innerText = "Anzahl Cocktails: " + payload.data["count_cocktails"]; - list.append(li); + table.append(tr); + } + modal.addContent(table); + modal.addContent(document.createElement("br")); + modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close()); + modal.open(); }); - await statsModal.open(); }; const menuSettingsBtn = document.getElementById("menu_settings") as HTMLButtonElement; @@ -159,8 +146,6 @@ function setupOnClickEvents() { Settings.addListeners(); - - } let wsHandler; diff --git a/update.sh b/update.sh index 58e027b..3b76962 100755 --- a/update.sh +++ b/update.sh @@ -1,5 +1,7 @@ #!/bin/bash +cd /home/itender/itender || exit -1 git pull "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet yarn yarn run compile sudo systemctl restart itender +exit 0 \ No newline at end of file diff --git a/views/index.pug b/views/index.pug index 1624eb9..5c791f1 100644 --- a/views/index.pug +++ b/views/index.pug @@ -11,7 +11,7 @@ block setup input#ledGPIO.input(type="number" value="40" style="width:15%" disabled="disabled") div.inputGroup label Ambiente Farbe - input#ambientColor.input(type="color" value="#05445E" style="width:15%" disabled="disabled") + input#ambientColor.input(type="color" value="#05445E" style="width:15%") div#setupExtraDiv h1 Erweiterte Einstellungen @@ -54,11 +54,13 @@ block menu block settings // Settings - button.btn.btn-primary#settings_refreshDrinks Getränke herunterladen - button.btn.btn-primary#settings_update System aktualisieren + button.btn.btn-primary#settings_refreshDrinks Getränke aktualisieren + button.btn.btn-primary#settings_deleteDrinks(disabled="disabled") Getränke-DB löschen + button.btn.btn-primary#settings_reload Oberfläche neu starten button.btn.btn-primary#settings_getInfo Systeminformationen - button.btn.btn-primary#settings_reload Oberfläche neustarten - + button.btn.btn-primary#settings_update System aktualisieren + button.btn.btn-primary#settings_restart(disabled="disabled") iTender neu starten + button.btn.btn-primary#settings_shutdown(disabled="disabled") iTender herunterfahren block main