V2: Add proxy for pumps and sensors
Took 30 minutes
This commit is contained in:
parent
c9a0ac68c4
commit
243715dab7
12
DOCME.md
Normal file
12
DOCME.md
Normal file
@ -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)
|
18
README.md
18
README.md
@ -1 +1,19 @@
|
|||||||
# iTender
|
# 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.
|
||||||
|
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
"compile": "tsc && webpack",
|
"compile": "tsc && webpack",
|
||||||
"compileStart": "yarn run compile && yarn start",
|
"compileStart": "yarn run compile && yarn start",
|
||||||
"watchTS": "tsc --watch",
|
"watchTS": "tsc --watch",
|
||||||
"watchWP": "webpack --watch"
|
"watchWP": "webpack --watch",
|
||||||
|
"doc": "typedoc"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@serialport/parser-readline": "^10.5.0",
|
"@serialport/parser-readline": "^10.5.0",
|
||||||
@ -37,6 +38,7 @@
|
|||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"net-ping": "^1.2.3",
|
"net-ping": "^1.2.3",
|
||||||
"onoff": "^6.0.3",
|
"onoff": "^6.0.3",
|
||||||
|
"pi-hx711": "^1.2.0",
|
||||||
"pug": "^3.0.2",
|
"pug": "^3.0.2",
|
||||||
"rpi-gpio": "^2.1.7",
|
"rpi-gpio": "^2.1.7",
|
||||||
"rpi-ws281x-native": "^1.0.4",
|
"rpi-ws281x-native": "^1.0.4",
|
||||||
|
14
src/HX711.ts
14
src/HX711.ts
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
41
src/Mixer.ts
41
src/Mixer.ts
@ -7,6 +7,9 @@ import {clearInterval} from "timers";
|
|||||||
import {IContainer} from "./database/IContainer";
|
import {IContainer} from "./database/IContainer";
|
||||||
import {iTender} from "./iTender";
|
import {iTender} from "./iTender";
|
||||||
import debug from "debug";
|
import debug from "debug";
|
||||||
|
import {ArduinoProxyPayload} from "./ArduinoProxyPayload";
|
||||||
|
import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType";
|
||||||
|
import {ArduinoProxy} from "./ArduinoProxy";
|
||||||
|
|
||||||
const isPI = require("detect-rpi");
|
const isPI = require("detect-rpi");
|
||||||
|
|
||||||
@ -54,9 +57,18 @@ export class Mixer {
|
|||||||
|
|
||||||
// Start pump here
|
// Start pump here
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
if (isPI()) {
|
if (isPI()) {
|
||||||
log("[ERROR] GPIO I/O Error " + e);
|
log("[ERROR] GPIO I/O Error " + e);
|
||||||
@ -83,7 +95,17 @@ export class Mixer {
|
|||||||
log(`Stopping output of pump ${x.container.pumpPin}`);
|
log(`Stopping output of pump ${x.container.pumpPin}`);
|
||||||
// Stop pump here
|
// Stop pump here
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
if (isPI()) {
|
if (isPI()) {
|
||||||
log("[ERROR] GPIO I/O Error " + e);
|
log("[ERROR] GPIO I/O Error " + e);
|
||||||
@ -143,12 +165,21 @@ export class Mixer {
|
|||||||
for (let jobIngredient of this._currentJob.amounts) {
|
for (let jobIngredient of this._currentJob.amounts) {
|
||||||
// stop pump pin
|
// stop pump pin
|
||||||
try {
|
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) {
|
} catch (e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToDo
|
// ToDo v2 calc
|
||||||
let container: IContainer = jobIngredient.container;
|
let container: IContainer = jobIngredient.container;
|
||||||
let deltaStartStop = (this._currentJob.endAt.getTime() - this._currentJob.startedAt.getTime()) / 1000;
|
let deltaStartStop = (this._currentJob.endAt.getTime() - this._currentJob.startedAt.getTime()) / 1000;
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import GPIO from "rpi-gpio";
|
import GPIO from "rpi-gpio";
|
||||||
import Container from "./database/Container";
|
import Container from "./database/Container";
|
||||||
import debug from "debug";
|
import debug from "debug";
|
||||||
|
import {IContainer} from "./database/IContainer";
|
||||||
|
|
||||||
const log = debug("itender:gpio");
|
const log = debug("itender:gpio");
|
||||||
|
|
||||||
@ -45,12 +46,15 @@ export class MyGPIO {
|
|||||||
let containers = await Container.find({});
|
let containers = await Container.find({});
|
||||||
for (let c of containers) {
|
for (let c of containers) {
|
||||||
try {
|
try {
|
||||||
if (c.sensorType) {
|
if (c.sensorType && !c.sensorProxy) {
|
||||||
await MyGPIO.setup(c.sensorPin1, GPIO.DIR_IN);
|
await MyGPIO.setup(c.sensorPin1, GPIO.DIR_IN);
|
||||||
await MyGPIO.setup(c.sensorPin2, GPIO.DIR_IN);
|
await MyGPIO.setup(c.sensorPin2, GPIO.DIR_IN);
|
||||||
}
|
}
|
||||||
await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT);
|
if( c.pumpPin && !c.pumpProxy )
|
||||||
await MyGPIO.write(c.pumpPin, false);
|
{
|
||||||
|
await MyGPIO.setup(c.pumpPin, GPIO.DIR_OUT);
|
||||||
|
await MyGPIO.write(c.pumpPin, false);
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import {IContainer} from "./database/IContainer";
|
import {IContainer} from "./database/IContainer";
|
||||||
import {SensorType} from "./SensorType";
|
import {SensorType} from "./SensorType";
|
||||||
import {HX711} from "./HX711";
|
|
||||||
import debug from "debug";
|
import debug from "debug";
|
||||||
import {ArduinoProxyPayload} from "./ArduinoProxyPayload";
|
import {ArduinoProxyPayload} from "./ArduinoProxyPayload";
|
||||||
import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType";
|
import {ArduinoProxyPayloadType} from "./ArduinoProxyPayloadType";
|
||||||
import {ArduinoProxy} from "./ArduinoProxy";
|
import {ArduinoProxy} from "./ArduinoProxy";
|
||||||
import Container from "./database/Container";
|
import Container from "./database/Container";
|
||||||
|
import {HCSR04} from "hc-sr04";
|
||||||
|
const HX711 = require("pi-hx711");
|
||||||
|
|
||||||
const log = debug("itender:sensor");
|
const log = debug("itender:sensor");
|
||||||
|
|
||||||
@ -31,7 +33,7 @@ export class SensorHelper {
|
|||||||
container.rawData = val.data.value;
|
container.rawData = val.data.value;
|
||||||
} else {
|
} else {
|
||||||
let sensor = new HX711(container.sensorPin1, container.sensorPin2);
|
let sensor = new HX711(container.sensorPin1, container.sensorPin2);
|
||||||
container.rawData = sensor.measure();
|
container.rawData = await sensor.readRaw();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log("Sensor (Weight cell) of container " + container._id + " is broken or has malfunction - Removing it!");
|
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) {
|
} else if (container.sensorType == SensorType.ULTRASOUND) {
|
||||||
try {
|
try {
|
||||||
// V2: Measure weight
|
// 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) {
|
} catch (e) {
|
||||||
log("Sensor (Ultrasound) of container " + container._id + " is broken or has malfunction - Removing it!");
|
log("Sensor (Ultrasound) of container " + container._id + " is broken or has malfunction - Removing it!");
|
||||||
|
@ -14,6 +14,7 @@ export const ContainerSchema = new Mongoose.Schema<IContainer>({
|
|||||||
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},
|
sensorProxy: {type: Boolean, default: false},
|
||||||
|
pumpProxy: { type: Boolean, default: false },
|
||||||
filled: Number,
|
filled: Number,
|
||||||
enabled: {type: Boolean, default: false},
|
enabled: {type: Boolean, default: false},
|
||||||
});
|
});
|
||||||
|
@ -19,9 +19,18 @@ export interface IContainer extends mongoose.Document {
|
|||||||
* HX711 CLOCK-Pin
|
* HX711 CLOCK-Pin
|
||||||
*/
|
*/
|
||||||
sensorPin2: number;
|
sensorPin2: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the arduino used as proxy for the sensor?
|
||||||
|
*/
|
||||||
sensorProxy: boolean
|
sensorProxy: boolean
|
||||||
rawData: number;
|
rawData: number;
|
||||||
pumpPin: number;
|
pumpPin: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the arduino used as proxy for the pump?
|
||||||
|
*/
|
||||||
|
pumpProxy: boolean
|
||||||
filled: number;
|
filled: number;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
}
|
@ -2,13 +2,15 @@
|
|||||||
"entryPoints": [
|
"entryPoints": [
|
||||||
"src/main.ts",
|
"src/main.ts",
|
||||||
"src/iTender.ts",
|
"src/iTender.ts",
|
||||||
|
"src/Mixer.ts",
|
||||||
|
"src/ArduinoProxy.ts",
|
||||||
"src/web/main.ts",
|
"src/web/main.ts",
|
||||||
"src/WebsocketApp.ts",
|
"src/WebsocketApp.ts",
|
||||||
"src/App.ts",
|
"src/App.ts",
|
||||||
"src/routes/ws/websocketRoute.ts"
|
"src/routes/ws/websocketRoute.ts"
|
||||||
],
|
],
|
||||||
"out": "docs/",
|
"out": "docs/",
|
||||||
"readme": "README.md",
|
"readme": "DOCME.md",
|
||||||
"name": "iTender Documentation",
|
"name": "iTender internal Code Docs",
|
||||||
"tsconfig": "./tsconfig.json"
|
"tsconfig": "./tsconfig.json"
|
||||||
}
|
}
|
||||||
|
15
yarn.lock
15
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"
|
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||||
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
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:
|
picocolors@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
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"
|
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
|
||||||
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
|
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:
|
pkg-dir@^4.2.0:
|
||||||
version "4.2.0"
|
version "4.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user