add huuuge stuff

This commit is contained in:
2022-11-14 00:53:09 +01:00
parent 0ddfa4d66f
commit 6aa6955fa8
30 changed files with 1768 additions and 72 deletions

6
src/Category.ts Normal file
View File

@ -0,0 +1,6 @@
export enum Category {
ALCOHOLIC,
ALCOHOL_FREE,
SYRUP,
JUICE
}

15
src/Utils.ts Normal file
View File

@ -0,0 +1,15 @@
import * as dns from "dns";
export class Utils {
public static checkInternet(): Promise<boolean> {
return new Promise(resolve => {
dns.resolve('gaminggeneration.de', (err) => {
if (err)
resolve(false);
else
resolve(true);
});
});
}
}

7
src/WebSocketEvent.ts Normal file
View File

@ -0,0 +1,7 @@
export enum WebSocketEvent {
STATUS_STARTING,
STATUS_READY,
STATUS_FILLING,
STATUS_REFRESHING,
STATUS_ERROR
}

52
src/WebSocketPayload.ts Normal file
View File

@ -0,0 +1,52 @@
import {WebSocketEvent} from "./WebSocketEvent";
export class WebSocketPayload {
set event(value: WebSocketEvent) {
this._event = value;
}
set status(value: boolean) {
this._status = value;
}
set data(value: object | undefined) {
this._data = value;
}
private _event: WebSocketEvent;
private _status: boolean;
private _data: object | undefined;
get event(): WebSocketEvent {
return this._event;
}
get status(): boolean {
return this._status;
}
get data(): object | undefined {
return this._data;
}
constructor(event: WebSocketEvent, status: boolean, data?: object) {
this._event = event;
this._status = status;
this._data = data;
}
public static parseFromJSON(json: string): WebSocketPayload | null {
json = (window) ? atob(json) : Buffer.from(json, "base64").toString();
let rawPayload: { event: string, status: boolean, data: object };
try {
rawPayload = JSON.parse(json);
} catch (e) {
return null;
}
let wsEvent = <keyof typeof WebSocketEvent> rawPayload.event;
return new WebSocketPayload(wsEvent, rawPayload.status, rawPayload.data);
}
}

View File

@ -33,13 +33,12 @@ export class WebsocketApp {
this.log("Error " + err);
});
this._app.set("port", WebsocketApp.port);
this.loadRoutes();
}
public loadRoutes( ) : void
{
this._app.use( "/", require("./routes/ws/websocket") );
}
public listen(): Promise<void> {

View File

@ -0,0 +1,26 @@
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);
}
}

17
src/database/Container.ts Normal file
View File

@ -0,0 +1,17 @@
import * as Mongoose from "mongoose";
import {AbstractContainer} from "./AbstractContainer";
import mongoose from "mongoose";
export const ContainerSchema = new Mongoose.Schema<AbstractContainer>({
slot: {type: Number},
volume: {type: Number, required: true, default: 1000},
sensorEcho: Number,
sensorTrigger: Number,
content: {type: String},
sensorFilledMax: Number,
sensorFilledMin: Number
});
const Container = mongoose.model<AbstractContainer>('Container', ContainerSchema);
export default Container;

33
src/database/Database.ts Normal file
View File

@ -0,0 +1,33 @@
import * as Mongoose from "mongoose";
import debug from "debug";
import Ingredient from "./Ingredient";
import Drink from "./Drink";
import Container from "./Container";
const log = debug("itender:server");
export class Database {
public static connect(): Promise<void> {
return new Promise(async (resolve, reject) => {
try {
await Mongoose.connect("mongodb://localhost:27017/iTender?retryWrites=true");
log("Connected to Database");
/*if (Mongoose.connection.readyState == Mongoose.ConnectionStates.connected) {
resolve();
} else {
reject("Can't connect to database");
}*/
// Preload schemes
Ingredient.find();
Drink.find();
Container.find();
resolve();
} catch (e) {
reject("Exception whilst connecting to Database " + e);
}
});
}
}

11
src/database/Drink.ts Normal file
View File

@ -0,0 +1,11 @@
import {IDrink} from "./IDrink";
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
});
const Drink = mongoose.model<IDrink>('Drink', DrinkSchema);
export default Drink;

View File

@ -0,0 +1,12 @@
import {IIngredient} from "./IIngredient";
import * as mongoose from "mongoose";
export interface IContainer extends mongoose.Document {
slot: number;
content: IIngredient|undefined;
volume: number;
sensorFilledMin : number;
sensorFilledMax: number;
sensorTrigger: number;
sensorEcho: number;
}

15
src/database/IDrink.ts Normal file
View File

