Update many stuff, see toDo

Took 9 seconds
This commit is contained in:
Tobias Hopp 2023-01-11 18:34:17 +01:00
parent 05fa75f63c
commit cb72920611
16 changed files with 2540 additions and 2103 deletions

26
ToDo.md
View File

@ -2,10 +2,10 @@
- [ ] Behälter unten rechts anzeigen - [ ] Behälter unten rechts anzeigen
- [ ] Status für Netzwerk oben neben Uhrzeit - [ ] Status für Netzwerk oben neben Uhrzeit
- [ ] Fix Fehler, wenn keine Getränke hinzugefügt worden sind - [ ] ~~Fix Fehler, wenn keine Getränke hinzugefügt worden sind~~
- [ ] Schriftarten Lokal machen - [x] Schriftarten Lokal machen
- [x] Probleme beim Laden der Container im Setup - [x] Probleme beim Laden der Container im Setup
- [ ] Container option "Auto tare" hinzufügen - [ ] ~~Container option "Auto tare" hinzufügen~~
- Heißt, sobald ein Inhalt in einen Container eingestellt wird und das Volumen angegeben ist, werden die Sensoren auf den aktuellen Füllstand als 100% gesetzt - Heißt, sobald ein Inhalt in einen Container eingestellt wird und das Volumen angegeben ist, werden die Sensoren auf den aktuellen Füllstand als 100% gesetzt
- [ ] Nach Speichern des Setups und bei Einmessen auf Schließen, Setup verlassen - [ ] Nach Speichern des Setups und bei Einmessen auf Schließen, Setup verlassen
@ -13,11 +13,17 @@
------ ------
# New # New
- Gesamtvolumen des Containers komplett entfernen - [X] Gesamtvolumen des Containers in fill status entfernen
- Bei Behälter aktualisieren wird das Volumen des neu zu stellendes Behälters eingestellt, welches dann als 100% interpretiert wird - [X] Bei Behälter aktualisieren wird das Volumen des neu zu stellendes Behälters eingestellt, welches dann als 100% interpretiert wird
- Im Setup kommt ein neues Feature, tarieren von Wägezelle (also der 0-Wert der Wägezelle) nach Speicherung, anstatt aktueller 2-Wege-Tarierung - [X] Im Setup kommt ein neues Feature, tarieren von Wägezelle (also der 0-Wert der Wägezelle) nach Speicherung, anstatt aktueller 2-Wege-Tarierung
- Ultraschallsensor wird entfernt - [X] Ultraschallsensor wird entfernt
- Wenn Sensorik für Behälter vorhanden ist, nutze Wägezelle des Containers und messe anhand dessen Inhaltsmenge - [X] Wenn Sensorik für Behälter vorhanden ist, nutze Wägezelle des Containers und messe anhand dessen Inhaltsmenge
- 1G=1ML - 1G=1ML
- Bei Einstellung neues Inhalts wird das Gewicht als ml übersetzt, danach wird Gewicht-Eingestellte Millitier gerechnet, das Ergebnis ist das Gewicht des Behälters - [X] Bei Einstellung neues Inhalts wird das Gewicht als ml übersetzt, danach wird Gewicht-Eingestellte Millitier gerechnet, das Ergebnis ist das Gewicht des Behälters
- 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 - [ ] 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
- [ ] Automatischer Flash
- [ ] Bei Container erstellung kann optional "Arduino Proxy" angewählt werden
- Danach werden die Daten dieses Containers über den Arduino bezogen

View File

