Commit Graph
36 Commits
Author SHA1 Message Date
maziggy 7cb905ad0c feat(inventory): toggle to disable auto-add of unknown RFID spools + global confirmation modal (issue #1764)
New setting "Auto-add unknown RFID spools" under Settings -> Filament -> Filament Tracking,
  default ON for back-compat. When turned off, the backend stops auto-creating an inventory
  record for an unknown RFID tag and instead broadcasts an unknown_tag WS event that pops
  a global confirmation modal in the Bambuddy UI showing the printer / AMS-X label / slot /
  material / colour. Add or Cancel; no nag on every MQTT push.

  Backend
  - Module-level _unknown_tag_last_broadcast dict dedupes per (printer, slot, tag). Set is
    committed AFTER ws_manager.broadcast() returns so a crashed broadcast doesn't poison
    the dedup and permanently silence the slot.
  - Empty-slot MQTT push clears that slot's entry, so remove+reinsert reliably re-prompts.
  - Successful matches via get_spool_by_tag / find_matching_untagged_spool / create_spool
    also clear the entry so a future tag swap re-prompts.
  - Tray data (tray_type, tray_color, tray_sub_brands, tray_count) shipped in the WS payload
    directly so the modal renders the real material / colour instead of relying on the
    React Query cache that lags the WS event by several seconds.
  - Two new endpoints back the modal's confirm action:
      POST /api/v1/inventory/spools/from-slot     (INVENTORY_UPDATE)
      POST /api/v1/spoolman/spools/from-slot      (FILAMENTS_UPDATE)
    Both look up the slot's tray data server-side and create + auto-assign atomically.
  - Spoolman /from-slot now raises HTTP 500 when the slot-assignment INSERT fails instead
    of returning success while the DB rolled back the binding.
  - sync_ams_tray gained an optional auto_add_unknown_rfid kwarg (default True so existing
    callers are unaffected); auto-sync and both manual sync routes thread the setting.

  Frontend
  - useUnknownTagPrompt hook listens for the unknown-tag CustomEvent, reads the tray fields
    out of the event detail, and feeds a single-modal queue. No long-lived dismissed set;
    the backend dedup handles spam suppression.
  - UnknownSpoolModal wraps the existing ConfirmModal with a material + colour-swatch
    preview block.
  - Mounted in Layout.tsx alongside useSponsorPrompt so SpoolBuddy kiosk / login / setup
    routes are excluded.
  - getAmsLabel moved to utils/amsHelpers.ts; ConfigureAmsSlotModal.tsx and PrintersPage.tsx
    both import the shared version (canonical AMS-A / HT-A / External labels).
  - AppSettings TS interface gained spoolman_enabled, auto_add_unknown_rfid, spoolman_url
    so the runtime cast in the hook is no longer needed.
  - SpoolmanSettings.tsx gets a new toggle row in the Filament Tracking card, visible in
    both built-in and Spoolman branches; auto-save + toast already wired.
2026-06-23 09:59:05 +02:00
Poltavtcev af5d24e289 feat(inventory): structured storage locations catalog (#1505) 2026-06-17 11:33:23 +02:00
maziggy 632334953c fix(inventory): support transparent / clear filament end-to-end (#1545)
Reporter wanted to select a transparent filament colour in the spool
  editor; CMW-ISS confirmed on v0.2.5b1 that AMS-detected transparent
  spools were silently labelled "Black" in the filament-mapping dropdown
  because the colour name resolver dropped the alpha byte and the underlying
  RGB 000000 HSL-bucketed to "Black". Spoolman already supported 8-digit
  hex; the built-in inventory didn't.

  Eight collapsing sites fixed together so transparent reaches the user
  intact:

  - frontend/src/utils/colors.ts: hexToColorName / getColorName /
    resolveSpoolColorName / isLightColor short-circuit to "Clear" for
    alpha=00 before HSL bucketing or catalog lookup
  - frontend/src/utils/amsHelpers.ts::normalizeColor preserves the alpha
    byte when alpha < FF (normalizeColorForCompare unchanged so type/colour
    matching is unaffected)
  - frontend/src/components/spool-form/constants.ts: new
    { name: 'Clear', hex: '00000000' } preset in QUICK_COLORS
  - frontend/src/components/spool-form/ColorSection.tsx: hex draft accepts
    0-8 chars, commits at 6 (+FF) or 8 verbatim; blur pads 7-char to 8;
    selectColor passes 6-char as +FF / 8-char verbatim; isSelected matches
    on full rgba; swatch buttons paint a checkerboard for alpha=00
  - backend/app/api/routes/printers.py::get_available_filaments preserves
    the full rgba on both AMS and vt_tray branches (6-char dedup key
    unchanged)
  - backend/app/services/spoolman.py::parse_ams_tray drops the silent
    00000000 -> F5E6D3FF cream rewrite — the swatch renderer paints a
    checkerboard underlay for alpha < FF already (added in #1154), so the
    rewrite was hidden technical debt that made every AMS-detected
    transparent spool land in inventory as cream
  - backend/app/services/spool_tag_matcher.py::create_spool_from_tray
    short-circuits the colour-catalog lookup for alpha=00 and stores
    color_name="Clear" directly — otherwise an RFID-tagged transparent
    Bambu spool would resolve against the #000000 catalog row (or "Black"
    via the HSL fallback) before the frontend's resolver ever saw it
  - Two shared helpers in utils/colors.ts — getSwatchStyle(rgba) (style
    object: checkerboard for alpha=00) and spoolColorString(rgba)
    (8-char hex string for SVG fill) — applied to every simple-swatch
    site that would otherwise have rendered Clear spools as solid black:
    LabelTemplatePickerModal, SpoolBuddyInventoryPage (SpoolCircle + dot),
    SpoolBuddyAmsPage (both branches), SpoolBuddyWriteTagPage (4 sites),
    ForecastPanel, AssignToAmsModal, AssignSpoolModal (both branches),
    InventorySpoolInfoCard, TagDetectedModal, SpoolInfoCard, LinkSpoolModal,
    and the FilamentSwatch tooltip title fallback

  Intentionally NOT changed: native <input type="color"> keeps 6-char hex
  (can't pick alpha; onChange still emits +FF, correct); Spoolman's
  _find_or_create_filament strips alpha (Spoolman catalog is 6-char only);
  print_scheduler colour matching strips alpha (auto-mapping treats Clear
  as Black for slot compatibility); label_renderer prints "#RRGGBB" on the
  physical label (printers can't print transparency, swatch fill via
  _color_from_hex still honours alpha).
2026-05-29 10:15:53 +02:00
maziggy 3b552094a7 fix(spoolman): edit-spool patches the linked filament in place when singleton (#1357 follow-up)
Editing a Spoolman spool used to mint a brand-new filament every time
  a match-key field (subtype/material/brand/color_hex) changed, orphan
  the previous one, and re-link the spool. The reporter ended up with
  dozens of duplicate "Amazon Basics / PLA Glow" filament rows.

  PATCH /spoolman/inventory/spools/{id} now:

  - Reuses the current filament_id when no filament-shaping field
    changed (a note/weight_used edit never touches the catalogue).
  - PATCHes the existing filament in place when it's a singleton
    (only this spool points at it, archived spools included).
  - Falls back to find_or_create_filament only when the filament is
    genuinely shared with another spool.

  Mirrors internal-inventory behaviour where editing a spool updates
  the thing the spool points at instead of proliferating new entities.
2026-05-18 11:35:10 +02:00
maziggy 8b9efd0160 fix(inventory): "Reset usage to 0" works in Spoolman mode too (#1390)
First cut of this action only wired the built-in inventory path, so the
  eraser buttons vanished when the user switched to Spoolman mode. Mirror
  the endpoints on the Spoolman router:

  - POST /spoolman/inventory/spools/{id}/reset-usage
  - POST /spoolman/inventory/spools/reset-usage-bulk

  Both route to a new SpoolmanClient.reset_spool_usage() helper that PATCHes
  /spool/{id} with used_weight=0. The bulk variant keeps the same typo-wipe
  guard (rejects empty/missing spool_ids), and individual Spoolman failures
  are logged + counted out without aborting the batch.

  InventoryPage mutations now switch on spoolmanMode to pick the right
  client method, and the three "spoolmanMode ? undefined : ..." gates on
  the eraser buttons are gone.
2026-05-17 15:04:31 +02:00
maziggy 4a98914d4a fix(spoolman): persist Color Name via spool.extra — Spoolman has no filament.color_name field (#1357)
Reporter pgladel edited a spool's Color Name in Spoolman mode, hit
  Save, and saw the value snap back to the subtype on the next read.
  The earlier #1319 fix correctly handled the read/form-prefill half
  (the color_name_is_synthesized flag, blank-on-synth form init), but
  the write half assumed Spoolman has a `color_name` field on Filament.

  It doesn't. Verified against the live FilamentUpdateParameters schema
  on Spoolman 0.23.1 — the accepted fields are name, vendor_id, material,
  price, density, diameter, weight, spool_weight, article_number,
  comment, settings_extruder_temp, settings_bed_temp, color_hex,
  multi_color_hexes, multi_color_direction, external_id, extra. No
  color_name. Spoolman's PATCH happily returns 200 for
  {"color_name": "Red"} and silently discards the unknown key, so
  find_or_create_filament was either patching a void or creating
  filament after filament with the same field-that-doesn't-stick (which
  is what produced the "BB also created a bunch of new filaments"
  duplicate trail on each save attempt).

  The fix follows the same pattern as the existing BambuStudio slicer-
  preset storage: persist color_name on spool.extra.bambu_color_name as
  a JSON-encoded string, register the extra field via
  ensure_extra_field before write (Spoolman 400s on unknown extra keys),
  and read it back in _map_spoolman_spool with priority
  extra > filament.color_name (forward-compat for any future Spoolman
  release that adds the field) > subtype synth.

  Dropped the now-dead color_name passing through
  find_or_create_filament and create_filament — Spoolman would discard
  it anyway and keeping the dead pipe risked the same confusion the
  next time someone reads this code. The previous "match by name then
  patch color_name" loop is gone; what survives is the name-match
  resilience that lets an AMS-sync-created filament named "Glow" still
  match the user-driven edit's composed "PLA Glow", which prevents
  re-introducing the duplicate-filament trail.

  The frontend form's color_name_is_synthesized handling is unchanged
  — that part already worked.
2026-05-17 09:10:20 +02:00
a1d6fb22ae fix(spoolman): filter external library lookup by Bambu Lab manufacturer (#1330)
Bambuddy's external SpoolmanDB lookup in `_find_or_create_filament` matched
on material+color only, with no manufacturer filter. Because SpoolmanDB is a
multi-vendor catalog and entries are roughly ID-sorted, the first hit for
any common combination is almost always a competitor — `bambulab_pla_black_1000_175_n`
is the 15th entry for PLA + `#000000`. Bambu Lab RFID spools were being
labeled with competitor product names (`3DJAKE Black`, `3DXTECH™ Black`, etc).

Restrict the external-library loop to entries whose manufacturer is
`"Bambu Lab"` (with `id.startswith("bambulab_")` as a defensive fallback
for schema drift). When multiple Bambu Lab candidates exist, prefer the
entry whose `name` equals the AMS `tray_sub_brands` so `"PLA Basic"` wins
over generic `"Black"` when both are present. Forward `density` from the
chosen external entry so it is no longer overwritten by the PLA-default
1.24 in `create_filament`.

Six unit tests added: internal short-circuit preserved, non-Bambu external
entries skipped, PLA Basic > generic PLA tiebreaker, no-match fallback,
id-prefix defensive fallback, density propagation.

Fixes #1309

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: MartinNYHC <mz@v8w.de>
2026-05-14 09:14:24 +02:00
maziggy b8e350c3bf fix(spoolman): persist color_name edits and stop form round-tripping the subtype synth fallback (#1319)
Editing a spool's color name on Spoolman-backed inventory appeared to
  accept the new value but the inventory list column and the next edit
  showed it back to the subtype. Three layers stacked to produce this:

  1. find_or_create_filament matches by material/name/color_hex/vendor —
     color_name is intentionally not part of the match key, but on a
     match it returned the existing filament's id unchanged, silently
     dropping the new value.
  2. The read helper falls back to subtype when filament.color_name is
     empty (kept on purpose: without it Spoolman installs that don't
     fill the field render every spool as "Unknown color").
  3. The edit form prefilled color_name from spool.color_name — which
     on those installs was the synth value. Changing subtype but not
     color_name silently round-tripped the OLD subtype back to Spoolman
     as if it were a real user-set color_name.

  Fixes:
  - find_or_create_filament now patches the matched filament's
    color_name via the existing patch_filament wrapper when the request
    differs. Parameter convention: None = don't touch, "" = explicit
    clear, any other string = set/update. A patch failure is logged but
    does not block the match.
  - The PATCH route uses model_fields_set to distinguish "field omitted"
    from "field explicitly set to null" (mirrors the existing
    storage_location pattern at the same site).
  - The map helper returns color_name_is_synthesized: bool. The edit
    form leaves the input blank when true, so the user sees the real
    stored state and can't accidentally round-trip the synth value back.
2026-05-14 08:27:06 +02:00
MartinNYHC b30a283184 Feature/spoolman inventory UI (#1241)
feat(spoolman-inventory): squashed feature work for rebase onto dev

Squashed all commits from feature/spoolman-inventory-ui onto a single commit
to enable a clean rebase onto dev. Original per-commit history preserved at
backup tag backup/spoolman-inventory-ui-prerebase-20260507-105721.
2026-05-08 11:52:42 +02:00
MartinNYHC dac2a31192 Revert "feat(inventory): unified Spoolman inventory UI + AMS slot assignments…" (#1232)
This reverts commit 55d71498e9.
2026-05-07 11:30:31 +02:00
Sn0rrii 55d71498e9 feat(inventory): unified Spoolman inventory UI + AMS slot assignments + Storage Location + NFC write support + Spoolman Filament Catalog Picker (#1114)
feat(spoolman-inventory): squashed feature work for rebase onto dev

Squashed all commits from feature/spoolman-inventory-ui onto a single commit
to enable a clean rebase onto dev. Original per-commit history preserved at
backup tag backup/spoolman-inventory-ui-prerebase-20260507-105721.
2026-05-07 11:15:24 +02:00
maziggy 9e938cbc8c Revert "feat(inventory): unified Spoolman inventory UI + Storage Location + AMS deep-link + SpoolBuddy NFC write support (#1063)"
This reverts commit 89f14c57ad.
2026-04-24 14:33:33 +02:00
Sn0rrii 89f14c57ad feat(inventory): unified Spoolman inventory UI + Storage Location + AMS deep-link + SpoolBuddy NFC write support (#1063)
feat(inventory): replace Spoolman iframe with internal inventory UI

When Spoolman is enabled, the Inventory page now uses the same internal
UI (spool list, create/edit modal, archive, delete, weight sync) backed
by a new proxy layer instead of opening an iframe.
2026-04-24 14:00:45 +02:00
maziggy 9a0be3477e Fix ruff format for user_notifications and spoolman 2026-03-22 14:22:49 +01:00
Dakota G ac7cfe2930 [Fix]: Send Bambu RFID Tags to Spoolman, Allow Unlink in Manual Mode, Stop Location Clearing for Generic Spools (#719)
[Fix]: Send Bambu RFID Tags to Spoolman, Allow Unlink in Manual Mode, Stop Location Clearing for Generic Spools (#719)
2026-03-16 15:45:06 +01:00
Dakota G c52505cd3a [Fix]: Ensures AMS-HT devices are properly identified in Spoolman (#711)
[Fix]: Ensures AMS-HT devices are properly identified in Spoolman (#711)
2026-03-15 09:28:30 +01:00
maziggy 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 e3f3c90c3d Sync 2026-02-13 07:53:14 +01:00
maziggy a6f6df2e34 Sync fixes 2026-02-12 18:23:55 +01:00
bambuman c04df8ceb9 Add retry logic and connection resilience to Spoolman sync
Implements retry mechanism to handle intermittent network errors when
fetching spools cache for AMS sync operations.

Changes:
- Add retry logic to get_spools() with 3 attempts and 500ms delay
- Configure httpx client with connection pool limits to prevent stale
  connection reuse (max_keepalive_connections=5, keepalive_expiry=30s)
- Recreate client on connection errors (ReadError, RemoteProtocolError)
- Abort sync operations if cache fetch fails after all retries
- Update on_ams_change, sync_single_printer, and sync_all_printers to
  handle cache fetch failures gracefully

This addresses ReadError(ClosedResourceError()) failures that occurred
intermittently when Spoolman closed idle connections or connection
pooling reused stale connections.

Testing:
- Added 4 new unit tests for retry behavior
- All 1018 tests passing
2026-02-07 23:11:27 +02:00
bambuman deab81287f Optimize AMS Spoolman sync performance with spool caching
- Add cached_spools parameter to find_spool_by_tag, find_spools_by_location_prefix, sync_ams_tray, and clear_location_for_removed_spools
- Fetch spools once before loops in on_ams_change, sync_single_printer, and sync_all_printers endpoints
- Cache newly created spools during sync to avoid duplicate API calls
- Add 5 unit tests for caching functionality (all passing)
- Reduce redundant API calls when syncing multiple AMS trays
- Improve sync performance for users with large spool databases
- Maintain backward compatibility with optional cached_spools parameters
2026-02-07 22:29:52 +02: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
bambuman 6e82cc611e Add per-filament Spoolman usage tracking with G-code parsing
Implement accurate per-filament usage tracking for Spoolman integration,
similar to OpenSpoolman v0.3.0. This replaces the previous single-spool
reporting with multi-material aware tracking.

Features:
- Parse G-code from 3MF files at print start to build per-layer,
  per-filament cumulative extrusion maps
- Store tracking data in new `active_print_spoolman` database table
  (survives server restarts for long prints)
- Report accurate partial usage when prints fail/cancel based on
  actual layer progress and G-code data
- Add "Disable AMS Weight Sync" setting to prevent AMS percentage-based
  weight estimates from overwriting Spoolman's granular tracking
- Add "Report Partial Usage for Failed Prints" toggle (only shown when
  weight sync is disabled)
- Use Spoolman's filament density instead of defaults for mm-to-grams
  conversion
- Prefer tray_uuid over tag_uid for spool identification
2026-02-05 17:16:02 +02:00
maziggy 819ab896bd Fix Python 3.10 compatibility (Issue #269)
Replace datetime.UTC with timezone.utc for Python 3.10 support.
datetime.UTC was added in Python 3.11, but requirements state 3.10+.

Closes #269
2026-02-05 07:46:22 +01:00
maziggy 5004d94388 Fix Spoolman sync for transparent/natural filament spools
Transparent spools (like Natural PLA Support) report color "00000000"
which was being skipped as invalid. Now these spools are synced with
a light cream color (F5E6D3) that represents how natural PLA looks.

Fixes #190
2026-01-30 12:25:09 +01:00
maziggy 0caa68b77f Auto-create Spoolman 'tag' extra field on connect (Issue #123)
The 'tag' extra field is required in Spoolman for storing RFID/UUID
identifiers that link Bambu Lab spools to Spoolman entries. Previously,
users had to manually create this field in Spoolman, causing sync
failures for fresh installations.

Added ensure_tag_extra_field() method to SpoolmanClient that:
- Checks if the 'tag' field exists via GET /api/v1/field/spool/tag
- Creates it via POST if missing

The method is called automatically:
- On app startup when auto-connecting to Spoolman
- When user clicks "Connect" in Spoolman settings
2026-01-22 09:23:40 +01:00
maziggy 61c6473eca Fix Bambu Lab spool detection in Spoolman sync and AMS cards
The spool detection only checked tray_uuid and tag_uid, but some Bambu Lab
  spools have RFID read issues causing these to be missing while still having
  valid tray_info_idx (Bambu filament preset ID like "GFA00").

  Backend changes (backend/app/services/spoolman.py):
  - Add tray_info_idx to AMSTray dataclass
  - Parse tray_info_idx from raw MQTT data in parse_ams_tray()
  - Check tray_info_idx first in is_bambu_lab_spool() - most reliable indicator
  - Bambu Lab presets start with "GF" (GFA00, GFB00, GFL00, etc.)
  - Fall back to tray_uuid then tag_uid for unique spool identification
  - Add warning when Bambu spool detected but no unique ID for Spoolman

  Backend changes (backend/app/api/routes/spoolman.py):
  - Update /sync/{printer_id} and /sync-all to pass tray_info_idx
  - Guard against empty spool_tag when adding to tracking set

  Frontend changes (frontend/src/pages/PrintersPage.tsx):
  - Add isBambuLabSpool() helper with same detection logic as backend
  - Update all 4 vendor detection locations in AMS cards to use new helper

  Detection priority (same on frontend and backend):
  1. tray_info_idx starts with "GF" (Bambu preset ID)
  2. tray_uuid is valid 32-char hex (non-zero)
  3. tag_uid is valid 16-char hex (non-zero)
2026-01-15 16:23:09 +01:00
maziggy 6eedf55713 Fix Spoolman sync skipping Bambu Lab spools with missing tray_uuid
The spool detection logic only checked tray_uuid (32 hex chars) to identify
  Bambu Lab spools. Some spools have RFID read issues causing missing or
  invalid tray_uuid while still having valid tag_uid (16 hex chars).

  Changes:
  - Update is_bambu_lab_spool() to accept tag_uid as fallback parameter
  - Prefer tray_uuid for identification, fall back to tag_uid if invalid
  - Use whichever valid identifier for Spoolman tag storage and matching
  - Update both /sync/{printer_id} and /sync-all endpoints

  This fixes spools being incorrectly marked as "Non-Bambu Lab spool (no RFID
  tag)" when they have valid tag_uid but missing/zero tray_uuid.
2026-01-15 16:01:55 +01:00
maziggy b4bc046684 Clear Spoolman location when spool is removed from AMS
Previously, when syncing to Spoolman, the location field was set to the
  printer/AMS slot but was never cleared when the spool was removed from
  the AMS.

  Now during sync, the system tracks which tray UUIDs are currently in the
  AMS and clears the location for any spools that were previously at this
  printer but are no longer present.

  Changes:
  - Add clear_location parameter to update_spool() method
  - Add find_spools_by_location_prefix() to find spools at a printer
  - Add clear_location_for_removed_spools() to clear stale locations
  - Update sync_printer_ams and sync_all_printers endpoints to clear
    locations for removed spools after syncing
2026-01-09 07:43:40 +01:00
maziggy 8639f39028 Add resizable printer cards and Queue Only mode
Features:
  - Resizable printer cards (S/M/L/XL) with toolbar controls on Printers page
  - Queue Only mode for staging prints without automatic scheduling
    - "Queue Only" option in add/edit queue modals
    - Purple "Staged" badge and Play button to release to queue
    - manual_start field in database with migration

  Fixes:
  - Improved camera stream stuck detection with automatic reconnection

  Tests:
  - Added 16 integration tests for print queue API endpoints
2026-01-04 09:10:06 +01:00
maziggy d03fe7598f Fixed bug in Spoolman sync 2026-01-03 08:11:55 +01:00
maziggyandClaude Opus 4.5 a1c12331db Add Spoolman integration tests and update spool comment
Backend tests:
- 21 integration tests for all Spoolman API endpoints
- Status, connect/disconnect, spools, filaments, link, sync

Frontend tests:
- 20 component tests for SpoolmanSettings
- Rendering, disabled/enabled states, connection status, sync UI

Also changed auto-created spool comment to "Created by Bambuddy"

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-02 10:42:43 +01:00
maziggy 5b8d24f2ce - Spoolman: Add link spool feature, UUID display, and sync feedback
- Link to Spoolman: Manually link existing Spoolman spools to AMS trays
    - Hover over AMS slot to see "Link to Spoolman" button
    - Select from list of unlinked Spoolman spools
    - Automatically sets extra.tag field in Spoolman
  - Spool UUID display: View and copy Bambu Lab spool UUID in AMS hover card
    - Shows first 8 chars with copy button (full UUID to clipboard)
    - Fallback copy method for HTTP contexts
  - Sync feedback: Shows synced count and skipped spools with reasons
    - Expandable list when more than 5 skipped
    - Color swatches for identification
  - Fixed Spoolman 400 Bad Request: extra field values must be valid JSON
  - Updated documentation (wiki, website)
2026-01-02 09:20:24 +01:00
maziggy 83fc278b75 Fixed bug where not all AMS spools were synced to Spoolman 2025-12-10 10:02:11 +00:00
Martin Ziegler 8bc263ad02 Added Spoolman support to add unknown Bambu Lab spools and track them 2025-11-30 19:37:36 +01:00
Martin Ziegler a862958deb Added Spoolman support to add unknown Bambu Lab spools and track them 2025-11-30 19:30:14 +01:00