Commit Graph
54 Commits
Author SHA1 Message Date
MartinNYHC 67f91d94de v0.2.2.2 (#830)
v0.2.2.2 (#830)
2026-03-27 09:27:47 +01:00
maziggy 35ce075486 [Fix] Suppress spurious "waiting for filament" notification when printers are busy (#753)
When all matching printers were busy and a job was queued with ASAP
  timing, the scheduler immediately fired a "Job Waiting for Filament"
  notification even though the job was just waiting for a printer to
  finish — no user action required.

  Added _is_busy_only() check to skip the waiting notification when the
  only reason is "Busy". Notifications still fire for actionable reasons
  (missing filament, offline, wrong color). Also renamed the default
  notification template title to "Queue Job Waiting" and updated
  descriptions across all 7 locales.
2026-03-20 11:34:23 +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
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 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 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
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 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
maziggy fe5bb1fd90 Fix naive-vs-aware datetime crash from 0.2.1 timezone migration
The timezone fix (ed36eaf) replaced datetime.utcnow() with
datetime.now(timezone.utc) across ~80 call sites, but SQLAlchemy's
SQLite DateTime columns strip tzinfo on read, returning naive datetimes.
Any Python-side comparison (subtraction, <, >) between an aware "now"
and a naive DB value raises TypeError.

Add `if value.tzinfo is None: value = value.replace(tzinfo=timezone.utc)`
guards at all 8 affected comparison sites:
- maintenance.py: last_performed_at subtraction (500 on /maintenance/overview)
- auth.py: API key expires_at check (2 locations)
- print_scheduler.py: scheduled_time comparison
- smart_plug_manager.py: auto_off_pending_since elapsed calc
- smart_plugs.py: power_alert_last_triggered cooldown
- main.py: last_runtime_update elapsed calc
- archives.py: timelapse completed_at fallback
2026-02-27 17:39:32 +01:00
maziggy 2284a76381 Fix VP queue mode missing AMS mapping for printer-specific items (#529)
The print scheduler had two code paths for queue items: model-based
(target_model set) and printer-specific (printer_id set). Only the
model-based path computed ams_mapping before starting the print. VP
queue items assigned to a specific printer went through the
printer-specific path with null ams_mapping, causing the printer to
default to the first AMS slot regardless of what the 3MF required.

Add _compute_ams_mapping_for_printer() call to the printer-specific
path, matching the existing model-based behavior.
2026-02-27 07:24:59 +01:00
maziggy c770f842f2 Fix "Queue to Any Printer" ignoring filament color override (#486)
When scheduling a print to "any printer" with a filament color override,
the scheduler picked a printer with the correct filament type but wrong
color. _find_idle_printer_for_model() used color matching only for
ranking candidates, not filtering — a printer with 0 color matches was
still selected if it had the right types.

Now requires at least 1 color match when filament overrides specify
colors. Printers with 0 matches are skipped and reported in the
"waiting for filament" reason instead of being treated as candidates.
2026-02-26 07:44:43 +01:00
maziggy ed36eafbec Fix timestamps off by timezone offset in non-UTC containers (#504)
All backend timestamps used datetime.now() (server local time) or the
deprecated datetime.utcnow(). The frontend's parseUTCDate() assumes
timestamps without timezone indicators are UTC and appends 'Z', so
stored timestamps were off by the timezone offset when the container's
timezone wasn't UTC.

Backend: replaced datetime.now() and datetime.utcnow() with
datetime.now(timezone.utc) across 16 files (~80 call sites) for all
database fields and DB comparisons. Cosmetic timestamps (filenames,
user-facing local time formatting) intentionally left as local time.

Frontend: replaced 13 new Date(backendTimestamp) calls with
parseUTCDate() across 8 files to correctly interpret UTC timestamps.
2026-02-24 08:18:02 +01:00
maziggy 38af5df050 Add filament override for model-based queue assignment (#486)
When scheduling a print to "any printer" (model-based assignment),
users can now override the 3MF's original filament choices per slot.
The override dropdown shows compatible filaments loaded across all
printers of the selected model, filtered by type and nozzle (H2D).
The scheduler matches against overridden type/color instead of the
original 3MF values, preferring printers with exact color matches.

Backend:
- New GET /printers/available-filaments endpoint (aggregates loaded
  filaments across printers of a model, includes extruder_id for
  dual-nozzle nozzle-aware filtering)
- New filament_overrides JSON column on print_queue table
- Scheduler applies overrides before AMS mapping, clears tray_info_idx
  on overridden slots so color matching takes priority
- Printer selection prefers printers with most override color matches

Frontend:
- New FilamentOverride component with per-slot override dropdowns
- Type-filtered options (PLA slots only show PLA)
- Nozzle-aware filtering (H2D: only shows filaments on correct extruder)
- Integrated into PrintModal for model-based queue mode

Tests:
- 11 backend unit tests (color match counting, override application)
- 12 frontend tests (rendering, type/nozzle filtering, interactions)

i18n: All 6 locales (en, de, fr, it, ja, pt-BR)
2026-02-22 16:43:16 +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 732ab8cb6d Fix "Any Model" queue jobs stuck in "Waiting" after plate clear (#435)
MQTT raw data returns AMS unit and tray IDs as strings (e.g. "0"),
but _build_loaded_filaments() compared them to integers without
casting. After the scheduler assigned an idle printer to an "Any
Model" job, it crashed computing AMS mapping with:

  '>=' not supported between instances of 'str' and 'int'

The exception prevented the assignment from committing, so the
scheduler retried every 30 seconds in an infinite loop. The job
stayed in "Waiting" and the "Clear Plate" button kept reappearing.

Cast ams_id and tray_id to int(), matching the pattern already used
for external spool IDs on line 550.
2026-02-20 14:22:09 +01:00
maziggy 9c81657df7 Fix Print Queue showing UUID hash instead of filename (#438)
Library files are stored on disk with UUID-hex filenames for uniqueness,
but archive_print() used the disk path as the display name. Pass the
original LibraryFile.filename through from both the print scheduler and
direct-print-from-library flow so the archive's filename, print_name,
and directory name all use the human-readable name.
2026-02-19 08:16:07 +01:00
maziggy 29e9593f6c AMS mapping fixes (7 bugs):
- backend/app/services/print_scheduler.py — hard nozzle filter + external spool extruder
- backend/app/api/routes/printers.py — ams_extruder_map race condition
- backend/app/utils/threemf_tools.py — group_id priority + dual-nozzle detection
- frontend/src/hooks/useFilamentMapping.ts — external spool extruder
- frontend/src/pages/PrintersPage.tsx — AMS-HT globalTrayId
- frontend/src/components/PrintModal/FilamentMapping.tsx — dropdown nozzle filter

Usage tracking fix:
- backend/app/services/bambu_mqtt.py — capture last valid progress/layer
- backend/app/services/usage_tracker.py — use captured values on cancel

UI fix:
- frontend/src/components/spool-form/ColorSection.tsx — color tooltip z-index

Tests:
- backend/tests/unit/test_scheduler_ams_mapping.py — 63 tests
- frontend/src/__tests__/hooks/useFilamentMapping.test.ts — 43 tests

Static assets:
- static/ — rebuilt frontend bundles
2026-02-18 09:17:50 +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 e13a72ef19 fix(queue): create archive for library-file prints so 3MF usage tracking works (#364)
When a print was queued from the file manager (library_file_id path),
the scheduler never created an archive or called register_expected_print().
This forced on_print_start to re-download the 3MF via FTP, and if that
failed, a fallback archive with no file was created — breaking 3MF-based
filament usage tracking entirely. The queue item's archive_id also stayed
NULL, so the usage tracker couldn't find the AMS slot mapping.

Now the scheduler creates an archive from the library file before uploading,
sets item.archive_id, and the existing register_expected_print() call fires
since archive is no longer None.
2026-02-16 13:04:10 +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 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 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
maziggy b423283ec3 Fix queued jobs incorrectly skipped after duplicate execution detection (#341)
When the same file was queued multiple times from the archive, all jobs
after the first were automatically skipped with "already printed X hours
ago". The scheduler's 4-hour safety check compared the shared archive's
completed_at timestamp, incorrectly treating legitimate repeat prints as
phantom reprints from crash recovery. This also affected single queue
items created from recently completed archives.

Remove the check entirely — the crash scenario it guarded against is
already prevented by committing item.status="printing" before sending
the print command.
2026-02-12 12:04:41 +01:00
maziggy aa87e5598b Add clear plate confirmation between queued prints
The print scheduler previously treated FINISH/FAILED as idle states
and would auto-start the next queued print before the user cleared
the build plate. Now requires explicit user confirmation via a
"Clear Plate & Start Next" button on the printer card. Uses an
in-memory plate-cleared flag — no MQTT command needed since the
scheduler's start_print overrides the printer state.
2026-02-12 08:45:05 +01:00
maziggy c5fff9bc15 Fix AMS-HT mapping for left nozzle on H2D Pro (#318)
AMS-HT global tray ID was calculated as ams_id * 4 (= 512 for unit 128)
but AMS-HT uses the raw ams_id directly since it has a single tray.
The backend misidentified 512 as an external spool, producing wrong
ams_mapping2. Fixed in 4 locations: frontend getGlobalTrayId(), backend
start_print() ams_mapping2 builder, print scheduler, and Spoolman tracking.
2026-02-10 13:54:21 +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 b4285913a9 Remove 24-hour queue item expiration logic
Queue items were being marked as "expired" if older than 24 hours,
which breaks legitimate use cases like weekend print queues or
printers that are offline for extended periods.
2026-02-06 08:32:28 +01:00
maziggy 4b3b615a2c Fix Bandit B314: Replace xml.etree with defusedxml
Security scan (Bandit) identified vulnerable XML parsing in 3MF file
processing. The standard xml.etree.ElementTree is vulnerable to XXE
(XML External Entity) attacks.

Changes:
- Add defusedxml>=0.7.0 to requirements.txt
- Replace all xml.etree.ElementTree imports with defusedxml.ElementTree
  in production code (6 files)

Affected files:
- backend/app/services/archive.py
- backend/app/services/print_scheduler.py
- backend/app/api/routes/print_queue.py
- backend/app/api/routes/library.py
- backend/app/api/routes/printers.py
- backend/app/api/routes/archives.py

Test files intentionally left unchanged (test XML is trusted).
2026-02-05 17:30:14 +01:00
maziggy 3571cd1a42 Fix AMS auto-matching when multiple trays have same tray_info_idx
The tray_info_idx field is a filament TYPE identifier (e.g., "GFA00" for
generic PLA), not unique per spool. When multiple AMS trays are loaded
with the same filament type, the previous code used find() which always
returned the first match regardless of color.

Now checks if tray_info_idx is unique among available trays:
- If unique: use that tray as definitive match (existing behavior)
- If not unique: fall back to color matching among matching trays

Fixed in both backend (print_scheduler.py) and frontend (useFilamentMapping.ts).

Closes #245
2026-02-04 14:03:50 +01:00
maziggy a0d878a231 Fix AMS auto-matching to use tray_info_idx from 3MF files
When multiple AMS trays have the same filament type and color, Bambuddy
now uses the tray_info_idx attribute from the 3MF file to identify the
exact spool selected during slicing. This ensures the correct tray is
used rather than just picking the first match.

Matching priority: tray_info_idx > exact color > similar color > type-only

Closes #245
2026-02-04 08:13:54 +01:00
maziggy b6ce486fba Fix phantom reprint bug in print scheduler
Addresses reports of files being automatically reprinted hours after
the original print completed. The root cause was a race condition where
the queue item status was updated to "printing" AFTER the print command
was sent, allowing stuck "pending" items to be re-triggered on restart.

Changes:
- Set status to "printing" BEFORE sending print command to prevent
  re-triggering if backend crashes after print starts
- Add 24-hour expiration for stale pending queue items
- Add duplicate prevention: skip archives completed within last 4 hours

Trade-off: If backend crashes after status update but before print
command, item will be stuck in "printing" without actually printing.
This is safer than accidentally reprinting and wasting filament.
2026-02-03 17:18:22 +01:00
maziggy be18ebb36c Fix P2S printer support - disable vibration_cali and fix FTP SSL
Author: deathly1987 <andre@welker.one>
2026-02-02 14:09:40 +01:00
maziggy 018a744475 Location filter for queue and auth fixes (Issue #220)
Features:
- Add location filter for "Any {Model}" queue assignments
- Queue items can target a specific location (e.g., "Any X1C in Workshop")
- Location dropdown filter on Queue page to view jobs by location
- Scheduler considers location when assigning model-based jobs

Closes #220
2026-02-02 07:39:58 +01:00
maziggyandClaude Opus 4.5 4b2ea2d2c2 Fix P2S FTP upload failure - pass skip_session_reuse to ImplicitFTP_TLS (Issue #218)
The fix for A1/P1S FTP uploads (commit 82a6025) was accidentally broken in
commit 9969005 which removed the skip_session_reuse parameter from the
ImplicitFTP_TLS constructor. This caused P2S (and other models in
SKIP_SESSION_REUSE_MODELS) to still use SSL on the data channel, resulting
in "426 Failure reading network stream" errors.

The fix was implemented in commit b96ecfa on test/issue_174 branch but
never merged to main. This cherry-picks that fix.

Also includes:
- Storage diagnostics for debugging upload issues
- Better FTP error logging with specific error codes (553, 550, 552)
- Improved error messages in print scheduler

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-01 15:15:18 +01:00
MartinNYHC be7b3f99a2 Merge branch '0.1.6-final' into feature/192 2026-01-31 15:36:17 +01:00
maziggy 428f54a68d Fix Home Assistant smart plug auto-on for queued prints (Issue #200)
The print scheduler was hardcoded to use Tasmota service when powering
on printers for queued prints. Home Assistant plugs were not checked,
causing "Tasmota device not found" errors.

Changes:
- Make get_service_for_plug() public in smart_plug_manager
- Update print_scheduler to use smart_plug_manager.get_service_for_plug()
  instead of tasmota_service directly
- Fixes both _power_on_and_wait() and _power_off_if_needed() methods

Closes #200
2026-01-31 12:59:45 +01:00
maziggy 42a14f024d Fix AMS mapping for model-based queue jobs (Issue #192)
When using "Any [Model]" queue assignment, the scheduler now computes
AMS mapping after a printer is assigned, instead of requiring it upfront.

This fixes H2D Pro (and other printers) failing at filament loading when
queued via model-based assignment. The issue was that no AMS mapping was
sent to the printer because the specific printer wasn't known at queue time.

Closes #192
2026-01-31 08:39:21 +01:00
maziggy 74379da28e Fix X1E model-based queue
Backend - X1E model-based queue support:
- Fix 'PrinterState' object has no attribute 'ams_units' error
  by accessing AMS data via status.raw_data.get("ams", [])
- Add model name normalization in print_queue.py to convert
  "Bambu Lab X1E" or "C13" to canonical "X1E" format
- Add case-insensitive model matching in print_scheduler.py
  using func.lower() for database queries

Fixes #162
2026-01-30 12:05:18 +01:00
maziggy 836335be7d Correct AMS data access in print scheduler filament validation
The _get_missing_filament_types() method was incorrectly accessing
status.ams_units and status.virtual_tray, but PrinterState stores
this data in raw_data["ams"] and raw_data["vt_tray"] respectively.

This caused "'PrinterState' object has no attribute 'ams_units'" error
when using model-based queue assignment with filament type requirements.

Fixes #162
2026-01-30 11:32:35 +01:00
maziggy 7c5c4ee5bb Model-based queue assignment with filament validation and queue notifications (#162)
Model-based queue assignment:
- Extract printer_model from sliced 3MF files during upload
- Display sliced-for model in archive view
- New queue mode: assign to "Any [Model]" instead of specific printer
- Scheduler auto-assigns to first idle printer of matching model
- Filament validation: only assign to printers with required filament types loaded
- Waiting reason display shows why jobs are waiting (e.g., "Waiting for filament: Printer1 (needs PLA)")
- "Waiting" status badge (purple) distinguishes from regular "Pending"

Queue notifications (7 new events):
- Job Added: When a job is added to queue
- Job Assigned: When a model-based job is assigned to a printer
- Job Started: When a queue job starts printing
- Job Waiting: When a job is waiting for filament (enabled by default)
- Job Skipped: When a job is skipped due to previous failure (enabled by default)
- Job Failed: When a job fails to start (enabled by default)
- Queue Complete: When all queued jobs finish

Backend changes:
- New columns: print_queue.target_model, print_queue.required_filament_types, print_queue.waiting_reason
- New columns: notification_providers.on_queue_job_* (7 event triggers)
- Notification templates for all queue events
- Scheduler validates filament compatibility before model-based assignment
- Queue API extracts filament types from 3MF when adding model-based items
- Local backup/restore includes queue notification settings

Frontend changes:
- TypeScript interfaces updated for new fields
- Queue page shows waiting reason and "Waiting" badge
- Notification settings includes "Print Queue" section with 7 toggles

Closes #162
2026-01-28 13:39:08 +01:00
maziggy 2eb21e8b42 Issue #162 2026-01-28 09:14:22 +01:00
maziggy 2c761e7663 Add library file support to print queue scheduler
The print queue now supports two sources:
- archive_id: Print from existing archive (existing behavior)
- library_file_id: Print from file manager library files (NEW)

Previously, queue items from the file manager failed with "Archive not
found" because the scheduler only handled archive-based prints.

Changes:
- Add LibraryFile model import
- Update _start_print() to handle both archive and library file sources
- Handle absolute vs relative file paths correctly
- Update logging and MQTT notifications to use correct filename

Fixes GitHub issue #163
2026-01-27 15:40:27 +01:00
maziggy 84fe13dd07 Fix print queue not starting when printer state is FAILED
The print scheduler only considered IDLE, FINISH, and unknown as valid
idle states. This caused the queue to not process items when the printer
was in FAILED state (e.g., after an aborted print).

Added FAILED to the list of idle states since a failed print means the
printer is ready to accept a new print job.
2026-01-27 15:16:18 +01:00
maziggy d48abe0f6a Add File Manager and enhanced Queue features
File Manager:
- Add full File Manager page for browsing local library files
- Implement folder hierarchy with create/rename/delete operations
- Add file uploads with drag-and-drop support
- Enable adding sliced files directly to print queue
- Add linked folders with external path mounting

Queue Enhancements:
- Add plate selection for multi-plate 3MF files
- Add print options (bed levelling, flow calibration, vibration
  calibration, layer inspection, timelapse, use AMS)
- Fix print_count increment to only occur on actual prints

Testing:
- Add backend integration tests for library API (15 tests)
- Add backend integration tests for queue print options (8 tests)
- Add frontend tests for EditQueueItemModal (10 tests)
- Suppress console noise in frontend test suite

Closes #94
2026-01-19 13:29:37 +01:00
maziggy 03f4f8436a Fix queue prints failing with SD card error on A1 printers
Queue prints were uploading files to /cache/ directory but the MQTT
print command referenced files by name only (ftp://{filename}), which
resolves to the root directory. The printer couldn't find the file,
causing "MicroSD Card read/write exception error".

Changes:
- Upload queue prints to root / instead of /cache/ (matches reprint)
- Add filename cleaning for .gcode.3mf double extensions
- Pre-delete existing files before upload to avoid FTP 553 errors
- Fix misleading docstring in bambu_mqtt.py

Fixes #86
2026-01-16 07:41:52 +01:00
maziggy 368999a234 Add MQTT publishing for external automation integration
New feature: Publish BamBuddy events to external MQTT brokers for integration
with Home Assistant, Node-RED, and other automation platforms.

Backend changes:
  - New MQTTRelayService (backend/app/services/mqtt_relay.py) with paho-mqtt
  - MQTT settings added to AppSettings schema (enabled, broker, port, auth, TLS)
  - New /settings/mqtt/status endpoint for connection status
  - Event hooks in main.py, print_queue.py, print_scheduler.py, maintenance.py, smart_plugs.py
  - PrinterInfo class and get_printer() method added to PrinterManager
  - MQTT reconfiguration added to backup/restore flow
  - Printer status throttled to 1 update/sec to avoid flooding

Frontend changes:
  - New "Network" tab in Settings (between Filament and API Keys)
  - FTP Retry settings moved from General to Network tab
  - MQTT configuration card with broker, port, TLS toggle, auth fields
  - Port auto-populates when TLS toggled (1883 ↔ 8883)
  - Connection status indicator (green/red dot) in tab and card header
  - Real-time status polling when on Network tab

Published topics:
  - bambuddy/status - Online/offline
  - bambuddy/printers/{serial}/status - Printer state (throttled)
  - bambuddy/printers/{serial}/print/* - Print lifecycle
  - bambuddy/printers/{serial}/ams/changed - AMS changes
  - bambuddy/queue/* - Queue events
  - bambuddy/maintenance/* - Maintenance alerts
  - bambuddy/smart_plugs/* - Plug state/energy
  - bambuddy/archive/* - Archive events

Tests:
  - Added MQTT settings and status endpoint tests

Closes #78
2026-01-13 12:31:45 +01:00
maziggyandClaude Opus 4.5 ad4e4fc3a2 Add manual AMS slot selection for prints (#76)
- ReprintModal: Dropdown to override auto-matched AMS slots
- AddToQueueModal: Collapsible filament mapping section
- Backend: Store ams_mapping in print queue, apply when print starts
- Color names in dropdowns (decoded from Bambu codes or derived from hex)
- Blue ring indicator for manually selected vs auto-matched slots
- Status indicators: green (match), yellow (type only), orange (not found)

Closes #76

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-12 08:37:47 +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