update
This commit is contained in:
parent
1380575845
commit
a7fac21442
@ -19,6 +19,7 @@
|
||||
"@types/mongoose": "^5.11.97",
|
||||
"@types/morgan": "^1.9.3",
|
||||
"@types/node": "^18.11.9",
|
||||
"@types/rpi-gpio": "^2.1.1",
|
||||
"cookie-parser": "^1.4.6",
|
||||
"debug": "^4.3.4",
|
||||
"express": "~4.16.1",
|
||||
@ -27,7 +28,8 @@
|
||||
"http-errors": "~1.6.3",
|
||||
"mongoose": "^6.7.2",
|
||||
"morgan": "^1.10.0",
|
||||
"pug": "2.0.0-beta11"
|
||||
"pug": "2.0.0-beta11",
|
||||
"rpi-gpio": "^2.1.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/electron": "^1.6.10",
|
||||
|
@ -1,11 +1,10 @@
|
||||
.btn {
|
||||
padding: 11px 15px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: white;
|
||||
font-size: 0.8em;
|
||||
border-radius: 2px;
|
||||
|
||||
cursor:none !important;
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,11 +3,26 @@
|
||||
@import url("/stylesheets/buttons.css");
|
||||
@import url("/stylesheets/modal.css");
|
||||
|
||||
|
||||
:root {
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
|
||||
html * {cursor: none !important}
|
||||
|
||||
|
||||
body::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
body {
|
||||
color: white;
|
||||
scroll-behavior: smooth;
|
||||
font-family: "Roboto", serif;
|
||||
font-style: normal;
|
||||
cursor: none;
|
||||
}
|
||||
|
||||
|
||||
@ -118,10 +133,13 @@ body {
|
||||
border-radius: 30px 10px 30px;
|
||||
}
|
||||
|
||||
|
||||
.drink .thumbnail {
|
||||
grid-column: span 1;
|
||||
grid-row: span 2;
|
||||
}
|
||||
|
||||
|
||||
.drink .name {
|
||||
grid-column: span 1;
|
||||
grid-row: span 1;
|
||||
|
33
src/WebSocketHandler.ts
Normal file
33
src/WebSocketHandler.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import {WebSocketPayload} from "./WebSocketPayload";
|
||||
|
||||
export class WebSocketHandler {
|
||||
private static _ws: WebSocket;
|
||||
|
||||
static get ws(): WebSocket {
|
||||
return this._ws;
|
||||
}
|
||||
|
||||
static set ws(value: WebSocket) {
|
||||
this._ws = value;
|
||||
}
|
||||
|
||||
public static send(payload: WebSocketPayload): Promise<void> {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if( this.ws && this.ws.readyState == 1 )
|
||||
{
|
||||
await this.ws.send(payload.toString());
|
||||
resolve();
|
||||
}
|
||||
else
|
||||
{
|
||||
reject("Websocket is not connected!");
|
||||
}
|
||||
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -49,4 +49,13 @@ export class WebSocketPayload {
|
||||
|
||||
return new WebSocketPayload(wsEvent, rawPayload.status, rawPayload.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the payload as base64 encoded json string
|
||||
*/
|
||||
public toString(): string {
|
||||
let json = JSON.stringify({"event": this._event, status: this._status, data: this._data});
|
||||
json = (window) ? btoa(json) : Buffer.from(json).toString("base64");
|
||||
return json;
|
||||
}
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
import {IContainer} from "./IContainer";
|
||||
import {IIngredient} from "./IIngredient";
|
||||
import {HCSR04} from "hc-sr04";
|
||||
|
||||
export abstract class AbstractContainer implements IContainer {
|
||||
slot: number = 1;
|
||||
content: IIngredient | undefined;
|
||||
sensorEcho: number = 26;
|
||||
sensorFilledMax: number = 0;
|
||||
sensorFilledMin: number = 0;
|
||||
sensorTrigger: number = 27;
|
||||
volume: number = 1000;
|
||||
sensor: HCSR04;
|
||||
|
||||
protected constructor() {
|
||||
this.sensor = new HCSR04(this.sensorTrigger, this.sensorEcho);
|
||||
}
|
||||
|
||||
public measure() : Number {
|
||||
let dist = this.sensor.distance();
|
||||
return dist * 100 / (this.sensorFilledMax + this.sensorFilledMin);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,17 +1,18 @@
|
||||
import * as Mongoose from "mongoose";
|
||||
import {AbstractContainer} from "./AbstractContainer";
|
||||
import mongoose from "mongoose";
|
||||
import {IContainer} from "./IContainer";
|
||||
|
||||
export const ContainerSchema = new Mongoose.Schema<AbstractContainer>({
|
||||
export const ContainerSchema = new Mongoose.Schema<IContainer>({
|
||||
slot: {type: Number},
|
||||
volume: {type: Number, required: true, default: 1000},
|
||||
sensorEcho: Number,
|
||||
sensorTrigger: Number,
|
||||
content: {type: String},
|
||||
content: {type: mongoose.Types.ObjectId},
|
||||
sensorFilledMax: Number,
|
||||
sensorFilledMin: Number
|
||||
sensorFilledMin: Number,
|
||||
filled: Number,
|
||||
});
|
||||
|
||||
const Container = mongoose.model<AbstractContainer>('Container', ContainerSchema);
|
||||
const Container = mongoose.model<IContainer>('Container', ContainerSchema);
|
||||
export default Container;
|
||||
|
||||
|
@ -4,7 +4,8 @@ import * as mongoose from "mongoose";
|
||||
export const DrinkSchema = new mongoose.Schema<IDrink>({
|
||||
name: {type: String, required: true},
|
||||
ingredients: [{type: {type: mongoose.Types.ObjectId, ref: "Ingredient", required: true}, amount: { type: Number } }],
|
||||
category: String
|
||||
category: String,
|
||||
recommendedQuantity: {type: Number, default: 200 }
|
||||
});
|
||||
|
||||
const Drink = mongoose.model<IDrink>('Drink', DrinkSchema);
|
||||
|
@ -1,7 +1,7 @@
|
||||
import {IIngredient} from "./IIngredient";
|
||||
import * as mongoose from "mongoose";
|
||||
|
||||
export interface IContainer {
|
||||
export interface IContainer extends mongoose.Document{
|
||||
slot: number;
|
||||
content: IIngredient|undefined;
|
||||
volume: number;
|
||||
@ -9,4 +9,5 @@ export interface IContainer {
|
||||
sensorFilledMax: number;
|
||||
sensorTrigger: number;
|
||||
sensorEcho: number;
|
||||
filled: Number;
|
||||
}
|
@ -12,4 +12,7 @@ export interface IDrink extends mongoose.Document {
|
||||
// Category of the drink
|
||||
category: Category;
|
||||
|
||||
// Recommended amount in milliliters
|
||||
recommendedQuantity: number;
|
||||
|
||||
}
|
@ -1,10 +1,15 @@
|
||||
import {iTenderStatus} from "./iTenderStatus";
|
||||
import {AbstractContainer} from "./database/AbstractContainer";
|
||||
import Container from "./database/Container";
|
||||
import {HCSR04} from "hc-sr04";
|
||||
import {IContainer} from "./database/IContainer";
|
||||
import Drink from "./database/Drink";
|
||||
import {IDrink} from "./database/IDrink";
|
||||
|
||||
export class iTender {
|
||||
private static _status: iTenderStatus;
|
||||
|
||||
private static containers: AbstractContainer[];
|
||||
private static containers: { container: IContainer, sensor: HCSR04, pump: null }[];
|
||||
private static drinks: IDrink[];
|
||||
|
||||
static set status(value: iTenderStatus) {
|
||||
this._status = value;
|
||||
@ -22,15 +27,65 @@ export class iTender {
|
||||
// todo Stop fill method
|
||||
}
|
||||
|
||||
static measureContainers() {
|
||||
for( let container of this.containers )
|
||||
{
|
||||
container.measure();
|
||||
static measureContainers(): Promise<void> {
|
||||
return new Promise(async resolve => {
|
||||
let containers = await Container.find();
|
||||
/*
|
||||
public measure() : Number {
|
||||
let dist = this.sensor.distance();
|
||||
return dist * 100 / (this.sensorFilledMax + this.sensorFilledMin);
|
||||
}
|
||||
*/
|
||||
})
|
||||
}
|
||||
|
||||
static loadContainers() {
|
||||
static refreshDrinks(): Promise<void> {
|
||||
return new Promise(async resolve => {
|
||||
this.drinks = [];
|
||||
for (let d of (await Drink.find().populate("ingredients.type"))) {
|
||||
|
||||
|
||||
let drinkAccept = true;
|
||||
|
||||
for (let i of d.ingredients) {
|
||||
let c = await Container.findOne({content: i["type"]});
|
||||
|
||||
if (!c) {
|
||||
drinkAccept = false;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if (drinkAccept)
|
||||
this.drinks.push(d);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static refreshContainers(): Promise<void> {
|
||||
|
||||
return new Promise(async resolve => {
|
||||
let containers = await Container.find();
|
||||
for (let c of containers) {
|
||||
let i = 0;
|
||||
let found = false;
|
||||
for (let c2 of this.containers) {
|
||||
if (c2.container._id == c._id) {
|
||||
this.containers[i] = {
|
||||
container: c,
|
||||
sensor: new HCSR04(c.sensorTrigger, c.sensorEcho),
|
||||
pump: null
|
||||
};
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (!found)
|
||||
this.containers.push({container: c, sensor: new HCSR04(c.sensorTrigger, c.sensorEcho), pump: null});
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,7 +1,14 @@
|
||||
export enum iTenderStatus {
|
||||
// Machine is going to start
|
||||
STARTING,
|
||||
// Machine is ready
|
||||
READY,
|
||||
// Machine is filling your drink and destroying your leberwurst
|
||||
FILLING,
|
||||
// Drinks will be refreshed from global database (the internet neuland :O)
|
||||
REFRESHING,
|
||||
// Drinks will be calculated (check containers and which drinks can be done)
|
||||
CALCULATING,
|
||||
// An error happened; Oh no :(
|
||||
ERROR
|
||||
}
|
48
src/main.ts
48
src/main.ts
@ -4,7 +4,8 @@ import {WebsocketApp} from "./WebsocketApp";
|
||||
import {Database} from "./database/Database";
|
||||
import Drink from "./database/Drink";
|
||||
import Ingredient from "./database/Ingredient";
|
||||
import {Category} from "./Category";
|
||||
import Container from "./database/Container";
|
||||
import {iTender} from "./iTender";
|
||||
|
||||
const log = debug("itender:server");
|
||||
|
||||
@ -12,31 +13,64 @@ const app = new App();
|
||||
const wsApp = new WebsocketApp();
|
||||
|
||||
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
log("Starting...");
|
||||
await Database.connect();
|
||||
await app.listen();
|
||||
await wsApp.listen();
|
||||
await test();
|
||||
} catch( e )
|
||||
{
|
||||
await init();
|
||||
} catch (e) {
|
||||
console.error("---- ERROR ----")
|
||||
console.error(e);
|
||||
process.exit(-1);
|
||||
}
|
||||
})();
|
||||
|
||||
function init() : Promise<void> {
|
||||
log("Initializing...");
|
||||
return new Promise(async resolve => {
|
||||
await iTender.refreshContainers();
|
||||
await iTender.refreshDrinks();
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
async function test() {
|
||||
console.log("Testing fn");
|
||||
|
||||
let ingredient = await Ingredient.findOne({name: "Cola"});
|
||||
if (!ingredient)
|
||||
return;
|
||||
|
||||
let drink = await Drink.findOne( { name: "Mezzo Mix" } ).populate("ingredients.type");
|
||||
/*let drink = new Drink();
|
||||
drink.name = "Cola";
|
||||
drink.ingredients = [{type: ingredient, amount: 200}];
|
||||
|
||||
await drink.save();*/
|
||||
|
||||
let drink = await Drink.findOne({name: "Cola"}).populate("ingredients.type");
|
||||
if (!drink) return;
|
||||
|
||||
console.log(drink.ingredients);
|
||||
console.log(drink);
|
||||
|
||||
/*let container = new Container();
|
||||
container.slot = 1;
|
||||
container.volume = 750;
|
||||
container.sensorEcho = 26;
|
||||
container.sensorTrigger = 27;
|
||||
container.content = ingredient;
|
||||
container.sensorFilledMax = 2;
|
||||
container.sensorFilledMin = 15;
|
||||
|
||||
await container.save();*/
|
||||
|
||||
let container = await Container.findOne({slot: 1});
|
||||
if (!container) return;
|
||||
|
||||
console.log(container);
|
||||
|
||||
|
||||
//console.log(drink.ingredients)
|
||||
/*let ingredient = new Ingredient();
|
||||
ingredient.name = "Cola";
|
||||
|
@ -1,10 +1,10 @@
|
||||
import {WebSocketPayload} from "../../WebSocketPayload";
|
||||
import debug from "debug";
|
||||
import {WebSocketHandler} from "../../WebSocketHandler";
|
||||
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
|
||||
let currentWS: WebSocket;
|
||||
|
||||
const log = debug("itender:websocket");
|
||||
|
||||
@ -24,9 +24,9 @@ router.ws('/', (ws, req, next) => {
|
||||
});
|
||||
|
||||
ws.on('open', (listener) => {
|
||||
if (currentWS)
|
||||
currentWS.close(1001);
|
||||
currentWS = ws;
|
||||
if (WebSocketHandler.ws)
|
||||
WebSocketHandler.ws.close(1001);
|
||||
WebSocketHandler.ws = ws;
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import {Modal} from "./Modal";
|
||||
|
||||
export class WebSocketHandler {
|
||||
export class WebWebSocketHandler {
|
||||
private socket : WebSocket;
|
||||
|
||||
constructor() {
|
@ -1,4 +1,4 @@
|
||||
import {WebSocketHandler} from "./WebSocketHandler";
|
||||
import {WebWebSocketHandler} from "./WebWebSocketHandler";
|
||||
import {Modal} from "./Modal";
|
||||
|
||||
const main = document.getElementById("main");
|
||||
@ -54,6 +54,6 @@ function load()
|
||||
let wsHandler;
|
||||
function connect()
|
||||
{
|
||||
wsHandler = new WebSocketHandler();
|
||||
wsHandler = new WebWebSocketHandler();
|
||||
|
||||
}
|
||||
|
40
yarn.lock
40
yarn.lock
@ -991,6 +991,13 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
|
||||
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
|
||||
|
||||
"@types/rpi-gpio@^2.1.1":
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/rpi-gpio/-/rpi-gpio-2.1.1.tgz#1f9c04926bae9bc95461c428b0397cf9f7ddbc4a"
|
||||
integrity sha512-GGKVP2BatDgGEnxqBe6PbE2Wu2ZqYXpW5o6GIkOsbuj5hKS4W7DtP3gz3Vq+fNQ6JIDkv9qR0YAyDR4w9He3Bw==
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
"@types/serve-static@*":
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155"
|
||||
@ -1278,6 +1285,13 @@ asap@~2.0.3:
|
||||
resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
||||
integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==
|
||||
|
||||
async-retry@^1.2.1:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280"
|
||||
integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==
|
||||
dependencies:
|
||||
retry "0.13.1"
|
||||
|
||||
babel-runtime@^6.26.0:
|
||||
version "6.26.0"
|
||||
resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe"
|
||||
@ -1641,7 +1655,7 @@ debug@4.x, debug@^4.1.0, debug@^4.1.1, debug@^4.3.4:
|
||||
dependencies:
|
||||
ms "2.1.2"
|
||||
|
||||
debug@^3.2.7:
|
||||
debug@^3.1.0, debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
@ -1762,6 +1776,14 @@ envinfo@^7.7.3:
|
||||
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475"
|
||||
integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==
|
||||
|
||||
epoll@^2.0.10:
|
||||
version "2.0.10"
|
||||
resolved "https://registry.yarnpkg.com/epoll/-/epoll-2.0.10.tgz#aae54a267d7fb8108074b62646d658b267f73915"
|
||||
integrity sha512-kx5y1SxivN99HjXDZpE/A73FHJV/dzRQt+qoF88CEza3RcEKGqNfkXPPY/oqVBV5w6G2N6b8xd5s5zprgrUVnQ==
|
||||
dependencies:
|
||||
bindings "^1.5.0"
|
||||
nan "^2.14.0"
|
||||
|
||||
epoll@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/epoll/-/epoll-4.0.1.tgz#62b787d29980394798fa7b9a45fbefea518fc732"
|
||||
@ -2521,7 +2543,7 @@ ms@2.1.3, ms@^2.1.1:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||
|
||||
nan@^2.14.2:
|
||||
nan@^2.14.0, nan@^2.14.2:
|
||||
version "2.17.0"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.17.0.tgz#c0150a2368a182f033e9aa5195ec76ea41a199cb"
|
||||
integrity sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==
|
||||
@ -2927,6 +2949,11 @@ responselike@^1.0.2:
|
||||
dependencies:
|
||||
lowercase-keys "^1.0.0"
|
||||
|
||||
retry@0.13.1:
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658"
|
||||
integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==
|
||||
|
||||
right-align@^0.1.1:
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/right-align/-/right-align-0.1.3.tgz#61339b722fe6a3515689210d24e14c96148613ef"
|
||||
@ -2946,6 +2973,15 @@ roarr@^2.15.3:
|
||||
semver-compare "^1.0.0"
|
||||
sprintf-js "^1.1.2"
|
||||
|
||||
rpi-gpio@^2.1.7:
|
||||
version "2.1.7"
|
||||
resolved "https://registry.yarnpkg.com/rpi-gpio/-/rpi-gpio-2.1.7.tgz#0a478d77133733830b4eb62075fddf5d6bb7ec82"
|
||||
integrity sha512-u6McqKR6QuHP5zq/3UuXkJfY2fJHhvNaJMP58jz7pIf4OFyhBI3hh0vyYn5OGMwFbFdcBfOMC1RAPeRXLKF6YA==
|
||||
dependencies:
|
||||
async-retry "^1.2.1"
|
||||
debug "^3.1.0"
|
||||
epoll "^2.0.10"
|
||||
|
||||
safe-buffer@5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
|
Loading…
x
Reference in New Issue
Block a user