Took 46 minutes
This commit is contained in:
Tobias Hopp 2023-02-03 13:55:21 +01:00
parent de1a2641f7
commit f4da186fb7
6 changed files with 234 additions and 212 deletions

View File

@ -11,6 +11,7 @@ import {MyGPIO} from "./MyGPIO";
import {ContainerHelper} from "./ContainerHelper"; import {ContainerHelper} from "./ContainerHelper";
import {Mixer} from "./Mixer"; import {Mixer} from "./Mixer";
import {ArduinoProxy} from "./ArduinoProxy"; import {ArduinoProxy} from "./ArduinoProxy";
import path from "path";
const log = debug("itender:server"); const log = debug("itender:server");
@ -18,6 +19,8 @@ const app = new App();
const wsApp = new WebsocketApp(); const wsApp = new WebsocketApp();
global.appRoot = path.resolve(__dirname);
(async () => { (async () => {
try { try {
log("Starting..."); log("Starting...");

View File

@ -18,6 +18,7 @@ import {ContainerHelper} from "../../ContainerHelper";
import * as os from "os"; import * as os from "os";
import {promisify} from "util"; import {promisify} from "util";
import Drink from "../../database/Drink"; import Drink from "../../database/Drink";
import path from "path";
const exec = promisify(require('child_process').exec) const exec = promisify(require('child_process').exec)
@ -59,8 +60,7 @@ router.ws('/', async (ws, req, next) => {
for (let c of data) { for (let c of data) {
let container: IContainer | null = null; let container: IContainer | null = null;
if( c.id ) if (c.id) {
{
container = await Container.findOne({_id: c.id}); container = await Container.findOne({_id: c.id});
} }
@ -81,8 +81,7 @@ router.ws('/', async (ws, req, next) => {
} }
let containers: IContainer[] = await Container.find(); let containers: IContainer[] = await Container.find();
for( let c of containers ) for (let c of containers) {
{
let find = data.find((e) => { let find = data.find((e) => {
return c._id == e.id; return c._id == e.id;
}); });
@ -215,8 +214,7 @@ router.ws('/', async (ws, req, next) => {
if (conf["arduino_proxy_enabled"]) { if (conf["arduino_proxy_enabled"]) {
try { try {
await ArduinoProxy.disconnect(); await ArduinoProxy.disconnect();
} catch( e ) } catch (e) {
{
} }
try { 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; break;
} }
case RequestType.TARE: { case RequestType.TARE: {
@ -272,7 +270,6 @@ router.ws('/', async (ws, req, next) => {
} }
} }
} catch (e) { } catch (e) {
// { success: boolean, msg: string }
WebSocketHandler.answerRequest(type, {success: false, msg: e}); WebSocketHandler.answerRequest(type, {success: false, msg: e});
success = false; success = false;
for (let t of timeouts) for (let t of timeouts)
@ -305,16 +302,23 @@ router.ws('/', async (ws, req, next) => {
return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, false); return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, false);
WebSocketHandler.answerRequest(msg.data["type"] as RequestType, true); WebSocketHandler.answerRequest(msg.data["type"] as RequestType, true);
try { try {
let result = await exec("/home/itender/itender/update.sh"); let result = await exec(path.join(global.appRoot, "/update.sh"));
if (result.stderr) if (result.stderr)
await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Der iTender konnte das Update nicht installieren.<br>Möglicherweise ist die Internetverbindung nicht ausreichend oder das Update enthält Fehler.<br>")); await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Der iTender konnte das Update nicht installieren.<br>Möglicherweise ist die Internetverbindung nicht ausreichend oder das Update enthält Fehler.<br>"));
} catch( e ) } catch (e ) {
{ console.error(e);
await WebSocketHandler.send(new WebSocketPayload(WebSocketEvent.ERROR, "Der iTender konnte das Update nicht installieren.<br>Möglicherweise ist die Internetverbindung nicht ausreichend oder das Update enthält Fehler.<br>")); 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.<br><br>" + msg ));
log("Could not execute update.sh" );
}
break; break;
} }
@ -325,17 +329,14 @@ router.ws('/', async (ws, req, next) => {
net = nets["wlp0s20f3"]; net = nets["wlp0s20f3"];
let ipAddr: string = ""; let ipAddr: string = "";
if (net) if (net)
for( let addr of net ) for (let addr of net) {
{
if (addr.family == "IPv4" && addr.address && addr.address !== "127.0.0.1") if (addr.family == "IPv4" && addr.address && addr.address !== "127.0.0.1")
ipAddr = addr.address; ipAddr = addr.address;
} }
let packageJson = require('../../../package.json'); let packageJson = require('../../../package.json');
let wifi = (await exec("iwgetid")).stdout let wifi = (await exec("iwgetid")).stdout
let data = { let data = {
"internet": iTender.internetConnection, "internet": iTender.internetConnection,
"ip": ipAddr, "ip": ipAddr,
@ -353,8 +354,7 @@ router.ws('/', async (ws, req, next) => {
case RequestType.CLEAR_DB: { case RequestType.CLEAR_DB: {
await Drink.deleteMany({}); await Drink.deleteMany({});
await Ingredient.deleteMany({}); await Ingredient.deleteMany({});
for( let c of (await Container.find()) ) for (let c of (await Container.find())) {
{
c.content = undefined; c.content = undefined;
c.save(); c.save();
} }
@ -373,7 +373,6 @@ router.ws('/', async (ws, req, next) => {
} }
} }
}); });
}); });
module.exports = router; module.exports = router;

View File

@ -8,9 +8,15 @@ export class Settings {
// Settings Btns // Settings Btns
const downloadDrinks = document.getElementById("settings_refreshDrinks") as HTMLButtonElement; const downloadDrinks = document.getElementById("settings_refreshDrinks") as HTMLButtonElement;
downloadDrinks.onclick = () => this.onClickRefreshDrinks(); downloadDrinks.onclick = () => this.onClickRefreshDrinks();
const deleteDrinks = document.getElementById("settings_deleteDrinks") as HTMLButtonElement;
deleteDrinks.onclick = () => this.onClickDelete();
const getInfo = document.getElementById("settings_getInfo") as HTMLButtonElement; const getInfo = document.getElementById("settings_getInfo") as HTMLButtonElement;
getInfo.onclick = () => this.onClickInfo(); getInfo.onclick = () => this.onClickInfo();
const reload = document.getElementById("settings_reload") as HTMLButtonElement; const reload = document.getElementById("settings_reload") as HTMLButtonElement;
reload.onclick = () => window.location.reload(); reload.onclick = () => window.location.reload();
@ -74,8 +80,7 @@ export class Settings {
WebWebSocketHandler.request(RequestType.UPDATE, null).then((payload) => { WebWebSocketHandler.request(RequestType.UPDATE, null).then((payload) => {
let modal = new Modal("info", "System-Update"); let modal = new Modal("info", "System-Update");
let txt = document.createElement("p"); let txt = document.createElement("p");
if (payload.data as boolean) { if (!!payload.data) {
txt.innerHTML = `Der iTender wird nun aktualisiert!<br><br> txt.innerHTML = `Der iTender wird nun aktualisiert!<br><br>
Sobald das Update installiert ist, wird das System neu gestartet.<br>Die dadurch hergehende Verbindungswarnung kann ignoriert werden.<br>Der iTender stellt die Verbindung automatisch wieder her.<br><br><span style="color:red;font-weight: bold">Schalten Sie das System nicht aus und entfernen Sie nicht das Netzkabel!</span>`; Sobald das Update installiert ist, wird das System neu gestartet.<br>Die dadurch hergehende Verbindungswarnung kann ignoriert werden.<br>Der iTender stellt die Verbindung automatisch wieder her.<br><br><span style="color:red;font-weight: bold">Schalten Sie das System nicht aus und entfernen Sie nicht das Netzkabel!</span>`;
modal.addContent(txt); modal.addContent(txt);
@ -88,4 +93,22 @@ Sobald das Update installiert ist, wird das System neu gestartet.<br>Die dadurch
modal.open(); 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.<br>Um nun Cocktails auszugeben, muss die Datenbank aktualisiert werden.<br><br>Wähle dazu bitte <strong>Getränke herunterladen</strong> in den Einstellungen.<br><br>`;
modal.addContent(txt);
} else {
txt.innerHTML = `Die Datenbank des iTenders konnte aus einem unbekannten Grund nicht geleert werden.<br>Bitte versuche es zu einem späteren Zeitpunkt erneut.<br><br>`;
}
modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close());
modal.open();
});
}
} }

View File

@ -12,7 +12,6 @@ import {Fill} from "./Fill";
export class WebWebSocketHandler { 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;
private static eventRegister: { event: WebSocketEvent, fn: (payload: WebSocketPayload) => void }[] = []; private static eventRegister: { event: WebSocketEvent, fn: (payload: WebSocketPayload) => void }[] = [];
@ -39,6 +38,70 @@ export class WebWebSocketHandler {
WebWebSocketHandler.eventRegister.push({event: event, fn: fn}); WebWebSocketHandler.eventRegister.push({event: event, fn: fn});
} }
/**
* @return Promise<WebSocketPayload>
* @param type
* @param content
*/
public static request(type: RequestType, content: any = null): Promise<WebSocketPayload> {
console.log("Request to " + type)
return new Promise(resolve => {
WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
if ((payload.data["type"] as RequestType) == type) {
resolve(payload.data);
}
});
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, {
type: type,
data: content
}));
});
}
public static send(payload: WebSocketPayload): Promise<void> {
console.log("[WS] Sending " + payload.event + " Event", payload);
return new Promise(async (resolve, reject) => {
try {
if (this.socket && this.socket.readyState == 1) {
await this.socket.send(payload.toString());
resolve();
}
} catch (e) {
/*let modal = new Modal("error", "Verbindungsfehler");
let txt = document.createElement("p");
txt.innerHTML = `Beim Austausch von Informationen ist ein Problem aufgetreten.<br>Falls dies öfter passieren sollte, ist der Support zu kontaktieren.`;
modal.addContent(txt);
await modal.open();*/
reject();
}
});
}
private static checkConnection(): Promise<boolean> {
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) { private onMessage(msgEvent: MessageEvent) {
let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data); let payload = WebSocketPayload.parseFromBase64Json(msgEvent.data);
if (!payload) { if (!payload) {
@ -105,13 +168,12 @@ export class WebWebSocketHandler {
case iTenderStatus.DOWNLOADING: { case iTenderStatus.DOWNLOADING: {
let modal = new Modal("download", "Aktualisieren"); let modal = new Modal("download", "Aktualisieren");
let txt = document.createElement("p"); let txt = document.createElement("p");
txt.innerHTML = `Einen Augenblick bitte<br>iTender aktualisiert die Getränke vom Server...`; txt.innerHTML = `Einen Augenblick bitte<br>iTender synchronisiert die Datenbank mit der Cloud...`;
modal.addContent(txt); modal.addContent(txt);
modal.loader = true; modal.loader = true;
modal.open(); modal.open();
setTimeout(() => { setTimeout(() => {
if( txt ) if (txt) {
{
txt.innerHTML = txt.innerHTML + "<br><br>Der Vorgang dauert länger als gewöhnlich.<br>Überprüfe deine Internetverbindung!" txt.innerHTML = txt.innerHTML + "<br><br>Der Vorgang dauert länger als gewöhnlich.<br>Überprüfe deine Internetverbindung!"
} }
}, 1000 * 15) }, 1000 * 15)
@ -136,7 +198,6 @@ export class WebWebSocketHandler {
} }
} }
private onOpen(event) { private onOpen(event) {
console.log("[WS] Connected", event); console.log("[WS] Connected", event);
@ -175,31 +236,6 @@ export class WebWebSocketHandler {
}*/ }*/
} }
private static checkConnection(): Promise<boolean> {
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) { private onError(event) {
console.error("[WS] Error", event); console.error("[WS] Error", event);
/*let connectionElement = document.getElementById("right"); /*let connectionElement = document.getElementById("right");
@ -209,44 +245,5 @@ export class WebWebSocketHandler {
//window.location.reload(); //window.location.reload();
} }
/**
* @return Promise<WebSocketPayload>
* @param type
* @param content
*/
public static request(type: RequestType, content: any = null): Promise<WebSocketPayload> {
console.log("Request to " + type)
return new Promise(resolve => {
WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
if ((payload.data["type"] as RequestType) == type) {
resolve(payload.data);
}
});
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, {
type: type,
data: content
}));
});
}
public static send(payload: WebSocketPayload): Promise<void> {
console.log("[WS] Sending " + payload.event + " Event", payload);
return new Promise(async (resolve, reject) => {
try {
if (this.socket && this.socket.readyState == 1) {
await this.socket.send(payload.toString());
resolve();
}
} catch (e) {
/*let modal = new Modal("error", "Verbindungsfehler");
let txt = document.createElement("p");
txt.innerHTML = `Beim Austausch von Informationen ist ein Problem aufgetreten.<br>Falls dies öfter passieren sollte, ist der Support zu kontaktieren.`;
modal.addContent(txt);
await modal.open();*/
reject();
}
});
}
} }

View File

@ -3,9 +3,9 @@ cd /home/itender/itender || exit -1
git pull "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet git pull "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet
yarn yarn
yarn run compile yarn run compile
sudo systemctl stop itender
cd ./arduino/itender/ cd ./arduino/itender/
arduino-cli compile --fqbn arduino:avr:mega itender.ino || true 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 arduino-cli upload --port /dev/ACM0 --fqbn arduino:avr:mega itender.ino || true
sudo systemctl start itender sudo systemctl start itender
exit 0 exit 0

View File

@ -54,8 +54,8 @@ block menu
block settings block settings
// Settings // Settings
button.btn.btn-primary#settings_refreshDrinks Getränke aktualisieren button.btn.btn-primary#settings_refreshDrinks Datenbank aktualisieren
button.btn.btn-primary#settings_deleteDrinks(disabled="disabled") Getränke-DB löschen button.btn.btn-primary#settings_deleteDrinks Datenbank leeren
button.btn.btn-primary#settings_reload Oberfläche neu starten button.btn.btn-primary#settings_reload Oberfläche neu starten
button.btn.btn-primary#settings_getInfo Systeminformationen button.btn.btn-primary#settings_getInfo Systeminformationen
button.btn.btn-primary#settings_update System aktualisieren button.btn.btn-primary#settings_update System aktualisieren