Commit Graph
176 Commits
Author SHA1 Message Date
maziggy aeca15b585 Add SpoolBuddy integration as optional filament management add-on
SpoolBuddy turns a Raspberry Pi 4B with a PN5180 NFC reader and
NAU7802 scale into a filament management station that integrates
with Bambuddy via REST API and WebSocket.

Backend: SpoolBuddyDevice model, 10 REST endpoints (/spoolbuddy/*),
6 WebSocket broadcast types, background offline-detection watchdog.

RPi daemon: asyncio service with concurrent NFC polling (300ms,
MIFARE Classic + Bambu HKDF key derivation), scale reading (10 SPS,
5-sample moving average, stability detection), and 10s heartbeat
with exponential backoff reconnect.

Frontend: kiosk-optimized 1024x600 UI at /spoolbuddy with Dashboard
(live weight + NFC spool detection), AMS Overview, Inventory,
Printers, and Settings pages. useSpoolBuddyState reducer hook
driven by WebSocket CustomEvents.

i18n: all 6 locales (en, de, fr, it, ja, pt-BR).
2026-02-22 15:27:54 +01:00
maziggy 7232ddb5a6 Fix finish photo not captured when archive has no source 3MF (#484)
When the 3MF source file wasn't downloaded from the printer (e.g. FTP
failure on P2S), archive.file_path was null. The finish photo capture
silently skipped because it derived the save directory from file_path.

Now falls back to archive/{id}/ directory and logs a warning.
2026-02-21 17:19:47 +01:00
maziggy 055243683c Fix archive endpoints crash with "Is a directory" for BambuStudio prints (#475)
When FTP download of a 3MF fails (e.g. BambuStudio-initiated prints),
the fallback archive has file_path="". Path.exists() on
settings.base_dir / "" resolves to the base directory itself and
returns True, so ZipFile() then fails with [Errno 21] Is a directory.

Replace .exists() with .is_file() across all 15 archive route checks
and 1 in main.py. Add file_path truthiness guard for finish photo
capture to prevent saving photos under the base directory.
2026-02-21 11:35:18 +01:00
maziggy e6236301b4 Fix phantom prints from lingering SD card files (#477)
Three bugs allowed uploaded gcode files to survive on the printer's SD
card, causing firmware restarts to auto-start old prints hours later.

1. The post-print cleanup retry loop always broke after attempt 1
   regardless of delete success — delete_file_async returns False on
   failure instead of raising, so the except-based retry never fired.

2. When start_print() failed after uploading, the file was never cleaned
   up since on_print_complete never fires for prints that never started.

3. Cleanup failures were logged at DEBUG level, invisible in production.
2026-02-21 09:51:42 +01:00
maziggy d7a15c79bb Filter non-actionable HMS errors from notifications (#470)
Infrastructure/auth HMS error codes like 0500_0007 (MQTT command
verification failed) triggered false-alarm printer error notifications
even though they don't indicate actual print problems.

- Add suppress list for non-actionable error codes: 0500_0007 (MQTT
  auth failure), 0500_4001 (cloud connection failure), 0500_400E
  (print cancelled by user)
- Skip suppressed codes in the notification loop so they are still
  tracked in HMS state and shown in the UI, but don't fire notifications
2026-02-21 08:36:16 +01:00
maziggy 1404242e0c Fix cost tracking issues 2026-02-20 16:31:16 +01:00
MartinNYHC 965000c3ca Merge branch '0.2.1b2' into feature/cost_tracker 2026-02-20 16:26:01 +01:00
Wesley Reuel Marques SilvaandMartinNYHC ceb2de7164 Adding the energy cost from 2 to 3 decimal precision (#416)
* Adding the energy cost from 2 to 3 decimal precision

* Complying with pr

* Complying with PR

* Complying with PR

* Fix energy cost display precision in ProjectDetailPage

* Change energy cost formatting to two decimal places

* Change decimal precision for energy cost display

---------

Co-authored-by: MartinNYHC <mz@v8w.de>
2026-02-20 16:23:00 +01:00
Keybored 85645ce184 Merge branch '0.2.1b2' into feature/cost_tracker 2026-02-20 15:44:34 +01:00
maziggy b22f091dd0 Fix SD card cleanup silently failing after print completion (#374)
The post-print SD card cleanup used printer_manager.get_printer(),
which returns a PrinterInfo object with only name and serial_number.
The code then accessed .ip_address, .access_code, and .model, which
don't exist on PrinterInfo — raising AttributeError on every print
completion. The outer except Exception handler silently swallowed it
at debug level.

Result: uploaded gcode files were never deleted from the printer's
SD card root. On some printers (e.g. P1S), files left in root
auto-start on power cycle, causing phantom prints.

Replaced with a DB query for the Printer model, matching the pattern
used everywhere else in on_print_complete().
2026-02-20 14:30:26 +01:00
maziggy 3f201594f1 Fix spool usage lost when spool runs empty mid-print (#459)
When a spool ran empty during a print and the AMS auto-switched to a
backup, on_ams_change eagerly deleted the SpoolAssignment (fingerprint
mismatch). on_print_complete then queried the now-deleted assignment
and silently dropped usage.

Snapshot all spool assignments into PrintSession at print start. At
completion, prefer the snapshot over live DB queries in both the 3MF
primary path and the AMS remain% delta fallback. Fall back to live
query for backward compatibility with in-flight sessions started
before upgrade.
2026-02-20 14:08:35 +01:00
maziggy e4e6e9f8c4 Decouples file uploads and print start commands so that they run in the background asynchronously. When a print is started, the print modal no longer waits for the print to upload and start. Instead, a new toast-based UI appears with the status of prints being dispatched. Prints being dispatched can be cancelled during upload. If cancelled, the partially-uploaded gcode is deleted from the printer automatically before the FTP connection is closed.
This allows users sending particularly large prints to slow printers such as the P1-series to start a print and then move onto another task in Bambuddy immediately (such as starting more prints on more printers). It also gives the user visibility into what's happening instead of a loading indicator appearing for an indefinite period of time.

The new toast-based UI uses websockets to update in real time. It will also appear for other users / instances of Bambuddy, not just the user who started the prints, allowing more transparency and handling cases where the user closes the page and then comes back wanting to know the status of the dispatching.

fix: review fixes for background dispatch PR #408

- Restore missing imports in main.py (inventory, print_log, virtual_printers, mqtt_smart_plug_service)
- Guard voidresp() for A1 printers to prevent hang after upload
- Don't fail upload on voidresp() error since data transfer already completed
- Add ams_mapping to register_expected_print calls for Spoolman usage tracking
- Fix cancel_job TOCTOU race by using single lock acquisition
- Fix batch counter reset TOCTOU by re-checking condition inside second lock
- Add backgroundDispatch translations to fr.ts and pt-BR.ts
- Remove dead upload_progress_callback definitions
- Skip redundant "Print queued" toast in reprint mode (dispatch toast handles it)
- 5 backend tests: cancel_job single-lock TOCTOU, batch reset re-check,
  job lifecycle
- 2 FTP regression tests: voidresp error handling (upload-loop fix),
  A1 model voidresp skip
- 1 frontend test: reprint toast suppression
- CHANGELOG: background dispatch feature + test coverage entries
- README: add background dispatch to Scheduling & Automation
- Website: add feature item to Automation section
- Wiki: add Background Print Dispatch section to print-queue.md
2026-02-20 09:26:50 +01:00
Ryan Ewen 88fa58fff8 Add background print dispatching + tests 2026-02-20 08:52:49 +01:00
Ryan Ewen 4a625c1ef2 Add background print dispatching + tests 2026-02-20 08:51:13 +01:00
Matteo Parenti 04ffca204f Add cost tracking for spools and usage history 2026-02-19 14:13:18 +01:00
maziggy d24e7cdf84 feat: multiple virtual printers with dedicated bind IPs + dual bind/detect ports (#445)
Multiple Virtual Printers:
- Each VP gets a dedicated bind IP with independent FTP, MQTT, SSDP, and Bind services
- New VirtualPrinter DB model, CRUD API (/api/virtual-printers), React UI
- VirtualPrinterList, VirtualPrinterCard, VirtualPrinterAddDialog components
- Per-instance TLS certificates (shared CA), 11 printer models, all 4 modes
- Auto-incremented serial suffixes, network interface override per VP

Dual Bind/Detect Ports (#445):
- Listen on both ports 3000 and 3002 for slicer bind/detect handshake
- Different BambuStudio/OrcaSlicer versions use different ports
- Applies to BindServer (server mode) and SlicerProxyManager (proxy mode)
- Updated Dockerfile, docker-compose.yml, firewall rules in wiki

Also:
- Rewrote VP test suite for new multi-instance architecture (75 tests)
- Rewritten "How it works" section with 3-step workflow explanation
- Updated all 5 locales (en, de, ja, fr, it)
- Updated wiki and website for multi-VP + dual ports
- New multi-VP screenshot
2026-02-19 11:22:28 +01:00
b8d48b0362 Fix/hms flapping notifications (#444)
* Debounce HMS error tracking to prevent flapping notifications

HMS errors on newer printers (e.g. H2S) can flicker on and off
every few seconds as conditions fluctuate around thresholds. For
example, chamber temperature regulation during PETG prints sends
HMS code 0300A70000030001 repeatedly as temps oscillate. Previously
each reappearance after a brief hms:[] gap was treated as a new
error, triggering duplicate notifications. This adds a 30-second
grace period before clearing the notification tracking state so
flapping errors are only notified once per episode.

* build(deps): bump aquasecurity/trivy-action

Bumps the github_actions group with 1 update in the /.github/workflows directory: [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action).


Updates `aquasecurity/trivy-action` from 0.33.1 to 0.34.0
- [Release notes](https://github.com/aquasecurity/trivy-action/releases)
- [Commits](https://github.com/aquasecurity/trivy-action/compare/0.33.1...0.34.0)

---
updated-dependencies:
- dependency-name: aquasecurity/trivy-action
  dependency-version: 0.34.0
  dependency-type: direct:production
  dependency-group: github_actions
...

Signed-off-by: dependabot[bot] <support@github.com>

* Updated CI

* build(deps): bump aquasecurity/trivy-action

Bumps the github_actions group with 1 update in the /.github/workflows directory: [aquasecurity/trivy-action](https://github.com/aquasecurity/trivy-action).


Updates `aquasecurity/trivy-action` from 0.33.1 to 0.34.0
- [Release notes](https://github.com/aquasecurity/trivy-action/releases)
- [Commits](https://github.com/aquasecurity/trivy-action/compare/0.33.1...0.34.0)

---
updated-dependencies:
- dependency-name: aquasecurity/trivy-action
  dependency-version: 0.34.0
  dependency-type: direct:production
  dependency-group: github_actions
...

Signed-off-by: dependabot[bot] <support@github.com>

* Updated CI

* Updated CI

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: MartinNYHC <mz@v8w.de>
2026-02-19 08:30:52 +01:00
maziggy a903816b8a fix(slicer): token-based auth for Open in Slicer downloads (#433)
Slicer protocol handlers (bambustudio://, orcaslicer://) launch the
slicer app which fetches files via HTTP but cannot send auth headers.
The global auth middleware returned 401, causing "importing failed."

Add short-lived, single-use download tokens: the frontend fetches a
token via authenticated POST, then builds a /dl/{token}/{filename} URL
the slicer can access without auth headers. Tokens are validated
server-side (5-min expiry, single-use). Applies to archive files,
source 3MFs, and library files.

Also fix platform-specific URL formats to match slicer source code:
- macOS: bambustudioopen:// with encodeURIComponent
- Windows/Linux: bambustudio://open?file= (was wrongly using macOS scheme on Linux)
- OrcaSlicer: orcaslicer://open?file=
2026-02-18 16:37:35 +01:00
maziggy b02e9da943 WIP: multi virtual printer support 2026-02-18 06:37:27 +01:00
maziggy c82521efc9 fix(timelapse): support AVI format from P1-series printers (#405)
P1S/P1P save timelapses as AVI (MJPEG), but the scanner only looked
for MP4 files — so P1-series timelapses were never found or attached.
2026-02-17 08:29:47 +01:00
maziggy 4cd36abfef fix(queue): update queue item status before archive lookup early return
The queue item status update (printing → completed/failed) was placed
after `if not archive_id: return` in on_print_complete. When archive
lookup failed (app restart mid-print, manual deletion), the function
returned early and the queue item stayed stuck in "printing" forever.

Over multiple print cycles, stale items accumulated — showing double
the actual printer count in the "Printing" stat and completed prints
remaining in the "Currently Printing" section.

Move the entire queue item status update block (status transition,
MQTT relay, queue-completed notification, auto-power-off) to before
the archive_id early return, matching the pattern used for SD card
cleanup.
2026-02-17 07:41:12 +01:00
maziggy 27e4fe49bd fix(ghost-print): run SD card cleanup before archive lookup and add retry logic (#374)
The SD card file cleanup (which prevents phantom prints on power cycle)
was placed after the archive_id early-return in on_print_complete. Users
with auto-archiving disabled never reached the cleanup code, so ghost
prints persisted on every reboot.

- Move cleanup before the archive_id check so it always runs
- Add retry loop (3 attempts, 2s delay) for printers that briefly lock
  the filesystem after a print ends
- Try both .3mf and .gcode extensions

Reported by @DIYofThings in #374.
2026-02-17 07:26:28 +01:00
maziggy 12399abfea fix(usage-tracker): capture ams_mapping from MQTT request topic for slicer-initiated prints
Subscribe to the MQTT request topic (device/{serial}/request) to intercept
print commands from any source (BambuStudio, OrcaSlicer, Bambu Handy, or
Bambuddy itself). Captures ams_mapping from project_file commands and passes
it through print start/complete callbacks. Fixes wrong tray attribution on
H2D Pro when prints are started from external slicers.
2026-02-17 07:07:39 +01:00
maziggy cf7c459099 fix(inventory): fix usage tracking for remapped AMS slots and slicer prints
Three fixes for inventory spool usage not updating after prints:

1. Store ams_mapping from print command (reprint, library print, queue)
   so the usage tracker maps 3MF slots to the actual physical trays
   the user selected, not the default slicer mapping.

2. Track last_loaded_tray on printer state — the last valid tray_now
   (0-253) seen during printing. On H2D printers, tray_now is always
   255 in AMS data; the real tray resolves via snow field ~44s after
   print start but reverts to "unloaded" at completion. The fallback
   chain is: tray_now_at_start > current tray_now > last_loaded_tray.

3. Use color similarity (Euclidean RGB distance, threshold 50) instead
   of exact hex match for auto-unlink fingerprint checks. RFID sensors
   report slightly different shades across reads (e.g. distance ~43.6
   for the same spool), causing false assignment unlinks after prints.
2026-02-16 15:46:32 +01:00
maziggy f35e662e8b fix: delete uploaded 3MF from SD card after print completes (#374)
The print scheduler uploads .3mf files to the printer's SD card root
but never cleans them up. Some printers (e.g. P1S) auto-start files
found in root on power cycle, causing phantom/ghost prints on every
reboot. Now deletes the uploaded file via FTP after print completion
(best-effort, non-blocking).
2026-02-16 08:12:14 +01:00
maziggy be569f7577 fix: prevent spool weight corruption, add AMS weight sync, fix extruder_id
Three bugs fixed and one recovery feature added:

1. AMS remain=0 zeroed all spools on printer power-off. The weight sync
   treated 0% remain as "fully consumed," setting weight_used to
   label_weight for every assigned spool. Fix: skip remain=0 in AMS
   weight sync — empty spools are tracked by the usage tracker.

2. Editing any spool field sent stale weight_used from the React Query
   cache back to the server, resetting usage-tracked weight. Fix: only
   include weight_used in PATCH when the user explicitly changes it.

3. K-profile auto-select crashed on dual-nozzle printers for non-BL
   spools with 'SpoolKProfile has no attribute extruder_id'. The model
   attribute is 'extruder', not 'extruder_id'.

4. New "Sync Weights from AMS" button in Settings > Filament Tracking
   (built-in inventory mode) to force-recover spool weights from live
   AMS sensor data. Bypasses the "only increase" guard for explicit
   user-initiated recovery.
2026-02-15 15:47:41 +01:00
maziggy 27cecbed87 feat: add print log timeline view in archives page
Add a chronological, table-based print log as a 4th view mode in the
Archives page. Log entries are stored in a separate print_log_entries
table — clearing the log never touches archives or queue items.

Backend:
- New PrintLogEntry model with independent table
- GET /print-log/ endpoint with search, printer, user, status, date filters
- DELETE /print-log/ clears only log entries
- Thumbnail serving endpoint for log entries
- write_log_entry() service called on print completion
- Auth: ARCHIVES_READ for viewing, ARCHIVES_DELETE_ALL for clearing

Frontend:
- New 'log' ViewMode with ClipboardList icon toggle
- Filterable/searchable table with pagination (10/25/50/100 rows)
- Colored status badges, duration formatting, filament color swatches
- Clear button with confirmation modal
- All filter state persisted to localStorage
- i18n: EN, DE, JA, FR, IT translations
2026-02-15 13:14:15 +01:00
maziggy caedfffa5b fix: add logging and harden archive matching for phantom print investigation (#374)
Suppress SQL/aiosqlite debug noise (~90% log volume reduction), add
caller-traced PRINT COMMAND logging to start_print(), log scheduler
queue checks, tighten stale archive ilike match to exact match, and
warn on multiple queue items in "printing" status. Includes 18 new
unit tests.
2026-02-15 11:35:24 +01:00
maziggy 53a4933c36 feat: add bed cooled notification after print completes (#378)
Notify users when the print bed cools below a configurable threshold
(default 35°C) after a print finishes, so they know when to remove parts.

- Backend: DB migration, model, schemas, notification template, service
  method, background cooldown monitor (polls every 15s, 30min timeout)
- Frontend: event toggle in provider card/modal, threshold setting in
  Settings > Notifications, i18n keys for all 5 locales
- Tests: 4 backend + 4 frontend tests
- Docs: README, website, wiki updated
2026-02-15 10:59:07 +01:00
maziggy e1b3329b68 fix: reduce MQTT log noise at INFO level (#365)
Downgrade 58 diagnostic logger.info calls to logger.debug in
bambu_mqtt.py — payload dumps, detector state changes, field
discovery, H2D disambiguation, and periodic status updates no longer
flood logs at the default INFO level. User-initiated actions (print,
stop, calibration, AMS load/unload) remain at INFO. Also suppress
paho-mqtt library INFO messages in production mode.
2026-02-15 09:56:51 +01:00
maziggy d67f1a1c03 fix: inventory spool weight_used reset by AMS remain% sync
The on_ams_change() handler recalculated weight_used from the AMS
remain% sensor on every status update, overwriting precise values
from the usage tracker. For small prints on large spools (e.g. 1.6g
on 1000g), the integer-resolution sensor (10g steps) still reported
100% remain, resetting weight_used back to 0. The sync now only
increases weight_used, never decreases it.
2026-02-15 08:40:12 +01:00
maziggy a37dfaf7fb feat: dual external spool support, AMS slot model filtering & pre-population
Backend:
- Add dual external spool support for H2D (vt_tray as list: Ext-L/Ext-R)
- Add cloud filament ID map endpoint (/cloud/filament-id-map)
- Fix RFID spool data erased by periodic AMS updates (skip tag matcher
  for RFID-tagged trays)
- Fix AMS slot config overwrites RFID spool state
- Fix K-profile selection corrupts existing profiles on X1C/P1S
- Resolve K-profiles filament name via cloud filament ID map
- Update print scheduler and usage tracker for dual external spools

Frontend:
- Add printer model filtering to ConfigureAmsSlotModal (cloud/local/builtin
  presets filtered by @BBL model suffix and compatible_printers)
- Add pre-population for configured slots (preset, color, K-profile)
- Add K-Profiles view with accurate filament name resolution
- Internationalize all ConfigureAmsSlotModal strings (en/de/fr/it/ja — 21 keys)
- Add 5 new ConfigureAmsSlotModal tests (model filtering, pre-selection,
  color pre-population, i18n)
- Update PrintersPage for dual external spool rendering

Docs:
- Update CHANGELOG, README, website features, and wiki AMS docs
2026-02-15 08:04:01 +01:00
maziggy f88c7704bc Add AMS slot info to filament_details notification variable (#336)
filament_details now shows which AMS unit and tray each filament came
from (e.g. "AMS-A T1 PLA: 12.4g | AMS-A T3 PETG: 2.8g"). External
spool holders show "Ext". Falls back to type-only format when usage
tracking data is unavailable (e.g. Spoolman mode).

- usage_tracker: include spool material in result dicts
- main.py: pass usage_results to notification flow via archive_data
- notification_service: build filament_details with AMS labels when
  usage_results available, fall back to existing slot-based format
- Update sample data and changelog
2026-02-13 16:10:58 +01:00
maziggy 2d989bc6e8 Unified 3MF-based filament tracking and notification usage variables (#336)
3MF slicer estimates are now the primary tracking source for ALL spools
(BL and non-BL), with AMS remain% delta as fallback. Per-layer G-code
analysis provides accurate partial usage for failed/cancelled prints.

Fix wrong-spool tracking bug: 3MF slot_id was mapped directly to AMS
tray position, but the printer remaps slicer slots at print time. Now
uses queue ams_mapping for queue prints and tray_now from printer state
for single-filament non-queue prints.

Add filament_grams, filament_details, and progress template variables
to print_complete, print_failed, and print_stopped notification events.
Webhook payloads include per-slot filament breakdown. Per-slot data
stored in archive extra_data during 3MF parsing.
2026-02-13 14:48:50 +01:00
maziggy f9b47282a1 Nozzle-aware AMS mapping for dual-nozzle printers, BL spool detection fix, AMS startup fix, SQLite WAL (#318)
Dual-nozzle H2D/H2D Pro: filament matching now respects nozzle assignments
from the 3MF file. Each AMS unit feeds a specific nozzle (L/R), and the
scheduler/frontend constrain matching to only trays on the correct nozzle.
Falls back to unfiltered matching when no trays exist on the target nozzle.
L/R badges shown in the filament mapping UI. Translated in en/de/ja/it.

Fix AMS slot config overwritten on startup: on_ams_change unconditionally
unlinked BL spool assignments on every MQTT pushall, then re-assigned them
sending ams_filament_setting without setting_id — clearing the printer's
filament preset. Now compares spool RFID identifiers before unlinking.

Fix BL spool detection false positives: removed tray_info_idx from detection
logic in both backend is_bambu_lab_spool() and frontend isBambuLabSpool().
Third-party spools using Bambu generic presets had GF-prefixed tray_info_idx
values, causing misidentification. Now uses only tray_uuid and tag_uid.

SQLite WAL mode with 5s busy timeout reduces "database is locked" errors.
2026-02-13 11:48:32 +01:00
MartinNYHC c5246e60fc Merge branch '0.2.0b' into fix/duplicate-error-notifications 2026-02-13 08:07:44 +01:00
MartinNYHC 7c36283665 Merge branch '0.2.0b' into fixes/327 2026-02-13 08:01:52 +01:00
maziggy e3f3c90c3d Sync 2026-02-13 07:53:14 +01:00
MartinNYHC 2af5289736 Merge branch '0.2.0b' into fixes/327 2026-02-13 06:42:50 +01:00
Jeff Kletsky c45568bc7e Shut down MQTT relay and smart plug services explicitly
Existing code did not allow the MQTT relay to be shut down gracefully.

Moved _client.loop_stop() after _client.disconnect() call to allow
Paho to be notified to disconnect and shut down without reconnecting.

Added _client._disconnection_event to help prevent a race condition where
a disconnection is requested but the loop is immediately stopped.
Modify _client.disconnect() to take a timeout parameter (default: 0).
Wait in that routine for the disconnection event with the given timeout.

Apply same logic to MQTTSmartPlugService and add to shutdown sequence.

Shutdown the MQTT relay last in lifespan() with a hard-coded 2 sec timeout.

The disconnect timeout is also available to printer MQTT clients.
It is left to the default of 0 at this time. If later enabled,
it should be a configuration parameters, especially for large farms.

Fixes: #327

Signed-off-by: Jeff Kletsky <git-commits@allycomm.com>
2026-02-12 10:25:05 -08:00
maziggy e6e62f2a68 Add spool inventory: AMS slot assignment, usage tracking, and remaining weight editing
Built-in spool inventory with AMS slot assignment for non-BL spools,
automatic filament usage tracking via 3MF estimates, and remaining
weight editing in the spool form.

Inventory features:
- AMS slot assignment: assign/unassign manual spools to AMS tray slots
- Filter out Bambu Lab spools (RFID-managed) from assignment modal
- Filter out already-assigned spools (one spool per slot)
- Auto-unlink manual assignments when a BL spool is inserted
- Hide assign/unassign UI on BL-occupied slots
- Case-insensitive fingerprint matching for auto-unlink logic

Usage tracking:
- 3MF-based filament consumption tracking for non-BL spools
- Extract per-filament used_g from archived 3MF slice_info
- Map 3MF slot_id to AMS (ams_id, tray_id) positions
- Scale estimates by print progress for failed/aborted prints
- Skip BL spools (tracked via AMS remain% delta, Path 1)
- Prevent double-counting with handled_trays set

Other:
- Add remaining weight field to spool edit form
- Fix hardcoded "Empty" string in AssignSpoolModal (now i18n)
- Add backend unit tests for usage_tracker (11 tests)
- Add frontend tests for AssignSpoolModal filters (5 tests)
- Update CHANGELOG, README, wiki docs, and website
2026-02-12 15:42:27 +01:00
SBCrumb 107947495d Fix duplicate HMS error notifications from race condition
Move _notified_hms_errors tracking update before the async notification
send to prevent concurrent status callbacks from both seeing the same
errors as new. This mirrors the existing milestone tracking pattern
which correctly updates before the await.
2026-02-12 09:12:50 -05:00
maziggy 1f0931e00c Sync 2026-02-12 11:54:50 +01:00
maziggy ec82092bc7 Sync 2026-02-12 07:07:50 +01:00
maziggy 0fe2bb1342 Fix timelapse baseline race condition (#315)
The snapshot-diff timelapse detection captured its baseline of existing
MP4 files at print completion time inside a background task. Fast-
encoding printers could finish writing the timelapse before the baseline
was taken, so the new file appeared in the baseline and was never
detected as "new" — resulting in no timelapse attached.

Move baseline capture to print start time, when the timelapse file
cannot possibly exist yet. The baseline is stored in a module-level dict
keyed by printer_id and popped at completion time. Falls back to
completion-time baseline if the app was restarted mid-print.
2026-02-11 07:33:07 +01:00
maziggy 142c7f99f6 Merge branch 'feature_user_authentication' of https://github.com/cadtoolbox/bambuddy into test-merge
# Conflicts:
#	frontend/src/components/ConfigureAmsSlotModal.tsx
#	frontend/src/i18n/locales/ja.ts
#	static/index.html
2026-02-10 16:40:10 +01:00
maziggy c3018f06b2 Fix wrong timelapse attached to archive and skip calibration prints (#315)
Timelapse: Replace mtime-based "most recent file" approach with a
snapshot-diff strategy — baseline existing MP4 filenames before waiting,
then detect the new file that appears after encoding. Fixes wrong
timelapse in LAN-only mode where printer clock is unsynchronized.
Falls back to print-name matching if no new file appears after retries.

Calibration: Skip archiving internal printer files under /usr/ (e.g.
/usr/etc/print/auto_cali_for_user.gcode) so calibration prints don't
appear in the archive.
2026-02-10 10:53:05 +01:00
maziggy acd2aa825e Fix wrong thumbnail when reprinting same project name (#314)
The cover image cache was keyed by subtask_name and never invalidated
between prints. When a user printed the same project name twice with a
different bed layout, the cached thumbnail from the first print was
returned instead of fetching the new one from the printer.

Clear the cover cache for the printer on every print start so the next
cover request downloads a fresh 3MF and extracts the current thumbnail.
2026-02-10 10:13:11 +01:00
maziggy edf244c469 Add local profiles — import OrcaSlicer presets without Bambu Cloud (#310)
Users who use OrcaSlicer without Bambu Cloud can now import slicer
presets directly into Bambuddy. Supports .orca_filament, .bbscfg,
.bbsflmt, .zip, and .json exports with automatic inheritance resolution
via OrcaSlicer's GitHub base profiles (cached with 7-day TTL).
2026-02-09 17:00:02 +01:00
copilot-swe-agent[bot]andcadtoolbox 66be730cc8 Add advanced auth endpoints to public routes and tests
Co-authored-by: cadtoolbox <12723486+cadtoolbox@users.noreply.github.com>
2026-02-09 09:29:31 +00:00