@ -0,0 +1,15 @@
import {IIngredient} from "./IIngredient";
import {Category} from "../Category";
import * as mongoose from "mongoose";
export interface IDrink extends mongoose.Document {
// Name for the Drink
name: string;
// Ingredients
ingredients: { type: IIngredient, amount: Number }[];
// Category of the drink
category: Category;
}

View File

@ -0,0 +1,10 @@
import {Category} from "../Category";
import * as mongoose from "mongoose";
export interface IIngredient extends mongoose.Document{
// Name of the ingredient
name: string;
// Category of the ingredient
category: Category;
}

View File

@ -0,0 +1,12 @@
import * as Mongoose from "mongoose";
import mongoose from "mongoose";
import {IIngredient} from "./IIngredient";
export const IngredientSchema = new Mongoose.Schema<IIngredient>({
name: {type: String, required: true},
category: String
});
const Ingredient = mongoose.model<IIngredient>('Ingredient', IngredientSchema);
export default Ingredient;

36
src/iTender.ts Normal file
View File

@ -0,0 +1,36 @@
import {iTenderStatus} from "./iTenderStatus";
import {AbstractContainer} from "./database/AbstractContainer";
export class iTender {
private static _status: iTenderStatus;
private static containers: AbstractContainer[];
static set status(value: iTenderStatus) {
this._status = value;
}
static get status(): iTenderStatus {
return this._status;
}
static startFill() {
// todo Fill method
}
static stopFill() {
// todo Stop fill method
}
static measureContainers() {
for( let container of this.containers )
{
container.measure();
}
}
static loadContainers() {
}
}

7
src/iTenderStatus.ts Normal file
View File

@ -0,0 +1,7 @@
export enum iTenderStatus {
STARTING,
READY,
FILLING,
REFRESHING,
ERROR
}

View File

@ -1,6 +1,10 @@
import {App} from "./App";
import debug from "debug";
import {WebsocketApp} from "./WebsocketApp";
import {Database} from "./database/Database";
import Drink from "./database/Drink";
import Ingredient from "./database/Ingredient";
import {Category} from "./Category";
const log = debug("itender:server");
@ -11,9 +15,11 @@ const wsApp = new WebsocketApp();
(async( ) => {
try {
log("Starting...")
log("Starting...");
await Database.connect();
await app.listen();
await wsApp.listen();
await test();
} catch( e )
{
console.error("---- ERROR ----")
@ -22,3 +28,31 @@ const wsApp = new WebsocketApp();
}
})();
async function test() {
console.log("Testing fn");
let drink = await Drink.findOne( { name: "Mezzo Mix" } ).populate("ingredients.type");
console.log(drink);
//console.log(drink.ingredients)
/*let ingredient = new Ingredient();
ingredient.name = "Cola";
ingredient.category = Category.ALCOHOL_FREE;
await ingredient.save();
let ingredient2 = new Ingredient();
ingredient2.name = "Fanta";
ingredient2.category = Category.ALCOHOL_FREE;
await ingredient2.save();
let drink = new Drink();
drink.name = "Mezzo Mix";
drink.ingredients = [ {type: ingredient2, amount: 2}, { type: ingredient, amount: 10 } ];
await drink.save();*/
}

View File

@ -1,9 +0,0 @@
var express = require('express');
var router = express.Router();
/* GET users listing. */
router.get('/', function(req, res, next) {
res.send('respond with a resource');
});
module.exports = router;

View File

@ -0,0 +1,33 @@
import {WebSocketPayload} from "../../WebSocketPayload";
import debug from "debug";
const express = require('express');
const router = express.Router();
let currentWS: WebSocket;
const log = debug("itender:websocket");
router.ws('/', (ws, req, next) => {
log("Incoming websocket connection")
ws.on('message', async (raw, bool) => {
let msg = WebSocketPayload.parseFromJSON(raw);
// If message is null, close the socket because it could not be decompiled
if (!msg) {
ws.close(1011);
return;
}
switch (msg.event) {
}
});
ws.on('open', (listener) => {
if (currentWS)
currentWS.close(1001);
currentWS = ws;
});
});
module.exports = router;

5
src/web/ButtonType.ts Normal file
View File

@ -0,0 +1,5 @@
export enum ButtonType {
SUCCESS = "success",
ERROR = "error",
}

105
src/web/Modal.ts Normal file
View File

