diff --git a/api/services/status_poller.py b/api/services/status_poller.py index 4530e63..8230067 100644 --- a/api/services/status_poller.py +++ b/api/services/status_poller.py @@ -177,10 +177,15 @@ def update_bambu_printer_states(): if current_state == 'COOLING': continue - # Skip state updates for manually set printers (e.g., user clicked Mark Ready) - # The manually_set flag protects the READY state from being overwritten by MQTT - if printer.get('manually_set', False) and current_state == 'READY': - logging.debug(f"Bambu {printer_name}: skipping MQTT state update - printer is manually set to READY") + # Get the new state from Bambu MQTT + new_state = bambu_state.get('state', current_state) + + # Protect manually-set READY state from being overwritten by stale MQTT states + # (e.g., FINISHED), but still allow real activity (PRINTING, EJECTING, PREPARE) + # to come through so the printer can transition when a job actually starts. + if (printer.get('manually_set', False) and current_state == 'READY' + and new_state not in ['PRINTING', 'EJECTING', 'PREPARE', 'PAUSED']): + logging.debug(f"Bambu {printer_name}: preserving manually-set READY state (ignoring MQTT state {new_state})") # Still update temperatures even when preserving manual state if 'nozzle_temp' in bambu_state: printer['nozzle_temp'] = bambu_state['nozzle_temp'] @@ -188,9 +193,6 @@ def update_bambu_printer_states(): printer['bed_temp'] = bambu_state['bed_temp'] continue - # Get the new state from Bambu MQTT - new_state = bambu_state.get('state', current_state) - # Update temperatures if 'nozzle_temp' in bambu_state: printer['nozzle_temp'] = bambu_state['nozzle_temp'] @@ -222,6 +224,11 @@ def update_bambu_printer_states(): printer['status'] = state_map.get(new_state, 'Unknown') updates_made = True + # Clear manually_set when printer starts real activity + if new_state in ['PRINTING', 'EJECTING', 'PREPARE'] and printer.get('manually_set', False): + logging.info(f"Bambu {printer_name}: clearing manually_set flag on transition to {new_state}") + printer['manually_set'] = False + # Set finish_time when transitioning to FINISHED if new_state == 'FINISHED' and current_state != 'FINISHED': printer['finish_time'] = time.time() diff --git a/app/src/routeTree.gen.ts b/app/src/routeTree.gen.ts index e3f672d..2169cd5 100644 --- a/app/src/routeTree.gen.ts +++ b/app/src/routeTree.gen.ts @@ -9,12 +9,12 @@ // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. import { Route as rootRouteImport } from './routes/__root' +import { Route as SystemRouteImport } from './routes/system' +import { Route as StatsRouteImport } from './routes/stats' +import { Route as PrintersRouteImport } from './routes/printers' +import { Route as LicenseRouteImport } from './routes/license' import { Route as EjectionCodesRouteImport } from './routes/ejection-codes' import { Route as IndexRouteImport } from './routes/index' -import { Route as LicenseRouteImport } from './routes/license' -import { Route as PrintersRouteImport } from './routes/printers' -import { Route as StatsRouteImport } from './routes/stats' -import { Route as SystemRouteImport } from './routes/system' const SystemRoute = SystemRouteImport.update({ id: '/system', @@ -74,10 +74,23 @@ export interface FileRoutesById { } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/ejection-codes' | '/license' | '/printers' | '/stats' | '/system' + fullPaths: + | '/' + | '/ejection-codes' + | '/license' + | '/printers' + | '/stats' + | '/system' fileRoutesByTo: FileRoutesByTo to: '/' | '/ejection-codes' | '/license' | '/printers' | '/stats' | '/system' - id: '__root__' | '/' | '/ejection-codes' | '/license' | '/printers' | '/stats' | '/system' + id: + | '__root__' + | '/' + | '/ejection-codes' + | '/license' + | '/printers' + | '/stats' + | '/system' fileRoutesById: FileRoutesById } export interface RootRouteChildren { @@ -148,9 +161,8 @@ export const routeTree = rootRouteImport ._addFileChildren(rootRouteChildren) ._addFileTypes() -import type { createStart } from '@tanstack/react-start' import type { getRouter } from './router.tsx' - +import type { createStart } from '@tanstack/react-start' declare module '@tanstack/react-start' { interface Register { ssr: true