Commit Graph
11 Commits
Author SHA1 Message Date
maziggy f243e4e598 fix(asyncio): track strong refs on orphan create_task sites
asyncio holds only a weak reference to tasks returned by
  ``create_task``. Fire-and-forget callers that discard the return value
  let the event loop GC the task before it finishes, logging
  ``Task was destroyed but it is pending!`` with no traceback. The #1648
  support-bundle review surfaced 94 such warnings in 8 days of v0.2.4.5
  -- the silently-vanished exceptions reach support bundles as opaque
  GC notices instead of actionable errors.

  New backend/app/core/tasks.py::spawn_background_task(coro, *, name=None)
  is the one place in the codebase that calls asyncio.create_task. It
  stores the task in a module-level set, attaches a done-callback that
  auto-removes on completion AND surfaces any uncaught exception via the
  logger with the originating traceback, and accepts name= so a leak
  source is traceable through /tracebacks and the log line. Cancelled
  tasks don't log (a shutting-down service is not an error).

  Migrated the 16 truly-orphan create_task call sites to the helper:

    main.py (8):
      reconcile-stale, cooldown-poweroff, energy calc, smart-plug,
      maintenance-check, photo-then-notify, layer-timelapse,
      scan-timelapse, print-scheduler, notify-no-archive (the last one
      was hand-rolling the same pattern with task + no-op done_callback)
    printers.py:3123        apply-pa-after-refresh
    print_queue.py:1034     queue cooldown-poweroff
    firmware_update.py:261  firmware upload
    archive.py:1514         timelapse mp4 convert
    print_scheduler.py:2199 watchdog print-start
    library.py:1614         STL backfill
    smart_plugs.py:259      tasmota scan
    discovery.py:159        subnet scan
    smart_plug_manager.py   x3 plug auto-off-pending
    background_dispatch.py  x2 (lambda-wrapped inside
                            loop.call_soon_threadsafe) upload progress

  Sites that already kept strong refs are unchanged:
    self._tasks.append(asyncio.create_task(...)) -- VP manager,
      tcp_proxy, mqtt_server
    self._x_task = asyncio.create_task(...) on service instances --
      mqtt_bridge, obico_detection, github_backup, archive_purge,
      local_backup, library_trash, discovery service
    Locally assigned + awaited/gathered -- tcp_proxy bidirectional
      pumps, camera_fanout, slice_dispatch, slicer_api progress_task,
      manager._finish_release_task, main.py module-level cleanup loops
