From 243715dab7647faf81315bff568ff0520da05c44 Mon Sep 17 00:00:00 2001 From: Tobias Hopp Date: Tue, 24 Jan 2023 00:34:41 +0100 Subject: [PATCH] V2: Add proxy for pumps and sensors Took 30 minutes --- DOCME.md | 12 +++++++++++ README.md | 18 +++++++++++++++++ package.json | 4 +++- src/HX711.ts | 14 ------------- src/Mixer.ts | 41 +++++++++++++++++++++++++++++++++----- src/MyGPIO.ts | 10 +++++++--- src/SensorHelper.ts | 10 ++++++---- src/database/Container.ts | 1 + src/database/IContainer.ts | 9 +++++++++ typedoc.json | 6 ++++-- yarn.lock | 15 ++++++++++++++ 11 files changed, 111 insertions(+), 29 deletions(-) create mode 100644 DOCME.md delete mode 100644 src/HX711.ts diff --git a/DOCME.md b/DOCME.md new file mode 100644 index 0000000..6c731b1 --- /dev/null +++ b/DOCME.md @@ -0,0 +1,12 @@ +# Willkommen! + +Willkommen im iTender Projekt von Tobias Hopp und Nick Thiele. + +Sie befinden sich in der internen Code-Dokumentation von iTender. + +Hier befinden sich Methoden und Klassen vom iTender, von Web-Client, über die WebSocket-App bis hin zum Server. + +Die Bedienung dieser Dokumentation erscheint anfangs vielleicht holprig, allerdings ist sie leichter als gedacht. + +Du willst vermutlich hier hin -> +[iTender Klasse](classes/iTender.iTender.html) \ No newline at end of file diff --git a/README.md b/README.md index 0662358..4ac1a56 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ # iTender + +Willkommen im iTender Projekt von Tobias Hopp und Nick Thiele. + +Das Projekt ist entstanden in einer Unterrichtseinheit zum Thema Abschlussprojekt. +Wir (Nick und Tobias) dachten zuerst an eine KI gesteuertes Auto, welches allerdings relativ schnell durch den iTender verworfen wurde. + +Der iTender ist längst über dem Niveau eines Schul-Projektes und befindet sich in stetigem Wachstum. +Bereits über 100 Stunden an Programmierarbeit, mehr als 20 Stunden Design sowie 50+ Stunden Dokumentationsaufwand sind in das Projekt geflossen. +Wie man leicht heraus lesen kann, nutzen wir auch viel unserer Freizeit für unser außergewöhnliches Projekt. + + +Das Projekt war anfangs nur sehr einfach geplant, mit einer Möglichkeit aus einer kleinen Liste Drinks zu wählen, welche dann zubereitet werden. +Die Idee lag bei einem kleinen 2-Zeiligem LCD-Display, welches mit einem Drehsensor verbunden ist und dann die Drinks mischt. + +Nun ja, wie man unschwer am Produkt erkennen kann, ist unsere Idee etwas expandiert. +Nicht nur, dass wir kein LCD-Display, sondern ein hochauflösendes Farbdisplay nutzen, viel mehr noch, dass wir eine Cloud, eine vollwertige Benutzeroberfläche, Handy Unterstützung und vieles mehr anbieten. +Die Liste hört grundlegend nicht mehr auf, wird sich aber im Benutzer-Handbuch vom iTender unter Features wiederfinden. + diff --git a/package.json b/package.json index d014950..bf367d6 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "compile": "tsc && webpack", "compileStart": "yarn run compile && yarn start", "watchTS": "tsc --watch", - "watchWP": "webpack --watch" + "watchWP": "webpack --watch", + "doc": "typedoc" }, "dependencies": { "@serialport/parser-readline": "^10.5.0", @@ -37,6 +38,7 @@ "morgan": "^1.10.0", "net-ping": "^1.2.3", "onoff": "^6.0.3", + "pi-hx711": "^1.2.0", "pug": "^3.0.2", "rpi-gpio": "^2.1.7", "rpi-ws281x-native": "^1.0.4", diff --git a/src/HX711.ts b/src/HX711.ts deleted file mode 100644 index 926653b..0000000 --- a/src/HX711.ts +++ /dev/null @@ -1,14 +0,0 @@ -export class HX711 { - private clockPin: number; - private dataPin: number; - - - constructor(dataPin: number, clockPin: number) { - this.clockPin = clockPin; - this.dataPin = dataPin; - } - - public measure(): number { - return 0; - } -} \ No newline at end of file diff --git a/src/Mixer.ts b/src/Mixer.ts index fbe178a..384b3f0 100644 --- a/src/Mixer.ts +++ b/src/Mixer.ts @@ -7,6 +7,9 @@ import {clearInterval} from "timers"; import {IContainer} from "./database/IContainer"; import {iTender} from "./iTender"; import debug from "debug"; +import {ArduinoProxyPayload} from "./ArduinoProxyPayload"; +import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType"; +import {ArduinoProxy} from "./ArduinoProxy"; const isPI = require("detect-rpi"); @@ -54,9 +57,18 @@ export class Mixer { // Start pump here try { - await MyGPIO.setup(x.container.pumpPin, GPIO.DIR_OUT) + if (x.container.pumpProxy) { + let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, { + pin: x.container.pumpPin, + mode: "DIGITAL", + value: 255 + }); + await ArduinoProxy.sendRequest(payload); + } else { + await MyGPIO.setup(x.container.pumpPin, GPIO.DIR_OUT) + await MyGPIO.write(x.container.pumpPin, true); + } - await MyGPIO.write(x.container.pumpPin, true); } catch (e) { if (isPI()) { log("[ERROR] GPIO I/O Error " + e); @@ -83,7 +95,17 @@ export class Mixer { log(`Stopping output of pump ${x.container.pumpPin}`); // Stop pump here try { - await MyGPIO.write(x.container.pumpPin, false); + if (x.container.pumpProxy) { + let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, { + pin: x.container.pumpPin, + mode: "DIGITAL", + "value": 0 + }); + await ArduinoProxy.sendRequest(payload); + } else { + await MyGPIO.write(x.container.pumpPin, false); + } + } catch (e) { if (isPI()) { log("[ERROR] GPIO I/O Error " + e); @@ -143,12 +165,21 @@ export class Mixer { for (let jobIngredient of this._currentJob.amounts) { // stop pump pin try { - await MyGPIO.write(jobIngredient.container.pumpPin, false); + if (jobIngredient.container.pumpProxy) { + let payload = new ArduinoProxyPayload(ArduinoProxyPayloadType.SET_PIN, { + pin: jobIngredient.container.pumpPin, + mode: "DIGITAL", + "value": 0 + }); + await ArduinoProxy.sendRequest(payload); + } else { + await MyGPIO.write(jobIngredient.container.pumpPin, false); + } } catch (e) { } - // ToDo + // ToDo v2 calc let container: IContainer = jobIngredient.container; let deltaStartStop = (this._currentJob.endAt.getTime() - this._currentJob.startedAt.getTime()) / 1000; diff --git a/src/MyGPIO.ts b/src/MyGPIO.ts index 7946ed2..543742b 100644 --- a/src/MyGPIO.ts +++ b/src/MyGPIO.ts @@ -1,6 +1,7 @@ import GPIO from "rpi-gpio"; import Container from "./database/Container"; import debug from "debug"; +import {IContainer} from "./database/IContainer"; const log = debug("itender:gpio"); @@ -45,12 +46,15 @@ export class MyGPIO { let containers = await Container.find({}); for (let c of containers) { try { - if (c.sensorType) { + if (c.sensorType && !c.sensorProxy) { await MyGPIO.setup(c.sensorPin1, GPIO.DIR_IN); await MyGPIO.setup(c.sensorPin2, GPIO.DIR_IN); } - await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT); - await MyGPIO.write(c.pumpPin, false); + if( c.pumpPin && !c.pumpProxy ) + { + await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT); + await MyGPIO.write(c.pumpPin, false); + } } catch (e) { } } diff --git a/src/SensorHelper.ts b/src/SensorHelper.ts index 916f193..f822cef 100644 --- a/src/SensorHelper.ts +++ b/src/SensorHelper.ts @@ -1,11 +1,13 @@ import {IContainer} from "./database/IContainer"; import {SensorType} from "./SensorType"; -import {HX711} from "./HX711"; + import debug from "debug"; import {ArduinoProxyPayload} from "./ArduinoProxyPayload"; import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType"; import {ArduinoProxy} from "./ArduinoProxy"; import Container from "./database/Container"; +import {HCSR04} from "hc-sr04"; +const HX711 = require("pi-hx711"); const log = debug("itender:sensor"); @@ -31,7 +33,7 @@ export class SensorHelper { container.rawData = val.data.value; } else { let sensor = new HX711(container.sensorPin1, container.sensorPin2); - container.rawData = sensor.measure(); + container.rawData = await sensor.readRaw(); } } catch (e) { log("Sensor (Weight cell) of container " + container._id + " is broken or has malfunction - Removing it!"); @@ -42,9 +44,9 @@ export class SensorHelper { } else if (container.sensorType == SensorType.ULTRASOUND) { try { // V2: Measure weight - let sensor = new HX711(container.sensorPin1, container.sensorPin2); + let sensor = new HCSR04(container.sensorPin1, container.sensorPin2); - container.rawData = sensor.measure(); + // container.rawData = sensor.measure(); ToDo } catch (e) { log("Sensor (Ultrasound) of container " + container._id + " is broken or has malfunction - Removing it!"); diff --git a/src/database/Container.ts b/src/database/Container.ts index 6da9447..f5af7b2 100644 --- a/src/database/Container.ts +++ b/src/database/Container.ts @@ -14,6 +14,7 @@ export const ContainerSchema = new Mongoose.Schema({ 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 }, filled: Number, enabled: {type: Boolean, default: false}, }); diff --git a/src/database/IContainer.ts b/src/database/IContainer.ts index dc54275..f05f213 100644 --- a/src/database/IContainer.ts +++ b/src/database/IContainer.ts @@ -19,9 +19,18 @@ export interface IContainer extends mongoose.Document { * HX711 CLOCK-Pin */ sensorPin2: number; + + /** + * Is the arduino used as proxy for the sensor? + */ sensorProxy: boolean rawData: number; pumpPin: number; + + /** + * Is the arduino used as proxy for the pump? + */ + pumpProxy: boolean filled: number; enabled: boolean; } \ No newline at end of file diff --git a/typedoc.json b/typedoc.json index 7cb976c..163fc60 100644 --- a/typedoc.json +++ b/typedoc.json @@ -2,13 +2,15 @@ "entryPoints": [ "src/main.ts", "src/iTender.ts", + "src/Mixer.ts", + "src/ArduinoProxy.ts", "src/web/main.ts", "src/WebsocketApp.ts", "src/App.ts", "src/routes/ws/websocketRoute.ts" ], "out": "docs/", - "readme": "README.md", - "name": "iTender Documentation", + "readme": "DOCME.md", + "name": "iTender internal Code Docs", "tsconfig": "./tsconfig.json" } diff --git a/yarn.lock b/yarn.lock index aa2c111..9dd6f53 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2466,6 +2466,13 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== +pi-hx711@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pi-hx711/-/pi-hx711-1.2.0.tgz#804f954f8c397c4442304118a95dda679fa94d24" + integrity sha512-HuoMIVo+T1wf8jig/VODiE9XYCEBgSfavxLrtG9SF6l8fQQPr618ri3mSQB8oCAoYrNiYA1hEXoH+GdtlKN3Ow== + dependencies: + pigpio "^3.3.1" + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -2476,6 +2483,14 @@ picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +pigpio@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/pigpio/-/pigpio-3.3.1.tgz#fc31885ea2bfb335cccb80b9d78b443fcfe56b90" + integrity sha512-z7J55K14IwWkA+oW5JHzWcgwThFAuJ7IzV3A2//yRm4jJ2DTU0DHIy91DB0siOi12rvvlrIhRetEuAo0ztF/vQ== + dependencies: + bindings "^1.5.0" + nan "^2.14.2" + pkg-dir@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"