@ -6,7 +6,7 @@ if [ "$EUID" -ne 0 ]; then
fi fi
echo "Creating user if not exists" echo "Creating user if not exists"
adduser itender || true useradd -p $(openssl passwd -1 iTender2022) itender || true
echo "Updating indexes" echo "Updating indexes"
apt update apt update
@ -52,6 +52,13 @@ echo "Installing mongodb and yarn..."
apt install nodejs yarn mongodb-org -y apt install nodejs yarn mongodb-org -y
apt upgrade -y apt upgrade -y
# V2: Arduino CLI
echo "Installing arduino-cli..."
sudo -u itender mkdir -p /home/itender/bin
sudo -u itender sh -c 'curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | BINDIR=/home/itender/bin/ sh'
sudo -u itender /home/itender/bin/arduino-cli config init
sudo -u itender /home/itender/bin/arduino-cli core update-index || true
echo "Installing autostart..." echo "Installing autostart..."
# Autostart # Autostart
cat <<EOT >/etc/xdg/openbox/autostart cat <<EOT >/etc/xdg/openbox/autostart
@ -98,7 +105,8 @@ if [ -d "$DIR" ]; then
git pull git pull
else else
echo "Cloning..." echo "Cloning..."
sudo git config --global credential.helper store || exit sudo -u itender git config --global credential.helper store
git config --global credential.helper store
git clone "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet git clone "https://tobiash:!IwedwrimmVeudiweN!@git.gaminggeneration.de/tobiash/itender.git" --quiet
fi fi
cd "$DIR" || exit cd "$DIR" || exit
@ -139,6 +147,7 @@ WantedBy=multi-user.target
EOT EOT
#sh -c "git pull --quiet || true" #sh -c "git pull --quiet || true"
echo "Activating systemctl daemons..." echo "Activating systemctl daemons..."
systemctl daemon-reload systemctl daemon-reload
systemctl enable mongod systemctl enable mongod
@ -178,6 +187,7 @@ if ! grep -w "gpu_freq=700" /boot/config.txt; then
echo "gpu_freq=700" >>/boot/config.txt echo "gpu_freq=700" >>/boot/config.txt
fi fi
echo "Setting no-logo..." echo "Setting no-logo..."
systemctl disable getty@tty1.service systemctl disable getty@tty1.service
@ -191,7 +201,7 @@ if ! grep -w "logo.nologo" /boot/cmdline.txt; then
sed -i 's/console=tty0/console=tty3/' /boot/cmdline.txt sed -i 's/console=tty0/console=tty3/' /boot/cmdline.txt
fi fi
echo "iTender 2022 echo "iTender© 2022-2023
Programmed by Tobias Hopp" >/etc/motd Programmed by Tobias Hopp" >/etc/motd
echo "[Service] echo "[Service]
@ -201,4 +211,6 @@ chown itender:itender -R /home/itender/
adduser itender gpio adduser itender gpio
adduser itender sudo adduser itender sudo
echo "Installation finished!"
reboot now reboot now

81
getSerialList.js Normal file
View File

@ -0,0 +1,81 @@
const { SerialPort } = require('serialport');
const { ReadlineParser } = require('@serialport/parser-readline');
( async( ) => {
console.log( await SerialPort.list() );
let port = new SerialPort( { path: '/dev/ttyS11', baudRate: 9600 } );
/*port.on('data', function (data) {
console.log('Data:', data.toString())
})*/
port.close()
let callbacks = {};
function request()
{
return new Promise((resolve, reject) => {
let id = makeid(8);
console.log(id);
let req = {
id: id,
type: "REQUEST",
data: "1,2"
}
callbacks[req.id] = resolve;
let done = false;
setTimeout( () => {
if( !done )
reject("Request with id " + id + " timed out");
}, 15000 );
port.write(JSON.stringify(req) + "\r", "utf-8");
});
}
const parser = port.pipe(new ReadlineParser({ delimiter: '\r' }))
parser.on('data', (data) => {
/*let req = {
id: id,
type: "ACK",
data: "1,2"
}*/
data = data.toString().trim();
let json = JSON.parse(data);
console.log("GOT: " + data );
callbacks[json.id]();
});
try {
await request();
console.log("FUNCTION RESOLVED YAY!");
} catch( e )
{
console.error(e);
}
} )();
function makeid(length) {
var result = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var i = 0; i < length; i++ ) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}

View File

