feat: add brew app connection

- initialize tcp communication with brew app
- WIP value editor sync

Signed-off-by: pakintada@gmail.com <Pakin>
This commit is contained in:
pakintada@gmail.com 2026-04-03 17:25:27 +07:00
parent 08f7626dcb
commit 274025ed33
14 changed files with 431 additions and 69 deletions

View file

@ -3,9 +3,11 @@
import * as Card from '$lib/components/ui/card/index';
import Label from '$lib/components/ui/label/label.svelte';
import Input from '$lib/components/ui/input/input.svelte';
import { onDestroy, onMount } from 'svelte';
import Button from '$lib/components/ui/button/button.svelte';
import { createEventDispatcher, onDestroy, onMount } from 'svelte';
import RecipelistTable from './recipelist-table.svelte';
import * as adb from '$lib/core/adb/adb';
import { columns, type RecipelistMaterial } from './columns';
import { get, readable, writable } from 'svelte/store';
import {
@ -17,6 +19,11 @@
import { machineInfoStore } from '$lib/core/stores/machineInfoStore';
import MachineInfo from '../machine-info.svelte';
import { v4 as uuidv4 } from 'uuid';
import { addNotification } from '$lib/core/stores/noti';
import { env } from '$env/dynamic/public';
import { sendCommand, sendReset } from '$lib/core/brew/command';
import { isAdbWriterAvailable } from '$lib/core/stores/adbWriter';
import { sendToAndroid } from '$lib/core/stores/adbWriter';
//
let {
@ -35,6 +42,8 @@
let toppingSlotState: any = $state([]);
const recipeDetailDispatch = createEventDispatcher();
function remappingToColumn(data: any[]): RecipelistMaterial[] {
let ret: RecipelistMaterial[] = [];
// expect recipelist
@ -90,6 +99,62 @@
return ret;
}
async function getCurrentQueue() {
let inst = adb.getAdbInstance();
if (inst) {
let current_brewing = await adb.pull(env.PUBLIC_BREW_CURRENT_RECIPE);
// console.log(`current brewing queue: ${current_brewing}`);
if (current_brewing === '') {
current_brewing = '{}';
}
return JSON.parse(current_brewing ?? '{}');
}
return {
error: 'instance lost'
};
}
async function resetAllPendingCmds() {
// send reset to brew
try {
await sendReset();
addNotification(`INFO:Reset completed!`);
} catch (e) {
addNotification(`ERR:${e}`);
}
}
async function saveRecipe() {}
async function sendTriggerBrewNow() {
// check queue ready
// let currentBrewingQueue = await getCurrentQueue();
// console.log('checking queue ... ', Object.keys(currentBrewingQueue).length);
await sendToAndroid({
type: 'brew_prep',
payload: {
start: new Date().toLocaleTimeString()
}
});
// if (Object.keys(currentBrewingQueue).length != 0) {
// addNotification('ERR:Brewing queue is full, please check machine or press `reset`');
// return;
// }
//
let inst = adb.getAdbInstance();
if (inst) {
console.log('check adb writer', isAdbWriterAvailable());
recipeDetailDispatch('brewNow');
} else {
console.log('result check fail');
}
}
async function checkChanges(original: any) {
console.log('old', original, 'updated', recipeListMatState);
if (recipeListOriginal.length == 0) {
@ -133,10 +198,23 @@
<div class="-mb-4 flex w-full flex-col gap-6">
<Tabs.Root value="info">
<Tabs.List>
<Tabs.Trigger value="info">Info</Tabs.Trigger>
<Tabs.Trigger value="details">Details</Tabs.Trigger>
</Tabs.List>
<div class="flex flex-row justify-between">
<Tabs.List>
<Tabs.Trigger value="info">Info</Tabs.Trigger>
<Tabs.Trigger value="details">Details</Tabs.Trigger>
</Tabs.List>
{#if refPage === 'brew'}
<div>
<Button type="button" variant="default" onclick={() => resetAllPendingCmds()}
>Force Reset Brewing</Button
>
<Button type="button" variant="default" onclick={() => saveRecipe()}>Save</Button>
<Button type="button" variant="default" onclick={async () => sendTriggerBrewNow()}
>Test Brew</Button
>
</div>
{/if}
</div>
<Tabs.Content value="info">
<Card.Root>