Commit Graph
382 Commits
Author SHA1 Message Date
maziggy 4f617c21e1 [Fix] X1C Virtual Printer not accepting sends (#735)
X1C and X1 virtual printers used legacy SSDP model codes
  (3DPrinter-X1-Carbon, 3DPrinter-X1) that BambuStudio doesn't
  recognize, causing "incompatible printer preset" errors when
  sending prints. Changed to the correct codes (BL-P001, BL-P002)
  that real printers report via SSDP.

  Also fixed proxy mode auto-inherit storing printer display names
  (e.g. "X1C") instead of SSDP codes, by adding a resolution layer
  that maps display names to model codes.

  DB migration auto-converts existing VPs on startup.
2026-03-17 16:25:31 +01:00
maziggy a6d307d739 Post work PR #693
Add tests, docs, and ruff fixes for per-user email notifications

  - Fix missing timezone import in email_service.py (F821)
  - Fix unused lambda arg in main.py asyncio done_callback (ARG005)
  - Fix E302 blank line spacing for mark_printer_stopped_by_user
  - Fix F821/UP037 forward reference in user_email_pref model
  - Fix SettingsPage test for duplicate "Notifications" text
  - Add backend unit tests for permissions, schemas, and templates
  - Add backend integration tests for user-notifications API
  - Add frontend tests for NotificationsPage
  - Add user_email_pref model import to test conftest
  - Update CHANGELOG and README
2026-03-17 12:24:36 +01:00
Thomas Rambach 9562d66b6b Feature: Advanced Authentication User Email Notifications (#693)
Feature: Advanced Authentication User Email Notifications (#693)
2026-03-17 12:01:18 +01:00
Dakota G ac7cfe2930 [Fix]: Send Bambu RFID Tags to Spoolman, Allow Unlink in Manual Mode, Stop Location Clearing for Generic Spools (#719)
[Fix]: Send Bambu RFID Tags to Spoolman, Allow Unlink in Manual Mode, Stop Location Clearing for Generic Spools (#719)
2026-03-16 15:45:06 +01:00
Keybored 92c3ce3993 [Feature] Rework Archive duplicates tagging (#718)
[Feature] Rework Archive duplicates tagging (#718)
2026-03-16 15:40:24 +01:00
maziggy 446da087a0 Fix webhook notifications missing camera snapshot (#679)
Webhook providers did not include image data (e.g. camera snapshots
  from first layer complete notifications) even though other providers
  like Telegram, Pushover, and Discord already attached them. The webhook
  payload now includes a base64-encoded "image" field when a snapshot is
  available (generic format only, excluded from Slack format).
2026-03-16 15:10:39 +01:00
maziggy 0feed83ce4 Fix P2S camera TLS compatibility via OpenSSL proxy (#661)
The Debian ffmpeg package uses GnuTLS, whose hardened defaults reject
  TLS renegotiation and legacy ciphers that some Bambu printer firmwares
  (notably P2S) rely on — causing RTSP sessions to drop after a few
  seconds.

  Add a local TLS termination proxy (Python ssl/OpenSSL) that handles
  the TLS connection to the printer and exposes a plain RTSP port to
  ffmpeg. The proxy rewrites RTSP request-line URLs (rtsp://proxy →
  rtsps://printer) while preserving Authorization headers so Digest
  auth hashes remain valid.

  Also:
  - Reduce RTSP reconnect delay from 1.0s to 0.2s
  - Add ffmpeg fast-start flags (-probesize 32, -analyzeduration 0,
    -fflags nobuffer, -flags low_delay)
  - Fix external camera double rate-limiting causing choppy streams
  - Apply TLS proxy to external camera rtsps:// URLs and snapshot capture
  - Update orphan ffmpeg cleanup to match rtsp:// (proxied) URLs
  - Add unit tests for RTSP URL rewriting and proxy lifecycle
2026-03-15 11:52:32 +01:00
Dakota G c52505cd3a [Fix]: Ensures AMS-HT devices are properly identified in Spoolman (#711)
[Fix]: Ensures AMS-HT devices are properly identified in Spoolman (#711)
2026-03-15 09:28:30 +01:00
maziggy 14855ba8f4 Add ambient drying mode and fix block mode humidity auto-stop (#292)
Ambient drying: automatically dry filament on idle printers when
  humidity exceeds threshold, regardless of queue state. Separate toggle
  from queue auto-drying — both can run simultaneously. Uses the same
  presets, humidity threshold, and power constraint detection.

  Fix: block mode (wait for drying) previously skipped the humidity
  auto-stop check for already-drying printers, causing drying to
  continue indefinitely. Now only prevents starting new drying.
2026-03-14 15:06:07 +01:00
maziggy cffba4a911 Add queue auto-drying, configurable drying presets, and AMS PSU detection (#292)
Queue auto-drying: scheduler automatically starts drying on idle printers
  with scheduled queue prints when AMS humidity exceeds the configured
  threshold. Uses conservative parameters (lowest temp, longest duration)
  for mixed filaments. Drying stops when humidity drops below threshold
  (30-minute minimum prevents oscillation), when scheduled items are
  removed, or when the feature is disabled. Optional "block queue" mode
  delays the next print until drying completes.

  Configurable presets: temperature and duration per filament type,
  editable in Settings → Print Queue, used by both manual drying popover
  and queue auto-drying. Separate presets for AMS 2 Pro (n3f) and AMS-HT
  (n3s) reflecting different heating capabilities.

  PSU detection: drying button disabled with tooltip when dry_sf_reason
  indicates insufficient power. Parses drying status bits and dry_sf_reason
  from AMS info hex string via MQTT.

  Backend: print_scheduler.py (+316 lines), bambu_mqtt.py, printer_manager,
  schemas, settings route. Frontend: PrintersPage drying presets prop,
  SettingsPage drying config UI, i18n (7 locales). Tests: 27 new tests in
  test_scheduler_auto_drying.py covering conservative params, presets,
  state sync, stop logic, minimum drying time, and auto-stop regressions.
2026-03-14 14:21:36 +01:00
maziggy 9f93c04f6f Revert " Camera P2S + snapshot fix (#661):"
This reverts commit 7ea78a2969.
2026-03-14 10:33:21 +01:00
maziggy 7ea78a2969 Camera P2S + snapshot fix (#661):
Fix P2S camera stream dropping and snapshot capture race (#661)

  P2S firmware's TLS renegotiation is rejected by Debian's hardened GnuTLS
  defaults, causing ffmpeg RTSP sessions to drop after ~3 seconds. Add
  GnuTLS config allowing unsafe renegotiation and legacy ciphers. Also add
  ffmpeg fast-start flags, reduce reconnect delay from 1.0s to 0.2s,
  remove double rate-limiting on external camera streams, and fix orphan
  cleanup killing snapshot capture ffmpeg processes (exit code -9).

  Or as a single combined commit:
  Fix P2S camera streaming, snapshot race, and energy stats (#661, #695)

  Camera: P2S firmware's TLS renegotiation rejected by Debian's hardened
  GnuTLS defaults, dropping RTSP sessions after ~3s. Add GnuTLS compat
  config, ffmpeg fast-start flags, reduce reconnect delay to 0.2s, remove
  external camera double rate-limiting, and register snapshot ffmpeg PIDs
  with the orphan tracker to prevent SIGKILL during capture.
2026-03-14 10:31:46 +01:00
maziggy ecc9ec11f1 Fix HA switch badge toggle and multi-plug crash
Non-script HA entities (switch/light/input_boolean) on the printer card
  always sent turn_on when clicked, which is a no-op when the switch is
  already on. Now sends toggle for non-script entities so the badge click
  actually changes the switch state. Script entities still use turn_on.

  Also fix SmartPlugManager._get_plug_for_printer() using
  scalar_one_or_none() which crashes with MultipleResultsFound when
  multiple plugs are assigned to the same printer (e.g., Tasmota + HA
  switch). Now fetches all plugs and returns the main non-script plug.

  Add tests for both fixes: _get_plug_for_printer multi-plug handling
  (5 tests) and canonicalFilamentType/filamentTypesCompatible/autoMatch
  PA-CF equivalence (8 tests).
2026-03-13 13:11:12 +01:00
maziggy 5a4a2260b1 Fix PA-CF/PA12-CF/PAHT-CF type matching and force color match click target (#688)
Bambu Lab firmware treats PA-CF, PA12-CF, and PAHT-CF as interchangeable,
  but the print scheduler and filament override UI used exact string matching.
  A 3MF requiring PA-CF wouldn't match PA12-CF in the AMS, leaving the
  override dropdown disabled and preventing scheduler assignment.

  Add a filament type equivalence system (both backend and frontend) so
  these PA variants are treated as compatible in scheduler assignment,
  AMS slot matching, force color match validation, and the override dropdown.

  Also fix the "Force color match" checkbox click target being too wide
  (entire row instead of just the checkbox/label) by changing flex to
  inline-flex on the label element.
2026-03-13 12:56:31 +01:00
maziggy 220717f174 Fix inventory usage tracker missing external spool mapping (#677)
When all higher-priority slot-to-tray mapping methods failed (MQTT
  mapping, print command mapping, queue mapping, color matching), the
  internal usage tracker fell back to slot_id - 1 which can never reach
  external spool IDs (254/255) or AMS-HT IDs (128+). Added position-based
  resolution using sorted available tray IDs, matching the Spoolman fix
  from PR #686.
2026-03-13 12:08:11 +01:00
Dakota G fb29eb4cd7 [Fix]: Properly track filament usage data in Spoolman (#686)
Properly track filament usage data in Spoolman#686
2026-03-13 11:59:44 +01:00
maziggy 0b6facc91c Add first layer complete notification with camera snapshot (#679)
Notify users when the first layer finishes printing so they can check
  adhesion remotely. Triggers once per print when layer 2 begins
  (layer_num >= 2, capped at <= 5 to handle reconnects). Includes a
  camera snapshot attachment. Adds the on_first_layer_complete toggle
  to all notification providers, with backend/frontend/i18n support
  across all 7 locales.
2026-03-13 10:53:21 +01:00
maziggy f21e502b8f Add remote AMS drying controls (#292)
Start, monitor, and stop drying sessions for AMS 2 Pro (n3f) and
  AMS-HT (n3s) directly from the Printers page. Flame icon in AMS card
  header opens a popover with filament-based temperature/duration presets
  from BambuStudio. Live countdown status bar shows time remaining.

  Backend: cache module_type from MQTT get_version, expose dry_time and
  module_type in both WebSocket and REST paths, add supports_drying()
  with firmware gating, add server-side guard on start_drying endpoint.

  Frontend: drying button, popover with filament select + temp/duration
  sliders, status bar, start/stop mutations. i18n for all 7 locales.

  Supported: X1/X1C (fw 01.09+), P1P/P1S (fw 01.08+), H2D (fw 01.02.30+),
  H2D Pro, X1E. Not supported: P2S, A1, A1 Mini, H2S, H2C.
2026-03-12 16:46:10 +01:00
maziggy 374895f959 Fix ethernet badge false positive and MQTT thread crash (#585)
Three bugs: (1) home_flag bit 18 is set on all printers regardless
    of connection type, so every ethernet-capable model showed the badge
    even on WiFi. Replaced with wifi_signal heuristic — ethernet printers
    with WiFi disabled report a hardcoded -90 dBm sentinel. (2) The lazy
    import used `from app.utils.printer_models` which crashes with
    ModuleNotFoundError in paho-mqtt's background thread (correct path:
    backend.app.utils.printer_models). This killed the thread, causing
    all printers to go stale after 60s and disconnect/reconnect in a
    loop. (3) WiFi-only models excluded via model-based gating.
2026-03-11 14:35:05 +01:00
maziggy 26a3b2172d Fix ethernet badge shown on WiFi-only printers (#585)
home_flag bit 18 is set on all printers regardless of hardware,
    causing the ethernet badge to appear on WiFi-only models (A1, P1P,
    etc.). The previous fix removed the feature entirely, so ethernet
    printers lost their badge too.

    Now only trusts bit 18 on models with an ethernet port (X1C, X1E,
    P1S, P2S, H2D, H2D Pro, H2C, H2S). WiFi-only models always show
    the WiFi signal badge.
2026-03-11 12:56:23 +01:00
maziggy f28421d1ae Add Home Assistant as notification provider (#656)
Sends persistent notifications to the HA dashboard using the existing
  HA connection from Settings. Zero config — just select "Home Assistant"
  as provider type. Users can forward notifications to mobile via HA
  automations.
2026-03-10 10:10:14 +01:00
maziggy 68d2230cab Fix H2D AMS units displayed on wrong nozzle (#659)
Three interrelated bugs in AMS info field parsing caused AMS units
  to appear on the wrong nozzle on H2D dual-nozzle printers:

  1. Info field parsed as decimal instead of hex (BambuStudio uses
     std::stoull with base 16)
  2. Extruder ID extracted as 1-bit instead of 4-bit field (bits 8-11)
  3. Partial MQTT updates replaced the full extruder map instead of
     merging into it
2026-03-10 08:18:23 +01:00
maziggy 121b3d53df fix: remove incorrect ethernet badge on printer cards
home_flag bit 18 was incorrectly interpreted as "wired/ethernet
  connection", causing the ethernet badge to always show — even on
  printers without an ethernet port (e.g. A1, P1S). This hid the
  WiFi signal indicator entirely.

  Removed the wired_network field and ethernet badge UI. The WiFi
  signal badge now shows correctly whenever the printer reports
  signal strength.
2026-03-09 12:16:22 +01:00
d7401a80df Feature: Force Color Match (#625)
* Added "Force Color Match" feature to filament override

* Update settings.py

* Update settings.py

* Label updates for warnings and checkbox case

* Initial plan

* Add noMatchingMaterial i18n translations to all 7 locale files

Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>

* Use {{material}} interpolation in noMatchingMaterial; populate from filament_overrides with getColorName

Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>

* Updates for PR#625 comments

* Added "Force Color Match" feature to filament override

* Update settings.py

* Update settings.py

* Label updates for warnings and checkbox case

* Initial plan

* Add noMatchingMaterial i18n translations to all 7 locale files

Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>

* Use {{material}} interpolation in noMatchingMaterial; populate from filament_overrides with getColorName

Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>

* Updates to PrintersPage and QueuePage

* Update QueuePage.tsx

* Rebase to 0.2.2b3

* Fix compile errors with FilamentOverride

* Updates for PR#625 comments

https://github.com/maziggy/bambuddy/pull/625#pullrequestreview-3908738261

* Fix force color match default, loadedFilamentTypes bug, remove dead translations

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
Co-authored-by: MartinNYHC <mz@v8w.de>
2026-03-09 11:54:02 +01:00
maziggy b3c37072b2 Add auto-dispatch toggle for virtual printer queue mode (#587)
Virtual printers in Queue mode now have an "Auto-dispatch" setting.
  When enabled (default), prints start automatically — preserving current
  behavior. When disabled, prints are added with manual_start so they
  wait for manual dispatch from the queue UI.
2026-03-07 11:41:01 +01:00
maziggy 0efb4690b9 Fix SD card error after FTP upload by waiting for 226 response (#645)
The FTP upload skipped reading the server's "Transfer complete"
  confirmation, sending the print command before the file was flushed
  to the SD card. Now waits for the 226 response with a 60s timeout.
2026-03-07 11:01:34 +01:00
maziggy 09c3c24111 Add ETA variable to print notification templates (#638)
Add {eta} template variable showing wall-clock completion time
  (e.g. "15:53" or "3:53 PM") to print_start, print_progress, and
  queue_job_started notifications. Respects the user's time_format
  setting (12h/24h). The existing {estimated_time} variable continues
  to show duration ("1h 23m").
2026-03-07 09:34:01 +01:00
maziggy becc4669b1 Fix greenlet_spawn error in spool auto-assign
Two lazy-load bugs caused greenlet_spawn errors in the RFID auto-assign
  flow:

  1. create_spool_from_tray set spool.k_profiles=[] AFTER db.flush(),
     but assigning to a relationship on a persistent object triggers a
     lazy load (SQLAlchemy loads the current collection before replacing).
     Moved initialization to BEFORE db.add().

  2. spool.assignments was never initialized or eagerly loaded, so
     db.add(SpoolAssignment) triggered a back_populates lazy load
     outside the async greenlet. Added assignments=[] in create and
     selectinload(Spool.assignments) in get_spool_by_tag.

  Also added exc_info=True to error handlers for full tracebacks, and
  19 new tests including greenlet regression tests that reproduce the
  exact failure.
2026-03-05 12:40:53 +01: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 aa39f6c866 Fix Bind-TLS proxy handshake failure on OpenSSL 3.x
Bambu printers only support plain RSA key exchange ciphers
  (AES256-GCM-SHA384, AES128-GCM-SHA256), but Python's OpenSSL 3.x
  defaults exclude them in favor of forward-secrecy (ECDHE/DHE) only.
  Add the RSA ciphers to the client SSL context so the TLS proxy can
  connect to the printer's bind port (3002).
2026-03-05 10:08:31 +01:00
maziggy 0bff20662c Add scheduler diagnostic logging for queue stall debugging (#616)
When the print queue scheduler finds pending items but doesn't start
  any, there was no logging to explain why. Added INFO-level summary
  after each queue check showing skip reasons (manual_start,
  scheduled_future) and busy printer details (state, connected,
  plate_cleared). Also added DEBUG-level logging in _is_printer_idle()
  for the specific condition that failed.
2026-03-05 09:18:38 +01:00
Thomas RambachandMartinNYHC 7ba67012f6 Feature AMS Info Card (#570)
* AMS Labels addition to PrintersPage

* Added database reinitialization for schema migrations on database restore

* Bug fixes and AMS Label persistence updates

* Update database.py to resolve PR conflicts

* PR Comment Resolution

* Resolve conflicts in database.py for PR#570

* Updates to address PR#570 additional comments

* Optimize visibility handling for popup component

* Improve serial key handling in printers.py

Refactor serial key assignment to handle empty AMS serial gracefully.

* Implement error handling in serial number mapping

Add error handling for serial number mapping.

* Add migration to drop old ams_labels table

---------

Co-authored-by: MartinNYHC <mz@v8w.de>
2026-03-05 08:36:39 +01:00
maziggy 058f74a7da Add in-app bug reporting with relay, debug log collection, and privacy controls
Floating bug report button submits issues via bambuddy.cool relay (no GitHub
  token needed locally). Collects 30s debug logs with printer push_all, sanitizes
  all sensitive data, uploads logs as files to GitHub. Screenshot upload/paste/drag
  with JPEG compression. Translated into all 7 languages. Includes 21 tests.
2026-03-04 13:33:19 +01:00
maziggy 6388b0df9b Show ethernet indicator instead of WiFi signal for wired printers (#585)
Parse home_flag bit 18 (0x00040000) from MQTT to detect ethernet
  connections. When set, the printer card shows a green "Ethernet"
  badge with a cable icon instead of WiFi signal strength in dBm.
  The printer info modal also displays "Ethernet" instead of WiFi
  signal details.
2026-03-04 09:44:08 +01: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 acae51b938 Fix spurious 0300_0002 error notification via HMS array path (#583)
The previous fix only filtered status codes (< 0x4000) from the
  print_error field. Firmware can also send the same false positive
  through the hms array in MQTT, which had no such filter. Apply the
  same < 0x4000 check to the HMS parser so status/phase indicators
  are skipped regardless of which MQTT field carries them.
2026-03-04 09:26:51 +01:00
maziggy 19a1a7584b Fix archive card showing "Source" badge for sliced .3mf files
The isSlicedFile() check only matched .gcode or .gcode.3mf extensions,
  so archives from .3mf prints (the standard Bambu slicer output) showed
  a "SOURCE" badge instead of "GCODE". Since .3mf can be either sliced or
  a raw CAD export, now checks the archive's total_layers and
  print_time_seconds metadata to distinguish them. Also passes the
  original filename when creating archives from file manager prints.
2026-03-03 14:26:03 +01:00
maziggy 6b92a99dd8 Improve FTP upload progress and widen print modal
FTP upload: reduce chunk size from 1MB to 64KB for smooth progress bar
  updates (~1s intervals instead of 20+ second gaps). Skip voidresp() for
  all printer models — H2D delays the 226 response by 30+ seconds after
  data transfer, causing a hang at 100%. Add transfer speed and TLS
  handshake timing to logs for diagnosing slow connections.

  Print/Schedule modal: widen from max-w-lg (512px) to max-w-2xl (672px)
  to accommodate long filament profile names like "PLA Support for PETG
  PETG Basic @Bambu Lab H2D 0.4 nozzle".
2026-03-03 14:14:26 +01:00
maziggy 330d77198a Fix AMS slot showing wrong material for "Support for" profiles
Profiles like "PLA Support for PETG PETG Basic @Bambu Lab H2D" have
  filament_type PETG, but both the frontend and backend name parsers
  found "PLA" first (iterating material types in order). The MQTT command
  sent tray_type=PLA and tray_info_idx=GFL99 (PLA generic), so the
  slicer displayed PLA instead of PETG.

  - Frontend parsePresetName(): detect "X Support for Y" pattern, extract
    material after "Support for"
  - Frontend ConfigureAmsSlotModal: prefer corrected parsed material over
    stored localPreset.filament_type for tray_type, tray_info_idx, and
    temperature fallback
  - Backend _parse_material_from_name(): same "Support for" handling for
    future profile imports
  - Backend assign_spool: prioritize spool.material over lp.filament_type
    for generic filament ID lookup
2026-03-03 13:34:03 +01:00
maziggy e2ba768c2e Fix spurious error notifications from print_error status codes
Some firmware sends non-zero print_error values (e.g. 0x03000002 →
  0300_0002) during normal printing as status/phase indicators. The
  parser treated any non-zero value as a real error, triggering
  notifications. All known real errors have codes >= 0x4000 (fatal,
  warning, prompt ranges). Now skips print_error values where the
  low 16 bits are below 0x4000.

  Also fix K-profile greenlet error on auto-created RFID spools by
  eagerly setting k_profiles=[] after flush in create_spool_from_tray().
2026-03-02 14:06:06 +01:00
maziggy 219214f0af Fix K-profile greenlet error on auto-created RFID spools
create_spool_from_tray() didn't eagerly load the k_profiles
  relationship, so auto_assign_spool() triggered a lazy load in async
  context when iterating spool.k_profiles. Set k_profiles=[] on new
  spools since they can never have K-profiles yet.
2026-03-02 14:00:52 +01:00
maziggy f943420ea2 Add SpoolBuddy NFC tag writing with OpenTag3D format
Write NTAG213/215/216 tags for third-party spools via the SpoolBuddy
  kiosk UI. New "Write" page with three workflows: existing spool, new
  spool creation, and tag replacement. Backend encodes 133-byte OpenTag3D
  NDEF payloads (material, color, brand, weight, temp). Daemon writes
  page-by-page via PN5180 NTAG WRITE command with read-back verification.
  Write commands flow through heartbeat polling with WebSocket status
  updates. Includes 39 new tests and translations for all 6 languages.
2026-03-02 13:56:15 +01:00
MartinNYHC 2b2a407648 Fix num_weeks calculation to ensure at least one week 2026-03-01 15:20:02 +01:00
AneoPsy 168c00f47d feat(stats): add /archives/slim endpoint and fix dashboard bugs
- Add lightweight GET /archives/slim endpoint with column-level SELECT
  (13 fields vs 46), skipping duplicate detection for ~70-80% payload
  reduction on the stats dashboard
- Add ArchiveSlim Pydantic schema and TypeScript type
- Switch StatsPage and FilamentTrends to use ArchiveSlim
- Fix critical bug in failure_analysis.py: use effective_days for week
  count, separate non-date filters, build fresh week_filter per loop
- Fix busiestDay timezone bug: parse YYYY-MM-DD with split() + local
  Date constructor instead of new Date() which creates UTC midnight
- Fix success streak ordering: sort by completed_at || created_at
  instead of created_at alone
- Add 6 integration tests for /archives/slim endpoint
2026-03-01 03:11:28 -10:00
AneoPsy 792a86f1e5 feat(stats): add new widgets, shared MetricToggle, and timeframe filtering
Add Print Time of Day, Color Distribution, and Records widgets to the
Stats page. Extract shared MetricToggle component for consistent
weight/prints/time toggles. Add date range filtering to archives and
stats API endpoints. Reorganize widgets into parent cards (Printer Stats
and Filament Trends) and fix Dashboard layout persistence for new widgets.
2026-03-01 03:11:28 -10:00
maziggy e5b2cee2f1 Fix VP bind server rejecting TLS connections on port 3002 (#559)
BambuStudio uses TLS on port 3002 for certain printer models (e.g. A1
  Mini / N1). The bind server only spoke plain TCP on both ports, so the
  TLS ClientHello was rejected as "invalid frame" and the slicer could
  never discover or connect to the virtual printer.

  Port 3002 now uses TLS (reusing the VP's existing certificate), port
  3000 remains plain TCP. Also updated proxy-mode to use TLSProxy for
  the port 3002 bind proxy instead of raw TCPProxy.
2026-03-01 12:43:13 +01:00
maziggy f39464d073 Fix virtual printer config changes ignored on running instances
sync_from_db() skipped VPs already in self._instances without checking
  if their config had changed. Mode, model, access code, bind IP, remote
  interface IP, and target printer changes were silently ignored until
  manual toggle off/on or full restart. Now detects config drift and
  restarts affected instances.
2026-03-01 09:40:39 +01:00
maziggy 8843af6665 Fix support package: mask subnet IPs, detect host mode, parse top-level fun, add virtual printers
Four support package improvements:

  1. Mask first two octets of subnet IPs in support info
     (192.168.1.0/24 → x.x.1.0/24) to avoid leaking private network
     addresses.

  2. Fix Docker network_mode_hint detection. The old heuristic
     (interface count > 2) always reported "bridge" on single-NIC
     hosts because get_network_interfaces() excludes Docker
     interfaces. Now checks for docker0/br-*/veth* visibility via
     socket.if_nameindex() — these are only visible in host mode.

  3. Parse MQTT "fun" field at top level of payload (not just inside
     "print" key). Some firmware versions send it there, which
     explains why developer_mode was null for most users.

  4. Add virtual_printers section to support info with mode, model,
     enabled/running status, and pending file count.
2026-03-01 08:39:30 +01:00
maziggy ce97a47627 Add H2C dual nozzle variant O1C2 model support (#489)
The H2C dual nozzle variant reports model code O1C2 via MQTT, but only
  O1C was recognized. This caused the camera to use the wrong protocol
  (chamber image on port 6000 instead of RTSP on port 322), producing a
  reconnect loop. Added O1C2 to all model ID maps across 8 files.
2026-02-28 11:53:38 +01:00
maziggy 691234457c Fix A1 Mini "unknown" status from non-UTF-8 MQTT payload (#549)
Some firmware versions send MQTT payloads with non-UTF-8 bytes.
  UnicodeDecodeError was uncaught, silently dropping the entire message
  and leaving printer status as "unknown" with 0°C temps and no AMS.

  Fall back to decode(errors="replace") to keep JSON parseable.
2026-02-28 10:26:39 +01:00