@ -13,6 +13,7 @@
"watchWP": "webpack --watch" "watchWP": "webpack --watch"
}, },
"dependencies": { "dependencies": {
"@serialport/parser-readline": "^10.5.0",
"@types/cookie-parser": "^1.4.3", "@types/cookie-parser": "^1.4.3",
"@types/debug": "^4.1.7", "@types/debug": "^4.1.7",
"@types/express": "^4.17.14", "@types/express": "^4.17.14",
@ -22,6 +23,7 @@
"@types/node": "^18.11.9", "@types/node": "^18.11.9",
"@types/rpi-gpio": "^2.1.1", "@types/rpi-gpio": "^2.1.1",
"@types/rpi-ws281x-native": "^1.0.0", "@types/rpi-ws281x-native": "^1.0.0",
"@types/serialport": "^8.0.2",
"axios": "^1.2.0", "axios": "^1.2.0",
"buffer": "^6.0.3", "buffer": "^6.0.3",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
@ -37,7 +39,8 @@
"onoff": "^6.0.3", "onoff": "^6.0.3",
"pug": "2.0.0-beta11", "pug": "2.0.0-beta11",
"rpi-gpio": "^2.1.7", "rpi-gpio": "^2.1.7",
"rpi-ws281x-native": "^1.0.4" "rpi-ws281x-native": "^1.0.4",
"serialport": "^10.5.0"
}, },
"devDependencies": { "devDependencies": {
"nodemon": "^2.0.20", "nodemon": "^2.0.20",

93
src/ArduinoProxy.ts Normal file
View File

@ -0,0 +1,93 @@
import SerialPort from "serialport";
import debug from "debug";
import {ArduinoProxyPayload} from "./ArduinoProxyPayload";
import {Utils} from "./Utils";
import {ReadlineParser} from "@serialport/parser-readline";
const log = debug("itender:arduinoProxy");
export class ArduinoProxy {
private static serialPort;
private static callbacks: Record<string, { resolve: Function, reject: Function }> = {};
private static encoding: string = "utf-8";
private static onData(data) {
data = data.toString().trim();
try {
let json = JSON.parse(data) as ArduinoProxyPayload;
if (this.callbacks[json.id]) {
this.callbacks[json.id].resolve(json);
delete this.callbacks[json.id];
log("Answered request " + json.id);
} else {
log("ERROR - Got an response from arduino but we are not waiting for it?");
}
} catch (e) {
log("ERROR - Got an invalid response from arduino?");
}
}
public static connect() {
return new Promise<void>(async (resolve, reject) => {
// @ts-ignore
let list = await SerialPort.list()
let arduino = list.find((ele) => {
return ele.manufacturer == "Arduino";
});
if (!arduino) {
return reject("No arduino found");
}
// @ts-ignore
this.serialPort = new SerialPort({
path: arduino.path,
baudRate: 9600,
autoOpen: false,
});
this.serialPort.open((err: Error | null | undefined) => {
if (err) {
log("Error whilst connecting to proxy (open serial-connection)");
log(err.name + "\n" + err.message + "\n" + err.stack);
return reject(err.name);
}
// @ts-ignore
const parser = this.serialPort.pipe(new ReadlineParser({delimiter: '\r'}));
parser.on('data', (data) => this.onData(data));
resolve();
});
});
}
public static disconnect() {
if (this.serialPort.isOpen) {
this.serialPort.close((err) => {
this.serialPort = null;
});
}
}
public static sendRequest(request: ArduinoProxyPayload, timeout: number = 1000) {
return new Promise<ArduinoProxyPayload>((resolve, reject) => {
let id = Utils.generateRandomString(8);
request.id = id;
this.callbacks[id] = {resolve: resolve, reject: reject};
this.serialPort.write(JSON.stringify(request), ArduinoProxy.encoding, (err: Error | null | undefined) => {
if (err) {
reject("I/O error on request " + id);
}
});
setTimeout(() => {
reject("Timeout on request " + id);
delete this.callbacks[id];
}, timeout);
});
}
}

View File

@ -0,0 +1,35 @@
import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType";
import {ArduinoProxy} from "./ArduinoProxy";
export class ArduinoProxyPayload {
set id(value: string) {
this._id = value;
}
private readonly _type: ArduinoProxyPayloadType;
private readonly _data: any;
private _id: string ="";
constructor(type: ArduinoProxyPayloadType, data: any) {
this._type = type;
this._data = data;
}
get type(): ArduinoProxyPayloadType {
return this._type;
}
get data(): any {
return this._data;
}
get id(): string {
return this._id;
}
public send() {
return ArduinoProxy.sendRequest(this);
}
}

View File

@ -0,0 +1,7 @@
export enum ArduinoProxyPayloadType {
ACK="ACK",
SET_PIN="SET_PIN",
GET_VAL="GET_VAL",
GET_SENSOR="GET_SENSOR",
RESTART="RESTART",
}

View File

View File

@ -5,5 +5,7 @@ export enum RequestType {
JOB = "JOB", JOB = "JOB",
STARTFILL = "STARTFILL", STARTFILL = "STARTFILL",
STOPFILL = "STOPFILL", STOPFILL = "STOPFILL",
DOWNLOAD_DRINKS = "DOWNLOAD_DRINKS" DOWNLOAD_DRINKS = "DOWNLOAD_DRINKS",
TARE = "TARE",
CHECK = "CHECK",
} }

View File

@ -84,4 +84,14 @@ export class Utils {
} }
static generateRandomString(number: number) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
}
} }

