parent
a021d25332
commit
937f825e82
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "itender",
|
||||
"version": "1.0.2",
|
||||
"version": "2.2.8",
|
||||
"private": true,
|
||||
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
|
||||
"license": "UNLICENSED",
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
17
src/main.ts
17
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);
|
||||
|
@ -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.<br>Technische Details: " + e;
|
||||
content.msg = "Bei der Kommunikation mit dem Arduino Proxy ist ein Fehler aufgetreten.<br><br><em>Technische Details: " + e + "</em>";
|
||||
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.<br>Möglicherweise ist die Internetverbindung nicht ausreichend oder das Update enthält Fehler.<br>"));
|
||||
} catch( 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>"));
|
||||
}
|
||||
|
||||
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);
|
||||
|
@ -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();
|
||||
|
@ -177,7 +177,7 @@ export class Modal {
|
||||
modalContent.classList.remove("modalBlendOut");
|
||||
modal.classList.remove("modalBlendOut");
|
||||
this.modalInClose = false;
|
||||
}, 800);
|
||||
}, 402);
|
||||
|
||||
this.currentModalId = undefined;
|
||||
}
|
||||
|
@ -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!<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>`;
|
||||
modal.addContent(txt);
|
||||
modal.loader = true;
|
||||
} else {
|
||||
txt.innerHTML = `Das System kann nicht aktualisiert werden.<br>iTender hat keine Internet-Konnektivität fest gestellt.<br>Versuchen Sie es zu einem späteren Zeitpunkt erneut.`;
|
||||
modal.addButton(ButtonType.PRIMARY, "Schließen", () => modal.close());
|
||||
}
|
||||
|
||||
modal.open();
|
||||
});
|
||||
}
|
||||
|
@ -199,9 +199,9 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>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!<br>${answer.data["msg"]}`;
|
||||
ele.innerHTML = `Die Überprüfung schlug fehl!<br>${answer.data["msg"]}`;
|
||||
await errorModal.open();
|
||||
return;
|
||||
}
|
||||
@ -552,8 +552,11 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
|
||||
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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user