Procházet zdrojové kódy

● Fix SpoolBuddy update status stuck after restart

  The SSH update set status to "complete" after the daemon had already
  restarted and re-registered, overwriting the cleared state so it stuck
  forever. Removed the post-restart "complete" write — daemon
  re-registration is now the completion signal, clearing any update status.
maziggy před 2 měsíci
rodič
revize
b83a99ebab

+ 1 - 1
CHANGELOG.md

@@ -9,7 +9,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **SpoolBuddy Updates Now Use SSH** — Replaced the fragile self-update mechanism (daemon pulls its own code via git, permission errors on `.git/`, hardcoded `main` branch) with SSH-based updates driven by the Bambuddy backend. Bambuddy now SSHes into the SpoolBuddy Pi and runs git fetch/checkout, pip install, systemctl restart, and kiosk browser restart remotely. Updates automatically use the same branch as Bambuddy. SSH key pairing is fully automatic — Bambuddy generates an ED25519 keypair and includes the public key in the device registration response; the daemon deploys it to `authorized_keys` on first connect. The install script creates the `spoolbuddy` user with a bash shell and sudoers entries for daemon and kiosk restart. A "Force Update" button allows re-deploying even when versions match. The SSH public key is also shown in SpoolBuddy Settings → Updates → SSH Setup for manual pairing if needed.
 - **SpoolBuddy Updates Now Use SSH** — Replaced the fragile self-update mechanism (daemon pulls its own code via git, permission errors on `.git/`, hardcoded `main` branch) with SSH-based updates driven by the Bambuddy backend. Bambuddy now SSHes into the SpoolBuddy Pi and runs git fetch/checkout, pip install, systemctl restart, and kiosk browser restart remotely. Updates automatically use the same branch as Bambuddy. SSH key pairing is fully automatic — Bambuddy generates an ED25519 keypair and includes the public key in the device registration response; the daemon deploys it to `authorized_keys` on first connect. The install script creates the `spoolbuddy` user with a bash shell and sudoers entries for daemon and kiosk restart. A "Force Update" button allows re-deploying even when versions match. The SSH public key is also shown in SpoolBuddy Settings → Updates → SSH Setup for manual pairing if needed.
 - **SpoolBuddy Kiosk Shows Stale Frontend After Update** — After an update, the kiosk browser displayed the old frontend because Chromium served cached assets even after restarting. Added `--disk-cache-size=0` to the Chromium launch flags so it always loads fresh content from the Bambuddy backend.
 - **SpoolBuddy Kiosk Shows Stale Frontend After Update** — After an update, the kiosk browser displayed the old frontend because Chromium served cached assets even after restarting. Added `--disk-cache-size=0` to the Chromium launch flags so it always loads fresh content from the Bambuddy backend.
 - **SpoolBuddy Kiosk Starts Before Network Is Ready** — On fresh installs, the kiosk browser launched before the network was fully up, showing a connection error for 10-15 seconds until connectivity was restored. The getty@tty1 autologin override now waits for `network-online.target` so Chromium has connectivity when it starts.
 - **SpoolBuddy Kiosk Starts Before Network Is Ready** — On fresh installs, the kiosk browser launched before the network was fully up, showing a connection error for 10-15 seconds until connectivity was restored. The getty@tty1 autologin override now waits for `network-online.target` so Chromium has connectivity when it starts.
