diff --git a/src/main.ts b/src/main.ts
index a2efc59..cdf17be 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -11,6 +11,7 @@ import {MyGPIO} from "./MyGPIO";
import {ContainerHelper} from "./ContainerHelper";
import {Mixer} from "./Mixer";
import {ArduinoProxy} from "./ArduinoProxy";
+import path from "path";
const log = debug("itender:server");
@@ -18,6 +19,8 @@ const app = new App();
const wsApp = new WebsocketApp();
+global.appRoot = path.resolve(__dirname);
+
(async () => {
try {
log("Starting...");
diff --git a/src/routes/ws/websocketRoute.ts b/src/routes/ws/websocketRoute.ts
index a13ec1a..245ff7a 100644
--- a/src/routes/ws/websocketRoute.ts
+++ b/src/routes/ws/websocketRoute.ts
@@ -18,6 +18,7 @@ import {ContainerHelper} from "../../ContainerHelper";
import * as os from "os";
import {promisify} from "util";
import Drink from "../../database/Drink";
+import path from "path";
const exec = promisify(require('child_process').exec)
@@ -57,14 +58,13 @@ router.ws('/', async (ws, req, next) => {
let i = 0;
for (let c of data) {
- let container : IContainer | null = null;
+ let container: IContainer | null = null;
- if( c.id )
- {
- container = await Container.findOne( {_id: c.id } );
+ if (c.id) {
+ container = await Container.findOne({_id: c.id});
}
- if( !container )
+ if (!container)
container = new Container();
@@ -80,14 +80,13 @@ router.ws('/', async (ws, req, next) => {
i++;
}
- let containers : IContainer[] = await Container.find();
- for( let c of containers )
- {
- let find = data.find( (e) => {
+ 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 });
+ });
+ if (!find)
+ await Container.deleteOne({_id: c._id});
}
break;
@@ -215,8 +214,7 @@ router.ws('/', async (ws, req, next) => {
if (conf["arduino_proxy_enabled"]) {
try {
await ArduinoProxy.disconnect();
- } catch( e )
- {
+ } catch (e) {
}
try {
@@ -246,7 +244,7 @@ router.ws('/', async (ws, req, next) => {
}
}
- return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content);
+ WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content);
break;
}
case RequestType.TARE: {
@@ -272,7 +270,6 @@ router.ws('/', async (ws, req, next) => {
}
}
} catch (e) {
- // { success: boolean, msg: string }
WebSocketHandler.answerRequest(type, {success: false, msg: e});
success = false;
for (let t of timeouts)
@@ -301,45 +298,49 @@ router.ws('/', async (ws, req, next) => {
}
case RequestType.UPDATE: {
- if( !iTender.internetConnection )
+ 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 )
+ let result = await exec(path.join(global.appRoot, "/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.
"));
- }
+ } catch (e ) {
+ console.error(e);
+ let error = e as {code: number, killed: boolean, cmd: string};
+ let msg = "";
+ if(error.code == 127 )
+ msg = "Beim Ausführen ist ein unbekanntes Problem aufgetreten.";
+ else if ( error.code == 1 )
+ msg = "Die Internetverbindung ist nicht ausreichend, um iTender zu aktualisieren.";
+
+ await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Der iTender konnte das Update nicht installieren.
" + msg ));
+ log("Could not execute update.sh" );
+ }
break;
}
case RequestType.INFO: {
let nets = os.networkInterfaces();
let net = nets["wlan0"];
- if(!net)
+ if (!net)
net = nets["wlp0s20f3"];
- let ipAddr : string = "";
- if( net )
- for( let addr of net )
- {
- if( addr.family == "IPv4" && addr.address && addr.address !== "127.0.0.1" )
+ let ipAddr: string = "";
+ if (net)
+ for (let addr of net) {
+ if (addr.family == "IPv4" && addr.address && addr.address !== "127.0.0.1")
ipAddr = addr.address;
}
let packageJson = require('../../../package.json');
-
let wifi = (await exec("iwgetid")).stdout
-
let data = {
"internet": iTender.internetConnection,
"ip": ipAddr,
- "network": wifi.substring(wifi.indexOf('"')+1,wifi.length-2),
+ "network": wifi.substring(wifi.indexOf('"') + 1, wifi.length - 2),
"uptime": (await exec("uptime -p")).stdout.substring(3),
"version": packageJson.version,
"author": "Tobias Hopp",
@@ -353,8 +354,7 @@ router.ws('/', async (ws, req, next) => {
case RequestType.CLEAR_DB: {
await Drink.deleteMany({});
await Ingredient.deleteMany({});
- for( let c of (await Container.find()) )
- {
+ for (let c of (await Container.find())) {
c.content = undefined;
c.save();
}
@@ -373,7 +373,6 @@ router.ws('/', async (ws, req, next) => {
}
}
});
-
});
module.exports = router;
diff --git a/src/web/Settings.ts b/src/web/Settings.ts
index f82d67e..2eadd98 100644
--- a/src/web/Settings.ts
+++ b/src/web/Settings.ts
@@ -8,9 +8,15 @@ export class Settings {
// Settings Btns
const downloadDrinks = document.getElementById("settings_refreshDrinks") as HTMLButtonElement;
downloadDrinks.onclick = () => this.onClickRefreshDrinks();
+
+ const deleteDrinks = document.getElementById("settings_deleteDrinks") as HTMLButtonElement;
+ deleteDrinks.onclick = () => this.onClickDelete();
+
+
const getInfo = document.getElementById("settings_getInfo") as HTMLButtonElement;
getInfo.onclick = () => this.onClickInfo();
+
const reload = document.getElementById("settings_reload") as HTMLButtonElement;
reload.onclick = () => window.location.reload();
@@ -74,8 +80,7 @@ export class Settings {
WebWebSocketHandler.request(RequestType.UPDATE, null).then((payload) => {
let modal = new Modal("info", "System-Update");
let txt = document.createElement("p");
- if (payload.data as boolean) {
-
+ if (!!payload.data) {
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);
@@ -88,4 +93,22 @@ Sobald das Update installiert ist, wird das System neu gestartet.
Die dadurch
modal.open();
});
}
+
+ private static onClickDelete() {
+ WebWebSocketHandler.request(RequestType.CLEAR_DB, null).then((payload) => {
+ let modal = new Modal("delete", "Datenbank leeren");
+ let txt = document.createElement("p");
+ if (payload.data as boolean) {
+
+ txt.innerHTML = `Die Datenbank des iTender's wurde geleert.
Um nun Cocktails auszugeben, muss die Datenbank aktualisiert werden.
Wähle dazu bitte Getränke herunterladen in den Einstellungen.
`;
+ modal.addContent(txt);
+ } else {
+ txt.innerHTML = `Die Datenbank des iTenders konnte aus einem unbekannten Grund nicht geleert werden.
Bitte versuche es zu einem späteren Zeitpunkt erneut.
`;
+ }
+
+
+ modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close());
+ modal.open();
+ });
+ }
}
\ No newline at end of file
diff --git a/src/web/WebWebSocketHandler.ts b/src/web/WebWebSocketHandler.ts
index 3cd4b39..cc1e79c 100644
--- a/src/web/WebWebSocketHandler.ts
+++ b/src/web/WebWebSocketHandler.ts
@@ -12,7 +12,6 @@ import {Fill} from "./Fill";
export class WebWebSocketHandler {
private static socket: WebSocket;
private static url = (window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005";
- public static tareContainerUpdates: (payload: WebSocketPayload) => void;
private static eventRegister: { event: WebSocketEvent, fn: (payload: WebSocketPayload) => void }[] = [];
@@ -39,176 +38,6 @@ export class WebWebSocketHandler {
WebWebSocketHandler.eventRegister.push({event: event, fn: fn});
}
- private onMessage(msgEvent: MessageEvent) {
- let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data);
- if (!payload) {
- console.log("[WS] Could not parse message: ", msgEvent);
- return;
- }
- 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) {
- case WebSocketEvent.CONFIG: {
- Setup.onConfigUpdate(payload);
- break;
- }
-
- case WebSocketEvent.DRINKS: {
- WebHandler.onDrinkUpdate(payload);
- break;
- }
-
- case WebSocketEvent.ERROR: {
- let modal = new Modal("error", "Aww crap!");
- let txt = document.createElement("p");
- txt.innerHTML = payload.data;
- modal.addContent(txt);
- modal.addContent(document.createElement("br"));
- modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close() );
- modal.open();
- break;
- }
-
- // Incoming WebSocketStatus
- case WebSocketEvent.STATUS: {
- let statusElement = document.getElementById("status");
- if (statusElement)
- statusElement.innerText = payload.data.status;
-
- let status: iTenderStatus = payload.data.status;
-
- switch (status) {
- case iTenderStatus.READY: {
- Modal.close("start");
- Modal.close("setup");
- Modal.close("fill");
- Modal.close("download");
- if (WebHandler.currentPane != Pane.MENU)
- WebHandler.openPane(Pane.MAIN);
- (document.getElementById("menuBtn") as HTMLButtonElement).disabled = false;
- break;
- }
- case iTenderStatus.STARTING: {
- let modal = new Modal("start", "Willkommen!");
- let txt = document.createElement("p");
- txt.innerHTML = `Einen Augenblick bitte
iTender startet...`;
- modal.addContent(txt);
- modal.loader = true;
- modal.open();
- break;
- }
- case iTenderStatus.DOWNLOADING: {
- let modal = new Modal("download", "Aktualisieren");
- let txt = document.createElement("p");
- txt.innerHTML = `Einen Augenblick bitte
iTender aktualisiert die Getränke vom Server...`;
- modal.addContent(txt);
- modal.loader = true;
- modal.open();
- setTimeout( () => {
- if( txt )
- {
- txt.innerHTML = txt.innerHTML + "
Der Vorgang dauert länger als gewöhnlich.
Überprüfe deine Internetverbindung!"
- }
- }, 1000 * 15 )
- break;
- }
- case iTenderStatus.SETUP: {
- Modal.close("start");
- Setup.openSetup();
- break;
- }
- case iTenderStatus.FILLING: {
- Fill.onFillEvent(payload);
- break;
- }
- default: {
- console.log("Unknown to handle " + status);
- }
- }
- break;
- }
-
- }
- }
-
-
- private onOpen(event) {
- console.log("[WS] Connected", event);
-
- const blockPanel = document.getElementById("blockPanel") as HTMLDivElement;
- blockPanel.classList.add("opacityOutDisplayNone");
- }
-
- private onClose(event) {
- console.error("[WS] Closed!", event);
- if (event.wasClean) {
- let modal = new Modal("socketClosed", "Sitzung beendet!");
- let txt = document.createElement("p");
- txt.innerHTML = `Diese Sitzung wurde beendet, da der iTender nun an einem anderen Gerät bzw. an dem Hauptgerät gesteuert wird.
`;
- modal.addContent(txt);
- modal.addButton(ButtonType.PRIMARY, "Sitzung wiederherstellen", () => {
- window.location.reload();
- });
- modal.open();
- } else {
- let modal = new Modal("socketClosed", "Verbindungsproblem!");
- let txt = document.createElement("p");
- txt.innerHTML = `Die Benutzeroberfläche hat die Verbindung mit dem Gerät verloren.
Die Verbindung wird wiederhergestellt...
`;
- modal.addContent(txt);
- modal.loader = true;
- modal.open();
- setInterval(async () => {
- if ((await WebWebSocketHandler.checkConnection()))
- window.location.reload();
- }, 2000);
- }
-
- /* let connectionElement = document.getElementById("right");
- if (connectionElement) {
- connectionElement.innerText = "Getrennt";
- connectionElement.style.color = "red";
- }*/
- }
-
- private static checkConnection(): Promise {
- return new Promise(async resolve => {
- const xhr = new XMLHttpRequest();
- xhr.open("GET", '/status', true);
-
- //Send the proper header information along with the request
- xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
-
- xhr.onreadystatechange = () => { // Call a function when the state changes.
- if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
- resolve(true);
- } else if (xhr.readyState == XMLHttpRequest.DONE) {
- resolve(false);
- }
- }
-
- try {
- await xhr.send();
- } catch (e) {
- resolve(false);
- }
-
- })
- }
-
- private onError(event) {
- console.error("[WS] Error", event);
- /*let connectionElement = document.getElementById("right");
- if (connectionElement)
- connectionElement.innerText = "Fehler";*/
- //openModal("Einen Augenblick...", `Es wurde ein kritischer Fehler festgestellt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
- //window.location.reload();
- }
-
/**
* @return Promise
* @param type
@@ -248,5 +77,173 @@ export class WebWebSocketHandler {
});
}
+ private static checkConnection(): Promise {
+ return new Promise(async resolve => {
+ const xhr = new XMLHttpRequest();
+ xhr.open("GET", '/status', true);
+
+ //Send the proper header information along with the request
+ xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+ xhr.onreadystatechange = () => { // Call a function when the state changes.
+ if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
+ resolve(true);
+ } else if (xhr.readyState == XMLHttpRequest.DONE) {
+ resolve(false);
+ }
+ }
+
+ try {
+ await xhr.send();
+ } catch (e) {
+ resolve(false);
+ }
+
+ })
+ }
+
+ private onMessage(msgEvent: MessageEvent) {
+ let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data);
+ if (!payload) {
+ console.log("[WS] Could not parse message: ", msgEvent);
+ return;
+ }
+ 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) {
+ case WebSocketEvent.CONFIG: {
+ Setup.onConfigUpdate(payload);
+ break;
+ }
+
+ case WebSocketEvent.DRINKS: {
+ WebHandler.onDrinkUpdate(payload);
+ break;
+ }
+
+ case WebSocketEvent.ERROR: {
+ let modal = new Modal("error", "Aww crap!");
+ let txt = document.createElement("p");
+ txt.innerHTML = payload.data;
+ modal.addContent(txt);
+ modal.addContent(document.createElement("br"));
+ modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close());
+ modal.open();
+ break;
+ }
+
+ // Incoming WebSocketStatus
+ case WebSocketEvent.STATUS: {
+ let statusElement = document.getElementById("status");
+ if (statusElement)
+ statusElement.innerText = payload.data.status;
+
+ let status: iTenderStatus = payload.data.status;
+
+ switch (status) {
+ case iTenderStatus.READY: {
+ Modal.close("start");
+ Modal.close("setup");
+ Modal.close("fill");
+ Modal.close("download");
+ if (WebHandler.currentPane != Pane.MENU)
+ WebHandler.openPane(Pane.MAIN);
+ (document.getElementById("menuBtn") as HTMLButtonElement).disabled = false;
+ break;
+ }
+ case iTenderStatus.STARTING: {
+ let modal = new Modal("start", "Willkommen!");
+ let txt = document.createElement("p");
+ txt.innerHTML = `Einen Augenblick bitte
iTender startet...`;
+ modal.addContent(txt);
+ modal.loader = true;
+ modal.open();
+ break;
+ }
+ case iTenderStatus.DOWNLOADING: {
+ let modal = new Modal("download", "Aktualisieren");
+ let txt = document.createElement("p");
+ txt.innerHTML = `Einen Augenblick bitte
iTender synchronisiert die Datenbank mit der Cloud...`;
+ modal.addContent(txt);
+ modal.loader = true;
+ modal.open();
+ setTimeout(() => {
+ if (txt) {
+ txt.innerHTML = txt.innerHTML + "
Der Vorgang dauert länger als gewöhnlich.
Überprüfe deine Internetverbindung!"
+ }
+ }, 1000 * 15)
+ break;
+ }
+ case iTenderStatus.SETUP: {
+ Modal.close("start");
+ Setup.openSetup();
+ break;
+ }
+ case iTenderStatus.FILLING: {
+ Fill.onFillEvent(payload);
+ break;
+ }
+ default: {
+ console.log("Unknown to handle " + status);
+ }
+ }
+ break;
+ }
+
+ }
+ }
+
+ private onOpen(event) {
+ console.log("[WS] Connected", event);
+
+ const blockPanel = document.getElementById("blockPanel") as HTMLDivElement;
+ blockPanel.classList.add("opacityOutDisplayNone");
+ }
+
+ private onClose(event) {
+ console.error("[WS] Closed!", event);
+ if (event.wasClean) {
+ let modal = new Modal("socketClosed", "Sitzung beendet!");
+ let txt = document.createElement("p");
+ txt.innerHTML = `Diese Sitzung wurde beendet, da der iTender nun an einem anderen Gerät bzw. an dem Hauptgerät gesteuert wird.
`;
+ modal.addContent(txt);
+ modal.addButton(ButtonType.PRIMARY, "Sitzung wiederherstellen", () => {
+ window.location.reload();
+ });
+ modal.open();
+ } else {
+ let modal = new Modal("socketClosed", "Verbindungsproblem!");
+ let txt = document.createElement("p");
+ txt.innerHTML = `Die Benutzeroberfläche hat die Verbindung mit dem Gerät verloren.
Die Verbindung wird wiederhergestellt...
`;
+ modal.addContent(txt);
+ modal.loader = true;
+ modal.open();
+ setInterval(async () => {
+ if ((await WebWebSocketHandler.checkConnection()))
+ window.location.reload();
+ }, 2000);
+ }
+
+ /* let connectionElement = document.getElementById("right");
+ if (connectionElement) {
+ connectionElement.innerText = "Getrennt";
+ connectionElement.style.color = "red";
+ }*/
+ }
+
+ private onError(event) {
+ console.error("[WS] Error", event);
+ /*let connectionElement = document.getElementById("right");
+ if (connectionElement)
+ connectionElement.innerText = "Fehler";*/
+ //openModal("Einen Augenblick...", `Es wurde ein kritischer Fehler festgestellt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
+ //window.location.reload();
+ }
+
}
\ No newline at end of file
diff --git a/update.sh b/update.sh
index 05bdba8..d5691ef 100755
--- a/update.sh
+++ b/update.sh
@@ -3,9 +3,9 @@ cd /home/itender/itender || exit -1
git pull "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet
yarn
yarn run compile
-sudo systemctl stop itender
cd ./arduino/itender/
arduino-cli compile --fqbn arduino:avr:mega itender.ino || true
+sudo systemctl stop itender
arduino-cli upload --port /dev/ACM0 --fqbn arduino:avr:mega itender.ino || true
sudo systemctl start itender
exit 0
\ No newline at end of file
diff --git a/views/index.pug b/views/index.pug
index 5c791f1..df3a523 100644
--- a/views/index.pug
+++ b/views/index.pug
@@ -54,8 +54,8 @@ block menu
block settings
// Settings
- 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_refreshDrinks Datenbank aktualisieren
+ button.btn.btn-primary#settings_deleteDrinks Datenbank leeren
button.btn.btn-primary#settings_reload Oberfläche neu starten
button.btn.btn-primary#settings_getInfo Systeminformationen
button.btn.btn-primary#settings_update System aktualisieren