Took 1 hour 17 minutes
This commit is contained in:
Tobias Hopp 2023-01-30 11:40:11 +01:00
parent 8f3e62f70e
commit 3e1d88a0e5
13 changed files with 92 additions and 41 deletions

View File

@ -28,4 +28,5 @@
- [ ] Bei Container erstellung kann optional "Arduino Proxy" angewählt werden - [ ] Bei Container erstellung kann optional "Arduino Proxy" angewählt werden
- Danach werden die Daten dieses Containers über den Arduino bezogen - Danach werden die Daten dieses Containers über den Arduino bezogen
- [ ] Behälter Menü neu designen - [ ] Behälter Menü neu designen
- [ ] In den ganzen messfn checken ob überhaupt eingestellt ist, den proxy zu nutzen - [ ] In den ganzen messFn checken ob überhaupt eingestellt ist, den proxy zu nutzen
- [ ] Slot mit in Container senden nehmen

View File

@ -95,4 +95,4 @@
#setupContainers .setupContainer select { #setupContainers .setupContainer select {
margin-bottom: 2%; margin-bottom: 2%;
} }

View File

@ -37,7 +37,7 @@ export class ArduinoProxy {
return ele.manufacturer == "Arduino"; return ele.manufacturer == "Arduino";
}); });
if (!arduino) { if (!arduino) {
return reject("No arduino found"); return reject("No arduino found. Is it plugged in?");
} }
// @ts-ignore // @ts-ignore
@ -51,7 +51,7 @@ export class ArduinoProxy {
if (err) { if (err) {
log("Error whilst connecting to proxy (open serial-connection)"); log("Error whilst connecting to proxy (open serial-connection)");
log(err.name + "\n" + err.message + "\n" + err.stack); log(err.name + "\n" + err.message + "\n" + err.stack);
return reject(err.name); return reject("Could not open serial connection to arduino");
} }
// @ts-ignore // @ts-ignore

View File

@ -28,6 +28,7 @@ export class WebSocketHandler {
try { try {
if (this.ws && this.ws.readyState == 1) { if (this.ws && this.ws.readyState == 1) {
log("Sending " + payload.event); log("Sending " + payload.event);
await this.ws.send(payload.toString()); await this.ws.send(payload.toString());
resolve(); resolve();
} }
@ -38,7 +39,8 @@ export class WebSocketHandler {
} }
public static answerRequest(type: RequestType, content: any) { 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"); log("Answered " + type + " request");
} }

View File

@ -3,6 +3,7 @@ import debug from "debug";
import Ingredient from "./Ingredient"; import Ingredient from "./Ingredient";
import Drink from "./Drink"; import Drink from "./Drink";
import Container from "./Container"; import Container from "./Container";
import mongoose from "mongoose";
// create a namespace for logging // create a namespace for logging
const log = debug("itender:server"); const log = debug("itender:server");
@ -13,6 +14,7 @@ export class Database {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
try { try {
//connect to mongodb using mongoose //connect to mongodb using mongoose
mongoose.set("strictQuery", false);
await Mongoose.connect("mongodb://127.0.0.1:27017/iTender?retryWrites=true"); await Mongoose.connect("mongodb://127.0.0.1:27017/iTender?retryWrites=true");
log("Connected to Database"); log("Connected to Database");
// Preload the schema for Ingredient, Drink and Container // Preload the schema for Ingredient, Drink and Container

View File

@ -13,6 +13,7 @@ import {IJob} from "../../database/IJob";
import {SensorHelper} from "../../SensorHelper"; import {SensorHelper} from "../../SensorHelper";
import {IContainer} from "../../database/IContainer"; import {IContainer} from "../../database/IContainer";
import {Mixer} from "../../Mixer"; import {Mixer} from "../../Mixer";
import {ArduinoProxy} from "../../ArduinoProxy";
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
@ -168,32 +169,44 @@ router.ws('/', async (ws, req, next) => {
"ambient_color": string "ambient_color": string
} }
await SensorHelper.clearAllRawMeasurements(); await SensorHelper.clearAllRawMeasurements();
let content: { error: boolean, msg: string } = { let content: { success: boolean, msg: string } = {
error: false, success: true,
msg: "" msg: "Prüfung erfolgreich."
}; };
// Check config // Check config
/// Check Proxy /// 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.<br>Technische Details: " + e;
return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content);
}
} }
// Check measurements // Check measurements
await SensorHelper.measureAllRaw(); try {
await SensorHelper.measureAllRaw();
} catch (e) {
content.success = false;
content.msg = e + "<br>Überprüfe die Einstellungen der Sensoren-Pins.";
return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content);
}
for (let c of await Container.find()) { for (let c of await Container.find()) {
if (c.sensorType != SensorType.NONE && c.rawData == -1) { 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.<br>Überprüfe die Einstellungen der Sensoren-Pins."; content.msg = "Container " + (c.slot + 1) + " weist Fehler im Sensor auf.<br>Ü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);
} }
} }
return WebSocketHandler.answerRequest(msg.data["type"] as RequestType, content);
break; break;
} }
case RequestType.TARE: { case RequestType.TARE: {
@ -208,6 +221,8 @@ router.ws('/', async (ws, req, next) => {
} }
} }
let timeouts: NodeJS.Timer[] = [];
async function measureAndSafe() { async function measureAndSafe() {
try { try {
await SensorHelper.measureAllRaw(); await SensorHelper.measureAllRaw();
@ -220,13 +235,15 @@ router.ws('/', async (ws, req, next) => {
// { success: boolean, msg: string } // { 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)
clearTimeout(t);
} }
} }
setTimeout(measureAndSafe, 500); timeouts.push(setTimeout(measureAndSafe, 500));
setTimeout(measureAndSafe, 1000); timeouts.push(setTimeout(measureAndSafe, 1000));
setTimeout(measureAndSafe, 2000); timeouts.push(setTimeout(measureAndSafe, 2000));
setTimeout(measureAndSafe, 3000); timeouts.push(setTimeout(measureAndSafe, 3000));
setTimeout(async () => { setTimeout(async () => {
if (success) { if (success) {

View File

@ -111,7 +111,7 @@ export class Containers {
WebWebSocketHandler.request(RequestType.CONTAINERS).then((payload) => { 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; containerVolumes[container._id] = container.volume;
let option = document.createElement("option"); let option = document.createElement("option");
option.value = container._id; option.value = container._id;
@ -119,10 +119,10 @@ export class Containers {
selectContainer.append(option); selectContainer.append(option);
containers[container._id] = container; containers[container._id] = container;
} }
//containers = payload.data["content"] as IContainer[]; //containers = payload.data as IContainer[];
}); });
WebWebSocketHandler.request(RequestType.INGREDIENTS).then((payload) => { 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"); let option = document.createElement("option");
option.value = ingredient._id; option.value = ingredient._id;
option.innerText = ingredient.name; option.innerText = ingredient.name;

View File

@ -64,7 +64,7 @@ export class Fill {
modal.open().then(() => { modal.open().then(() => {
WebWebSocketHandler.request(RequestType.JOB).then((payload) => { WebWebSocketHandler.request(RequestType.JOB).then((payload) => {
let minus = 0; 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"; ml.innerText = Math.floor((job.completeAmount / job.estimatedTime) * minus) + "ml";
waterAnimDiv.style.setProperty("--fillTime", job.estimatedTime + "s"); waterAnimDiv.style.setProperty("--fillTime", job.estimatedTime + "s");
waterAnimDiv.style.backgroundImage = `url("/images/${job.drink._id}.png")`; waterAnimDiv.style.backgroundImage = `url("/images/${job.drink._id}.png")`;

View File

@ -29,6 +29,22 @@ export class Setup {
const proxyCheckbox = document.getElementById("proxyCheckbox") as HTMLInputElement; const proxyCheckbox = document.getElementById("proxyCheckbox") as HTMLInputElement;
proxyCheckbox.checked = !!payload.data["arduino_proxy_enabled"]; 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"]; ledCheckbox.checked = !!payload.data["led_enabled"];
allowRemoteCheckbox.checked = !!payload.data["remote_enabled"]; allowRemoteCheckbox.checked = !!payload.data["remote_enabled"];
hotspotCheckbox.checked = !!payload.data["hotspot_enabled"]; hotspotCheckbox.checked = !!payload.data["hotspot_enabled"];
@ -80,6 +96,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
const cancelBtn = document.getElementById("setup_cancelBtn") as HTMLButtonElement; const cancelBtn = document.getElementById("setup_cancelBtn") as HTMLButtonElement;
cancelBtn.onclick = () => { cancelBtn.onclick = () => {
let payload = new WebSocketPayload(WebSocketEvent.SETUP, false); let payload = new WebSocketPayload(WebSocketEvent.SETUP, false);
menuBtn.disabled = false;
WebWebSocketHandler.send(payload); WebWebSocketHandler.send(payload);
} }
@ -147,8 +164,6 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
setupSaveBtn.disabled = true; setupSaveBtn.disabled = true;
const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement; const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement;
const ledGPIO = document.getElementById("ledGPIO") as HTMLInputElement; const ledGPIO = document.getElementById("ledGPIO") as HTMLInputElement;
const ambientColor = document.getElementById("ambientColor") 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.<br>D
// Check // Check
let answer = await WebWebSocketHandler.request(RequestType.CHECK, newConf); 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!<br>${answer.data["msg"]}`; ele.innerHTML = `Die Konfiguration weist Fehler auf!<br>${answer.data["msg"]}`;
await errorModal.open(); await errorModal.open();
return; return;
@ -214,6 +229,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
setTimeout(() => { setTimeout(() => {
saveModal.close(); saveModal.close();
this.startTare(); this.startTare();
}, 1000); }, 1000);
@ -223,8 +239,6 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
}); });
menuBtn.disabled = false;
} }
} }
@ -236,6 +250,12 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
tareModal.addButton(ButtonType.PRIMARY, "Nein", () => { tareModal.addButton(ButtonType.PRIMARY, "Nein", () => {
tareModal.close(); 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; let ul;
@ -275,6 +295,10 @@ Alle Sensoren wurden erfolgreich kalibriert.<br>`;
btn.onclick = () => { btn.onclick = () => {
modal.close(); modal.close();
clearInterval(tareInterval); clearInterval(tareInterval);
let event = new Event('click', {bubbles: true});
let btn = document.getElementById("setup_cancelBtn");
if(btn )
btn.dispatchEvent(event);
}; };
} else { } else {
btn.innerText = "Erneut versuchen"; btn.innerText = "Erneut versuchen";
@ -321,19 +345,24 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
// Proxy Label // Proxy Label
let proxyLabel = document.createElement("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); containerDiv.append(proxyLabel);
// Proxy checkbox // Proxy checkbox
let proxyCheckbox = document.createElement("input"); let proxyCheckbox = document.createElement("input");
proxyCheckbox.type = "checkbox"; proxyCheckbox.type = "checkbox";
proxyCheckbox.classList.add("input");
proxyCheckbox.style.marginLeft = "3%";
proxyCheckbox.checked = !!(Setup.usingProxy && container?.useProxy); // Auto Check proxyCheckbox.checked = !!(Setup.usingProxy && container?.useProxy); // Auto Check
proxyCheckbox.disabled = !(Setup.usingProxy); proxyCheckbox.disabled = !(Setup.usingProxy);
this.arduinoProxyCheckboxes.push(proxyCheckbox); this.arduinoProxyCheckboxes.push(proxyCheckbox);
containerDiv.append(proxyCheckbox); proxyLabel.append(proxyCheckbox);
containerDiv.append(document.createElement("br"));
// Pump Pin Selector // Pump Pin Selector
let pumpPinSelect; let pumpPinSelect;
@ -343,7 +372,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
pumpPinSelect = selectPin.cloneNode(true); pumpPinSelect = selectPin.cloneNode(true);
pumpPinSelect.onchange = () => Setup.checkContainers(); pumpPinSelect.onchange = () => Setup.checkContainers();
pumpPinSelect.selectedIndex = 0; pumpPinSelect.selectedIndex = 0;
containerDiv.append(pumpPinSelect); pumpLabel.append(pumpPinSelect);
containerDiv.append(document.createElement("br")); containerDiv.append(document.createElement("br"));
@ -369,7 +398,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
sensorTypeScale.innerText = "Wägezelle"; sensorTypeScale.innerText = "Wägezelle";
sensorTypeScale.value = "1"; sensorTypeScale.value = "1";
sensorType.append(sensorTypeScale); sensorType.append(sensorTypeScale);
containerDiv.append(sensorType); sensorTypeLabel.append(sensorType);
containerDiv.append(document.createElement("br")); containerDiv.append(document.createElement("br"));
@ -429,7 +458,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
pumpPinSelect.append(noSel.cloneNode(true)); pumpPinSelect.append(noSel.cloneNode(true));
sensor1Select.append(noSel.cloneNode(true)); sensor1Select.append(noSel.cloneNode(true));
sensor2Select.append(noSel.cloneNode(true)); sensor2Select.append(noSel.cloneNode(true));
selectPin.selectedIndex = 0; pumpPinSelect.selectedIndex = 0;
sensor1Select.selectedIndex = 0; sensor1Select.selectedIndex = 0;
sensor2Select.selectedIndex = 0; sensor2Select.selectedIndex = 0;
// Add pins // Add pins
@ -483,7 +512,7 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
let containerDiv = document.getElementById("setupContainers") as HTMLDivElement; let containerDiv = document.getElementById("setupContainers") as HTMLDivElement;
containerDiv.innerHTML = ""; containerDiv.innerHTML = "";
let containers = payload.data["content"] as IContainer[]; let containers = payload.data as IContainer[];
for (let c of containers) { for (let c of containers) {
Setup.addSetupContainer(c); Setup.addSetupContainer(c);
} }

View File

@ -46,7 +46,7 @@ export class WebHandler {
drinkEle.onclick = () => { drinkEle.onclick = () => {
WebWebSocketHandler.request(RequestType.STARTFILL, {drink: drink}).then((payload) => { 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) { if (!data.success) {
let modal = new Modal("fill", "Oh nein!"); let modal = new Modal("fill", "Oh nein!");

View File

@ -219,7 +219,7 @@ export class WebWebSocketHandler {
return new Promise(resolve => { return new Promise(resolve => {
WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => { WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
if ((payload.data["type"] as RequestType) == type) { if ((payload.data["type"] as RequestType) == type) {
resolve(payload); resolve(payload.data);
} }
}); });
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, { WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, {

View File

@ -77,19 +77,19 @@ function setupOnClickEvents() {
WebWebSocketHandler.request(RequestType.STATS).then((payload) => { WebWebSocketHandler.request(RequestType.STATS).then((payload) => {
let li = document.createElement("li"); 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); list.append(li);
li = document.createElement("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); list.append(li);
li = document.createElement("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); list.append(li);
li = document.createElement("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); list.append(li);
}); });

View File

@ -22,7 +22,7 @@ block setup
label(onclick="document.getElementById('hotspotCheckbox').checked = !document.getElementById('hotspotCheckbox').checked;") Ohne WiFi Hotspot aktivieren label(onclick="document.getElementById('hotspotCheckbox').checked = !document.getElementById('hotspotCheckbox').checked;") Ohne WiFi Hotspot aktivieren
input#hotspotCheckbox.input(type="checkbox") input#hotspotCheckbox.input(type="checkbox")
div.inputGroup 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") input#proxyCheckbox.input(type="checkbox")