2026-06-06 10:41:28 +02:00
maziggy 405dd1525b fix(firmware): keep download-URL resolution working when bambulab.com 403s (#1350)
The firmware update dialog showed "01.11.02.00 newer · Unavailable" with the
  misleading error "Firmware file is not available from Bambu Lab" while the
  logs spammed "Failed to get Bambu Lab page: 403". The wiki scrape was fine —
  only the Next.js buildId fetch on bambulab.com was being blocked by Cloudflare
  on the reporter's network, and the buildId was cached in memory only, so a
  single 403 broke download-URL resolution for the rest of the session.

  - Send Accept + Accept-Language headers alongside the honest Bambuddy/1.0 UA
    so the request stops tripping Cloudflare's "bare scraper" signal.
  - Persist the buildId to <data_dir>/firmware/build_id.json so a transient
    403 or a backend restart can't wipe a previously-valid buildId.
  - Add a download_page_unreachable flag and use it in the prepare-update flow
    to render an honest error ("page unreachable from this network — try later
    or download manually from bambulab.com") instead of implying Bambu doesn't
    have the file.
  - Retry the per-model JSON once when a cached buildId returns 404 (page
    rebuild), give up gracefully on 403 without churning.
2026-05-15 10:06:55 +02:00
maziggy d74ab06072 feat(firmware): list all announced versions with usable/unavailable status, support rollback
Firmware update modal now shows every version from Bambu's wiki release
  history, each badged Usable/Unavailable/Installed. Selecting a usable row
  — newer or older than current — swaps the release notes and enables
  install for that version, so rollback no longer requires hand-flashing.

  Wiki scraper tightened to only read heading-anchor ids (h-XXXXXXXX-YYYYMMDD)
  instead of any XX.XX.XX.XX substring, eliminating false positives like an
  AMS firmware version mentioned in an H2D changelog being listed as H2D
  firmware.

  Refs #568
2026-04-14 11:10:24 +02:00
maziggy 0faf03ecb3 Fix Python 3.10 compatibility (StrEnum requires 3.11)
enum.StrEnum was added in Python 3.11, but the documented minimum is
  3.10. Add a compatibility shim in backend/app/core/compat.py that falls
  back to (str, Enum) on older versions. Updated all 5 import sites and
  lowered pyproject.toml target-version to py310.
2026-03-05 10:44:24 +01:00
maziggy aa3482e48b Add printer_model to 18 FTP call sites for A1/A1 Mini, PS1 compatibility
Several FTP operations (file browser, timelapse scan, storage info,
cover download, skip objects, etc.) were missing the printer_model
parameter. Without it, A1/A1 Mini and PS1 printers can't use the prot_p/prot_c
auto-detection and fallback logic, causing FTP failures on these models
when the mode cache isn't already populated.
2026-02-06 16:29:01 +01:00
maziggy 53bd4fadb3 Fix safe security findings: hashlib, log injection, broad excepts
- Add usedforsecurity=False to MD5 (AMS fingerprint) and SHA1 (git blob
  hash) calls to silence Bandit B303 / CodeQL weak-crypto findings
- Convert ~996 f-string logging calls to parameterized %s-style across
  55 files to prevent log injection (Bandit G201 / CodeQL log-injection)
- Narrow ~199 broad except Exception blocks to specific types:
  OperationalError for DB migrations, OSError for network/file cleanup,
  (OSError, ftplib.error_reply) for FTP, and targeted tuples for
  ZIP/XML/JSON parsing — 36 intentionally left broad (mixed async,
  re-raise patterns)
2026-02-06 11:37:59 +01:00
maziggy 8bdd64e54d Fixed ruff errors 2026-02-04 14:47:15 +01:00
maziggy 169f2aaf08 Updated linter 2026-01-11 07:23:37 +01:00
maziggy 0e3e37ffc1 Fix A1/A1 Mini FTP compatibility and add configurable timeout
Resolves FTP transfer failures on A1/A1 Mini printers caused by SSL
session reuse incompatibility. Also adds configurable FTP timeout
setting for slow WiFi connections.

Changes:
  - Add SSL session reuse bypass for A1/A1 Mini printers (auto-detected)
  - Add printer_model parameter to FTP functions for model detection
  - Add configurable FTP timeout (10-120s, default 30s) in Settings
  - Update all FTP callers: archiving, reprint, timelapse, firmware upload

Technical details:
  - A1/A1 Mini printers don't support vsFTPd's SSL session reuse
  - X1C/P1S continue to use session reuse as required by their FTP server
  - ImplicitFTP_TLS now accepts skip_session_reuse flag
  - BambuFTPClient auto-detects A1/A1 Mini and sets flag accordingly
2026-01-09 09:17:02 +01:00
maziggy d8cecb0695 Add FTP retry for unreliable WiFi connections
Added configurable retry logic for all FTP operations to handle
  unreliable WiFi on P1S, X1C, and other Bambu Lab printers.

  Features:
  - Enable/disable retry in Settings > General > FTP Retry
  - Configurable retry count (1-10 attempts, default: 3)
  - Configurable retry delay (1-30 seconds, default: 2s)
  - Applies to: 3MF archiving, print uploads, timelapse downloads,
    reprint uploads, and firmware updates
2026-01-09 08:52:45 +01:00
maziggy 6fb71de6a2 Add firmware update helper for LAN-only printers
Enables checking and uploading firmware updates for printers operating
  in LAN-only mode without Bambu Cloud connectivity.

  Features:
  - Automatic firmware version checking against Bambu Lab servers
  - Orange "Update" badge on printer cards when updates available
  - Firmware update modal with version info and release notes
  - One-click firmware upload to printer SD card via FTP
  - Real-time upload progress (actual bytes transferred)
  - Step-by-step instructions for triggering update from printer
  - Local firmware caching for faster re-uploads
  - Supports all Bambu Lab printer models

  New files:
  - backend/app/services/firmware_check.py - Version checking service
  - backend/app/services/firmware_update.py - Upload orchestration
  - backend/app/api/routes/firmware.py - REST API endpoints

  Also includes:
  - FTP upload progress callback support
  - 10-minute upload timeout protection
  - Firmware cache directory in .gitignore
2026-01-04 18:41:24 +01:00