import { get } from 'svelte/store'; import { updateMachineStatus } from '../stores/machineInfoStore'; import { addNotification } from '../stores/noti'; import { loadAndroidRecipeExportFromDevice, saveAndroidRecipeExportPayload } from '../services/androidRecipeExportService'; import { handleIncomingMessages } from './messageHandler'; import { setMenuSaved, setMenuSaveError } from '../stores/menuSaveStore'; import { recipeFromMachineQuery } from '../stores/recipeStore'; type AdbPayload = { type: string; payload: any }; async function handleAdbPayload(raw_payload: string) { console.log('[ADB] Received payload:', raw_payload.slice(0, 300)); try { const payload: AdbPayload = JSON.parse(raw_payload); console.log('[ADB] Parsed type:', payload.type, 'payload:', payload.payload); switch (payload.type) { case 'log': let log_level = payload.payload['level'] ?? 'INFO'; let log_message = payload.payload['msg'] ?? ''; if (log_message !== '') { console.log('[ADB LOG]', log_level, log_message); addNotification(`${log_level}:${log_message}`); } break; case 'response': if (typeof payload.payload === 'string' || payload.payload instanceof String) { // single message response let raw_payload = payload.payload.toString(); if ( raw_payload.startsWith('save_recipe_machine') || raw_payload.startsWith('save_recipe_menu_file') ) { let res = raw_payload.split('/'); let pd = res[1] ?? ''; let action = res[2] ?? ''; let uiAction = res[3] ?? ''; console.log('[ADB] Save response parsed:', { pd, action, uiAction, raw_payload }); // Track menu save status if (raw_payload.startsWith('save_recipe_menu_file') && pd) { if (action === 'success' || action === 'ok' || uiAction === 'refreshNow') { setMenuSaved(pd); addNotification(`INFO:Menu saved: ${pd}`); } else if (action === 'error' || action === 'fail') { setMenuSaveError(pd, 'Save failed'); addNotification(`ERR:Failed to save menu: ${pd}`); } else { // Assume success if we get a response setMenuSaved(pd); addNotification(`INFO:Menu saved: ${pd}`); } } if (raw_payload.startsWith('save_recipe_machine')) { handleIncomingMessages( JSON.stringify({ type: 'ui_action', payload: { action: uiAction, from: 'brew', ref: `${pd}.${action}` } }) ); } } else if (raw_payload.startsWith('state')) { let res = raw_payload.split('/'); let new_machine_state = res[1] ?? ''; if (new_machine_state != '') { updateMachineStatus(new_machine_state.replace('MACHINE_STATE_', '')); } } } break; case 'ACK': // acknowledge response from app if (payload.payload !== 'OK') { // abnormal console.error('error from ACK', payload.payload); addNotification('ERR:Request rejected'); } break; case 'machine': // machine state if (payload.payload) { let states = payload.payload.split('/'); let curr = states[0].replace('MACHINE_STATE_', ''); let next = states[1].replace('MACHINE_STATE_', ''); console.log('current state', curr, 'next state', next); addNotification('INFO:Machine Status Updated, ' + next); updateMachineStatus(next); } break; case 'brew-finish': if (payload.payload) { let plist = payload.payload.split('/'); let pd = plist[0] ?? ''; let total_time = plist[1] ?? ''; let mode_ref = plist[2] ?? ''; // update recipe data store console.log('brewing finish', pd, 'total time', total_time); // update recipe from brew now let recipeDevSnapshot = get(recipeFromMachineQuery) ?? {}; let recipe01Snap = recipeDevSnapshot['recipe']; if (recipe01Snap) { recipe01Snap[pd].total_time = mode_ref != 'sim' ? total_time : recipe01Snap[pd].total_time; recipeDevSnapshot['recipe'] = recipe01Snap; recipeFromMachineQuery.set(recipeDevSnapshot); } } break; case 'error': // show error to user from brew app addNotification(`ERR:${payload.payload}`); // send message to server if needed break; case 'recipe-export': if (payload.payload?.content) { saveAndroidRecipeExportPayload({ content: payload.payload.content, exportedAt: payload.payload.exportedAt, source: payload.payload.source, fileSizeBytes: payload.payload.fileSizeBytes, lineCount: payload.payload.lineCount, message: payload.payload.message }); addNotification('INFO:Recipe export received from Android'); } else if (payload.payload?.message) { addNotification(`ERR:${payload.payload.message}`); } break; case 'recipe-export-ready': if (payload.payload?.message && payload.payload?.fileSizeBytes === 0) { addNotification(`ERR:${payload.payload.message}`); break; } void loadAndroidRecipeExportFromDevice({ exportedAt: payload.payload?.exportedAt, source: payload.payload?.source, fileSizeBytes: payload.payload?.fileSizeBytes, lineCount: payload.payload?.lineCount, message: payload.payload?.message }) .then(() => addNotification('INFO:Recipe export loaded from Android')) .catch((error: any) => addNotification(`ERR:${error?.message ?? 'Unable to load recipe export from Android'}`) ); break; default: } } catch (error: any) { // invalid format } } export { handleAdbPayload };