Took 2 hours 54 minutes
This commit is contained in:
Tobias Hopp 2023-01-28 16:17:37 +01:00
parent 243715dab7
commit 666f8a93a9
8 changed files with 163 additions and 109 deletions

View File

@ -23,7 +23,9 @@
- [ ] Da nun generell eine Fehlermeldung erscheint, sobald eine Wägezelle inkorrekt läuft, muss vor dem Tarieren (also beim Drücken von Speichern) erst eine CHECK request gesendet werden, danach folgt dann bei erfolgreich die Tarierung
- [ ] Unterstützung von Arduino
- [X] Programmierung der Schnittstelle für Arduino (Proxy)
- [ ] Programmierung des Arduino Codes
- [X] Programmierung des Arduino Codes
- [ ] Automatischer Flash
- [ ] Bei Container erstellung kann optional "Arduino Proxy" angewählt werden
- Danach werden die Daten dieses Containers über den Arduino bezogen
- [ ] Behälter Menü neu designen
- [ ] In den ganzen messfn checken ob überhaupt eingestellt ist, den proxy zu nutzen

View File

@ -57,7 +57,7 @@ export class Mixer {
// Start pump here
try {
if (x.container.pumpProxy) {
if (x.container.useProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, {
pin: x.container.pumpPin,
mode: "DIGITAL",
@ -95,7 +95,7 @@ export class Mixer {
log(`Stopping output of pump ${x.container.pumpPin}`);
// Stop pump here
try {
if (x.container.pumpProxy) {
if (x.container.useProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, {
pin: x.container.pumpPin,
mode: "DIGITAL",
@ -165,7 +165,7 @@ export class Mixer {
for (let jobIngredient of this._currentJob.amounts) {
// stop pump pin
try {
if (jobIngredient.container.pumpProxy) {
if (jobIngredient.container.useProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, {
pin: jobIngredient.container.pumpPin,
mode: "DIGITAL",

View File

@ -46,11 +46,11 @@ export class MyGPIO {
let containers = await Container.find({});
for (let c of containers) {
try {
if (c.sensorType && !c.sensorProxy) {
if (c.sensorType && !c.useProxy) {
await MyGPIO.setup(c.sensorPin1, GPIO.DIR_IN);
await MyGPIO.setup(c.sensorPin2, GPIO.DIR_IN);
}
if( c.pumpPin && !c.pumpProxy )
if( c.pumpPin && !c.useProxy )
{
await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT);
await MyGPIO.write(c.pumpPin, false);

View File

@ -21,7 +21,7 @@ export class SensorHelper {
return new Promise(async (resolve, reject) => {
if (container.sensorType == SensorType.LOADCELL) {
try {
if (container.sensorProxy) {
if (container.useProxy) {
let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.GET_SENSOR, {
pin_data: container.sensorPin1,
pin_clock: container.sensorPin2

View File

@ -13,8 +13,7 @@ export const ContainerSchema = new Mongoose.Schema<IContainer>({
content: {type: mongoose.Types.ObjectId, ref: "Ingredient"},
sensorDelta: Number, // V2: Now sensorDelta - Differenz, welche beim Einstellen der Zutat aus Gewicht(Sensor) - Volumen errechnet wird
sensorTare: Number, // V2: Now sensorTare
sensorProxy: {type: Boolean, default: false},
pumpProxy: { type: Boolean, default: false },
useProxy: { type: Boolean, default: false },
filled: Number,
enabled: {type: Boolean, default: false},
});

View File

@ -21,16 +21,12 @@ export interface IContainer extends mongoose.Document {
sensorPin2: number;
/**
* Is the arduino used as proxy for the sensor?
* Is the arduino used as proxy?
*/
sensorProxy: boolean
useProxy: boolean
rawData: number;
pumpPin: number;
/**
* Is the arduino used as proxy for the pump?
*/
pumpProxy: boolean
filled: number;
enabled: boolean;
}

View File

@ -33,11 +33,23 @@ export class Modal {
}
/**
* Adds an html element to the modal
* @param element
*/
public addContent(element: HTMLElement) {
this._elements.push(element);
}
/**
* Adds a spacer line to the modal
*/
public addBR() {
this.addContent(document.createElement("br"));
}
set id(value: string) {
this._id = value;
}
@ -130,10 +142,19 @@ export class Modal {
}
/**
* Closes the modal
*/
public close(): void {
Modal.close(this._id);
}
/**
* Closes the modal with id
* @param id The id of the modal
*/
public static close(id?: string): void {
if (id && this.currentModalId != id)
return;

View File

@ -11,17 +11,28 @@ import {RequestType} from "../RequestType";
export class Setup {
private static usingProxy = false;
private static pins_pi = [3, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 35, 36, 37, 38];
private static pins_arduino = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53];
public static arduinoProxyCheckboxes: HTMLInputElement[] = [];
public static onConfigUpdate(payload: WebSocketPayload) {
// Setup containers updated
const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement;
const ledGPIO = document.getElementById("ledGPIO") as HTMLInputElement;
const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement;
const ambientColor = document.getElementById("ambientColor") as HTMLInputElement;
const allowRemoteCheckbox = document.getElementById("allowRemoteCheckbox") as HTMLInputElement;
const hotspotCheckbox = document.getElementById("hotspotCheckbox") as HTMLInputElement;
const proxyCheckbox = document.getElementById("proxyCheckbox") as HTMLInputElement;
proxyCheckbox.checked = !!payload.data["arduino_proxy_enabled"];
ledCheckbox.checked = !!payload.data["led_enabled"];
allowRemoteCheckbox.checked = !!payload.data["remote_enabled"];
hotspotCheckbox.checked = !!payload.data["hotspot_enabled"];
if (payload.data["led_gpio"]) {
ledGPIO.value = payload.data["led_gpio"];
}
@ -31,6 +42,8 @@ export class Setup {
}
(document.getElementById("setup_cancelBtn") as HTMLButtonElement).disabled = !payload.data["setupDone"];
if (!payload.data["setupDone"]) {
let modal = new Modal("setup", "Willkommen!");
let txt = document.createElement("p");
@ -71,7 +84,9 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
}
const containerAddBtn = document.getElementById("containerAddBtn") as HTMLButtonElement;
containerAddBtn.onclick = Setup.addSetupContainer;
containerAddBtn.onclick = () => {
Setup.addSetupContainer()
};
const setupSaveBtn = document.getElementById("setup_saveBtn") as HTMLButtonElement;
@ -82,7 +97,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
let ele = document.createElement("p");
ele.innerHTML = `Das Setup konnte nicht abgeschlossen werden.<br>`;
errorModal.addContent(ele);
errorModal.addContent(document.createElement("br"));
errorModal.addBR();
errorModal.addButton(ButtonType.PRIMARY, "Schließen", () => {
errorModal.close();
});
@ -106,7 +121,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
}
if (selects[1].value == "0") {
ele.innerHTML += `Die Sensorart Ultraschall wird nicht mehr unterstützt.<br>Sollten Sie diesen Support wünschen wenden Sie sich an den Kundensupport.`;
ele.innerHTML += `Die Sensorart Ultraschall wird nicht mehr unterstützt.<br>Sollten Sie diese Funktion wünschen wenden Sie sich an den Kundensupport.`;
errorModal.open();
return;
}
@ -146,7 +161,8 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
const proxyCheckbox = document.getElementById("proxyCheckbox") as HTMLInputElement;
let cons: { pumpPin: number; sensorType: SensorType; sensor1: number; sensor2: number; volume: number; }[] = [];
// Containers
let cons: { pumpPin: number; sensorType: SensorType; sensor1: number; sensor2: number; useProxy: boolean }[] = [];
for (let c of (document.getElementById("setupContainers") as HTMLDivElement).getElementsByTagName("div")) {
let sensorType = c.getElementsByTagName("select")[1].value;
let type;
@ -158,11 +174,11 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
type = SensorType.LOADCELL;
cons.push({
"useProxy": (c.getElementsByTagName("input")[0] as HTMLInputElement).checked,
"pumpPin": parseInt(c.getElementsByTagName("select")[0].value),
"sensorType": type,
"sensor1": parseInt(c.getElementsByTagName("select")[2].value),
"sensor2": parseInt(c.getElementsByTagName("select")[3].value),
"volume": parseInt(c.getElementsByTagName("select")[4].value)
"sensor2": parseInt(c.getElementsByTagName("select")[3].value)
});
}
@ -177,12 +193,13 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
"led_gpio": parseInt(ledGPIO.value),
"ambient_color": ambientColor.value
});
menuBtn.disabled = false;
WebWebSocketHandler.send(payload).then(() => {
setTimeout(() => {
saveModal.close();
setupSaveBtn.disabled = false;
this.startTare();
}, 1000);
@ -191,6 +208,7 @@ Dort werden die Behälter definiert, welche in den iTender gestellt werden.<br>D
txt.innerHTML = `Fehler beim Speichern.<br>iTender hat nicht reagiert.`;
setTimeout(() => saveModal.close(), 2500);
});
menuBtn.disabled = false;
}
@ -261,54 +279,67 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
}
public static addSetupContainer() {
public static addSetupContainer(container?: IContainer) {
let setupContainers = document.getElementById("setupContainers") as HTMLDivElement;
let con = document.createElement("div");
// Div
let containerDiv = document.createElement("div");
if (container)
containerDiv.id = container._id;
// Name
let containerName = document.createElement("p");
containerName.innerText = "Behälter " + (setupContainers.getElementsByTagName("div").length + 1);
con.classList.add("setupContainer");
con.append(containerName);
containerDiv.classList.add("setupContainer");
containerDiv.append(containerName);
// General Pin Select
let selectPin = document.createElement("select");
selectPin.style.display = "none";
selectPin.classList.add("input");
selectPin.style.display = "inline";
// NoSelect in Pin Select
let noSel = document.createElement("option") as HTMLOptionElement;
noSel.innerText = "Bitte wählen";
noSel.value = "-1";
noSel.disabled = true;
selectPin.append(noSel.cloneNode(true));
selectPin.selectedIndex = 0;
// 3,5,7,8,10,11,12,13,15,16,18,19,21,22,23,24,26,29,31,32,33,35,36,37,38,40
const pins = [3, 7, 8, 10, 11, 12, 13, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 35, 36, 37, 38];
for (let pin of pins) {
let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + pin;
pinEle.value = "" + pin;
selectPin.append(pinEle);
}
// Proxy Label
let proxyLabel = document.createElement("label");
proxyLabel.innerText = "Pumpen Pin";
containerDiv.append(proxyLabel);
// Proxy checkbox
let nSelect;
let proxyCheckbox = document.createElement("input");
proxyCheckbox.type = "checkbox";
proxyCheckbox.checked = !!(Setup.usingProxy && container?.useProxy); // Auto Check
proxyCheckbox.disabled = !(Setup.usingProxy);
this.arduinoProxyCheckboxes.push(proxyCheckbox);
containerDiv.append(proxyCheckbox);
// Pump Pin Selector
let pumpPinSelect;
let pumpLabel = document.createElement("label");
pumpLabel.innerText = "Pumpen Pin";
con.append(pumpLabel);
nSelect = selectPin.cloneNode(true);
nSelect.onchange = () => Setup.checkContainers();
nSelect.selectedIndex = 0;
con.append(nSelect);
containerDiv.append(pumpLabel);
pumpPinSelect = selectPin.cloneNode(true);
pumpPinSelect.onchange = () => Setup.checkContainers();
pumpPinSelect.selectedIndex = 0;
containerDiv.append(pumpPinSelect);
con.append(document.createElement("br"));
containerDiv.append(document.createElement("br"));
// Sensor Art
// Sensor Type Label
let sensorTypeLabel = document.createElement("label");
sensorTypeLabel.innerText = "Sensor Art ";
con.append(sensorTypeLabel);
containerDiv.append(sensorTypeLabel);
// Sensor Type Select
let sensorType = document.createElement("select");
sensorType.classList.add("noCheckup");
sensorType.classList.add("input");
@ -324,30 +355,33 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
sensorTypeScale.innerText = "Wägezelle";
sensorTypeScale.value = "1";
sensorType.append(sensorTypeScale);
con.append(sensorType);
con.append(document.createElement("br"));
containerDiv.append(sensorType);
containerDiv.append(document.createElement("br"));
// Sensor 1
// Sensor 1 Label
let sensor1Label = document.createElement("label");
sensor1Label.innerText = "Sensor 1 Pin";
con.append(sensor1Label);
containerDiv.append(sensor1Label);
// Sensor 1 Pin Select
let sensor1Select = selectPin.cloneNode(true) as HTMLSelectElement;
sensor1Select.selectedIndex = 0;
sensor1Select.disabled = true;
sensor1Select.onchange = () => Setup.checkContainers();
con.append(sensor1Select);
containerDiv.append(sensor1Select);
con.append(document.createElement("br"));
containerDiv.append(document.createElement("br"));
// Sensor 2
// Sensor 2 Label
let sensor2Label = document.createElement("label");
sensor2Label.innerText = "Sensor 2 Pin";
con.append(sensor2Label);
containerDiv.append(sensor2Label);
// Sensor 2 Pin Select
let sensor2Select = selectPin.cloneNode(true) as HTMLSelectElement;
sensor2Select.selectedIndex = 0;
sensor2Select.disabled = true;
sensor2Select.onchange = () => Setup.checkContainers();
con.append(sensor2Select);
containerDiv.append(sensor2Select);
sensorType.onchange = () => {
if (sensorType.value == "0") {
@ -367,49 +401,66 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
sensor2Select.disabled = true;
}
};
con.append(document.createElement("br"));
containerDiv.append(document.createElement("br"));
// Volume
let volumeLabel = document.createElement("label");
volumeLabel.innerText = "Volumen (ml) ";
//con.append(volumeLabel);
let volumeSelect = document.createElement("select");
volumeSelect.classList.add("noCheckup");
volumeSelect.classList.add("input");
const mls = [50, 100, 200, 250, 300, 330, 500, 750, 1000, 1250, 1500, 2000, 2500, 5000, 10000];
for (let ml of mls) {
let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + ml;
pinEle.value = "" + ml;
volumeSelect.append(pinEle);
volumeSelect["volume"] = volumeSelect;
// Proxy On change needs to be at the end to get all vars
proxyCheckbox.onchange = () => {
// Clear pins
pumpPinSelect.innerHTML = '';
sensor1Select.innerHTML = '';
sensor2Select.innerHTML = '';
// Set no-val
pumpPinSelect.append(noSel.cloneNode(true));
sensor1Select.append(noSel.cloneNode(true));
sensor2Select.append(noSel.cloneNode(true));
selectPin.selectedIndex = 0;
sensor1Select.selectedIndex = 0;
sensor2Select.selectedIndex = 0;
// Add pins
for (let pin of (proxyCheckbox.checked ? Setup.pins_arduino : Setup.pins_pi)) {
let pinEle = document.createElement("option") as HTMLOptionElement;
pinEle.innerText = "" + pin;
pinEle.value = "" + pin;
pumpPinSelect.append(pinEle.cloneNode(true));
sensor1Select.append(pinEle.cloneNode(true));
sensor2Select.append(pinEle.cloneNode(true));
}
};
// Needs to be after selectPin.append because noSel-Pin should always be at pos 0
let event = new Event('change', {bubbles: true});
proxyCheckbox.dispatchEvent(event); // Trigger virtual onChange event
// Auto selects (if container is given as arg) needs to be after the event, because the pin selectors may not there
if (container) {
pumpPinSelect.value = String(container.pumpPin);
sensor1Select.value = String(container.sensorPin1);
sensor2Select.value = String(container.sensorPin2);
}
volumeSelect.selectedIndex = 7;
//con.append(volumeSelect);
let removeBtn = document.createElement("button");
removeBtn.classList.add("btn", "btn-danger");
removeBtn.onclick = () => {
con.classList.add("removeSlowly");
containerDiv.classList.add("removeSlowly");
setTimeout(() => {
con.remove();
containerDiv.remove();
let i = 1;
for (let elementsByTagNameElement of setupContainers.getElementsByTagName("div")) {
let e = elementsByTagNameElement.getElementsByTagName("p")[0] as HTMLParagraphElement;
e.innerText = "Behälter " + i;
e.innerText = "Behälter " + i + (containerDiv.id.length != 0 ? " [" + containerDiv.id.substring(containerDiv.id.length - 3) + "]" : "");
i++;
}
}, 750);
}
removeBtn.style.float = "right";
removeBtn.innerText = "Entfernen";
con.append(removeBtn);
removeBtn.innerText = "Löschen";
containerDiv.append(removeBtn);
setupContainers.append(con);
setupContainers.append(containerDiv);
}
@ -420,46 +471,28 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
let containers = payload.data["content"] as IContainer[];
for (let c of containers) {
Setup.addSetupContainer();
Setup.addSetupContainer(c);
}
let i = 0;
let list = containerDiv.getElementsByTagName("div");
for (let c of containers) {
let current = list[i] as HTMLDivElement;
let selects = current.getElementsByTagName("select");
(selects[0] as HTMLSelectElement).value = c.pumpPin.toString();
let type;
if (c.sensorType == SensorType.NONE)
type = "-1";
else if (c.sensorType == SensorType.ULTRASOUND)
type = "0";
else
type = "1";
(selects[1] as HTMLSelectElement).value = type;
(selects[2] as HTMLSelectElement).value = c.sensorPin1.toString();
(selects[3] as HTMLSelectElement).value = c.sensorPin2.toString();
let event = new Event('change', {bubbles: true});
selects[1].dispatchEvent(event);
i++;
}
}
public static checkContainers(): boolean {
console.log("Checking containers...")
console.log("Checking containers...");
let returner = true;
const containers = document.getElementById("setupContainers") as HTMLDivElement;
let setupContainers = containers.getElementsByTagName("div");
for (let c of setupContainers) {
for (let c2 of setupContainers) {
for (let sel of c.getElementsByTagName("select")) {
if (sel.value == "-1") continue;
if (sel.value == "-1") continue; // maybe this shit
if (sel.classList.contains("noCheckup")) continue;
if (sel.disabled) continue;
let cIsProxy: HTMLInputElement = c.getElementsByTagName("input")[0];
for (let sel2 of c2.getElementsByTagName("select")) {
if (sel2.value == "-1") continue;
@ -467,8 +500,11 @@ Mindestens ein Sensor konnte nicht kalibriert werden.<br>${data.msg}<br>`;
if (sel == sel2) continue;
if (sel2.classList.contains("noCheckup")) continue;
let c2IsProxy: HTMLInputElement = c2.getElementsByTagName("input")[0];
if (sel.value == sel2.value) {
// Check if the two pins are the same, but also checks if one is using proxy, or another one is not using it
if (sel.value == sel2.value && cIsProxy.checked == c2IsProxy.checked) {
c.classList.add("error");
c2.classList.add("error");
sel.classList.add("error");