@ -0,0 +1,105 @@
import {ButtonType} from "./ButtonType";
export class Modal {
private static currentModalId = "";
private _title: string = "iTender";
private _content: string | undefined = "";
private _id: string = "";
private _loader: boolean = false;
private _buttons: { type: string, content: string, onclick: Function }[] = [];
constructor(id, title: string, content?: string) {
this._id = id;
this._title = title;
this._content = content;
}
set title(value: string) {
this._title = value;
}
set content(value: string | undefined) {
this._content = value;
}
set id(value: string) {
this._id = value;
}
set loader(value: boolean) {
this._loader = value;
}
public addButton( type: ButtonType, content: string, onclick: Function )
{
this._buttons.push({type: type, content: content, onclick: onclick});
}
public open() {
if (!this._content)
this._content = "";
if (this._loader)
this._content += "<br><div class=\"lds-ellipsis\">\n" +
" <div></div><div></div><div></div><div></div>\n" +
"</div>";
for (let btn of this._buttons) {
this._content += `<button class="btn btn-${btn.type}" onclick="${btn.onclick}">${btn.content}</button>`;
}
Modal.open(this._title, this._content, this._id);
}
/**
* @param title
* @param content
* @param id
*/
public static open(title: string, content: string, id?: string): void {
const modal = document.getElementById("modal");
const modalContent = document.getElementById("modalInnerContent");
if (!modal || !modalContent)
return;
modalContent.classList.add("modalBlendIn");
modal.classList.add("modalBlendIn");
setTimeout(() => {
modalContent.classList.remove("modalBlendIn");
modal.classList.remove("modalBlendIn");
}, 800);
modalContent.innerHTML = `<h1 id="modalTitle">${title}</h1>${content}`;
modal.style.display = "block";
this.currentModalId = id ? id : "null";
}
public static close(id?: string): void {
if (this.currentModalId != id)
return;
const modal = document.getElementById("modal");
const modalContent = document.getElementById("modal-content");
const modalInnerContent = document.getElementById("modalInnerContent");
if (!modal || !modalContent || !modalInnerContent)
return;
modalContent.classList.add("modalBlendOut");
modal.classList.add("modalBlendOut");
setTimeout(() => {
modal.style.display = "none";
modalInnerContent.innerHTML = "";
modalContent.classList.remove("modalBlendOut");
modal.classList.remove("modalBlendOut");
}, 800);
}
}

View File

@ -0,0 +1,29 @@
import {Modal} from "./Modal";
export class WebSocketHandler {
private socket : WebSocket;
constructor() {
this.socket = new WebSocket((window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005");
this.socket.onopen = this.onOpen;
this.socket.onclose = this.onClose;
this.socket.onerror = this.onError;
}
private onOpen( event )
{
Modal.close("start");
}
private onClose( event ) {
console.error("WS Closed!", event );
//openModal("Einen Augenblick...", `Es wurde ein Verbindungsfehler erkannt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
//window.location.reload();
}
private onError( event ) {
console.error("WS Error", event);
//openModal("Einen Augenblick...", `Es wurde ein kritischer Fehler festgestellt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
//window.location.reload();
}
}

View File

@ -1,3 +1,5 @@
import {WebSocketHandler} from "./WebSocketHandler";
import {Modal} from "./Modal";
const main = document.getElementById("main");
const time = document.getElementById("title");
@ -5,12 +7,13 @@ const time = document.getElementById("title");
document.addEventListener("DOMContentLoaded", () => {
console.log("DOM Loaded");
openModal("iTender", "Starten...")
let modal = new Modal("start", "iTender");
modal.content = "Willkommen";
modal.loader = true;
modal.open();
connect();
setTimeout( load, 1000);
setTimeout( () => closeModal(), 2500 );
});
function load()
@ -48,44 +51,9 @@ function load()
}
}
function openModal(title, content) {
const modal = document.getElementById("modal");
const modalContent = document.getElementById("modalInnerContent");
if(!modal || !modalContent)
return;
modalContent.classList.add("modalBlendIn");
modal.classList.add("modalBlendIn");
setTimeout(() => {
modalContent.classList.remove("modalBlendIn");
modal.classList.remove("modalBlendIn");
}, 800);
modalContent.innerHTML = `<h1 id="modalTitle">${title}</h1>${content}`;
modal.style.display = "block";
let wsHandler;
function connect()
{
wsHandler = new WebSocketHandler();
}
function closeModal() {
const modal = document.getElementById("modal");
const modalContent = document.getElementById("modal-content");
const modalInnerContent = document.getElementById("modalInnerContent");
if(!modal || !modalContent || !modalInnerContent)
return;
modalContent.classList.add("modalBlendOut");
modal.classList.add("modalBlendOut");
setTimeout(() => {
modal.style.display = "none";
modalInnerContent.innerHTML = "";
modalContent.classList.remove("modalBlendOut");
modal.classList.remove("modalBlendOut");
}, 800);
}