-- **SpoolBuddy Update Status Stale After Restart** — After a SpoolBuddy update completed, the UI continued showing "Update complete, daemon restarting..." and the old "update available" banner because stale status was never cleared. Fixed by clearing `update_status` on device re-registration (daemon restart), and adding WebSocket handlers for `spoolbuddy_update` and `spoolbuddy_online` events so the frontend immediately refreshes device state and update check results.
+- **SpoolBuddy Update Status Stale After Restart** — After a SpoolBuddy update completed, the UI permanently showed "Update complete, daemon restarting..." and a stale "update available" banner. Root cause: the SSH update set status to `"complete"` after the daemon had already restarted and re-registered, overwriting the cleared state. Fixed by letting daemon re-registration be the completion signal — it now clears any update status (`pending`/`updating`/`complete`/`error`), and the final `"complete"` write was removed. Also added WebSocket handlers for `spoolbuddy_update` and `spoolbuddy_online` events so the frontend refreshes immediately.
 - **Virtual Printer Proxy A1 Printing Fails** ([#757](https://github.com/maziggy/bambuddy/issues/757)) — BambuStudio could not send prints to A1 (and potentially P1S) virtual printers in proxy mode. The slicer connects to undocumented proprietary ports 2024-2026 on these models, which the proxy was not forwarding, causing BambuStudio to show an access code dialog instead of printing. Added transparent TCP pass-through proxying for ports 2024-2026. These ports are silently ignored on models that don't use them (X1C, H2C, P2S). Reported by @Utility9298.
 - **Virtual Printer Proxy A1 Printing Fails** ([#757](https://github.com/maziggy/bambuddy/issues/757)) — BambuStudio could not send prints to A1 (and potentially P1S) virtual printers in proxy mode. The slicer connects to undocumented proprietary ports 2024-2026 on these models, which the proxy was not forwarding, causing BambuStudio to show an access code dialog instead of printing. Added transparent TCP pass-through proxying for ports 2024-2026. These ports are silently ignored on models that don't use them (X1C, H2C, P2S). Reported by @Utility9298.
 - **Spool Assignment on Empty AMS Slots** ([#784](https://github.com/maziggy/bambuddy/issues/784)) — Empty AMS slots (no physical spool detected) showed "Assign Spool" and "Configure" buttons in the hover popup. Assigning a spool to an empty slot created a stuck state because no "Unassign" button is available for empty slots. Removed both buttons from empty AMS and HT AMS slot popups. External spool holders are unaffected. Reported by @RosdasHH.
 - **Spool Assignment on Empty AMS Slots** ([#784](https://github.com/maziggy/bambuddy/issues/784)) — Empty AMS slots (no physical spool detected) showed "Assign Spool" and "Configure" buttons in the hover popup. Assigning a spool to an empty slot created a stuck state because no "Unassign" button is available for empty slots. Removed both buttons from empty AMS and HT AMS slot popups. External spool holders are unaffected. Reported by @RosdasHH.
 
 

+ 1 - 1
backend/app/api/routes/spoolbuddy.py

@@ -102,7 +102,7 @@ async def register_device(
         device.has_backlight = req.has_backlight
         device.has_backlight = req.has_backlight
         device.last_seen = now
         device.last_seen = now
         # Clear stale update status on re-registration (daemon restarted after update)
         # Clear stale update status on re-registration (daemon restarted after update)
-        if device.update_status in ("complete", "error"):
+        if device.update_status in ("pending", "updating", "complete", "error"):
             device.update_status = None
             device.update_status = None
             device.update_message = None
             device.update_message = None
         logger.info("SpoolBuddy device re-registered: %s (%s)", req.device_id, req.hostname)
         logger.info("SpoolBuddy device re-registered: %s (%s)", req.device_id, req.hostname)

+ 1 - 1
backend/app/core/config.py

@@ -5,7 +5,7 @@ from pathlib import Path
 from pydantic_settings import BaseSettings
 from pydantic_settings import BaseSettings
 
 
 # Application version - single source of truth
 # Application version - single source of truth
-APP_VERSION = "0.2.3.b1"
+APP_VERSION = "0.2.3"
 GITHUB_REPO = "maziggy/bambuddy"
 GITHUB_REPO = "maziggy/bambuddy"
 BUG_REPORT_RELAY_URL = os.environ.get("BUG_REPORT_RELAY_URL", "https://bambuddy.cool/api/bug-report")
 BUG_REPORT_RELAY_URL = os.environ.get("BUG_REPORT_RELAY_URL", "https://bambuddy.cool/api/bug-report")
 
 

+ 0 - 3
backend/app/services/spoolbuddy_ssh.py

@@ -226,7 +226,6 @@ async def perform_ssh_update(device_id: str, ip_address: str, install_path: str
             return
             return
 
 
         # Step 6: Restart kiosk browser to load updated frontend
         # Step 6: Restart kiosk browser to load updated frontend
-        await _update_progress("updating", "Restarting kiosk browser...")
         rc, _, stderr = await _run_ssh_command(
         rc, _, stderr = await _run_ssh_command(
             ip_address,
             ip_address,
             "sudo /usr/bin/systemctl restart getty@tty1.service",
             "sudo /usr/bin/systemctl restart getty@tty1.service",
@@ -235,8 +234,6 @@ async def perform_ssh_update(device_id: str, ip_address: str, install_path: str
         if rc != 0:
         if rc != 0:
             # Non-fatal — kiosk may not be set up on all devices
             # Non-fatal — kiosk may not be set up on all devices
             logger.warning("SpoolBuddy %s: kiosk restart failed (non-fatal): %s", device_id, stderr[:200])
             logger.warning("SpoolBuddy %s: kiosk restart failed (non-fatal): %s", device_id, stderr[:200])
-
-        await _update_progress("complete", "Update complete, daemon restarting...")
         logger.info("SpoolBuddy %s: SSH update complete (branch=%s)", device_id, branch)
         logger.info("SpoolBuddy %s: SSH update complete (branch=%s)", device_id, branch)
 
 
     except Exception as e:
     except Exception as e: