Update v1.0.1
Took 1 hour 27 minutes
6
ToDo.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# ToDo
|
||||||
|
|
||||||
|
- [ ] Behälter unten rechts anzeigen
|
||||||
|
- [ ] Status für Netzwerk oben neben Uhrzeit
|
||||||
|
- [ ] Fix Fehler wenn keine Getränke hinzugefügt worden sind
|
||||||
|
-
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "itender",
|
"name": "itender",
|
||||||
"version": "0.0.1",
|
"version": "1.0.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
|
"author": "Tobias Hopp <tobi@gaminggeneration.de>",
|
||||||
"license": "UNLICENSED",
|
"license": "UNLICENSED",
|
||||||
@ -23,6 +23,7 @@
|
|||||||
"@types/rpi-gpio": "^2.1.1",
|
"@types/rpi-gpio": "^2.1.1",
|
||||||
"@types/rpi-ws281x-native": "^1.0.0",
|
"@types/rpi-ws281x-native": "^1.0.0",
|
||||||
"axios": "^1.2.0",
|
"axios": "^1.2.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"cookie-parser": "^1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"debug": "^4.3.4",
|
"debug": "^4.3.4",
|
||||||
"express": "~4.16.1",
|
"express": "~4.16.1",
|
||||||
|
BIN
public/images/6372bf5911e5032258e52b5d.png
Normal file
After Width: | Height: | Size: 1020 KiB |
BIN
public/images/637e780e92e2eb68eb272dbb.png
Normal file
After Width: | Height: | Size: 611 KiB |
BIN
public/images/637e782a92e2eb68eb272dc7.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
public/images/637e785c92e2eb68eb272dd9.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
public/images/637e789092e2eb68eb272de7.png
Normal file
After Width: | Height: | Size: 313 KiB |
BIN
public/images/637e78d392e2eb68eb272e0c.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/images/637e790816d571f976c7a7ae.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
public/images/637e790816d571f976c7a7b2.png
Normal file
After Width: | Height: | Size: 22 KiB |
BIN
public/images/637e790816d571f976c7a7b8.png
Normal file
After Width: | Height: | Size: 611 KiB |
BIN
public/images/637e790816d571f976c7a7bd.png
Normal file
After Width: | Height: | Size: 313 KiB |
BIN
public/images/637e790816d571f976c7a7c3.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
public/images/637e790992e2eb68eb272e2d.png
Normal file
After Width: | Height: | Size: 167 KiB |
BIN
public/images/637e793d92e2eb68eb272e3e.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
public/images/637e795f92e2eb68eb272e4a.png
Normal file
After Width: | Height: | Size: 462 KiB |
BIN
public/images/637e798b92e2eb68eb272e5a.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
public/images/637e79ea92e2eb68eb272e75.png
Normal file
After Width: | Height: | Size: 116 KiB |
BIN
public/images/637e7a1f92e2eb68eb272e8a.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
public/images/637e7c7b92e2eb68eb272e9c.png
Normal file
After Width: | Height: | Size: 817 KiB |
BIN
public/images/637e7cd392e2eb68eb272eb1.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/images/637e7d0492e2eb68eb272ec2.png
Normal file
After Width: | Height: | Size: 353 KiB |
BIN
public/images/637e7f175340730a377d606a.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
public/images/637e7f485340730a377d621e.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
public/images/637e7f955340730a377d6225.png
Normal file
After Width: | Height: | Size: 640 KiB |
BIN
public/images/637e7ff35340730a377d63a4.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
public/images/637e80175340730a377d63ac.png
Normal file
After Width: | Height: | Size: 370 KiB |
BIN
public/images/637e802d5340730a377d63b5.png
Normal file
After Width: | Height: | Size: 921 KiB |
BIN
public/images/637e804f5340730a377d63bf.png
Normal file
After Width: | Height: | Size: 938 KiB |
BIN
public/images/637e807d5340730a377d640d.png
Normal file
After Width: | Height: | Size: 706 KiB |
BIN
public/images/637e80a35340730a377d6417.png
Normal file
After Width: | Height: | Size: 688 KiB |
BIN
public/images/637e80c05340730a377d641f.png
Normal file
After Width: | Height: | Size: 982 KiB |
BIN
public/images/637e907619ee137bb0a010ed.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
public/images/637e907619ee137bb0a010f2.png
Normal file
After Width: | Height: | Size: 353 KiB |
BIN
public/images/637e907619ee137bb0a010fc.png
Normal file
After Width: | Height: | Size: 640 KiB |
BIN
public/images/637e907619ee137bb0a01100.png
Normal file
After Width: | Height: | Size: 162 KiB |
BIN
public/images/637e907619ee137bb0a01107.png
Normal file
After Width: | Height: | Size: 817 KiB |
BIN
public/images/637e907619ee137bb0a0110d.png
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
public/images/637e907619ee137bb0a01111.png
Normal file
After Width: | Height: | Size: 462 KiB |
BIN
public/images/637e907619ee137bb0a01116.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/images/637e907619ee137bb0a01136.png
Normal file
After Width: | Height: | Size: 167 KiB |
BIN
public/images/637e907619ee137bb0a01148.png
Normal file
After Width: | Height: | Size: 938 KiB |
BIN
public/images/637e907619ee137bb0a0114d.png
Normal file
After Width: | Height: | Size: 982 KiB |
BIN
public/images/637e907619ee137bb0a01151.png
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
public/images/637e907619ee137bb0a01159.png
Normal file
After Width: | Height: | Size: 73 KiB |
BIN
public/images/637e907619ee137bb0a01160.png
Normal file
After Width: | Height: | Size: 1.0 MiB |
BIN
public/images/637e907619ee137bb0a01165.png
Normal file
After Width: | Height: | Size: 688 KiB |
BIN
public/images/637e907619ee137bb0a0116a.png
Normal file
After Width: | Height: | Size: 706 KiB |
BIN
public/images/637e907619ee137bb0a0116f.png
Normal file
After Width: | Height: | Size: 370 KiB |
BIN
public/images/637e907619ee137bb0a01173.png
Normal file
After Width: | Height: | Size: 921 KiB |
BIN
public/images/637e907619ee137bb0a01178.png
Normal file
After Width: | Height: | Size: 116 KiB |
@ -12,6 +12,19 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-blendout {
|
||||||
|
animation: 1s blendOut forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blendOut {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.inputGroup {
|
.inputGroup {
|
||||||
margin-bottom: 1.5%;
|
margin-bottom: 1.5%;
|
||||||
}
|
}
|
||||||
@ -107,6 +120,7 @@ label {
|
|||||||
margin-right: 1%;
|
margin-right: 1%;
|
||||||
margin-bottom: 2%;
|
margin-bottom: 2%;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
background-color: #e9e9ed;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ body {
|
|||||||
top: -90%;
|
top: -90%;
|
||||||
left: -50%;
|
left: -50%;
|
||||||
border-radius: 40%;
|
border-radius: 40%;
|
||||||
animation: animWater 8s linear infinite, animFillIn var(--fillTime) linear forwards;
|
animation: animWater 7s linear infinite, animFillIn var(--fillTime) linear forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
.water::after {
|
.water::after {
|
||||||
@ -100,7 +100,7 @@ body {
|
|||||||
top: -100%;
|
top: -100%;
|
||||||
left: -52%;
|
left: -52%;
|
||||||
border-radius: 40%;
|
border-radius: 40%;
|
||||||
animation: animWater 8s linear infinite, animFillIn var(--fillTime) linear forwards;
|
animation: animWater 7s linear infinite, animFillIn var(--fillTime) linear forwards;
|
||||||
animation-delay: 0.4s;
|
animation-delay: 0.4s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +109,11 @@ body {
|
|||||||
transition: background-color 1s;
|
transition: background-color 1s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.waterFinished {
|
||||||
|
background-color: green;
|
||||||
|
transition: background-color 2s;
|
||||||
|
}
|
||||||
|
|
||||||
@keyframes animFillIn {
|
@keyframes animFillIn {
|
||||||
0% {
|
0% {
|
||||||
top: -100%;
|
top: -100%;
|
||||||
|
@ -63,12 +63,12 @@
|
|||||||
|
|
||||||
|
|
||||||
.modalBlendIn {
|
.modalBlendIn {
|
||||||
animation: modalBlendIn 0.5s ease;
|
animation: modalBlendIn 0.5s forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.modalBlendOut {
|
.modalBlendOut {
|
||||||
animation: modalBlendOut 0.8s ease;
|
animation: modalBlendOut 0.8s forwards;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ html * {
|
|||||||
-webkit-user-select: none; /* Safari */
|
-webkit-user-select: none; /* Safari */
|
||||||
-ms-user-select: none; /* IE 10 and IE 11 */
|
-ms-user-select: none; /* IE 10 and IE 11 */
|
||||||
user-select: none; /* Standard syntax */
|
user-select: none; /* Standard syntax */
|
||||||
cursor: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -55,6 +55,12 @@ h1 {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.45em;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-bottom: 2%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#overlay {
|
#overlay {
|
||||||
color: white;
|
color: white;
|
||||||
|
@ -43,4 +43,9 @@ export class Utils {
|
|||||||
fs.unlinkSync("./public/images/" + id + ".png");
|
fs.unlinkSync("./public/images/" + id + ".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static checkForImage( id )
|
||||||
|
{
|
||||||
|
return fs.existsSync("./public/images/" + id + ".png");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import {WebSocketEvent} from "./WebSocketEvent";
|
import {WebSocketEvent} from "./WebSocketEvent";
|
||||||
|
import {Buffer} from "buffer";
|
||||||
|
|
||||||
export class WebSocketPayload {
|
export class WebSocketPayload {
|
||||||
set event(value: WebSocketEvent) {
|
set event(value: WebSocketEvent) {
|
||||||
@ -37,7 +38,8 @@ export class WebSocketPayload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static parseFromBase64Json(json: string): WebSocketPayload | null {
|
public static parseFromBase64Json(json: string): WebSocketPayload | null {
|
||||||
json = (typeof window != 'undefined') ? atob(json) : Buffer.from(json, "base64").toString();
|
//json = (typeof window != 'undefined') ? atob(json).toString() : Buffer.from(json, "base64").toString("utf-8");
|
||||||
|
json = Buffer.from(json, "base64").toString("utf-8");
|
||||||
let rawPayload: { event: string, error: boolean, data: any };
|
let rawPayload: { event: string, error: boolean, data: any };
|
||||||
try {
|
try {
|
||||||
rawPayload = JSON.parse(json);
|
rawPayload = JSON.parse(json);
|
||||||
@ -55,6 +57,7 @@ export class WebSocketPayload {
|
|||||||
*/
|
*/
|
||||||
public toString(): string {
|
public toString(): string {
|
||||||
let json = JSON.stringify({"event": this._event, status: this._error, data: this._data});
|
let json = JSON.stringify({"event": this._event, status: this._error, data: this._data});
|
||||||
|
|
||||||
json = ((typeof window != 'undefined') ? btoa(json) : Buffer.from(json).toString("base64"));
|
json = ((typeof window != 'undefined') ? btoa(json) : Buffer.from(json).toString("base64"));
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,6 @@ import Ingredient from "./database/Ingredient";
|
|||||||
import {clearInterval} from "timers";
|
import {clearInterval} from "timers";
|
||||||
import {RejectReason} from "./RejectReason";
|
import {RejectReason} from "./RejectReason";
|
||||||
import {Settings} from "./Settings";
|
import {Settings} from "./Settings";
|
||||||
import GPIO from "rpi-gpio";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
const log = debug("itender:station");
|
const log = debug("itender:station");
|
||||||
@ -76,12 +75,14 @@ export class iTender {
|
|||||||
const job = new Job();
|
const job = new Job();
|
||||||
|
|
||||||
let amounts: { ingredient: IIngredient, amount: number, container?: IContainer }[] = [];
|
let amounts: { ingredient: IIngredient, amount: number, container?: IContainer }[] = [];
|
||||||
|
job.completeAmount = 0;
|
||||||
if (data.amounts) {
|
if (data.amounts) {
|
||||||
for (let x of data.amounts) {
|
for (let x of data.amounts) {
|
||||||
let ingredient = await Ingredient.findById(x.ingredient);
|
let ingredient = await Ingredient.findById(x.ingredient);
|
||||||
if (!ingredient) continue;
|
if (!ingredient) continue;
|
||||||
|
|
||||||
amounts.push({ingredient: ingredient, amount: x.amount});
|
amounts.push({ingredient: ingredient, amount: x.amount});
|
||||||
|
job.completeAmount+= x.amount;
|
||||||
}
|
}
|
||||||
} else if (data.amount) {
|
} else if (data.amount) {
|
||||||
let sum = 0;
|
let sum = 0;
|
||||||
@ -93,17 +94,19 @@ export class iTender {
|
|||||||
|
|
||||||
for (let x of (drink.ingredients as { type: IIngredient, amount: number }[])) {
|
for (let x of (drink.ingredients as { type: IIngredient, amount: number }[])) {
|
||||||
amounts.push({ingredient: x.type, amount: x.amount * factor})
|
amounts.push({ingredient: x.type, amount: x.amount * factor})
|
||||||
|
job.completeAmount+= x.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
for (let x of (drink.ingredients as { type: IIngredient, amount: number }[])) {
|
for (let x of (drink.ingredients as { type: IIngredient, amount: number }[])) {
|
||||||
amounts.push({ingredient: x.type, amount: x.amount});
|
amounts.push({ingredient: x.type, amount: x.amount});
|
||||||
|
job.completeAmount+= x.amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
job.estimatedTime = 0;
|
job.estimatedTime = 0;
|
||||||
let tolerance = 5;
|
let tolerance = 3;
|
||||||
for (let x of amounts) {
|
for (let x of amounts) {
|
||||||
let c = await Container.findOne({$and: [{enabled: true}, {filled: {$gt: x.amount + tolerance}}]});
|
let c = await Container.findOne({$and: [{enabled: true}, {filled: {$gt: x.amount + tolerance}}]});
|
||||||
if (!c) {
|
if (!c) {
|
||||||
@ -140,15 +143,15 @@ export class iTender {
|
|||||||
let timers: NodeJS.Timeout[] = [];
|
let timers: NodeJS.Timeout[] = [];
|
||||||
for (let x of job.amounts) {
|
for (let x of job.amounts) {
|
||||||
// Start pump here
|
// Start pump here
|
||||||
await GPIO.setup(x.container.pumpPin, GPIO.DIR_OUT);
|
//await GPIO.setup(x.container.pumpPin, GPIO.DIR_OUT);
|
||||||
await GPIO.write(x.container.pumpPin, true);
|
//await GPIO.write(x.container.pumpPin, true);
|
||||||
|
|
||||||
let waitTime = (Settings.get("secondsPer100ml") as number) / 100 * x.amount * 1000;
|
let waitTime = (Settings.get("secondsPer100ml") as number) / 100 * x.amount * 1000;
|
||||||
mixLog(`Starting output of pump ${x.container.pumpPin}`);
|
mixLog(`Starting output of pump ${x.container.pumpPin}`);
|
||||||
//mixLog(x.ingredient + " takes " + (waitTime / 1000) + "s for " + x.amount + "ml");
|
//mixLog(x.ingredient + " takes " + (waitTime / 1000) + "s for " + x.amount + "ml");
|
||||||
let timer = setTimeout(() => {
|
let timer = setTimeout(() => {
|
||||||
// Stop pump here
|
// Stop pump here
|
||||||
GPIO.write(x.container.pumpPin, false);
|
//GPIO.write(x.container.pumpPin, false);
|
||||||
|
|
||||||
// Remove from list of timers
|
// Remove from list of timers
|
||||||
let arr: NodeJS.Timer[] = [];
|
let arr: NodeJS.Timer[] = [];
|
||||||
@ -178,7 +181,7 @@ export class iTender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static cancelFill() {
|
static cancelFill() {
|
||||||
if (!this._currentJob)
|
if (!this._currentJob || this.status != iTenderStatus.FILLING)
|
||||||
return;
|
return;
|
||||||
clearInterval(this._jobCheckInterval);
|
clearInterval(this._jobCheckInterval);
|
||||||
this._currentJob.successful = false;
|
this._currentJob.successful = false;
|
||||||
@ -189,7 +192,7 @@ export class iTender {
|
|||||||
for (let x of this._currentJob.amounts) {
|
for (let x of this._currentJob.amounts) {
|
||||||
// stop pump pin
|
// stop pump pin
|
||||||
//x.container.pumpPin
|
//x.container.pumpPin
|
||||||
GPIO.write(x.container.pumpPin, false);
|
//GPIO.write(x.container.pumpPin, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
iTender.setStatus(iTenderStatus.READY);
|
iTender.setStatus(iTenderStatus.READY);
|
||||||
@ -235,7 +238,6 @@ export class iTender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static refreshDrinks(): Promise<void> {
|
static refreshDrinks(): Promise<void> {
|
||||||
this.setStatus(iTenderStatus.REFRESHING);
|
|
||||||
log("Refreshing drinks...");
|
log("Refreshing drinks...");
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
this._drinks = [];
|
this._drinks = [];
|
||||||
@ -256,7 +258,6 @@ export class iTender {
|
|||||||
|
|
||||||
}
|
}
|
||||||
log("Drinks refreshed!");
|
log("Drinks refreshed!");
|
||||||
iTender.setStatus(iTenderStatus.READY);
|
|
||||||
await WebSocketHandler.sendDrinks();
|
await WebSocketHandler.sendDrinks();
|
||||||
resolve();
|
resolve();
|
||||||
|
|
||||||
@ -305,11 +306,9 @@ export class iTender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found) {
|
||||||
{
|
|
||||||
await Ingredient.deleteOne({"_id": local._id});
|
await Ingredient.deleteOne({"_id": local._id});
|
||||||
for( let c of (await Container.find( {content: local._id } )) )
|
for (let c of (await Container.find({content: local._id}))) {
|
||||||
{
|
|
||||||
c.content = undefined;
|
c.content = undefined;
|
||||||
c.save();
|
c.save();
|
||||||
}
|
}
|
||||||
@ -319,16 +318,16 @@ export class iTender {
|
|||||||
|
|
||||||
|
|
||||||
for (let remote of serverIngredients) {
|
for (let remote of serverIngredients) {
|
||||||
let ingredient = await Ingredient.findOne({name: remote.name});
|
let ingredient = await Ingredient.findById(remote._id);
|
||||||
if (!ingredient)
|
if (!ingredient)
|
||||||
ingredient = new Ingredient();
|
ingredient = new Ingredient();
|
||||||
|
|
||||||
|
ingredient._id = remote._id;
|
||||||
ingredient.name = remote.name;
|
ingredient.name = remote.name;
|
||||||
await ingredient.save();
|
await ingredient.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const requestDrinks = await axios.get("https://itender.iif.li/api/drinks");
|
const requestDrinks = await axios.get("https://itender.iif.li/api/drinks");
|
||||||
let serverDrinks = requestDrinks.data as IDrink[];
|
let serverDrinks = requestDrinks.data as IDrink[];
|
||||||
log("Got " + serverDrinks.length + " drinks from server");
|
log("Got " + serverDrinks.length + " drinks from server");
|
||||||
@ -344,8 +343,7 @@ export class iTender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
if (!found) {
|
||||||
{
|
|
||||||
Utils.deleteImage(local._id);
|
Utils.deleteImage(local._id);
|
||||||
await Drink.deleteOne({"_id": local._id});
|
await Drink.deleteOne({"_id": local._id});
|
||||||
}
|
}
|
||||||
@ -354,10 +352,11 @@ export class iTender {
|
|||||||
|
|
||||||
|
|
||||||
for (let remote of serverDrinks) {
|
for (let remote of serverDrinks) {
|
||||||
let drink = await Drink.findOne({name: remote.name});
|
let drink = await Drink.findById(remote._id);
|
||||||
if (!drink)
|
if (!drink)
|
||||||
drink = new Drink();
|
drink = new Drink();
|
||||||
|
|
||||||
|
drink._id = remote._id;
|
||||||
drink.name = remote.name;
|
drink.name = remote.name;
|
||||||
drink.ingredients = remote.ingredients;
|
drink.ingredients = remote.ingredients;
|
||||||
|
|
||||||
@ -365,11 +364,14 @@ export class iTender {
|
|||||||
|
|
||||||
|
|
||||||
// Download thumbnail
|
// Download thumbnail
|
||||||
Utils.downloadImage("https://itender.iif.li/images/" + remote._id + ".png", "./public/images/" + drink._id + ".png").then(filepath => {
|
if (!Utils.checkForImage(remote._id)) {
|
||||||
log("Drink " + remote.name + "'s Thumbnail downloaded to " + filepath);
|
try {
|
||||||
}).catch(e => {
|
await Utils.downloadImage("https://itender.iif.li/images/" + remote._id + ".png", "./public/images/" + drink._id + ".png")
|
||||||
|
log("Drink " + remote.name + "'s Thumbnail downloaded");
|
||||||
|
} catch (e) {
|
||||||
log("Drink " + remote.name + " failed to download thumbnail!\n" + e);
|
log("Drink " + remote.name + " failed to download thumbnail!\n" + e);
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,6 @@ const wsApp = new WebsocketApp();
|
|||||||
function init(): Promise<void> {
|
function init(): Promise<void> {
|
||||||
log("Initializing...");
|
log("Initializing...");
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
iTender.setStatus(iTenderStatus.STARTING);
|
|
||||||
|
|
||||||
setTimeout( async () => {
|
setTimeout( async () => {
|
||||||
// Network
|
// Network
|
||||||
|
@ -40,7 +40,7 @@ export class WebHandler {
|
|||||||
drinkEle.append(drinkName);
|
drinkEle.append(drinkName);
|
||||||
|
|
||||||
drinkImg.alt = "Foto von " + drink.name;
|
drinkImg.alt = "Foto von " + drink.name;
|
||||||
drinkImg.src = "/images/" + drink.name + ".png";
|
drinkImg.src = "/images/" + drink._id + ".png";
|
||||||
drinkName.innerText = drink.name;
|
drinkName.innerText = drink.name;
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ import {WebHandler} from "./WebHandler";
|
|||||||
import {Setup} from "./Setup";
|
import {Setup} from "./Setup";
|
||||||
import {Pane} from "./Pane";
|
import {Pane} from "./Pane";
|
||||||
import {RequestType} from "../RequestType";
|
import {RequestType} from "../RequestType";
|
||||||
import {IDrink} from "../database/IDrink";
|
|
||||||
import {IJob} from "../database/IJob";
|
import {IJob} from "../database/IJob";
|
||||||
|
|
||||||
export class WebWebSocketHandler {
|
export class WebWebSocketHandler {
|
||||||
@ -64,8 +63,9 @@ export class WebWebSocketHandler {
|
|||||||
case iTenderStatus.READY: {
|
case iTenderStatus.READY: {
|
||||||
Modal.close("start");
|
Modal.close("start");
|
||||||
Modal.close("setup");
|
Modal.close("setup");
|
||||||
Modal.close("fill");
|
//Modal.close("fill");
|
||||||
if( WebHandler.currentPane != Pane.MENU )
|
Modal.close("download");
|
||||||
|
if (WebHandler.currentPane != Pane.MENU)
|
||||||
WebHandler.openPane(Pane.MAIN);
|
WebHandler.openPane(Pane.MAIN);
|
||||||
(document.getElementById("menuBtn") as HTMLButtonElement).disabled = false;
|
(document.getElementById("menuBtn") as HTMLButtonElement).disabled = false;
|
||||||
break;
|
break;
|
||||||
@ -79,6 +79,15 @@ export class WebWebSocketHandler {
|
|||||||
modal.open();
|
modal.open();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case iTenderStatus.DOWNLOADING: {
|
||||||
|
let modal = new Modal("download", "Aktualisieren");
|
||||||
|
let txt = document.createElement("p");
|
||||||
|
txt.innerHTML = `Einen Augenblick bitte<br>iTender aktualisiert die Getränke vom Server.`;
|
||||||
|
modal.addContent(txt);
|
||||||
|
modal.loader = true;
|
||||||
|
modal.open();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case iTenderStatus.REFRESHING: {
|
case iTenderStatus.REFRESHING: {
|
||||||
/* let modal = new Modal("refreshing", "Aktualisieren...");
|
/* let modal = new Modal("refreshing", "Aktualisieren...");
|
||||||
let txt = document.createElement("p");
|
let txt = document.createElement("p");
|
||||||
@ -111,10 +120,19 @@ export class WebWebSocketHandler {
|
|||||||
|
|
||||||
modal.addContent(waterAnimDiv);
|
modal.addContent(waterAnimDiv);
|
||||||
|
|
||||||
let seconds = document.createElement("p");
|
let seconds = document.createElement("span");
|
||||||
seconds.innerText = "60s";
|
seconds.innerText = "60s";
|
||||||
|
seconds.style.marginRight = "3%";
|
||||||
|
|
||||||
modal.addContent(seconds);
|
modal.addContent(seconds);
|
||||||
|
|
||||||
|
let ml = document.createElement("span");
|
||||||
|
ml.innerText = "200ml";
|
||||||
|
modal.addContent(ml);
|
||||||
|
|
||||||
|
modal.addContent(document.createElement("br"));
|
||||||
|
modal.addContent(document.createElement("br"));
|
||||||
|
|
||||||
|
|
||||||
let cancelBtn = document.createElement("button");
|
let cancelBtn = document.createElement("button");
|
||||||
cancelBtn.classList.add("btn", "btn-danger");
|
cancelBtn.classList.add("btn", "btn-danger");
|
||||||
@ -132,28 +150,53 @@ export class WebWebSocketHandler {
|
|||||||
};
|
};
|
||||||
modal.addContent(cancelBtn);
|
modal.addContent(cancelBtn);
|
||||||
|
|
||||||
|
function riseSlowlyUp(lastNumber:number, number: number) {
|
||||||
|
for (let i = lastNumber; i < number; i++) {
|
||||||
|
setTimeout(() => {
|
||||||
|
ml.innerText = i + "ml";
|
||||||
|
}, (number-lastNumber/1000)+i*4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modal.open().then(() => {
|
||||||
|
|
||||||
modal.open().then( () => {
|
|
||||||
WebWebSocketHandler.request(RequestType.JOB).then((payload) => {
|
WebWebSocketHandler.request(RequestType.JOB).then((payload) => {
|
||||||
|
let minus = 0;
|
||||||
let job = payload.data.content as IJob;
|
let job = payload.data.content as IJob;
|
||||||
|
ml.innerText = Math.floor((job.completeAmount / job.estimatedTime) * minus) + "ml";
|
||||||
waterAnimDiv.style.setProperty("--fillTime", job.estimatedTime + "s");
|
waterAnimDiv.style.setProperty("--fillTime", job.estimatedTime + "s");
|
||||||
waterAnimDiv.style.backgroundImage = `url("/images/${job.drink.name}.png")`;
|
waterAnimDiv.style.backgroundImage = `url("/images/${job.drink._id}.png")`;
|
||||||
header.innerText = job.drink.name;
|
header.innerText = job.drink.name;
|
||||||
seconds.innerText = job.estimatedTime + "s";
|
seconds.innerText = job.estimatedTime + "s";
|
||||||
let minus = 0;
|
|
||||||
let interval = setInterval( () => {
|
let last = 0;
|
||||||
|
let interval = setInterval(() => {
|
||||||
minus++;
|
minus++;
|
||||||
if( minus+1 > (job.estimatedTime as number) )
|
if (minus + 1 > (job.estimatedTime as number)) {
|
||||||
{
|
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds.innerText = (job.estimatedTime as number - minus) + "s";
|
seconds.innerText = (Math.floor(job.estimatedTime as number - minus)) + "s";
|
||||||
}, 1000 )
|
let calc = Math.floor((job.completeAmount / job.estimatedTime) * minus);
|
||||||
|
riseSlowlyUp(last, calc)
|
||||||
|
last = calc;
|
||||||
|
//ml.innerText = + "ml";
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
txt.innerHTML = "Bitte entnehme den Cocktail!";
|
||||||
|
/*cancelBtn.classList.add("btn-primary");
|
||||||
|
cancelBtn.classList.remove("btn-danger");
|
||||||
|
cancelBtn.innerText = "Schließen";*/
|
||||||
|
cancelBtn.classList.add("btn-blendout");
|
||||||
|
waterAnimDiv.classList.add("waterFinished");
|
||||||
|
cancelBtn.onclick = () => {
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
setTimeout(() => modal.close(), 1000 * 4.5);
|
||||||
|
}, job.estimatedTime * 1000);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
} );
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,7 +293,7 @@ export class WebWebSocketHandler {
|
|||||||
* @param type
|
* @param type
|
||||||
* @param content
|
* @param content
|
||||||
*/
|
*/
|
||||||
public static request(type: RequestType, content: any = null ): Promise<WebSocketPayload> {
|
public static request(type: RequestType, content: any = null): Promise<WebSocketPayload> {
|
||||||
console.log("Request to " + type)
|
console.log("Request to " + type)
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
|
WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
|
||||||
@ -258,7 +301,10 @@ export class WebWebSocketHandler {
|
|||||||
resolve(payload);
|
resolve(payload);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, false, {type: type, content: content}));
|
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, false, {
|
||||||
|
type: type,
|
||||||
|
content: content
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +51,7 @@ block menu
|
|||||||
|
|
||||||
block settings
|
block settings
|
||||||
// Settings
|
// Settings
|
||||||
|
button.btn.btn-primary#settings_refreshDrinks Getränke herunterladen
|
||||||
|
|
||||||
block main
|
block main
|
||||||
// Main is build dynamically
|
// Main is build dynamically
|
||||||
|
10
yarn.lock
@ -1384,6 +1384,14 @@ buffer@^5.6.0:
|
|||||||
base64-js "^1.3.1"
|
base64-js "^1.3.1"
|
||||||
ieee754 "^1.1.13"
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
|
buffer@^6.0.3:
|
||||||
|
version "6.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||||
|
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||||
|
dependencies:
|
||||||
|
base64-js "^1.3.1"
|
||||||
|
ieee754 "^1.2.1"
|
||||||
|
|
||||||
bytes@3.0.0:
|
bytes@3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
|
||||||
@ -1960,7 +1968,7 @@ iconv-lite@0.4.23:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
ieee754@^1.1.13:
|
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|