Commit Graph
1527 Commits
Author SHA1 Message Date
maziggy b2bf8c7100 Updated README 2026-02-28 15:25:00 +01:00
MartinNYHC f56882642f Merge pull request #555 from maziggy/0.2.1.1
v0.2.1.1

Just one day ago after the last release, but I decided to make life a little better for those of you guys who are just received their new H2C :)

What happened?

Recent H2C deliveries from Bambu Lab ship with an updated internal model identifier: O1C2 instead of the previously known O1C. Bambuddy only recognized O1C, so these newer H2C units were not properly identified.
  
 Also included some fixes.
 
- Fix sidebar navigation not respecting user permissions
- Fix camera button permissions & ffmpeg process leak (#550)
- Fix A1 Mini "unknown" status from non-UTF-8 MQTT payload (#549)
- Fix Windows install syntax error from LF line endings (#544)
- Fix queue badge showing on printers without matching filament (#486)
- Fix naive-vs-aware datetime crash from 0.2.1 timezone migration
v0.2.1.1
2026-02-28 15:16:46 +01:00
MartinNYHC 2c99b631fa Merge branch 'main' into 0.2.1.1 2026-02-28 15:04:45 +01:00
maziggy 9ee4bd51e4 Sync 2026-02-28 14:59:04 +01:00
maziggy 51ac1b1d35 Bumped version 2026-02-28 14:45:32 +01:00
maziggy cca4e6fab2 Uodated issue template 2026-02-28 14:39:18 +01:00
maziggy f2f43b98a3 Fix sidebar navigation not respecting user permissions
Sidebar nav items (Archives, Queue, Stats, Profiles, Maintenance,
  Projects, Inventory, Files) were visible to all users regardless of
  role permissions — only Settings was gated. Now each item is hidden
  when the user lacks the corresponding read permission. Printers
  remains always visible as the home page.

  Also adds missing inventory:read|create|update|delete to the frontend
  Permission type (existed in backend but was absent from the frontend
  type definition).
2026-02-28 14:39:10 +01:00
maziggy 90b9523998 Updated commit message (now includes the test fix):
Fix camera button permissions & ffmpeg process leak (#550)

  Camera button on printer card was clickable without camera:view
  permission. ffmpeg processes (~240MB each) accumulated after closing
  camera streams because: (1) stop endpoint called terminate() without
  wait()/kill(), (2) HTTP disconnect detection only ran between frames
  so was blocked when the generator was stuck on stdout read, and
  (3) no mechanism caught processes orphaned by generator abandonment
  or app restarts.

  - Add camera:view permission check + tooltip to camera button
  - Fix stop endpoint: terminate() → wait(2s) → kill() → wait()
  - Add background disconnect monitor (polls every 2s, kills ffmpeg
    directly on disconnect)
  - Add periodic /proc scan (every 60s) that SIGKILLs any ffmpeg
    with rtsps://bblp: not in an active stream
  - Add noCamera i18n key to all 6 locales
  - Fix camera API test mocks for async wait() and pid attribute
2026-02-28 14:38:45 +01:00
maziggy 240eeb4f5d 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 14:38:11 +01:00
maziggy 5df2b82673 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 14:36:56 +01:00
maziggy abd20056ae Fix Windows install syntax error from LF line endings (#544)
The start_bambuddy.bat launcher had Unix (LF) line endings. When a
user's git is configured with core.autocrlf=false or input, the file
is checked out with LF endings and cmd.exe fails with "the syntax of
the command is incorrect" before reaching the hash check.

Add .gitattributes forcing CRLF for *.bat files so they always get
correct line endings on checkout regardless of git config.
2026-02-28 14:36:25 +01:00
maziggy d3bae07edf Fix queue badge showing on printers without matching filament (#486)
The purple queue counter badge in the printer card header used the raw
unfiltered queue item count, so it appeared on ALL printers of the same
model when a job was scheduled for "any [model]" — even printers without
the matching filament color. The PrinterQueueWidget below it (which
shows "Clear Plate & Start") already filtered by filament type + color.

Apply the same filament compatibility filter (type check + color override
check) to the badge count so it only shows on printers that can actually
run the queued jobs.
2026-02-28 14:36:12 +01:00
maziggy b1cc3462ed 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 9 affected comparison sites:
- maintenance.py: last_performed_at subtraction (2 code paths — days-based
  and hours-based intervals both crashed 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-28 14:35:02 +01:00
maziggy 233e84c03a 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-28 14:34:55 +01:00
maziggy 105beb0929 Updated CI 2026-02-28 14:34:46 +01:00
maziggy b5a5462816 Uodated issue template 2026-02-28 13:10:48 +01:00
maziggy aeed41684b 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 9 affected comparison sites:
- maintenance.py: last_performed_at subtraction (2 code paths — days-based
  and hours-based intervals both crashed 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
v0.2.1
2026-02-27 17:45:58 +01:00
maziggy 0d0223cb52 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:38:47 +01:00
maziggy efccaadd6d Updated CI 2026-02-27 14:54:08 +01:00
MartinNYHC eee901fc20 Merge pull request #536 from maziggy/0.2.1
# Bambuddy v0.2.1

## New Features

- **Multiple Virtual Printers** — Run multiple virtual printers per installation, each with a dedicated bind IP and fully independent FTP, MQTT, SSDP, and Bind servers. Full CRUD API and React UI for creating, editing, and deleting instances. Supports all four modes, any of the 11 printer models, per-instance TLS certificates, and individual network interface override.
- **Background Print Dispatch** ([#112](https://github.com/maziggy/bambuddy/issues/112)) — Printing from archives and the file manager now runs in the background. FTP uploads are decoupled from API request latency, so the UI responds immediately. Real-time progress via WebSocket with per-job upload bars, status badges, and a cancel button.
- **Filament Cost Tracking** ([#452](https://github.com/maziggy/bambuddy/issues/452)) — Track per-spool filament costs and see cost breakdowns for every print. Archive cards display total cost, the print modal shows a real-time cost preview, and the inventory table includes a sortable cost/kg column. A global default filament cost setting provides a fallback. Contributed by @Keybored02.
- **Filament Override for Model-Based Queue** ([#486](https://github.com/maziggy/bambuddy/issues/486)) — When scheduling to "any printer", you can now override the 3MF's original filament choices. The scheduler matches against overridden type and color, preferring printers with exact color matches.
- **Bulk Spool Addition & Stock Spools** ([#480](https://github.com/maziggy/bambuddy/issues/480)) — Quick Add mode for inventorying filament without a slicer profile. Quantity field creates up to 100 identical spools in one transaction. Stock spools shown with an amber badge. New grouping toggle collapses identical unused spools into expandable rows.
- **Developer LAN Mode Detection** — Automatically detects printers without Developer LAN Mode enabled and shows a persistent warning banner with affected printer names and a link to Bambu Lab's documentation.
- **Clear Plate Permission** ([#446](https://github.com/maziggy/bambuddy/issues/446)) — New `printers:clear_plate` permission so users can confirm plate clears without needing full `printers:control`.
- **Full-Page Group Permission Editor** ([#446](https://github.com/maziggy/bambuddy/issues/446)) — Replaced the cramped permission modal with a dedicated full-page editor featuring a 2-column grid, search/filtering, and bulk actions.
- **External Materials & Brands in Spool Form** ([#455](https://github.com/maziggy/bambuddy/issues/455)) — The spool form now allows using custom materials and brands not in the Bambu filament catalog when adding or editing spools.
- **Energy Cost 3-Decimal Precision** ([#416](https://github.com/maziggy/bambuddy/issues/416)) — Energy cost values now support 3 decimal places (e.g., €0.123/kWh) instead of 2, for more accurate cost tracking in regions with fractional energy pricing.
- **Include Beta Updates Setting** — New toggle to opt in to beta/prerelease update notifications. Default: off (stable only).
- **Virtual Printer Dual Bind/Detect Ports** ([#445](https://github.com/maziggy/bambuddy/issues/445)) — The slicer bind/detect handshake now listens on both ports 3000 and 3002 for compatibility across BambuStudio/OrcaSlicer versions.

## Fixed

### Print Queue & Scheduling
- **Queue Empty After Container Restart** ([#523](https://github.com/maziggy/bambuddy/issues/523)) — SQLite WAL not checkpointed on shutdown. Now runs `PRAGMA wal_checkpoint(TRUNCATE)` before exit.
- **Queue Stuck on "Busy" for "Any Model" Jobs** ([#435](https://github.com/maziggy/bambuddy/issues/435)) — Queue API now uses OR logic to also return unassigned items whose `target_model` matches the printer's model.
- **Queue "Any Model" Jobs Stuck in "Waiting" After Plate Clear** ([#435](https://github.com/maziggy/bambuddy/issues/435)) — MQTT raw AMS data returned IDs as strings; fixed type casting.
- **"Queue to Any Printer" Ignores Filament Color Override** ([#486](https://github.com/maziggy/bambuddy/issues/486)) — Now requires at least 1 color match when filament overrides specify colors.
- **"Clear Plate & Start Next" Ignores Filament Override Color** ([#486](https://github.com/maziggy/bambuddy/issues/486)) — Frontend now checks override colors, mirroring the backend's color matching logic.
- **"Clear Plate & Start Next" Shown on Printers Without Correct Filament** ([#527](https://github.com/maziggy/bambuddy/issues/527)) — Widget now filters queue items by filament compatibility.
- **Virtual Printer Queue Sends Wrong Plate ID** ([#529](https://github.com/maziggy/bambuddy/issues/529)) — `plate_id` was always `1`; now extracts plate index from 3MF's `slice_info.config`.
- **Virtual Printer Queue Ignores AMS Mapping** ([#529](https://github.com/maziggy/bambuddy/issues/529)) — Scheduler now computes AMS mapping for all queue items that lack one.
- **Virtual Printer Queue Mode Doesn't Assign Printer** ([#518](https://github.com/maziggy/bambuddy/issues/518)) — Now assigns the VP's target printer or falls back to model-based scheduling.
- **Unnecessary Target Model Selector on "Any" Tab** ([#528](https://github.com/maziggy/bambuddy/issues/528)) — Dropdown hidden when sliced model is known.
- **Print Queue Shows UUID Hash Instead of Filename** ([#438](https://github.com/maziggy/bambuddy/issues/438)) — Library files now display the original human-readable name.
- **SD Card Cleanup After Print Never Runs** ([#374](https://github.com/maziggy/bambuddy/issues/374)) — Used wrong printer object type; fixed to use DB query.
- **Phantom Prints From Lingering SD Card Files** ([#477](https://github.com/maziggy/bambuddy/issues/477)) — Fixed retry loop, added cleanup on `start_print()` failure.

### AMS & Filament
- **AMS History Chart Shows Wrong Time Range** ([#535](https://github.com/maziggy/bambuddy/issues/535)) — X axis now pinned to the full requested time range.
- **Manual Spool Weight Overwritten by AMS Auto-Sync** ([#525](https://github.com/maziggy/bambuddy/issues/525)) — Added `weight_locked` flag for manual weight entries.
- **AMS Slot Auto-Config Falls Back to Generic Instead of Spool's Preset** — Fixed PFUS*/P* custom preset handling and "sticky" generic ID reuse.
- **PCTG Filament Misidentified as PC** ([#478](https://github.com/maziggy/bambuddy/issues/478)) — Reordered material parser; added PCTG to all material type arrays.
- **External Spool Mapping Inverted on H2C** ([#492](https://github.com/maziggy/bambuddy/issues/492)) — Now uses `active_extruder` on dual-nozzle printers.
- **External Spool Assignments Lost on Restart** ([#493](https://github.com/maziggy/bambuddy/issues/493)) — Now looks up external assignments in `vt_tray` data.
- **Filament Fill Level Wrong / Missing for External Spools** ([#496](https://github.com/maziggy/bambuddy/issues/496)) — Fixed priority chain, removed misleading gray fallback bar, added AMS remain fallback for external spools.
- **Wrong AMS Unit Displayed With Dual AMS on P2S** ([#420](https://github.com/maziggy/bambuddy/issues/420)) — Now cross-references `tray_now` with MQTT mapping field for multi-AMS printers.
- **H2D Tray Disambiguation Produces Bogus IDs for AMS-HT** ([#364](https://github.com/maziggy/bambuddy/issues/364)) — Fixed AMS-HT global tray ID computation across multiple code paths.
- **Usage Tracking Wrong Spool on Multi-AMS Printers** ([#364](https://github.com/maziggy/bambuddy/issues/364)) — Now decodes MQTT mapping field from snow encoding for universal spool resolution.
- **Spool Usage Lost When Spool Runs Empty Mid-Print** ([#459](https://github.com/maziggy/bambuddy/issues/459)) — Snapshots assignments at print start; splits weight across trays using per-layer gcode data.
- **Spool Form Allows Empty Brand & Subtype** ([#417](https://github.com/maziggy/bambuddy/issues/417)) — Brand and Subtype now mandatory.

### Printing & Archives
- **Inconsistent Print Cost on Reprints** ([#505](https://github.com/maziggy/bambuddy/issues/505)) — Removed redundant cost paths; now computes from current session only.
- **Finish Photo Not Captured When Archive Has No Source 3MF** ([#484](https://github.com/maziggy/bambuddy/issues/484)) — Falls back to `archive/{id}/` directory.
- **Finish Photo Not Shown for BambuStudio Prints** ([#474](https://github.com/maziggy/bambuddy/issues/474)) — Fixed path resolution for empty `file_path`.
- **Archive Endpoints Crash With "Is a directory"** ([#475](https://github.com/maziggy/bambuddy/issues/475)) — Replaced `.exists()` with `.is_file()` across 15 locations.
- **File Manager Rename Doesn't Update Displayed Name** ([#460](https://github.com/maziggy/bambuddy/issues/460)) — Rename now also updates `print_name` in file metadata.
- **"Open in Slicer" Fails for Special Characters** — Sanitizes `/`, `\`, `?`, `#` to `_` in slicer download URLs.
- **"Open in Slicer" Fails When Auth Enabled** ([#421](https://github.com/maziggy/bambuddy/issues/421)) — Added short-lived, single-use download tokens with platform-specific URL formats.
- **Non-Actionable HMS Errors Triggering Notifications** ([#470](https://github.com/maziggy/bambuddy/issues/470)) — Suppresses MQTT auth failures, cloud connection failures, and user cancellations.
- **ntfy Notifications Fail With "Illegal header value"** ([#466](https://github.com/maziggy/bambuddy/issues/466)) — Escapes newlines in HTTP headers; retries without image when attachments disabled.
- **Print Bed Cooled Notification Never Triggers** ([#497](https://github.com/maziggy/bambuddy/issues/497)) — Moved bed cooldown monitor before archive lookup early-return.
- **K-Profile Response Race Condition Crash** ([#462](https://github.com/maziggy/bambuddy/issues/462)) — Fixed TOCTOU race between MQTT callback and asyncio thread.

### Permissions & UI
- **"Power Off Printer" Not Gated by Control Permission** ([#500](https://github.com/maziggy/bambuddy/issues/500)) — Checkbox now disabled for users without `printers:control`.
- **Created Admin Users Can't See Settings Button** ([#503](https://github.com/maziggy/bambuddy/issues/503)) — Now uses `hasPermission('settings:read')` instead of hardcoded role check.
- **Settings Text Fields Reset While Typing** — Removed stale state overwrite from auto-save handler.
- **Spool Form Profile Dropdown Truncates Long Names** ([#534](https://github.com/maziggy/bambuddy/issues/534)) — Removed inline filament codes; widened modal.

### Timestamps & Dates
- **Timestamps Off by Timezone Offset in Non-UTC Containers** ([#504](https://github.com/maziggy/bambuddy/issues/504)) — Replaced `datetime.now()` / `datetime.utcnow()` with `datetime.now(timezone.utc)` across 16 files (~80 call sites). Fixed 13 frontend `new Date()` calls.
- **Inventory Date Format Ignores Settings** ([#463](https://github.com/maziggy/bambuddy/issues/463)) — Now respects date format setting.
- **Inventory Location Shows Garbled Characters for AMS-HT Slots** ([#463](https://github.com/maziggy/bambuddy/issues/463)) — Now uses shared `formatSlotLabel()` utility.

### Docker & Infrastructure
- **FTP Proxy Cannot Bind to Port 990 in Docker** — `cap_add: NET_BIND_SERVICE` didn't reliably propagate with the `user:` directive. Now sets file capabilities via `setcap` in the Dockerfile.
- **Support Bundle Leaking Personal Data** ([#473](https://github.com/maziggy/bambuddy/issues/473)) — Now queries DB for sensitive values; uses httpx `auth` parameter for smart plug credentials; redacts serial numbers fully.
- **IP Addresses Not Redacted From Support Bundle** — Added IPv4 regex that preserves firmware version strings.

### AMS Mapping & Dual-Nozzle (H2D/H2C)
- **7 AMS Mapping Fixes** — Hard nozzle filter, external spool extruder, `ams_extruder_map` race condition, `group_id` priority, dual-nozzle detection, AMS-HT `globalTrayId`, dropdown nozzle filter.
- **Nozzle Mapping Uses Wrong Source in 3MF** — Now uses `group_id` as primary source instead of `filament_nozzle_map`.
- **H2D Tray Disambiguation Triggers on Single-Nozzle Printers** — Now uses persistent `_is_dual_nozzle` flag.
- **Cancelled Print Usage Tracking Uses Stale Progress** — Now captures last valid progress/layer during printing.
- **Developer Mode Detection Always Reports Null** — Fixed `int(value, 16)` TypeError on integer MQTT field.

### Other
- **Wrong Documentation Link for "Lubricate Carbon Rods" on P2S** ([#490](https://github.com/maziggy/bambuddy/issues/490))
- **"Unknown stage (74)" on H2D** — Mapped stage 74 ("Preparing") and 77 ("Preparing AMS").
- **Color Tooltip Clipped Behind Adjacent Swatches** — Added z-index.
- **PAUSED State Never Matched** ([#447](https://github.com/maziggy/bambuddy/issues/447)) — Removed dead `PAUSED` checks; printer only sends `PAUSE`.

## Improved

- **Queue API Returns More Print Metadata** ([#524](https://github.com/maziggy/bambuddy/issues/524)) — Endpoints now include `filament_type`, `filament_color`, `layer_height`, `nozzle_diameter`, and `sliced_for_model`.
- **Filament Catalog API Renamed** ([#427](https://github.com/maziggy/bambuddy/issues/427)) — `/api/v1/filaments/` → `/api/v1/filament-catalog/` for clarity.
- **Clear Plate Dot Indicator on Sidebar** — Yellow dot on Printers icon when plate clear is needed.
- **Inventory Sidebar Always Visible** — Shows Spoolman iframe or internal inventory based on mode.
- **Queue Page Mobile Responsiveness** — Improved layout for mobile devices.
- **Storage Size Formatting & Overdue Queue Items** — UI polish and i18n fixes.
- **Brazilian Portuguese Translation** — Full translation contributed by @wreuel.
- **H2D Pro Printer Image** — Added H2D Pro image and model mapping. Contributed by @cimdDev.
- **Native Updater Script** — Systemd-based updater with backup and safety checks. Contributed by @uefigs139.
- **Docker Install iptables Option** — Option to add iptables port redirect during Docker install. Contributed by @wreuel.
- **Frontend Pre-Commit Hooks** ([#458](https://github.com/maziggy/bambuddy/issues/458)) — TypeScript type checking and ESLint on staged frontend files.
- **Show Remaining Spool Weight** — Displays remaining weight instead of used weight. Contributed by @Keybored02.

## Community Contributors

Thank you to everyone who contributed to this release:

- **@Keybored02** — Filament cost tracking, remaining weight display, spool form fixes
- **@wreuel** — Brazilian Portuguese translation, Docker iptables install option
- **@cimdDev** — H2D Pro printer image
- **@uefigs139** — Native updater script
- **@aneopsy** — Queue page mobile responsiveness, page refactoring, UI improvements
2026-02-27 10:44:36 +01:00
maziggy f8b2ebd695 Added # nosec B108 suppressions for virtual printer tests 2026-02-27 10:41:38 +01:00
MartinNYHC e8c0bae7c8 Merge branch 'main' into 0.2.1 2026-02-27 10:36:44 +01:00
maziggy 5cdeb4207c Updated CHANGELOG 2026-02-27 10:28:55 +01:00
maziggy d91d95a1ec Fix FTP proxy port 990 permission denied in Docker
cap_add: NET_BIND_SERVICE in docker-compose.yml doesn't reliably
propagate to the Python process when combined with the user: directive
(depends on ambient capability support in the container runtime).
Set the file capability directly on the Python binary via setcap in
the Dockerfile, which the kernel honors regardless of runtime config.
2026-02-27 10:25:48 +01:00
maziggy 55c332d91a Housekeeping 2026-02-27 10:05:03 +01:00
maziggy 6e2788517c Updated test_backend.sh 2026-02-27 09:48:31 +01:00
maziggy 94d0f55e1c Fix AMS history chart showing wrong time range (#535)
The chart X axis used dataMin/dataMax domain, compressing the view to
only the data present. A 6h view with 1.5h of data looked like 1.5h.
Pin the X axis to the full selected time range, pad data edges so the
line extends to both ends, and connect through nulls for a continuous
line.
2026-02-27 08:44:24 +01:00
maziggy ad6108c8a7 Fix "Clear Plate" button shown on printers without matching filament color (#486)
When a print was queued to "any printer" with a filament color override
(e.g., white PETG), the "Clear Plate & Start Next" button appeared on
printers that had the right type but wrong color. The backend scheduler
already rejected color mismatches, but the frontend only checked filament
types. Now passes loaded type+color pairs from AMS status to the widget
and filters against filament_overrides, mirroring the backend's
_count_override_color_matches() logic.
2026-02-27 08:03:21 +01:00
maziggy 2c8fbf3e33 Fix queue empty after restart by checkpointing WAL on shutdown (#523)
The SQLite WAL was never checkpointed during container shutdown, leaving
uncommitted data (including schema migrations) in the -wal file. On
restart, partial WAL recovery could cause inconsistent query results,
making the queue appear empty until a filter was applied. Add
PRAGMA wal_checkpoint(TRUNCATE) and engine.dispose() to the lifespan
shutdown handler.
2026-02-27 07:41:03 +01:00
maziggy 4f5a9f4b95 Fix spool form profile dropdown truncating long preset names (#534)
Long filament profile names were cut off because inline filament ID
codes consumed horizontal space in the dropdown. Remove the codes from
dropdown items (selected code still shown below the input) and widen
the modal from max-w-lg to max-w-xl.
2026-02-27 07:30:03 +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 a6d326f8fa Fix VP queue mode sending wrong plate_id → HMS 0500_4003 (#529)
When a virtual printer auto-queued a file, PrintQueueItem was created
without plate_id. The scheduler defaulted to plate_id=1, generating
MQTT path "Metadata/plate_1.gcode". For multi-plate 3MF files sliced
on a different plate, the printer couldn't find the gcode and returned
HMS error 0500_4003. Extract plate index from the 3MF's slice_info.config
before creating the queue item.
2026-02-26 10:00:33 +01:00
maziggy f4f09ccc2d Hide unnecessary target model selector on "Any" tab (#528)
When scheduling a print to "Any {model}", a redundant "Target Model"
dropdown appeared even though the G-code is already sliced for a
specific printer model. Changing it would lead to print failures.

Hide the dropdown when slicedForModel is known — the tab label already
communicates the target. The dropdown still appears as a fallback for
legacy files without model metadata.
2026-02-26 09:13:06 +01:00
maziggy 20c291d678 Fix "Clear Plate & Next" shown on printers without correct filament (#527)
The "Clear Plate & Start Next" button appeared on ALL printers of a
model when a job was queued via "Queue to Any X", even printers without
the required filament loaded. Clicking it started a print that fails.

PrinterQueueWidget now filters queue items by filament compatibility —
each item's required_filament_types must all be present in the printer's
loaded filaments (AMS + external spools). If no compatible items exist,
the widget is hidden entirely. Matching is type-only (not color) and
case-insensitive, consistent with the backend scheduler. When filament
data is unavailable, no filtering is applied (graceful degradation).
2026-02-26 08:57:39 +01:00
maziggy 37d9b4c841 Fix manual spool weight overwritten by AMS auto-sync (#525)
Add weight_locked flag to spools that auto-sets when weight_used is
explicitly updated via the API. Both the MQTT AMS remain% auto-sync and
the manual force-sync endpoint skip locked spools. Usage tracker delta
tracking is unaffected. Users can re-enable AMS sync by setting
weight_locked to false.
2026-02-26 08:42:19 +01:00
maziggy fa87e24968 Add print metadata to queue API response (#524)
Queue endpoints now return filament_type, filament_color, layer_height,
nozzle_diameter, and sliced_for_model from the archive or library file.
Previously this data was only available via the archive API.
2026-02-26 08:15:38 +01:00
maziggy 1973a5bead Fix virtual printer queue mode not assigning printer (#518), settings text fields resetting mid-typing
Virtual printer "print_queue" mode created queue items with no printer
assignment. Now sets target_model from the VP's SSDP model code (e.g.
P1S, X1C) for "Any Printer" scheduling, or uses target_printer_id if
configured.

Settings page auto-save onSuccess overwrote localSettings with the
server response, discarding characters typed during the save request.
Removed the stale state overwrite so in-progress input is preserved.
2026-02-26 08:06:56 +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 6317e7adce Updated README 2026-02-26 07:26:35 +01:00
MartinNYHC 3c86bdd27f Merge pull request #517 from maziggy/maziggy-patch-1
Make version check mandatory in bug report template
2026-02-24 17:50:36 +01:00
MartinNYHC 18f43e46ac Make version check mandatory in bug report template 2026-02-24 17:50:20 +01:00
MartinNYHC a6a01eb11b Merge pull request #516 from maziggy/maziggy-patch-1
Make 'latest version' field required in bug report
2026-02-24 17:49:36 +01:00
MartinNYHC a5ccdf561a Make 'latest version' field required in bug report 2026-02-24 17:49:20 +01:00
maziggy 8e39b12c5d Updated .github/ISSUE_TEMPLATE/bug_report.yml 2026-02-24 16:49:32 +01:00
maziggy 60f1be8935 Updated .github/ISSUE_TEMPLATE/bug_report.yml 2026-02-24 16:49:13 +01:00
maziggy 59be1b0d4d Updated .github/ISSUE_TEMPLATE/bug_report.yml 2026-02-24 16:48:12 +01:00
maziggy 3dc9ebcb6c Updated .github/ISSUE_TEMPLATE/bug_report.yml 2026-02-24 16:47:50 +01:00
maziggy d92803b557 Fix "Open in Slicer" failing for filenames with special characters
Filenames containing / \ ? or # (e.g. "Abzweigdose/Verteilerdose 70mm")
broke the slicer protocol handler. BambuStudio/OrcaSlicer url_decode()
the entire protocol URL before downloading, which decoded %2F back to /,
creating extra path segments that returned 404. Sanitize these characters
to _ in slicer download URLs — the filename is cosmetic (backend resolves
files by archive ID).
2026-02-24 12:32:46 +01:00
maziggy c2b7b6a99a Fix inconsistent print cost calculation on reprints (#505)
Three independent code paths wrote to archive.cost with conflicting
strategies, causing the same model to produce different prices on each
reprint (e.g. £0.77, £1.54, £2.03).

- Remove add_reprint_cost (Path 3) — redundant cost accumulation that
  double-counted on top of usage tracker
- Fix usage tracker (Path 2) — compute cost from current session's
  results only, not a SUM of all historical SpoolUsageHistory rows
- Remove _reprint_archives tracking set from main.py
- Update test mocks to match simplified query pattern

archive.cost now always reflects the cost of a single print.
2026-02-24 08:58:35 +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