18 Commits
Author SHA1 Message Date
maziggy ad3b5f1982 Map the P-series model codes to the right printers
C11 is the P1P, C12 the P1S, C13 the X1E and N7 the P2S, as the virtual
printer and a real P1P 3MF already say. The frontend map had them shifted,
so discovery pre-filled a P1S as a P1P and an X1E as a P2S. The backend
map read C11/C12 as X1C/X1 and lacked N7, the firmware check sent C13 to
the P2S line, and the capability lists never matched BL-P001 because
their lookup strips the dash.

-----

Post work PR #3134
2026-09-29 16:43:04 +02:00
maziggy defec334c4 feat(a2l): add Bambu Lab A2L support (#1684)
Internal code N9 (from BambuStudio resources/profiles/BBL/machine/Bambu Lab A2L.json),
  serial prefix 26A19 (5-char, same shape as H2C's late 31B8B). Capabilities from
  Bambu's official A2L specs page: linear rail, single FDM extruder + integrated
  cutter/plotter, no Ethernet (2.4 GHz Wi-Fi only), low-rate chamber camera on
  port 6000.

  The BambuStudio profile's use_double_extruder_default_texture: true flag
  describes two TOOL HEADS (FDM + cutter), not dual filament extrusion — A2L
  must NOT be classified as dual-nozzle or AMS routing will target the deputy
  slot and firmware rejects with 07FF_8012.

  Registry updates: printer_models.py, firmware_check.py, virtual_printer/manager.py,
  virtual_printer/mqtt_server.py, PrintersPage.tsx, SpoolBuddyAmsPage.tsx.
  12 new test cases in TestA2LModel pin every dimension.
2026-06-10 10:59:27 +02:00
maziggy 4bcab89eee fix(firmware-check): bypass Cloudflare TLS-fingerprint gate via curl_cffi (#1666)
Cloudflare on bambulab.com now serves cf-mitigated=challenge to plain
  Python TLS handshakes. Use curl_cffi.AsyncSession with impersonate="chrome"
  for the two bambulab.com fetches (index page + per-model JSON); wiki and
  CDN paths stay on httpx. HTTP User-Agent stays honest "Bambuddy/1.0" —
  only TLS-handshake bytes match Chrome, per the compliance commitment.

  Soft dependency — falls back to httpx with a startup warning when
  curl_cffi isn't importable; wiki-based version detection still works.
2026-06-06 13:30:13 +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 59f7d736e3 Added BACKERS.md 2026-05-12 12:18:56 +02:00
maziggy c7ad449e4e fix(firmware): parse P2S/X2D wiki anchors without dash and full-width parens (#1030)
The wiki scraper silently returned no versions for P2S and X2D, causing
  Bambuddy to fall back to the Bambu Lab download page, which still listed
  01.01.01.00 as "latest" even though 01.02.00.00 shipped on 2026-04-09.

  Two regex mismatches in _fetch_all_versions_from_wiki():

  1. Heading anchor ids require an optional dash between version bytes and
     date. H2D/X1/H2C/H2S use "h-01020000-20260409"; P2S and X2D publish
     "h-0102000020260409" (no dash).
  2. The text fallback only matched ASCII parens around release dates, but
     P2S, X2D, A1 and A1-mini render dates in full-width parens (YYYYMMDD)
     (U+FF08/U+FF09).

  Anchor regex now accepts an optional dash; fallback accepts both paren
  styles. Added regression tests for both shapes.
2026-04-19 12:27:06 +02:00
maziggy 6fb814c5ea feat(printer): add X2D support — camera, dual-nozzle, K-profile, maintenance (#988)
The Bambu Lab X2D (launched April 2026, dual-nozzle, enclosed, hardened
  steel rod gantry, AMS 2 Pro compatible) identifies itself as internal
  model code N6 via SSDP/MQTT, and real serials begin with 20P9. None of
  these identifiers existed in Bambuddy's registries, so the camera
  service fell back to the chamber-image protocol on port 6000 (X2D
  doesn't speak it), firmware-check logged "Unknown printer model: N6",
  and the dual-nozzle K-profile paths — gated on the H2D serial prefix
  "094" — would have treated X2D as single-nozzle.

  Backend:
  - Register N6 → X2D across every registry (PRINTER_MODEL_ID_MAP,
    PRINTER_MODEL_MAP, STEEL_ROD_MODELS, ETHERNET_MODELS,
    CHAMBER_TEMP_SUPPORTED_MODELS, firmware-check API keys + wiki path,
    virtual-printer SSDP/product/serial tables, DB vp_model_fixes).
  - supports_rtsp(): match the X2 display-name prefix and the N6 internal
    code; camera now routes to RTSP on port 322.
  - Dual-nozzle serial prefix check in bambu_mqtt.delete_kprofile and
    kprofiles.set_kprofile broadened to ("094", "20P9") — X2D now takes
    the H2D-style cali_idx in-place edit path.
  - is_h2d model gate in bambu_mqtt.start_print extended with "X2D" so
    timelapse / bed_leveling / flow_cali / vibration_cali / layer_inspect
    are sent as integers and external-spool ams_id 254/255 routing is
    preserved (H2D-style deputy-nozzle addressing).

  X2D uses hardened steel rods like P2S — it is intentionally placed in
  STEEL_ROD_MODELS, not CARBON_ROD_MODELS. A regression-guard test pins
  the classification.

  Frontend:
  - mapModelCode in PrintersPage and SpoolBuddyAmsPage handle N6 and X2D.
  - Enclosure-door badge and airduct-mode whitelists include X2D.
  - MaintenancePage.getMaintenanceWikiUrl routes X2D to P2S wiki URLs for
    steel-rod lubrication, belt tension, cold-pull, and PTFE tube
    (exported to enable direct unit testing).

  Tests:
  - test_printer_models.py: TestX2DModel (10 assertions).
  - test_bambu_mqtt.py: X2D in start_print ams_mapping and is_h2d gate;
    TestDeleteKProfileDualNozzleDetection across H2D, X2D, P2S, X1C.
  - MaintenancePageWikiUrls.test.tsx: 15 assertions covering X2D, P2S
    regression, X1C/H2D/A1Mini regression, and model-name normalisation.

  Docs:
  - README: added X2 series to the supported printers table.
  - CHANGELOG: new entry under 0.2.3b4 Fixed.

  Credit to @krautech for the report and debug bundle, and to @legend813
  for PR #989 which seeded most of the registry changes — rod-type
  classification was corrected (steel, not carbon) and the dual-nozzle /
  K-profile / is_h2d gaps were added on top.
2026-04-16 10:40:32 +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 76fd8c5c48 Add SSDP model codes to firmware check mapping (#584)
The firmware check only mapped display names (e.g., "H2D Pro") to
  API keys but not raw SSDP device codes (e.g., "O1E", "O2D"). If a
  printer's model was stored as the raw SSDP code, the firmware check
  either failed or matched the wrong model — H2D Pro matched against
  H2D firmware, showing a false update-available badge.

  Add all known SSDP device codes to MODEL_TO_API_KEY so firmware
  versions resolve correctly regardless of how the model was stored.
2026-03-04 09:34:33 +01:00
maziggy c52a67a5c3 fix: preserve original firmware filename on SD card upload (#385)
The firmware update cache stored downloaded files under a mangled name
(e.g. X1C_01_09_00_10.bin) instead of the original filename from
Bambu Lab's CDN. On cache hit the wrong filename was uploaded to the
printer's SD card, so the printer couldn't find the firmware file.
Now caches with the original filename so it's always correct.
2026-02-15 13:20:54 +01:00
maziggy 1f0931e00c Sync 2026-02-12 11:54:50 +01:00
maziggy ae63ec8a91 Fix H2C firmware update downloading wrong (H2D) firmware (#311)
H2C was mapped to the "h2d" firmware API key, causing it to check
the H2D firmware page and offer H2D firmware for download. H2C has
its own separate firmware track (01.01.x.x vs H2D's 01.02.x.x).

Changed H2C to use its own "h2c" API key and added the reverse
mapping. Also added missing H2C (O1C) and H2S (O1S) entries to
the printer model ID and 3MF model name maps.
2026-02-10 08:51:44 +01:00
maziggy 4b46e443dc Fix critical FTP upload failure and revert dangerous exception narrowing
The CodeQL cleanup in "Housekeeping" (2b11efd) bulk-narrowed except
clauses across 50+ files, breaking FTP uploads on ALL printer models.
ftplib.error_perm (550 errors) is not a subclass of ftplib.error_reply,
so diagnose_storage() CWD failures escaped the handler and prevented
STOR from ever executing — causing 100% upload failure and HTTP 500s
on /api/v1/archives/{id}/reprint and /api/v1/library/files/{id}/print.

FTP fixes:
- Remove diagnose_storage() from upload hot path
- Change all except (OSError, ftplib.error_reply) to
  except (OSError, ftplib.Error) across bambu_ftp.py

Exception handling reverts (9 files):
- Revert narrowed except clauses back to except Exception in route
  handlers and service code where broad catches are intentional
  defensive programming (archive parsing, HTTP clients, 3MF/ZIP
  processing, Home Assistant, firmware checks)
- Keep narrow exceptions only where safe (single-op blocks like
  int(), file.unlink(), socket.close())
- Remove unused XMLParseError imports from archive.py, threemf_tools.py

Closes #287
2026-02-07 09:20:06 +01:00
maziggy 93f416b922 Fix trivial conditionals, commented-out code, and dead variables (CodeQL)
Simplify always-true authEnabled ternary and localSettings truthiness
checks in SettingsPage.tsx. Remove commented-out auth re-setup guard
and its dead _existing_setting/_user_count queries from auth.py.
Add clarifying comments to firmware_check.py api_key logs (model
identifier, not a secret).
2026-02-06 12:32:29 +01:00
maziggy 5b0a985da2 Add explanatory comments to 265 empty except blocks
CodeQL flags except blocks where `pass` has no comment explaining
why the exception is silently ignored (py/empty-except rule).

Added context-specific comments to all 265 instances across 31 files:
- database.py (~112): ALTER TABLE migrations — "Already applied"
- archive/library/3MF parsing (~64): "Skip unparseable metadata"
- virtual_printer network cleanup (~32): "Best-effort socket cleanup"
- discovery/SSDP (~13): "SO_REUSEPORT not available" / socket cleanup
- bambu_ftp/mqtt (~13): FTP cleanup, JSON decode, signal parsing
- remaining routes/services (~31): context-specific comments
2026-02-06 11:58:38 +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 e87fe7ad87 Add H2D Pro printer model support
- Add H2D Pro option to printer model dropdowns (add/edit modals)
- Support both O1E and O2D internal codes for H2D Pro compatibility
- Add O2D to RTSP-capable and chamber temp supported models
- Add H2DPRO variant to firmware check mapping
- Add H2D Pro and X1E to bug report issue template

Closes #192
2026-01-30 15:38:52 +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