Update v1.0.1
Took 1 hour 27 minutes
This commit is contained in:
@ -43,4 +43,9 @@ export class Utils {
|
||||
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 {Buffer} from "buffer";
|
||||
|
||||
export class WebSocketPayload {
|
||||
set event(value: WebSocketEvent) {
|
||||
@ -37,7 +38,8 @@ export class WebSocketPayload {
|
||||
}
|
||||
|
||||
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 };
|
||||
try {
|
||||
rawPayload = JSON.parse(json);
|
||||
@ -55,6 +57,7 @@ export class WebSocketPayload {
|
||||
*/
|
||||
public toString(): string {
|
||||
let json = JSON.stringify({"event": this._event, status: this._error, data: this._data});
|
||||
|
||||
json = ((typeof window != 'undefined') ? btoa(json) : Buffer.from(json).toString("base64"));
|
||||
return json;
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ import Ingredient from "./database/Ingredient";
|
||||
import {clearInterval} from "timers";
|
||||
import {RejectReason} from "./RejectReason";
|
||||
import {Settings} from "./Settings";
|
||||
import GPIO from "rpi-gpio";
|
||||
import axios from "axios";
|
||||
|
||||
const log = debug("itender:station");
|
||||
@ -76,12 +75,14 @@ export class iTender {
|
||||
const job = new Job();
|
||||
|
||||
let amounts: { ingredient: IIngredient, amount: number, container?: IContainer }[] = [];
|
||||
job.completeAmount = 0;
|
||||
if (data.amounts) {
|
||||
for (let x of data.amounts) {
|
||||
let ingredient = await Ingredient.findById(x.ingredient);
|
||||
if (!ingredient) continue;
|
||||
|
||||
amounts.push({ingredient: ingredient, amount: x.amount});
|
||||
job.completeAmount+= x.amount;
|
||||
}
|
||||
} else if (data.amount) {
|
||||
let sum = 0;
|
||||
@ -93,17 +94,19 @@ export class iTender {
|
||||
|
||||
for (let x of (drink.ingredients as { type: IIngredient, amount: number }[])) {
|
||||
amounts.push({ingredient: x.type, amount: x.amount * factor})
|
||||
job.completeAmount+= x.amount;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
for (let x of (drink.ingredients as { type: IIngredient, amount: number }[])) {
|
||||
amounts.push({ingredient: x.type, amount: x.amount});
|
||||
job.completeAmount+= x.amount;
|
||||
}
|
||||
}
|
||||
|
||||
job.estimatedTime = 0;
|
||||
let tolerance = 5;
|
||||
let tolerance = 3;
|
||||
for (let x of amounts) {
|
||||
let c = await Container.findOne({$and: [{enabled: true}, {filled: {$gt: x.amount + tolerance}}]});
|
||||
if (!c) {
|
||||
@ -140,15 +143,15 @@ export class iTender {
|
||||
let timers: NodeJS.Timeout[] = [];
|
||||
for (let x of job.amounts) {
|
||||
// Start pump here
|
||||
await GPIO.setup(x.container.pumpPin, GPIO.DIR_OUT);
|
||||
await GPIO.write(x.container.pumpPin, true);
|
||||
//await GPIO.setup(x.container.pumpPin, GPIO.DIR_OUT);
|
||||
//await GPIO.write(x.container.pumpPin, true);
|
||||
|
||||
let waitTime = (Settings.get("secondsPer100ml") as number) / 100 * x.amount * 1000;
|
||||
mixLog(`Starting output of pump ${x.container.pumpPin}`);
|
||||
//mixLog(x.ingredient + " takes " + (waitTime / 1000) + "s for " + x.amount + "ml");
|
||||
let timer = setTimeout(() => {
|
||||
// Stop pump here
|
||||
GPIO.write(x.container.pumpPin, false);
|
||||
//GPIO.write(x.container.pumpPin, false);
|
||||
|
||||
// Remove from list of timers
|
||||
let arr: NodeJS.Timer[] = [];
|
||||
@ -178,7 +181,7 @@ export class iTender {
|
||||
}
|
||||
|
||||
static cancelFill() {
|
||||
if (!this._currentJob)
|
||||
if (!this._currentJob || this.status != iTenderStatus.FILLING)
|
||||
return;
|
||||
clearInterval(this._jobCheckInterval);
|
||||
this._currentJob.successful = false;
|
||||
@ -189,7 +192,7 @@ export class iTender {
|
||||
for (let x of this._currentJob.amounts) {
|
||||
// stop pump pin
|
||||
//x.container.pumpPin
|
||||
GPIO.write(x.container.pumpPin, false);
|
||||
//GPIO.write(x.container.pumpPin, false);
|
||||
}
|
||||
|
||||
iTender.setStatus(iTenderStatus.READY);
|
||||
@ -235,7 +238,6 @@ export class iTender {
|
||||
}
|
||||
|
||||
static refreshDrinks(): Promise<void> {
|
||||
this.setStatus(iTenderStatus.REFRESHING);
|
||||
log("Refreshing drinks...");
|
||||
return new Promise(async resolve => {
|
||||
this._drinks = [];
|
||||
@ -256,7 +258,6 @@ export class iTender {
|
||||
|
||||
}
|
||||
log("Drinks refreshed!");
|
||||
iTender.setStatus(iTenderStatus.READY);
|
||||
await WebSocketHandler.sendDrinks();
|
||||
resolve();
|
||||
|
||||
@ -305,11 +306,9 @@ export class iTender {
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (!found) {
|
||||
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.save();
|
||||
}
|
||||
@ -319,16 +318,16 @@ export class iTender {
|
||||
|
||||
|
||||
for (let remote of serverIngredients) {
|
||||
let ingredient = await Ingredient.findOne({name: remote.name});
|
||||
let ingredient = await Ingredient.findById(remote._id);
|
||||
if (!ingredient)
|
||||
ingredient = new Ingredient();
|
||||
|
||||
ingredient._id = remote._id;
|
||||
ingredient.name = remote.name;
|
||||
await ingredient.save();
|
||||
}
|
||||
|
||||
|
||||
|
||||
const requestDrinks = await axios.get("https://itender.iif.li/api/drinks");
|
||||
let serverDrinks = requestDrinks.data as IDrink[];
|
||||
log("Got " + serverDrinks.length + " drinks from server");
|
||||
@ -344,8 +343,7 @@ export class iTender {
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (!found) {
|
||||
Utils.deleteImage(local._id);
|
||||
await Drink.deleteOne({"_id": local._id});
|
||||
}
|
||||
@ -354,10 +352,11 @@ export class iTender {
|
||||
|
||||
|
||||
for (let remote of serverDrinks) {
|
||||
let drink = await Drink.findOne({name: remote.name});
|
||||
let drink = await Drink.findById(remote._id);
|
||||
if (!drink)
|
||||
drink = new Drink();
|
||||
|
||||
drink._id = remote._id;
|
||||
drink.name = remote.name;
|
||||
drink.ingredients = remote.ingredients;
|
||||
|
||||
@ -365,11 +364,14 @@ export class iTender {
|
||||
|
||||
|
||||
// Download thumbnail
|
||||
Utils.downloadImage("https://itender.iif.li/images/" + remote._id + ".png", "./public/images/" + drink._id + ".png").then(filepath => {
|
||||
log("Drink " + remote.name + "'s Thumbnail downloaded to " + filepath);
|
||||
}).catch(e => {
|
||||
log("Drink " + remote.name + " failed to download thumbnail!\n" + e);
|
||||
});
|
||||
if (!Utils.checkForImage(remote._id)) {
|
||||
try {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,6 @@ const wsApp = new WebsocketApp();
|
||||
function init(): Promise<void> {
|
||||
log("Initializing...");
|
||||
return new Promise(async resolve => {
|
||||
iTender.setStatus(iTenderStatus.STARTING);
|
||||
|
||||
setTimeout( async () => {
|
||||
// Network
|
||||
|
@ -40,7 +40,7 @@ export class WebHandler {
|
||||
drinkEle.append(drinkName);
|
||||
|
||||
drinkImg.alt = "Foto von " + drink.name;
|
||||
drinkImg.src = "/images/" + drink.name + ".png";
|
||||
drinkImg.src = "/images/" + drink._id + ".png";
|
||||
drinkName.innerText = drink.name;
|
||||
|
||||
|
||||
|
@ -7,7 +7,6 @@ import {WebHandler} from "./WebHandler";
|
||||
import {Setup} from "./Setup";
|
||||
import {Pane} from "./Pane";
|
||||
import {RequestType} from "../RequestType";
|
||||
import {IDrink} from "../database/IDrink";
|
||||
import {IJob} from "../database/IJob";
|
||||
|
||||
export class WebWebSocketHandler {
|
||||
@ -64,8 +63,9 @@ export class WebWebSocketHandler {
|
||||
case iTenderStatus.READY: {
|
||||
Modal.close("start");
|
||||
Modal.close("setup");
|
||||
Modal.close("fill");
|
||||
if( WebHandler.currentPane != Pane.MENU )
|
||||
//Modal.close("fill");
|
||||
Modal.close("download");
|
||||
if (WebHandler.currentPane != Pane.MENU)
|
||||
WebHandler.openPane(Pane.MAIN);
|
||||
(document.getElementById("menuBtn") as HTMLButtonElement).disabled = false;
|
||||
break;
|
||||
@ -79,6 +79,15 @@ export class WebWebSocketHandler {
|
||||
modal.open();
|
||||
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: {
|
||||
/* let modal = new Modal("refreshing", "Aktualisieren...");
|
||||
let txt = document.createElement("p");
|
||||
@ -111,10 +120,19 @@ export class WebWebSocketHandler {
|
||||
|
||||
modal.addContent(waterAnimDiv);
|
||||
|
||||
let seconds = document.createElement("p");
|
||||
let seconds = document.createElement("span");
|
||||
seconds.innerText = "60s";
|
||||
seconds.style.marginRight = "3%";
|
||||
|
||||
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");
|
||||
cancelBtn.classList.add("btn", "btn-danger");
|
||||
@ -132,28 +150,53 @@ export class WebWebSocketHandler {
|
||||
};
|
||||
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) => {
|
||||
let minus = 0;
|
||||
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.backgroundImage = `url("/images/${job.drink.name}.png")`;
|
||||
waterAnimDiv.style.backgroundImage = `url("/images/${job.drink._id}.png")`;
|
||||
header.innerText = job.drink.name;
|
||||
seconds.innerText = job.estimatedTime + "s";
|
||||
let minus = 0;
|
||||
let interval = setInterval( () => {
|
||||
|
||||
let last = 0;
|
||||
let interval = setInterval(() => {
|
||||
minus++;
|
||||
if( minus+1 > (job.estimatedTime as number) )
|
||||
{
|
||||
if (minus + 1 > (job.estimatedTime as number)) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
|
||||
seconds.innerText = (job.estimatedTime as number - minus) + "s";
|
||||
}, 1000 )
|
||||
seconds.innerText = (Math.floor(job.estimatedTime as number - minus)) + "s";
|
||||
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;
|
||||
}
|
||||
|
||||
@ -250,7 +293,7 @@ export class WebWebSocketHandler {
|
||||
* @param type
|
||||
* @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)
|
||||
return new Promise(resolve => {
|
||||
WebWebSocketHandler.registerForEvent(WebSocketEvent.RESPONSE, (payload) => {
|
||||
@ -258,7 +301,10 @@ export class WebWebSocketHandler {
|
||||
resolve(payload);
|
||||
}
|
||||
});
|
||||
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, false, {type: type, content: content}));
|
||||
WebWebSocketHandler.send(new WebSocketPayload(WebSocketEvent.REQUEST, false, {
|
||||
type: type,
|
||||
content: content
|
||||
}));
|
||||
});
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user