From a8584f7a7902b23f1292457f825cdf427f672045 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 7 Feb 2026 10:32:04 -0800 Subject: [PATCH] fix(status_poller): correct the polling status and release pipeline --- .github/workflows/release.yml | 9 ++- .github/workflows/version-bump.yml | 18 +++++- api/routes/__init__.py | 25 ++++++++ api/services/status_poller.py | 11 ++++ app/src/hooks/useStats.ts | 6 ++ app/src/routes/system.tsx | 95 +++++++++++++++++++++++++++++- package.json | 4 +- 7 files changed, 161 insertions(+), 7 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 126c082..efd4a4b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,10 +1,13 @@ name: Release Build +# Triggered automatically when a version tag is pushed (e.g. by Version Bump workflow). +# Manual run: use the "Run workflow" button in the Actions tab (requires write access). +# Note: Triggering workflow_dispatch via API (e.g. gh workflow run) requires a PAT with +# "workflow" scope; the default GITHUB_TOKEN cannot trigger workflows (403). on: push: tags: - 'v*.*.*' - # Manual trigger from GitHub Actions UI workflow_dispatch: inputs: version: @@ -175,9 +178,9 @@ jobs: 1. Download the ZIP file for your platform 2. Extract to a folder 3. Run the executable: - - **Windows**: Double-click `Start_PrintQue.bat` + - **Windows**: Double-click `PrintQue.exe` - **macOS**: Open `PrintQue.app` - - **Linux**: Run `./start_printque.sh` + - **Linux**: Run `./printque` 4. Open http://localhost:5000 in your browser files: | diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index 15e4b30..53c1d4d 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -99,5 +99,21 @@ jobs: echo "=== Pushing commit and tags ===" # Push the version commit first git push origin main - # Then push tags + # Then push tags (pushes from Actions do not trigger other workflows, so we trigger Release below) git push origin --tags + + # GITHUB_TOKEN cannot trigger other workflows (403). Per GitHub docs, use a PAT stored as a repo secret. + # Create a PAT with "workflow" scope → Settings → Secrets → Actions → New secret (e.g. name: RELEASE_DISPATCH_TOKEN). + - name: Trigger Release workflow + run: | + VERSION=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//') + if [ -z "$VERSION" ]; then + echo "Could not determine version, skipping release trigger" + exit 0 + fi + echo "Triggering Release workflow for version: $VERSION" + curl -sS -X POST \ + -H "Authorization: token ${{ secrets.RELEASE_DISPATCH_TOKEN }}" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/${{ github.repository }}/actions/workflows/release.yml/dispatches" \ + -d "{\"ref\":\"main\",\"inputs\":{\"version\":\"$VERSION\"}}" diff --git a/api/routes/__init__.py b/api/routes/__init__.py index 2bea526..dad7de8 100644 --- a/api/routes/__init__.py +++ b/api/routes/__init__.py @@ -318,7 +318,26 @@ def api_set_debug_flag(): }), 400 except Exception as e: return jsonify({'error': str(e)}), 500 + + @app.route('/api/v1/system/shutdown', methods=['POST']) + def api_shutdown(): + """API: Shut down the PrintQue server (for background/standalone mode with no console)""" + try: + import threading + import time + + def exit_after_delay(): + time.sleep(2) + logging.info("Shutdown requested from web UI - exiting.") + os._exit(0) # Force process exit from any thread + + threading.Thread(target=exit_after_delay, daemon=True).start() + return jsonify({ + 'success': True, + 'message': 'PrintQue is shutting down. Start it again from the executable or Start_PrintQue.bat when needed.', + }) except Exception as e: + logging.error(f"Error in api_shutdown: {str(e)}") return jsonify({'error': str(e)}), 500 # Printer routes @@ -458,14 +477,20 @@ def api_mark_printer_ready(printer_name): for printer in PRINTERS: if printer['name'] == printer_name: if printer['state'] in ['FINISHED', 'EJECTING', 'COOLING']: + import time printer['state'] = 'READY' printer['status'] = 'Ready' printer['manually_set'] = True + printer['manual_timeout'] = time.time() + 3600 # 1 hour protection printer['progress'] = 0 printer['time_remaining'] = 0 printer['file'] = None printer['job_id'] = None printer['order_id'] = None + printer['ejection_processed'] = False + printer['ejection_in_progress'] = False + printer['ejection_start_time'] = None + printer['finish_time'] = None # Clear cooldown state if skipping cooldown printer['cooldown_target_temp'] = None printer['cooldown_order_id'] = None diff --git a/api/services/status_poller.py b/api/services/status_poller.py index 9461a19..450440b 100644 --- a/api/services/status_poller.py +++ b/api/services/status_poller.py @@ -177,6 +177,17 @@ 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") + # Still update temperatures even when preserving manual state + if 'nozzle_temp' in bambu_state: + printer['nozzle_temp'] = bambu_state['nozzle_temp'] + if 'bed_temp' in bambu_state: + printer['bed_temp'] = bambu_state['bed_temp'] + continue + # Get the new state from Bambu MQTT new_state = bambu_state.get('state', current_state) diff --git a/app/src/hooks/useStats.ts b/app/src/hooks/useStats.ts index 496e193..8017a85 100644 --- a/app/src/hooks/useStats.ts +++ b/app/src/hooks/useStats.ts @@ -251,3 +251,9 @@ export function useSetDebugFlag() { }, }) } + +export function useShutdown() { + return useMutation({ + mutationFn: () => api.post('/system/shutdown'), + }) +} diff --git a/app/src/routes/system.tsx b/app/src/routes/system.tsx index cab3900..d343a5f 100644 --- a/app/src/routes/system.tsx +++ b/app/src/routes/system.tsx @@ -1,7 +1,17 @@ import { createFileRoute } from '@tanstack/react-router' -import { Bug, Clock, Cpu, HardDrive, Loader2, Server, Settings2 } from 'lucide-react' +import { Bug, Clock, Cpu, HardDrive, Loader2, Power, Server, Settings2 } from 'lucide-react' +import { useState } from 'react' import { toast } from 'sonner' +import { Button } from '@/components/ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, +} from '@/components/ui/dialog' import { Label } from '@/components/ui/label' import { Select, @@ -11,7 +21,13 @@ import { SelectValue, } from '@/components/ui/select' import { Switch } from '@/components/ui/switch' -import { useLoggingConfig, useSetDebugFlag, useSetLogLevel, useSystemInfo } from '@/hooks' +import { + useLoggingConfig, + useSetDebugFlag, + useSetLogLevel, + useShutdown, + useSystemInfo, +} from '@/hooks' export const Route = createFileRoute('/system')({ component: SystemPage }) @@ -123,6 +139,9 @@ function SystemPage() { {/* Logging Settings */} + {/* Shut down (when running in background with no console) */} + + About PrintQue @@ -269,3 +288,75 @@ function LoggingSettings() { ) } + +// Shut down PrintQue from the browser when running in background (no console) +function ShutDownCard() { + const [confirmOpen, setConfirmOpen] = useState(false) + const shutdown = useShutdown() + + const handleShutdown = async () => { + try { + await shutdown.mutateAsync() + toast.success( + 'PrintQue is shutting down. Start it again from the executable or Start_PrintQue.bat when needed.' + ) + setConfirmOpen(false) + // Page will stop loading when server exits + } catch { + toast.error('Failed to shut down') + } + } + + return ( + <> + + + + + Shut down PrintQue + + + When the app runs in the background (no console window), you can stop it from here. You + can start it again by running PrintQue.exe or Start_PrintQue.bat. + + + + + + + + + + + Shut down PrintQue? + + The server will stop and this page will no longer load. To use PrintQue again, run + PrintQue.exe or Start_PrintQue.bat. + + + + + + + + + + ) +} diff --git a/package.json b/package.json index b50f7d7..4dded9c 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,9 @@ "description": "PrintQue - Open Source Print Farm Manager", "scripts": { "commit": "cz", - "prepare": "husky" + "prepare": "husky", + "dev": "npm run dev --prefix app", + "api": "cd api && python app.py" }, "config": { "commitizen": {