Update v1.0.1

Took 1 hour 27 minutes
This commit is contained in:
2022-11-23 23:56:46 +01:00
parent 6446896565
commit 1b8376644e
63 changed files with 146 additions and 50 deletions

View File

@ -43,4 +43,9 @@ export class Utils {
fs.unlinkSync("./public/images/" + id + ".png");
}
static checkForImage( id )
{
return fs.existsSync("./public/images/" + id + ".png");
}
}

View File

@ -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;
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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
}));
});
}