update
Took 7 hours 48 minutes
This commit is contained in:
parent
c81713cd23
commit
03dd0e0fb6
@ -1,10 +1,12 @@
|
|||||||
.btn {
|
.btn {
|
||||||
padding: 12px 16px;
|
padding: 11px 15px;
|
||||||
border: none;
|
border: none;
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 0.95em;
|
font-size: 0.96em;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
cursor: none !important;
|
cursor: none !important;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-right: 2%;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,10 +112,10 @@ label {
|
|||||||
.input[type=checkbox] {
|
.input[type=checkbox] {
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
/* Double-sized Checkboxes */
|
/* Double-sized Checkboxes */
|
||||||
-ms-transform: scale(1.5); /* IE */
|
-ms-transform: scale(1.6); /* IE */
|
||||||
-moz-transform: scale(1.5); /* FF */
|
-moz-transform: scale(1.6); /* FF */
|
||||||
-webkit-transform: scale(1.5); /* Safari and Chrome */
|
-webkit-transform: scale(1.6); /* Safari and Chrome */
|
||||||
-o-transform: scale(1.5); /* Opera */
|
-o-transform: scale(1.6); /* Opera */
|
||||||
transform: scale(1.5);
|
transform: scale(1.6);
|
||||||
padding: 10px;
|
padding: 12px;
|
||||||
}
|
}
|
||||||
|
@ -4,34 +4,28 @@
|
|||||||
padding-top: 1%;
|
padding-top: 1%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(2, calc(95% / 2));
|
grid-template-columns: repeat(2, calc(95% / 2));
|
||||||
grid-template-rows: repeat(7, calc(100% / 7));
|
grid-template-rows: repeat(9, calc(100% / 9));
|
||||||
grid-gap: 2% 5%;
|
grid-gap: 2% 2%;
|
||||||
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup_slots {
|
|
||||||
min-width: 55px;
|
|
||||||
width: 10%;
|
|
||||||
margin-left: 3%;
|
|
||||||
border: 1px solid aliceblue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#setup #setupContainersDiv {
|
#setup #setupContainersDiv {
|
||||||
grid-row: span 5;
|
grid-row: span 18;
|
||||||
grid-column: span 2;
|
grid-column: span 2;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid cadetblue;
|
border: 1px solid white;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 1% 10px;
|
padding: 0.45% 10px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup #setupContainersDiv #containerAddBtn {
|
#setup #setupContainersDiv #containerAddBtn {
|
||||||
position: relative;
|
position: relative;
|
||||||
left: 43%;
|
left: 46%;
|
||||||
bottom: 10%;
|
bottom: 8%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#setup #setupLEDDiv {
|
#setup #setupLEDDiv {
|
||||||
@ -39,7 +33,7 @@
|
|||||||
grid-column: span 1;
|
grid-column: span 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid cadetblue;
|
border: 1px solid white;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 1% 10px;
|
padding: 1% 10px;
|
||||||
margin-right: 10%;
|
margin-right: 10%;
|
||||||
@ -52,7 +46,7 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: 1px solid cadetblue;
|
border: 1px solid white;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 1% 10px;
|
padding: 1% 10px;
|
||||||
|
|
||||||
@ -73,7 +67,7 @@
|
|||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
padding: 3% 10px;
|
padding: 3% 10px;
|
||||||
transition: 0.5s;
|
transition: 0.5s;
|
||||||
background-color: rgb(111, 109, 109);
|
background-color: rgb(135, 133, 133);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 1.7em;
|
font-size: 1.74em;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
margin-bottom: 2%;
|
margin-bottom: 2%;
|
||||||
color: black;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -53,12 +53,11 @@ h1 {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 9%;
|
height: 9%;
|
||||||
background-color: #1F5E5F;
|
|
||||||
color: white;
|
color: white;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
padding-right: 3px;
|
padding-right: 3px;
|
||||||
padding-left: 3px;
|
padding-left: 3px;
|
||||||
|
background-color: #167fcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -94,7 +93,7 @@ h1 {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 9%;
|
height: 9%;
|
||||||
background-color: #1F5E5F;
|
background-color: #167fcc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -121,10 +120,12 @@ h1 {
|
|||||||
|
|
||||||
#container {
|
#container {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 10%;
|
top: 9%;
|
||||||
left: 1%;
|
left: 0;
|
||||||
right: 1%;
|
right: 0;
|
||||||
height: 80%;
|
height: 82%;
|
||||||
|
color: white;
|
||||||
|
background-color: #0e1f31;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pane {
|
.pane {
|
||||||
@ -134,7 +135,7 @@ h1 {
|
|||||||
ms-overflow-style: none; /* IE and Edge */
|
ms-overflow-style: none; /* IE and Edge */
|
||||||
scrollbar-width: none; /* Firefox */
|
scrollbar-width: none; /* Firefox */
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
color: black;
|
color: white;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hiddenPane {
|
.hiddenPane {
|
||||||
|
11
src/HX711.ts
11
src/HX711.ts
@ -1,3 +1,14 @@
|
|||||||
export class HX711 {
|
export class HX711 {
|
||||||
|
private clockPin: number;
|
||||||
|
private dataPin: number;
|
||||||
|
|
||||||
|
|
||||||
|
constructor(clockPin: number, dataPin: number) {
|
||||||
|
this.clockPin = clockPin;
|
||||||
|
this.dataPin = dataPin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public measure(): number {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
5
src/SensorType.ts
Normal file
5
src/SensorType.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export enum SensorType {
|
||||||
|
NONE="NONE",
|
||||||
|
ULTRASOUND="ULTRASOUND",
|
||||||
|
LOADCELL="LOADCELL"
|
||||||
|
}
|
@ -2,12 +2,15 @@ import * as fs from "fs";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
export class Settings {
|
export class Settings {
|
||||||
|
static get json(): {} {
|
||||||
|
return this._json;
|
||||||
|
}
|
||||||
static get setupDone(): boolean {
|
static get setupDone(): boolean {
|
||||||
return this._setupDone;
|
return this._setupDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static _setupDone: boolean;
|
private static _setupDone: boolean;
|
||||||
private static json: {};
|
private static _json: {};
|
||||||
|
|
||||||
|
|
||||||
public static loadSettings() {
|
public static loadSettings() {
|
||||||
@ -17,22 +20,22 @@ export class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let file = fs.readFileSync(path.join(__dirname, "/config.json"));
|
let file = fs.readFileSync(path.join(__dirname, "/config.json"));
|
||||||
this.json = JSON.parse(file.toString("utf8"));
|
this._json = JSON.parse(file.toString("utf8"));
|
||||||
|
|
||||||
this._setupDone = this.json["setupDone"];
|
this._setupDone = this._json["setupDone"];
|
||||||
this._setupDone = false;
|
this._setupDone = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static saveSettings() {
|
public static saveSettings() {
|
||||||
fs.writeFileSync(path.join(__dirname, "/config.json"), JSON.stringify(this.json));
|
fs.writeFileSync(path.join(__dirname, "/config.json"), JSON.stringify(this._json));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static get(key: string): any {
|
public static get(key: string): any {
|
||||||
return this.json[key];
|
return this._json[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
public static set(key: string, value: any) {
|
public static set(key: string, value: any) {
|
||||||
this.json[key] = value;
|
this._json[key] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,4 +2,6 @@ export enum WebSocketEvent {
|
|||||||
STATUS= "STATUS",
|
STATUS= "STATUS",
|
||||||
DRINKS = "DRINKS",
|
DRINKS = "DRINKS",
|
||||||
CONTAINERS = "CONTAINERS",
|
CONTAINERS = "CONTAINERS",
|
||||||
|
CONFIG = "CONFIG",
|
||||||
|
TARE = "TARE",
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import {WebSocketPayload} from "./WebSocketPayload";
|
import {WebSocketPayload} from "./WebSocketPayload";
|
||||||
import {WebSocketEvent} from "./WebSocketEvent";
|
import {WebSocketEvent} from "./WebSocketEvent";
|
||||||
import {iTender} from "./iTender";
|
import {iTender} from "./iTender";
|
||||||
|
import {Settings} from "./Settings";
|
||||||
|
|
||||||
export class WebSocketHandler {
|
export class WebSocketHandler {
|
||||||
private static _ws: WebSocket;
|
private static _ws: WebSocket;
|
||||||
@ -33,4 +34,10 @@ export class WebSocketHandler {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static sendRunningConfig() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let payload = new WebSocketPayload(WebSocketEvent.CONFIG, false, Settings.json);
|
||||||
|
WebSocketHandler.send(payload).then(resolve);
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ export const ContainerSchema = new Mongoose.Schema<IContainer>({
|
|||||||
sensorType: String,
|
sensorType: String,
|
||||||
sensorPin1: Number,
|
sensorPin1: Number,
|
||||||
sensorPin2: Number,
|
sensorPin2: Number,
|
||||||
|
rawData: Number,
|
||||||
pumpPin: {type: Number, required: true},
|
pumpPin: {type: Number, required: true},
|
||||||
content: {type: mongoose.Types.ObjectId, ref: "Ingredient"},
|
content: {type: mongoose.Types.ObjectId, ref: "Ingredient"},
|
||||||
sensorFilledMax: Number,
|
sensorFilledMax: Number,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import {IIngredient} from "./IIngredient";
|
import {IIngredient} from "./IIngredient";
|
||||||
import * as mongoose from "mongoose";
|
import * as mongoose from "mongoose";
|
||||||
|
import {SensorType} from "../SensorType";
|
||||||
|
|
||||||
export interface IContainer extends mongoose.Document {
|
export interface IContainer extends mongoose.Document {
|
||||||
slot: number;
|
slot: number;
|
||||||
@ -7,11 +8,13 @@ export interface IContainer extends mongoose.Document {
|
|||||||
volume: number;
|
volume: number;
|
||||||
sensorFilledMin: number;
|
sensorFilledMin: number;
|
||||||
sensorFilledMax: number;
|
sensorFilledMax: number;
|
||||||
sensorType: string;
|
// Sensor Type
|
||||||
|
sensorType: SensorType;
|
||||||
sensorPin1: number;
|
sensorPin1: number;
|
||||||
sensorPin2: number;
|
sensorPin2: number;
|
||||||
|
rawData: number;
|
||||||
pumpPin: number;
|
pumpPin: number;
|
||||||
filled: Number;
|
filled: number;
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
autoDisabled: boolean;
|
autoDisabled: boolean;
|
||||||
}
|
}
|
@ -11,6 +11,7 @@ import {Utils} from "./Utils";
|
|||||||
import {WebSocketPayload} from "./WebSocketPayload";
|
import {WebSocketPayload} from "./WebSocketPayload";
|
||||||
import {WebSocketEvent} from "./WebSocketEvent";
|
import {WebSocketEvent} from "./WebSocketEvent";
|
||||||
import {HX711} from "./HX711";
|
import {HX711} from "./HX711";
|
||||||
|
import {SensorType} from "./SensorType";
|
||||||
|
|
||||||
const log = debug("itender:station");
|
const log = debug("itender:station");
|
||||||
|
|
||||||
@ -35,6 +36,10 @@ export class iTender {
|
|||||||
return this._internetConnection;
|
return this._internetConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Deprecated
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
private static _containers: { container: IContainer, sensor: HCSR04 | HX711, pump: null }[] = [];
|
private static _containers: { container: IContainer, sensor: HCSR04 | HX711, pump: null }[] = [];
|
||||||
private static _drinks: IDrink[];
|
private static _drinks: IDrink[];
|
||||||
|
|
||||||
@ -64,28 +69,34 @@ export class iTender {
|
|||||||
log("Measuring containers...");
|
log("Measuring containers...");
|
||||||
|
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
for (let c of this._containers) {
|
for (let c of (await Container.find({enabled: true}))) {
|
||||||
try {
|
try {
|
||||||
if (!(c.sensor instanceof HX711)) {
|
let rand = Math.random() * 5;
|
||||||
let dist = c.sensor.distance();
|
if (c.sensorType == SensorType.ULTRASOUND) {
|
||||||
c.container.filled = dist * 100 / (c.container.sensorFilledMax + c.container.sensorFilledMin);
|
let sensor = new HCSR04(c.sensorPin1, c.sensorPin2);
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
c.rawData = sensor.distance();
|
||||||
c.container.filled = -1;
|
c.rawData = rand;
|
||||||
|
c.filled = c.rawData * c.sensorFilledMin / 100;
|
||||||
|
|
||||||
|
} else if (c.sensorType == SensorType.LOADCELL) {
|
||||||
|
let sensor = new HX711(c.sensorPin1, c.sensorPin2);
|
||||||
|
|
||||||
|
c.rawData = sensor.measure();
|
||||||
|
c.rawData = rand;
|
||||||
|
c.filled = c.rawData * c.sensorFilledMax / 100;
|
||||||
}
|
}
|
||||||
await c.container.save();
|
} catch (e) {
|
||||||
|
c.filled = -1;
|
||||||
|
c.rawData = 0;
|
||||||
|
}
|
||||||
|
await c.save();
|
||||||
}
|
}
|
||||||
log("Containers measured!");
|
log("Containers measured!");
|
||||||
resolve();
|
resolve();
|
||||||
|
|
||||||
let cons: IContainer[] = [];
|
let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, false, (await Container.find()));
|
||||||
for (let c of this._containers) {
|
await WebSocketHandler.send(payload);
|
||||||
cons.push(c.container);
|
|
||||||
}
|
|
||||||
|
|
||||||
let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, false, cons);
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,6 +128,9 @@ export class iTender {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Deprecated
|
||||||
|
*/
|
||||||
static refreshContainers(): Promise<void> {
|
static refreshContainers(): Promise<void> {
|
||||||
log("Refreshing containers...");
|
log("Refreshing containers...");
|
||||||
this.setStatus(iTenderStatus.CALCULATING);
|
this.setStatus(iTenderStatus.CALCULATING);
|
||||||
@ -176,6 +190,7 @@ export class iTender {
|
|||||||
this._currentJob.endAt = new Date();
|
this._currentJob.endAt = new Date();
|
||||||
await this._currentJob.save();
|
await this._currentJob.save();
|
||||||
this._currentJob = null;
|
this._currentJob = null;
|
||||||
|
this.setStatus(iTenderStatus.READY);
|
||||||
}
|
}
|
||||||
}, 30000);
|
}, 30000);
|
||||||
}
|
}
|
||||||
@ -196,4 +211,14 @@ export class iTender {
|
|||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static interval;
|
||||||
|
|
||||||
|
public static toggleTare(state: boolean) {
|
||||||
|
clearInterval(iTender.interval);
|
||||||
|
if ( state )
|
||||||
|
this.interval = setInterval(async () => {
|
||||||
|
await this.measureContainers();
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
}
|
}
|
@ -69,7 +69,8 @@ function init(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Containers
|
// Containers
|
||||||
await iTender.refreshContainers();
|
//await iTender.refreshContainers();
|
||||||
|
await iTender.measureContainers();
|
||||||
// Drinks
|
// Drinks
|
||||||
await iTender.refreshDrinks();
|
await iTender.refreshDrinks();
|
||||||
// Start auto checkup for stuck jobs
|
// Start auto checkup for stuck jobs
|
||||||
|
@ -4,6 +4,8 @@ import {WebSocketHandler} from "../../WebSocketHandler";
|
|||||||
import {iTender} from "../../iTender";
|
import {iTender} from "../../iTender";
|
||||||
import {iTenderStatus} from "../../iTenderStatus";
|
import {iTenderStatus} from "../../iTenderStatus";
|
||||||
import {WebSocketEvent} from "../../WebSocketEvent";
|
import {WebSocketEvent} from "../../WebSocketEvent";
|
||||||
|
import Container from "../../database/Container";
|
||||||
|
import {SensorType} from "../../SensorType";
|
||||||
|
|
||||||
const express = require('express');
|
const express = require('express');
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -14,11 +16,13 @@ const log = debug("itender:websocket");
|
|||||||
router.ws('/', async (ws, req, next) => {
|
router.ws('/', async (ws, req, next) => {
|
||||||
log("Incoming websocket connection...");
|
log("Incoming websocket connection...");
|
||||||
|
|
||||||
if (WebSocketHandler.ws)
|
if (WebSocketHandler.ws) {
|
||||||
|
iTender.toggleTare(false);
|
||||||
WebSocketHandler.ws.close(1001);
|
WebSocketHandler.ws.close(1001);
|
||||||
|
}
|
||||||
WebSocketHandler.ws = ws;
|
WebSocketHandler.ws = ws;
|
||||||
|
|
||||||
|
await WebSocketHandler.sendRunningConfig();
|
||||||
await WebSocketHandler.sendStatus();
|
await WebSocketHandler.sendStatus();
|
||||||
|
|
||||||
async function sendWhenReady() {
|
async function sendWhenReady() {
|
||||||
@ -50,7 +54,31 @@ router.ws('/', async (ws, req, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (msg.event) {
|
switch (msg.event) {
|
||||||
|
case WebSocketEvent.TARE: {
|
||||||
|
if (msg.data["state"] == true) {
|
||||||
|
iTender.toggleTare(true);
|
||||||
|
} else {
|
||||||
|
iTender.toggleTare(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WebSocketEvent.CONTAINERS: {
|
||||||
|
let data = msg.data as { pumpPin: number; sensorType: SensorType; sensor1: number; sensor2: number; volume: number; }[];
|
||||||
|
await Container.remove({});
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
for (let c of data) {
|
||||||
|
let container = new Container();
|
||||||
|
container.slot = i;
|
||||||
|
container.volume = c.volume;
|
||||||
|
container.sensorType = c.sensorType;
|
||||||
|
container.sensorPin1 = c.sensor1;
|
||||||
|
container.sensorPin2 = c.sensor2;
|
||||||
|
container.enabled = true;
|
||||||
|
container.autoDisabled = true;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export enum ButtonType {
|
export enum ButtonType {
|
||||||
|
PRIMARY = "primary",
|
||||||
SUCCESS = "success",
|
SUCCESS = "success",
|
||||||
ERROR = "error",
|
ERROR = "error",
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ export class Modal {
|
|||||||
this._loader = value;
|
this._loader = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public addButton(type: ButtonType, content: string, onclick: Function): HTMLButtonElement {
|
public addButton(type: ButtonType, content: string, onclick: Function = () => {}): HTMLButtonElement {
|
||||||
let btn = document.createElement("button");
|
let btn = document.createElement("button");
|
||||||
btn.classList.add("btn", "btn-" + type);
|
btn.classList.add("btn", "btn-" + type);
|
||||||
btn.onclick = () => onclick(btn);
|
btn.onclick = () => onclick(btn);
|
||||||
@ -55,6 +55,8 @@ export class Modal {
|
|||||||
return btn;
|
return btn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public open(): Promise<void> {
|
public open(): Promise<void> {
|
||||||
return new Promise(async (resolve) => {
|
return new Promise(async (resolve) => {
|
||||||
/* if (this._leftCentered) {
|
/* if (this._leftCentered) {
|
||||||
@ -119,6 +121,10 @@ export class Modal {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public close() : void {
|
||||||
|
Modal.close(this._id);
|
||||||
|
}
|
||||||
|
|
||||||
public static close(id?: string): void {
|
public static close(id?: string): void {
|
||||||
if (id && this.currentModalId != id)
|
if (id && this.currentModalId != id)
|
||||||
return;
|
return;
|
||||||
|
425
src/web/Setup.ts
425
src/web/Setup.ts
@ -1,7 +1,428 @@
|
|||||||
|
import {Pane} from "./Pane";
|
||||||
|
import {Modal} from "./Modal";
|
||||||
|
import {ButtonType} from "./ButtonType";
|
||||||
|
import {WebHandler} from "./WebHandler";
|
||||||
|
import {WebSocketPayload} from "../WebSocketPayload";
|
||||||
|
import {WebSocketEvent} from "../WebSocketEvent";
|
||||||
|
import {WebWebSocketHandler} from "./WebWebSocketHandler";
|
||||||
|
import {IContainer} from "../database/IContainer";
|
||||||
|
import {SensorType} from "../SensorType";
|
||||||
|
|
||||||
|
|
||||||
export class Setup {
|
export class Setup {
|
||||||
public static onSetupUpdate()
|
public static onConfigUpdate(payload: WebSocketPayload) {
|
||||||
{
|
|
||||||
// Setup containers updated
|
// Setup containers updated
|
||||||
|
const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement;
|
||||||
|
const ledGPIO = document.getElementById("ledGPIO") as HTMLInputElement;
|
||||||
|
const ambientColor = document.getElementById("ambientColor") as HTMLInputElement;
|
||||||
|
const allowRemoteCheckbox = document.getElementById("allowRemoteCheckbox") as HTMLInputElement;
|
||||||
|
const hotspotCheckbox = document.getElementById("hotspotCheckbox") as HTMLInputElement;
|
||||||
|
|
||||||
|
ledCheckbox.checked = !!payload.data["led_enabled"];
|
||||||
|
allowRemoteCheckbox.checked = !!payload.data["remote_enabled"];
|
||||||
|
hotspotCheckbox.checked = !!payload.data["hotspot_enabled"];
|
||||||
|
if (payload.data["led_gpio"]) {
|
||||||
|
ledGPIO.value = payload.data["led_gpio"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payload.data["ambient_color"]) {
|
||||||
|
ambientColor.value = payload.data["ambient_color"];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static async openSetup() {
|
||||||
|
// new
|
||||||
|
WebHandler.openPane(Pane.SETUP);
|
||||||
|
let menuBtn = document.getElementById("menuBtn") as HTMLButtonElement;
|
||||||
|
menuBtn.disabled = true;
|
||||||
|
|
||||||
|
const containerAddBtn = document.getElementById("containerAddBtn") as HTMLButtonElement;
|
||||||
|
containerAddBtn.onclick = Setup.addSetupContainer;
|
||||||
|
|
||||||
|
|
||||||
|
const setupSaveBtn = document.getElementById("setup_saveBtn") as HTMLButtonElement;
|
||||||
|
setupSaveBtn.onclick = () => {
|
||||||
|
const containers = document.getElementById("setupContainers") as HTMLDivElement;
|
||||||
|
|
||||||
|
let errorModal = new Modal("setup", "Fehler!");
|
||||||
|
let ele = document.createElement("p");
|
||||||
|
ele.innerHTML = `Das Setup konnte nicht abgeschlossen werden.<br>`;
|
||||||
|
errorModal.addContent(ele);
|
||||||
|
errorModal.addContent(document.createElement("br"));
|
||||||
|
errorModal.addButton(ButtonType.PRIMARY, "Schließen", () => {
|
||||||
|
errorModal.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (containers.childNodes.length == 0) {
|
||||||
|
ele.innerHTML += `Es muss mindestens ein Behälter hinzugefügt worden sein.`;
|
||||||
|
errorModal.open();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let c of containers.getElementsByTagName("div")) {
|
||||||
|
let selects = c.getElementsByTagName("select");
|
||||||
|
if (selects[0].value == "-1") {
|
||||||
|
ele.innerHTML += `Es müssen alle Pumpen-Pins gesetzt sein.`;
|
||||||
|
errorModal.open();
|
||||||
|
c.classList.add("error");
|
||||||
|
setTimeout(() => {
|
||||||
|
c.classList.remove("error");
|
||||||
|
}, 2500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selects[1].value != "-1" && (selects[2].value == "-1" || selects[3].value == "-1")) {
|
||||||
|
ele.innerHTML += `Wenn ein Sensor-Typ definiert ist, müssen alle Sensor-Pins gesetzt sein.`;
|
||||||
|
errorModal.open();
|
||||||
|
c.classList.add("error");
|
||||||
|
setTimeout(() => {
|
||||||
|
c.classList.remove("error");
|
||||||
|
}, 2500);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Setup.checkContainers()) {
|
||||||
|
ele.innerHTML = `Einige Pins sind doppelt belegt.<br>Jeder GPIO-Pin kann nur einmal belegt werden!`;
|
||||||
|
errorModal.open();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupSaveBtn.disabled = true;
|
||||||
|
|
||||||
|
let saveModal = new Modal("setup", "Setup");
|
||||||
|
let txt = document.createElement("p");
|
||||||
|
txt.innerHTML = `Die Einstellungen werden gespeichert...<br>
|
||||||
|
<div class="lds-ellipsis"><div></div><div></div><div></div><div></div></div>`;
|
||||||
|
saveModal.addContent(txt);
|
||||||
|
saveModal.open();
|
||||||
|
|
||||||
|
const ledCheckbox = document.getElementById("ledCheckbox") as HTMLInputElement;
|
||||||
|
const ledGPIO = document.getElementById("ledGPIO") as HTMLInputElement;
|
||||||
|
const ambientColor = document.getElementById("ambientColor") as HTMLInputElement;
|
||||||
|
const allowRemoteCheckbox = document.getElementById("allowRemoteCheckbox") as HTMLInputElement;
|
||||||
|
const hotspotCheckbox = document.getElementById("hotspotCheckbox") as HTMLInputElement;
|
||||||
|
|
||||||
|
|
||||||
|
let cons: { pumpPin: number; sensorType: SensorType; sensor1: number; sensor2: number; volume: number; }[] = [];
|
||||||
|
for (let c of (document.getElementById("setupContainers") as HTMLDivElement).getElementsByTagName("div")) {
|
||||||
|
let sensorType = c.getElementsByTagName("select")[1].value;
|
||||||
|
let type;
|
||||||
|
if( sensorType == "-1" )
|
||||||
|
type = SensorType.NONE;
|
||||||
|
else if ( sensorType == "0" )
|
||||||
|
type = SensorType.ULTRASOUND;
|
||||||
|
else
|
||||||
|
type = SensorType.LOADCELL;
|
||||||
|
|
||||||
|
cons.push({
|
||||||
|
"pumpPin": parseInt(c.getElementsByTagName("select")[0].value),
|
||||||
|
"sensorType": type,
|
||||||
|
"sensor1": parseInt(c.getElementsByTagName("select")[2].value),
|
||||||
|
"sensor2": parseInt(c.getElementsByTagName("select")[3].value),
|
||||||
|
"volume": parseInt(c.getElementsByTagName("select")[4].value)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let payload = new WebSocketPayload(WebSocketEvent.CONTAINERS, false, cons);
|
||||||
|
WebWebSocketHandler.send(payload);
|
||||||
|
|
||||||
|
payload = new WebSocketPayload(WebSocketEvent.CONFIG, false, {
|
||||||
|
"led_enabled": ledCheckbox.checked,
|
||||||
|
"remote_enabled": allowRemoteCheckbox.checked,
|
||||||
|
"hotspot_enabled": hotspotCheckbox.checked,
|
||||||
|
"led_gpio": parseInt(ledGPIO.value),
|
||||||
|
"ambient_color": ambientColor.value
|
||||||
|
});
|
||||||
|
menuBtn.disabled = false;
|
||||||
|
WebWebSocketHandler.send(payload).then(() => {
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
saveModal.close();
|
||||||
|
setupSaveBtn.disabled = false;
|
||||||
|
let tareModal = new Modal("setup", "Einmessung Sensoren");
|
||||||
|
let txt = document.createElement("p");
|
||||||
|
txt.innerHTML = `Damit alle Sensoren korrekte Werte liefern, sollte eine Einmessung durchgeführt werden.<br>
|
||||||
|
Während der Einmessung müssen die Behälter je nachdem geleert, gefüllt oder komplett entnommen werden.<br><br>`;
|
||||||
|
tareModal.addContent(txt);
|
||||||
|
|
||||||
|
tareModal.addButton(ButtonType.PRIMARY, "Später", () => {
|
||||||
|
tareModal.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
let ul;
|
||||||
|
tareModal.addButton(ButtonType.PRIMARY, "Starten", async () => {
|
||||||
|
tareModal.close();
|
||||||
|
let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {state: true});
|
||||||
|
|
||||||
|
let modal = new Modal("tare", "Einmessung");
|
||||||
|
|
||||||
|
let txt = document.createElement("p");
|
||||||
|
txt.innerHTML = `Messung Teil 1<br>
|
||||||
|
Bitte alle <strong>Behälter entfernen</strong> und Sensoren freilegen.<br>
|
||||||
|
Die Gewichtssensoren werden beim Bestätigen austariert<br><br>Zum fortfahren Tarieren drücken.<br>`;
|
||||||
|
modal.addContent(txt);
|
||||||
|
|
||||||
|
ul = document.createElement("ul");
|
||||||
|
modal.addContent(ul);
|
||||||
|
|
||||||
|
let btn = document.createElement("button");
|
||||||
|
btn.classList.add("btn", "btn-primary");
|
||||||
|
btn.innerText = "Tarieren";
|
||||||
|
btn.style.marginTop = "3%";
|
||||||
|
btn.onclick = () => {
|
||||||
|
let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 0});
|
||||||
|
WebWebSocketHandler.send(payload);
|
||||||
|
|
||||||
|
txt.innerHTML = `Messung Teil 2<br>
|
||||||
|
Bitte nun alle <strong>Behälter ohne Inhalt</strong> einsetzen.<br>
|
||||||
|
Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren Tarieren drücken.<br>`;
|
||||||
|
btn.onclick = () => {
|
||||||
|
let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 1});
|
||||||
|
WebWebSocketHandler.send(payload);
|
||||||
|
|
||||||
|
txt.innerHTML = `Messung Teil 3<br>
|
||||||
|
Bitte nun alle <strong>Behälter mit vollständigem Inhalt</strong> einsetzen.<br>
|
||||||
|
Die Gewichtssensoren werden beim Bestätigen austariert.<br><br>Zum fortfahren Tarieren drücken.<br>`;
|
||||||
|
|
||||||
|
btn.onclick = () => {
|
||||||
|
let payload = new WebSocketPayload(WebSocketEvent.TARE, false, {tare: 2});
|
||||||
|
WebWebSocketHandler.send(payload);
|
||||||
|
payload = new WebSocketPayload(WebSocketEvent.TARE, false, {state: false});
|
||||||
|
WebWebSocketHandler.send(payload);
|
||||||
|
|
||||||
|
txt.innerHTML = `Alle Werte wurden erfolgreich gespeichert.<br>Die Einmessung kann jederzeit über die Speichern-Navigation wiederholt werden.<br><br>Das Einmessen sollte nach mehrfachem Benutzen wiederholt werden.<br>`;
|
||||||
|
btn.innerText = "Schließen";
|
||||||
|
btn.onclick = () => modal.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
modal.addContent(btn);
|
||||||
|
await modal.open();
|
||||||
|
await WebWebSocketHandler.send(payload);
|
||||||
|
});
|
||||||
|
|
||||||
|
tareModal.open();
|
||||||
|
// irgendwie müssen jz die container updates abgegriffen werden
|
||||||
|
WebWebSocketHandler.tareContainerUpdates = (payload: WebSocketPayload) => {
|
||||||
|
if (!ul) return;
|
||||||
|
|
||||||
|
ul.innerHTML = "";
|
||||||
|
let containers = payload.data as IContainer[];
|
||||||
|
for (let c of containers) {
|
||||||
|
if (c.sensorType == SensorType.NONE) continue;
|
||||||
|
|
||||||
|
let li = document.createElement("li");
|
||||||
|
li.innerText = `Behälter ${c.slot}: ${c.rawData} [${c.sensorType}]`;
|
||||||
|
ul.append(li);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
}).catch(() => {
|
||||||
|
setupSaveBtn.disabled = false;
|
||||||
|
txt.innerHTML = `Fehler beim Speichern.<br>iTender hat nicht reagiert.`;
|
||||||
|
setTimeout(() => saveModal.close(), 2500);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static addSetupContainer() {
|
||||||
|
let setupContainers = document.getElementById("setupContainers") as HTMLDivElement;
|
||||||
|
|
||||||
|
let con = document.createElement("div");
|
||||||
|
|
||||||
|
let containerName = document.createElement("p");
|
||||||
|
containerName.innerText = "Behälter " + (setupContainers.getElementsByTagName("div").length + 1);
|
||||||
|
con.classList.add("setupContainer");
|
||||||
|
con.append(containerName);
|
||||||
|
|
||||||
|
let selectPin = document.createElement("select");
|
||||||
|
selectPin.style.display = "none";
|
||||||
|
selectPin.classList.add("input");
|
||||||
|
selectPin.style.display = "inline";
|
||||||
|
|
||||||
|
let noSel = document.createElement("option") as HTMLOptionElement;
|
||||||
|
noSel.innerText = "Bitte wählen";
|
||||||
|
noSel.value = "-1";
|
||||||
|
noSel.disabled = true;
|
||||||
|
|
||||||
|
selectPin.append(noSel.cloneNode(true));
|
||||||
|
selectPin.selectedIndex = 0;
|
||||||
|
|
||||||
|
const pins = [3, 5, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 21, 23, 24, 26, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40];
|
||||||
|
for (let pin of pins) {
|
||||||
|
let pinEle = document.createElement("option") as HTMLOptionElement;
|
||||||
|
pinEle.innerText = "" + pin;
|
||||||
|
pinEle.value = "" + pin;
|
||||||
|
selectPin.append(pinEle);
|
||||||
|
}
|
||||||
|
|
||||||
|
let nSelect;
|
||||||
|
|
||||||
|
let pumpLabel = document.createElement("label");
|
||||||
|
pumpLabel.innerText = "Pumpen Pin";
|
||||||
|
con.append(pumpLabel);
|
||||||
|
nSelect = selectPin.cloneNode(true);
|
||||||
|
nSelect.onchange = () => Setup.checkContainers();
|
||||||
|
nSelect.selectedIndex = 0;
|
||||||
|
con.append(nSelect);
|
||||||
|
|
||||||
|
con.append(document.createElement("br"));
|
||||||
|
|
||||||
|
// Sensor Art
|
||||||
|
let sensorTypeLabel = document.createElement("label");
|
||||||
|
sensorTypeLabel.innerText = "Sensor Art ";
|
||||||
|
con.append(sensorTypeLabel);
|
||||||
|
|
||||||
|
let sensorType = document.createElement("select");
|
||||||
|
sensorType.classList.add("noCheckup");
|
||||||
|
sensorType.classList.add("input");
|
||||||
|
let sensorTypeNone = document.createElement("option") as HTMLOptionElement;
|
||||||
|
sensorTypeNone.innerText = "Kein Sensor";
|
||||||
|
sensorTypeNone.value = "-1";
|
||||||
|
sensorType.append(sensorTypeNone);
|
||||||
|
let sensorTypeUltrasound = document.createElement("option") as HTMLOptionElement;
|
||||||
|
sensorTypeUltrasound.innerText = "Ultraschall";
|
||||||
|
sensorTypeUltrasound.value = "0";
|
||||||
|
sensorType.append(sensorTypeUltrasound);
|
||||||
|
let sensorTypeScale = document.createElement("option") as HTMLOptionElement;
|
||||||
|
sensorTypeScale.innerText = "Wägezelle";
|
||||||
|
sensorTypeScale.value = "1";
|
||||||
|
sensorType.append(sensorTypeScale);
|
||||||
|
con.append(sensorType);
|
||||||
|
con.append(document.createElement("br"));
|
||||||
|
|
||||||
|
// Sensor 1
|
||||||
|
let sensor1Label = document.createElement("label");
|
||||||
|
sensor1Label.innerText = "Sensor 1 Pin";
|
||||||
|
con.append(sensor1Label);
|
||||||
|
let sensor1Select = selectPin.cloneNode(true) as HTMLSelectElement;
|
||||||
|
sensor1Select.selectedIndex = 0;
|
||||||
|
sensor1Select.disabled = true;
|
||||||
|
sensor1Select.onchange = () => Setup.checkContainers();
|
||||||
|
con.append(sensor1Select);
|
||||||
|
|
||||||
|
con.append(document.createElement("br"));
|
||||||
|
|
||||||
|
// Sensor 2
|
||||||
|
let sensor2Label = document.createElement("label");
|
||||||
|
sensor2Label.innerText = "Sensor 2 Pin";
|
||||||
|
con.append(sensor2Label);
|
||||||
|
let sensor2Select = selectPin.cloneNode(true) as HTMLSelectElement;
|
||||||
|
sensor2Select.selectedIndex = 0;
|
||||||
|
sensor2Select.disabled = true;
|
||||||
|
sensor2Select.onchange = () => Setup.checkContainers();
|
||||||
|
con.append(sensor2Select);
|
||||||
|
|
||||||
|
sensorType.onchange = () => {
|
||||||
|
if (sensorType.value == "0") {
|
||||||
|
sensor1Label.innerText = "Trigger Pin";
|
||||||
|
sensor2Label.innerText = "Trigger Pin";
|
||||||
|
sensor1Select.disabled = false;
|
||||||
|
sensor2Select.disabled = false;
|
||||||
|
} else if (sensorType.value == "1") {
|
||||||
|
sensor1Label.innerText = "Clock Pin";
|
||||||
|
sensor2Label.innerText = "Data Pin";
|
||||||
|
sensor1Select.disabled = false;
|
||||||
|
sensor2Select.disabled = false;
|
||||||
|
} else {
|
||||||
|
sensor1Label.innerText = "Sensor 1 Pin";
|
||||||
|
sensor2Label.innerText = "Sensor 2 Pin";
|
||||||
|
sensor1Select.disabled = true;
|
||||||
|
sensor2Select.disabled = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
con.append(document.createElement("br"));
|
||||||
|
|
||||||
|
|
||||||
|
// Volume
|
||||||
|
let volumeLabel = document.createElement("label");
|
||||||
|
volumeLabel.innerText = "Volumen (ml) ";
|
||||||
|
con.append(volumeLabel);
|
||||||
|
let volumeSelect = document.createElement("select");
|
||||||
|
volumeSelect.classList.add("noCheckup");
|
||||||
|
volumeSelect.classList.add("input");
|
||||||
|
const mls = [50, 100, 200, 250, 300, 330, 500, 750, 1000, 1250, 1500, 2000, 2500, 5000, 10000];
|
||||||
|
for (let ml of mls) {
|
||||||
|
let pinEle = document.createElement("option") as HTMLOptionElement;
|
||||||
|
pinEle.innerText = "" + ml;
|
||||||
|
pinEle.value = "" + ml;
|
||||||
|
volumeSelect.append(pinEle);
|
||||||
|
volumeSelect["volume"] = volumeSelect;
|
||||||
|
}
|
||||||
|
volumeSelect.selectedIndex = 7;
|
||||||
|
con.append(volumeSelect);
|
||||||
|
|
||||||
|
let removeBtn = document.createElement("button");
|
||||||
|
removeBtn.classList.add("btn", "btn-danger");
|
||||||
|
|
||||||
|
removeBtn.onclick = () => {
|
||||||
|
con.classList.add("removeSlowly");
|
||||||
|
setTimeout(() => {
|
||||||
|
con.remove();
|
||||||
|
let i = 1;
|
||||||
|
for (let elementsByTagNameElement of setupContainers.getElementsByTagName("div")) {
|
||||||
|
let e = elementsByTagNameElement.getElementsByTagName("p")[0] as HTMLParagraphElement;
|
||||||
|
e.innerText = "Behälter " + i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}, 750);
|
||||||
|
|
||||||
|
}
|
||||||
|
removeBtn.style.float = "right";
|
||||||
|
removeBtn.innerText = "Entfernen";
|
||||||
|
con.append(removeBtn);
|
||||||
|
|
||||||
|
setupContainers.append(con);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static checkContainers(): boolean {
|
||||||
|
console.log("Checking containers...")
|
||||||
|
let returner = true;
|
||||||
|
const containers = document.getElementById("setupContainers") as HTMLDivElement;
|
||||||
|
let setupContainers = containers.getElementsByTagName("div");
|
||||||
|
for (let c of setupContainers) {
|
||||||
|
for (let c2 of setupContainers) {
|
||||||
|
for (let sel of c.getElementsByTagName("select")) {
|
||||||
|
if (sel.value == "-1") continue;
|
||||||
|
if (sel.classList.contains("noCheckup")) continue;
|
||||||
|
if (sel.disabled) continue;
|
||||||
|
|
||||||
|
|
||||||
|
for (let sel2 of c2.getElementsByTagName("select")) {
|
||||||
|
if (sel2.value == "-1") continue;
|
||||||
|
if (sel2.disabled) continue;
|
||||||
|
if (sel == sel2) continue;
|
||||||
|
if (sel2.classList.contains("noCheckup")) continue;
|
||||||
|
|
||||||
|
|
||||||
|
if (sel.value == sel2.value) {
|
||||||
|
c.classList.add("error");
|
||||||
|
c2.classList.add("error");
|
||||||
|
sel.classList.add("error");
|
||||||
|
sel2.classList.add("error");
|
||||||
|
setTimeout(() => {
|
||||||
|
c.classList.remove("error");
|
||||||
|
c2.classList.remove("error");
|
||||||
|
sel.classList.remove("error");
|
||||||
|
sel2.classList.remove("error");
|
||||||
|
}, 2200);
|
||||||
|
returner = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returner;
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ import {IDrink} from "../database/IDrink";
|
|||||||
import {Modal} from "./Modal";
|
import {Modal} from "./Modal";
|
||||||
import {ButtonType} from "./ButtonType";
|
import {ButtonType} from "./ButtonType";
|
||||||
import {Pane} from "./Pane";
|
import {Pane} from "./Pane";
|
||||||
import {setup} from "rpi-gpio";
|
|
||||||
|
|
||||||
export class WebHandler {
|
export class WebHandler {
|
||||||
private static containers = [];
|
private static containers = [];
|
||||||
@ -63,110 +62,8 @@ ${ingredients}`*/ //todo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async openSetup() {
|
static async openSetup() {
|
||||||
// new
|
|
||||||
this.openPane(Pane.SETUP);
|
|
||||||
let menuBtn = document.getElementById("menuBtn") as HTMLButtonElement;
|
|
||||||
let setupContainers = document.getElementById("setupContainers") as HTMLDivElement;
|
|
||||||
menuBtn.disabled = true;
|
|
||||||
|
|
||||||
const containerAddBtn = document.getElementById("containerAddBtn") as HTMLButtonElement;
|
|
||||||
containerAddBtn.onclick = () => {
|
|
||||||
|
|
||||||
|
|
||||||
let con = document.createElement("div");
|
|
||||||
|
|
||||||
let containerName = document.createElement("p");
|
|
||||||
containerName.innerText = "Behälter " + (setupContainers.getElementsByTagName("div").length + 1);
|
|
||||||
con.classList.add("setupContainer");
|
|
||||||
con.append(containerName);
|
|
||||||
|
|
||||||
let sensorTypeLabel = document.createElement("label");
|
|
||||||
sensorTypeLabel.innerText = "Art des Sensors ";
|
|
||||||
con.append(sensorTypeLabel);
|
|
||||||
|
|
||||||
let sensorType = document.createElement("select");
|
|
||||||
sensorType.classList.add("input");
|
|
||||||
let sensorTypeNone = document.createElement("option") as HTMLOptionElement;
|
|
||||||
sensorTypeNone.innerText = "Keiner";
|
|
||||||
sensorTypeNone.value = "0";
|
|
||||||
sensorType.append(sensorTypeNone);
|
|
||||||
let sensorTypeUltrasound = document.createElement("option") as HTMLOptionElement;
|
|
||||||
sensorTypeUltrasound.innerText = "Ultraschall";
|
|
||||||
sensorTypeUltrasound.value = "1";
|
|
||||||
sensorType.append(sensorTypeUltrasound);
|
|
||||||
let sensorTypeScale = document.createElement("option") as HTMLOptionElement;
|
|
||||||
sensorTypeScale.innerText = "Wägezelle";
|
|
||||||
sensorTypeScale.value = "2";
|
|
||||||
sensorType.append(sensorTypeScale);
|
|
||||||
con.append(sensorType);
|
|
||||||
|
|
||||||
con.append(document.createElement("br"));
|
|
||||||
|
|
||||||
|
|
||||||
let selectPin = document.createElement("select");
|
|
||||||
selectPin.style.display = "none";
|
|
||||||
selectPin.classList.add("input");
|
|
||||||
selectPin.style.display = "inline";
|
|
||||||
|
|
||||||
let noSel = document.createElement("option") as HTMLOptionElement;
|
|
||||||
noSel.innerText = "Bitte wählen";
|
|
||||||
noSel.value = "-1";
|
|
||||||
noSel.disabled = true;
|
|
||||||
|
|
||||||
selectPin.append(noSel.cloneNode(true));
|
|
||||||
selectPin.selectedIndex = 0;
|
|
||||||
|
|
||||||
const pins = [3, 5, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 21, 22, 23, 24, 26, 29, 31, 32, 33, 34, 35, 36, 37, 38, 40];
|
|
||||||
for (let pin of pins) {
|
|
||||||
let pinEle = document.createElement("option") as HTMLOptionElement;
|
|
||||||
pinEle.innerText = "" + pin;
|
|
||||||
pinEle.value = "" + pin;
|
|
||||||
selectPin.append(pinEle);
|
|
||||||
}
|
|
||||||
|
|
||||||
let pumpLabel = document.createElement("label");
|
|
||||||
pumpLabel.innerText = "Pumpen Pin";
|
|
||||||
con.append(pumpLabel);
|
|
||||||
con.append(selectPin.cloneNode(true));
|
|
||||||
|
|
||||||
con.append(document.createElement("br"));
|
|
||||||
|
|
||||||
let sensor1Label = document.createElement("label");
|
|
||||||
sensor1Label.innerText = "Sensor 1 Pin";
|
|
||||||
con.append(sensor1Label);
|
|
||||||
con.append(selectPin.cloneNode(true));
|
|
||||||
|
|
||||||
con.append(document.createElement("br"));
|
|
||||||
|
|
||||||
let sensor2Label = document.createElement("label");
|
|
||||||
sensor2Label.innerText = "Sensor 2 Pin";
|
|
||||||
con.append(sensor2Label);
|
|
||||||
con.append(selectPin.cloneNode(true));
|
|
||||||
|
|
||||||
con.append(document.createElement("br"));
|
|
||||||
|
|
||||||
let removeBtn = document.createElement("button");
|
|
||||||
removeBtn.classList.add("btn", "btn-danger");
|
|
||||||
removeBtn.onclick = () => {
|
|
||||||
con.classList.add("removeSlowly");
|
|
||||||
setTimeout(() => {
|
|
||||||
con.remove();
|
|
||||||
let i = 1;
|
|
||||||
for (let elementsByTagNameElement of setupContainers.getElementsByTagName("div")) {
|
|
||||||
let e = elementsByTagNameElement.getElementsByTagName("p")[0] as HTMLParagraphElement;
|
|
||||||
e.innerText = "Behälter " + i;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}, 750);
|
|
||||||
|
|
||||||
}
|
|
||||||
removeBtn.style.float = "right";
|
|
||||||
removeBtn.innerText = "Entfernen";
|
|
||||||
con.append(removeBtn);
|
|
||||||
|
|
||||||
setupContainers.append(con);
|
|
||||||
|
|
||||||
};
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// old
|
// old
|
||||||
|
@ -4,17 +4,21 @@ import {WebSocketPayload} from "../WebSocketPayload";
|
|||||||
import {ButtonType} from "./ButtonType";
|
import {ButtonType} from "./ButtonType";
|
||||||
import {iTenderStatus} from "../iTenderStatus";
|
import {iTenderStatus} from "../iTenderStatus";
|
||||||
import {WebHandler} from "./WebHandler";
|
import {WebHandler} from "./WebHandler";
|
||||||
|
import {Setup} from "./Setup";
|
||||||
|
|
||||||
export class WebWebSocketHandler {
|
export class WebWebSocketHandler {
|
||||||
private socket: WebSocket;
|
private static socket: WebSocket;
|
||||||
private static url = (window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005";
|
private static url = (window.location.protocol == "http:" ? "ws://" : "wss://") + window.location.hostname + ":3005";
|
||||||
|
public static tareContainerUpdates: (payload: WebSocketPayload) => void;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.socket = new WebSocket(WebWebSocketHandler.url);
|
WebWebSocketHandler.socket = new WebSocket(WebWebSocketHandler.url);
|
||||||
this.socket.onopen = this.onOpen;
|
WebWebSocketHandler.socket.onopen = this.onOpen;
|
||||||
this.socket.onclose = this.onClose;
|
WebWebSocketHandler.socket.onclose = this.onClose;
|
||||||
this.socket.onerror = this.onError;
|
WebWebSocketHandler.socket.onerror = this.onError;
|
||||||
this.socket.onmessage = this.onMessage;
|
WebWebSocketHandler.socket.onmessage = this.onMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private onMessage(msgEvent: MessageEvent) {
|
private onMessage(msgEvent: MessageEvent) {
|
||||||
@ -24,13 +28,15 @@ export class WebWebSocketHandler {
|
|||||||
console.log("[WS] Could not parse message: ", msgEvent);
|
console.log("[WS] Could not parse message: ", msgEvent);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.debug(payload)
|
|
||||||
|
|
||||||
console.debug(payload.event);
|
|
||||||
|
|
||||||
console.log("[WS] Received " + payload.event + " Event");
|
console.log("[WS] Received " + payload.event + " Event");
|
||||||
|
|
||||||
switch (payload.event) {
|
switch (payload.event) {
|
||||||
|
case WebSocketEvent.CONFIG: {
|
||||||
|
// Incoming WebSocketStatus
|
||||||
|
Setup.onConfigUpdate(payload);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case WebSocketEvent.STATUS: {
|
case WebSocketEvent.STATUS: {
|
||||||
let statusElement = document.getElementById("status");
|
let statusElement = document.getElementById("status");
|
||||||
if (statusElement)
|
if (statusElement)
|
||||||
@ -64,7 +70,7 @@ export class WebWebSocketHandler {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case iTenderStatus.SETUP: {
|
case iTenderStatus.SETUP: {
|
||||||
WebHandler.openSetup();
|
Setup.openSetup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -100,7 +106,7 @@ export class WebWebSocketHandler {
|
|||||||
let txt = document.createElement("p");
|
let txt = document.createElement("p");
|
||||||
txt.innerHTML = `Diese Sitzung wurde beendet, da der iTender nun an einem anderen Gerät bzw. an dem Hauptgerät gesteuert wird.<br><br>`;
|
txt.innerHTML = `Diese Sitzung wurde beendet, da der iTender nun an einem anderen Gerät bzw. an dem Hauptgerät gesteuert wird.<br><br>`;
|
||||||
modal.addContent(txt);
|
modal.addContent(txt);
|
||||||
modal.addButton(ButtonType.SUCCESS, "Sitzung wiederherstellen", () => {
|
modal.addButton(ButtonType.PRIMARY, "Sitzung wiederherstellen", () => {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
modal.open();
|
modal.open();
|
||||||
@ -131,4 +137,24 @@ export class WebWebSocketHandler {
|
|||||||
//openModal("Einen Augenblick...", `Es wurde ein kritischer Fehler festgestellt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
|
//openModal("Einen Augenblick...", `Es wurde ein kritischer Fehler festgestellt.\nBitte warten Sie, während der Prozess neu gestartet wird...` );
|
||||||
//window.location.reload();
|
//window.location.reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static send(payload: WebSocketPayload): Promise<void> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
if (this.socket && this.socket.readyState == 1) {
|
||||||
|
await this.socket.send(payload.toString());
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
/*let modal = new Modal("error", "Verbindungsfehler");
|
||||||
|
let txt = document.createElement("p");
|
||||||
|
txt.innerHTML = `Beim Austausch von Informationen ist ein Problem aufgetreten.<br>Falls dies öfter passieren sollte, ist der Support zu kontaktieren.`;
|
||||||
|
modal.addContent(txt);
|
||||||
|
await modal.open();*/
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,28 @@
|
|||||||
extends layout
|
extends layout
|
||||||
|
|
||||||
block setup
|
block setup
|
||||||
|
div#setupLEDDiv
|
||||||
|
h1 LED-Einstellungen
|
||||||
|
div.inputGroup
|
||||||
|
label(onclick="document.getElementById('ledCheckbox').checked = !document.getElementById('ledCheckbox').checked;") Aktivieren
|
||||||
|
input#ledCheckbox.input(type="checkbox")
|
||||||
|
div.inputGroup
|
||||||
|
label GPIO-Pin
|
||||||
|
input#ledGPIO.input(type="number" value="22" style="width:15%" disabled="disabled")
|
||||||
|
div.inputGroup
|
||||||
|
label Ambiente Farbe
|
||||||
|
input#ambientColor.input(type="color" value="#05445E" style="width:15%" disabled="disabled")
|
||||||
|
|
||||||
|
div#setupExtraDiv
|
||||||
|
h1 Erweiterte Einstellungen
|
||||||
|
div.inputGroup
|
||||||
|
label(onclick="document.getElementById('allowRemoteCheckbox').checked = !document.getElementById('allowRemoteCheckbox').checked;") Remote-Verbindungen erlauben
|
||||||
|
input#allowRemoteCheckbox.input(type="checkbox")
|
||||||
|
div.inputGroup
|
||||||
|
label(onclick="document.getElementById('hotspotCheckbox').checked = !document.getElementById('hotspotCheckbox').checked;") Ohne WiFi Hotspot aktivieren
|
||||||
|
input#hotspotCheckbox.input(type="checkbox")
|
||||||
|
|
||||||
|
|
||||||
div#setupContainersDiv
|
div#setupContainersDiv
|
||||||
h1 Behälter
|
h1 Behälter
|
||||||
// Setup
|
// Setup
|
||||||
@ -9,32 +31,7 @@ block setup
|
|||||||
div#setupContainers
|
div#setupContainers
|
||||||
|
|
||||||
|
|
||||||
div#setupLEDDiv
|
button.btn.btn-success#setup_saveBtn(style="grid-row: span 1; grid-column: span 2; border-radius: 15px; font-size: 1.2em;") Speichern
|
||||||
h1 LED-Einstellungen
|
|
||||||
div.inputGroup
|
|
||||||
label Aktivieren
|
|
||||||
input.input(type="checkbox")
|
|
||||||
div.inputGroup
|
|
||||||
label GPIO-Pin
|
|
||||||
input.input(type="number" value="22" style="width:15%" disabled="disabled")
|
|
||||||
div.inputGroup
|
|
||||||
label Ambiente Farbe
|
|
||||||
input.input(type="color" value="#05445e" style="width:15%" disabled="disabled")
|
|
||||||
|
|
||||||
div#setupExtraDiv
|
|
||||||
h1 Erweiterte Einstellungen
|
|
||||||
div.inputGroup
|
|
||||||
label Remote-Verbindungen erlauben
|
|
||||||
input.input(type="checkbox" id="setup_remoteCheckbox")
|
|
||||||
div.inputGroup
|
|
||||||
label Ohne WiFi Hotspot aktivieren
|
|
||||||
input.input(type="checkbox" id="setup_hotspotCheckbox")
|
|
||||||
div.inputGroup
|
|
||||||
label Ohne WiFi Hotspot aktivieren
|
|
||||||
input.input(type="checkbox" id="setup_hotspotCheckbox")
|
|
||||||
|
|
||||||
|
|
||||||
button.btn.btn-success(style="grid-row: span 1; grid-column: span 2; border-radius: 15px; font-size: 1.2em;") Speichern
|
|
||||||
|
|
||||||
block menu
|
block menu
|
||||||
// Menu
|
// Menu
|
||||||
|
@ -14,7 +14,7 @@ html
|
|||||||
div#top
|
div#top
|
||||||
span#left <strong>Status:</strong> <span id="status">...</span>
|
span#left <strong>Status:</strong> <span id="status">...</span>
|
||||||
span#title iTender
|
span#title iTender
|
||||||
span#right Verbinden...
|
span#right 00:00
|
||||||
div#bottom
|
div#bottom
|
||||||
button.btn#menuBtn Menü
|
button.btn#menuBtn Menü
|
||||||
div#containers
|
div#containers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user