View File

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

View File

@ -12,6 +12,7 @@ export interface IContainer extends mongoose.Document {
sensorType: SensorType; sensorType: SensorType;
sensorPin1: number; sensorPin1: number;
sensorPin2: number; sensorPin2: number;
sensorProxy: boolean
rawData: number; rawData: number;
pumpPin: number; pumpPin: number;
filled: number; filled: number;

View File

@ -470,13 +470,31 @@ export class iTender {
}); });
} }
public static clearAllRawMeasurements()
{
return new Promise<void>(async (resolve, reject) => {
for (let c of (await Container.find({}))) {
if (c.sensorType != SensorType.NONE) {
c.rawData = -1;
await c.save();
}
}
resolve();
})
}
public static measureAllRaw() { public static measureAllRaw() {
return new Promise<void>(async (resolve, reject) => { return new Promise<void>(async (resolve, reject) => {
for (let c of (await Container.find({}))) { for (let c of (await Container.find({}))) {
if (c.sensorType != SensorType.NONE) { if (c.sensorType != SensorType.NONE) {
let weight = SensorHelper.measure(c); let weight : number | null = c.rawData;
if (weight == null) { if( !c.sensorProxy )
{
// Check values
weight = SensorHelper.measure(c);
}
if (weight == null || weight > 1000 || weight < 0 ) { //fixme werte
// Problem erkannt! // Problem erkannt!
return reject("Fehler Sensor (" + c.sensorPin1 + ", " + c.sensorPin2 + ") - Container " + c.slot + 1); return reject("Fehler Sensor (" + c.sensorPin1 + ", " + c.sensorPin2 + ") - Container " + c.slot + 1);
} }

View File

@ -157,6 +157,37 @@ router.ws('/', async (ws, req, next) => {
WebSocketHandler.answerRequest(msg.data["type"] as RequestType, "ok"); WebSocketHandler.answerRequest(msg.data["type"] as RequestType, "ok");
break; break;
} }
case RequestType.CHECK: {
await iTender.clearAllRawMeasurements();
let content : {error: boolean, msg: string} = {
error: false,
msg: ""
};
// Check config
/// Check Proxy
if( Settings.get("arduino_proxy_enabled") == true )
{
}
// Check measurements
await iTender.measureAllRaw();
for( let c of await Container.find() )
{
if( c.sensorType != SensorType.NONE && c.rawData == -1 )
{
content.error = true;
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);
}
}
break;
}
case RequestType.TARE: { case RequestType.TARE: {
let type = msg.data["type"]; let type = msg.data["type"];
// Start TARE // Start TARE

View File

@ -21,6 +21,9 @@ block setup
div.inputGroup div.inputGroup
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
label(onclick="document.getElementById('proxyCheckbox').checked = !document.getElementById('proxyCheckbox').checked;") Arduino Mega als Proxy erlauben
input#proxyCheckbox.input(type="checkbox")
div#setupContainersDiv div#setupContainersDiv
@ -52,6 +55,7 @@ block menu
block settings block settings
// Settings // Settings
button.btn.btn-primary#settings_refreshDrinks Getränke herunterladen button.btn.btn-primary#settings_refreshDrinks Getränke herunterladen
button.btn.btn-primary#settings_update System aktualisieren

4305
yarn.lock

File diff suppressed because it is too large Load Diff