P2S uses hardened steel rods, not carbon fiber. Move P2S from
carbon rod classification to new steel_rod category with its own
"Lubricate Steel Rods" / "Clean Steel Rods" maintenance tasks.
Add {eta} template variable showing wall-clock completion time
(e.g. "15:53" or "3:53 PM") to print_start, print_progress, and
queue_job_started notifications. Respects the user's time_format
setting (12h/24h). The existing {estimated_time} variable continues
to show duration ("1h 23m").
visibility into AMS spool assignments on printer cards without exposing
the full Inventory page (#635). The list_assignments endpoint now
requires this new permission instead of inventory:read. All default
groups (Administrators, Operators, Viewers) include it for backward
compatibility.
Closes#634
The print dispatch progress toast stayed visible forever after the
second print in a session. lastDispatchSummaryRef was never reset
between batches — every single-printer dispatch produced the same
summary key ("first-complete:1:0"), so subsequent completions matched
the stale ref and skipped creating the done toast.
Reset the dedup guard when the dispatch toast is dismissed and when
a new batch starts.
The print dispatch notification disappeared instantly for small files or
closed immediately when the progress bar reached 100%, giving no
confirmation that the job was submitted. The dispatch toast now stays
visible for 3 seconds showing the completion message before auto-
dismissing. For very fast uploads where no progress toast was shown,
a fresh confirmation toast is created instead.
When printing from the file manager, the print modal showed all printers
including busy ones. Selecting a busy printer resulted in a failed send.
The printer selector now fetches live status for each printer and shows
state badges (Idle, Printing, Paused, etc.). In reprint mode, non-available
printers (anything other than IDLE, FINISH, FAILED) are grayed out and
not selectable. "Select all" skips them. Queue/edit modes still allow
selecting busy printers since the job will wait.
Resize PWA icons to match their declared dimensions (192x192, 512x512,
180x180), split discouraged "any maskable" icon purpose, and add mobile
and desktop screenshots to manifest.json for Chrome's richer install UI.
Files added to a project from the archive (status="archived") were
incorrectly counted in completed_prints and parts_progress stats.
Only status="completed" (actually printed) now counts toward completion.
Replace all hardcoded English strings with t() translation calls across
9 components: SettingsPage, SmartPlugCard, AddSmartPlugModal,
SwitchbarPopover, NotificationProviderCard, AddNotificationModal,
NotificationTemplateEditor, NotificationLogViewer, GitHubBackupSettings,
and RestoreModal. Add ~600 new translation keys to all 7 locales
(en, de, ja, fr, it, pt-BR, zh-CN).
All filament mapping dropdowns (single-printer, multi-printer, and
"Print to Any" model-based) showed only the base material type (e.g.
"PLA") without distinguishing subtypes like "PLA Basic" vs "PLA Matte",
making entries with different subtypes but same color look identical.
Backend: Add tray_sub_brands to available-filaments response and include
it in the dedup key so different subtypes of the same color appear as
separate entries.
Frontend: Show tray_sub_brands in FilamentMapping, FilamentOverride, and
PrinterSelector dropdowns, falling back to base type when unset. Add
traySubBrands field to LoadedFilament interface.
Sync all locale files to match EN's 3,054-key structure:
- it: add 485 missing keys, remove 1 stale key
- pt-BR: add 51 missing keys, remove 10 stale keys
- fr: add 47 missing keys
- ja: add 47 missing keys, remove 116 stale keys
- zh-CN: add 25 missing keys, remove 1 stale key
All 655 new keys are properly translated.
Stale keys from past refactors are cleaned up (127 total removed).
The per-printer InlineMappingEditor showed filaments from both nozzles
on H2D printers. The single-printer FilamentMapping dropdown was fixed
in 29e9593 but the multi-printer code path was missed. Added nozzle_id
filtering to both auto-match logic and dropdown options via shared
autoMatchFilament() and filterFilamentsByNozzle() functions in
amsHelpers.ts, with 10 regression tests.
Two lazy-load bugs caused greenlet_spawn errors in the RFID auto-assign
flow:
1. create_spool_from_tray set spool.k_profiles=[] AFTER db.flush(),
but assigning to a relationship on a persistent object triggers a
lazy load (SQLAlchemy loads the current collection before replacing).
Moved initialization to BEFORE db.add().
2. spool.assignments was never initialized or eagerly loaded, so
db.add(SpoolAssignment) triggered a back_populates lazy load
outside the async greenlet. Added assignments=[] in create and
selectinload(Spool.assignments) in get_spool_by_tag.
Also added exc_info=True to error handlers for full tracebacks, and
19 new tests including greenlet regression tests that reproduce the
exact failure.
The install script hardcoded origin/main, so beta testers told to
install from a dev branch silently got the stable release instead.
Add a --branch CLI option and interactive prompt (defaults to main).
Invalid branch names are validated via git ls-remote before any work
is done, showing available branches on failure.
The install script hardcoded origin/main, so beta testers told to
install from a dev branch silently got the stable release instead.
Add a --branch CLI option and interactive prompt (defaults to main).
Fresh installs use git clone --branch, existing installs checkout
and reset to the selected branch.
enum.StrEnum was added in Python 3.11, but the documented minimum is
3.10. Add a compatibility shim in backend/app/core/compat.py that falls
back to (str, Enum) on older versions. Updated all 5 import sites and
lowered pyproject.toml target-version to py310.
Bambu printers only support plain RSA key exchange ciphers
(AES256-GCM-SHA384, AES128-GCM-SHA256), but Python's OpenSSL 3.x
defaults exclude them in favor of forward-secrecy (ECDHE/DHE) only.
Add the RSA ciphers to the client SSL context so the TLS proxy can
connect to the printer's bind port (3002).
Move the toast container from bottom-4 to bottom-20 so toast
notifications and upload progress stack above the bug report bubble
instead of rendering on top of each other.
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.
- Add 12 backend integration tests for AMS labels API (GET/PUT/DELETE,
serial resolution, synthetic key fallback, whitespace handling, validation)
- Add 10 frontend tests for FilamentSlotCircle component (rendering,
border styles, background colors, text contrast inversion)
- Fix ruff W293 trailing whitespace in inventory.py from contributor fix
- Add ams_label model import to test conftest.py
- Update CHANGELOG, README, website features page, and wiki AMS docs
* AMS Labels addition to PrintersPage
* Added database reinitialization for schema migrations on database restore
* Bug fixes and AMS Label persistence updates
* Update database.py to resolve PR conflicts
* PR Comment Resolution
* Resolve conflicts in database.py for PR#570
* Updates to address PR#570 additional comments
* Optimize visibility handling for popup component
* Improve serial key handling in printers.py
Refactor serial key assignment to handle empty AMS serial gracefully.
* Implement error handling in serial number mapping
Add error handling for serial number mapping.
* Add migration to drop old ams_labels table
---------
Co-authored-by: MartinNYHC <mz@v8w.de>
On Windows, process.terminate() on ffmpeg broadcasts CTRL_C_EVENT to
the entire process group, causing uvicorn to shut down. Spawn ffmpeg
with CREATE_NEW_PROCESS_GROUP so cleanup doesn't affect the server.
* Fix AMS slot modal not scrolling to preselected filament
The scroll useEffect fired before the loading spinner was replaced
by the preset list, so the DOM element didn't exist yet. The ref
guard was then set, preventing any retry once buttons appeared.
- Move isLoading computation before the scroll effect and add it
as a dependency so the effect re-runs when loading completes
- Gate scroll on !isLoading so it only runs when buttons exist
- Only mark scrolledToRef after the element is actually found
- Use requestAnimationFrame to scroll after browser layout
- Use block:'center' so the selected item is clearly visible
Preselect filament for printer-configured AMS slots
When an AMS slot was configured directly on the printer (no
savedPresetId), the modal didn't preselect the filament even though
it was in the list. Add a third fallback that matches trayInfoIdx
against the full filteredPresets list (cloud and builtin sources).
* Restore scrolledToRef lost during merge
The useRef import, scrolledToRef declaration, and its reset were
dropped during the 0.2.2b1 merge, causing a ReferenceError in the
scroll-to-preselected-filament effect.
* Fix preset scroll loop and wire up useEffect scroll logic
- Remove inline ref callbacks with scrollIntoView on both preset
button lists (fullscreen + standard) to stop the infinite scroll
loop on Windows
- Add data-preset-id attribute so the existing useEffect/querySelector
scroll logic can actually find the elements
- Replace filteredPresets dependency with builtinFilaments in the
selection useEffect to prevent search keystrokes from overriding
manual preset selection
* Adjust scroll behavior in ConfigureAmsSlotModal
---------
Co-authored-by: MartinNYHC <mz@v8w.de>
Floating bug report button submits issues via bambuddy.cool relay (no GitHub
token needed locally). Collects 30s debug logs with printer push_all, sanitizes
all sensitive data, uploads logs as files to GitHub. Screenshot upload/paste/drag
with JPEG compression. Translated into all 7 languages. Includes 21 tests.
Parse home_flag bit 18 (0x00040000) from MQTT to detect ethernet
connections. When set, the printer card shows a green "Ethernet"
badge with a cable icon instead of WiFi signal strength in dBm.
The printer info modal also displays "Ethernet" instead of WiFi
signal details.
The firmware check only mapped display names (e.g., "H2D Pro") to
API keys but not raw SSDP device codes (e.g., "O1E", "O2D"). If a
printer's model was stored as the raw SSDP code, the firmware check
either failed or matched the wrong model — H2D Pro matched against
H2D firmware, showing a false update-available badge.
Add all known SSDP device codes to MODEL_TO_API_KEY so firmware
versions resolve correctly regardless of how the model was stored.
The previous fix only filtered status codes (< 0x4000) from the
print_error field. Firmware can also send the same false positive
through the hms array in MQTT, which had no such filter. Apply the
same < 0x4000 check to the HMS parser so status/phase indicators
are skipped regardless of which MQTT field carries them.
- Extract shared detectSystemDateFormat() helper to eliminate
duplicated system locale detection in date.ts
- Derive SUPPORTED_CURRENCIES from CURRENCY_SYMBOLS map instead
of maintaining a duplicate hardcoded list
- Consolidate redundant time-parsing regex paths into one
- Use applyTimeFormat() consistently in formatETA()
- Add exhaustive switch default for type safety
The isSlicedFile() check only matched .gcode or .gcode.3mf extensions,
so archives from .3mf prints (the standard Bambu slicer output) showed
a "SOURCE" badge instead of "GCODE". Since .3mf can be either sliced or
a raw CAD export, now checks the archive's total_layers and
print_time_seconds metadata to distinguish them. Also passes the
original filename when creating archives from file manager prints.
FTP upload: reduce chunk size from 1MB to 64KB for smooth progress bar
updates (~1s intervals instead of 20+ second gaps). Skip voidresp() for
all printer models — H2D delays the 226 response by 30+ seconds after
data transfer, causing a hang at 100%. Add transfer speed and TLS
handshake timing to logs for diagnosing slow connections.
Print/Schedule modal: widen from max-w-lg (512px) to max-w-2xl (672px)
to accommodate long filament profile names like "PLA Support for PETG
PETG Basic @Bambu Lab H2D 0.4 nozzle".
Profiles like "PLA Support for PETG PETG Basic @Bambu Lab H2D" have
filament_type PETG, but both the frontend and backend name parsers
found "PLA" first (iterating material types in order). The MQTT command
sent tray_type=PLA and tray_info_idx=GFL99 (PLA generic), so the
slicer displayed PLA instead of PETG.
- Frontend parsePresetName(): detect "X Support for Y" pattern, extract
material after "Support for"
- Frontend ConfigureAmsSlotModal: prefer corrected parsed material over
stored localPreset.filament_type for tray_type, tray_info_idx, and
temperature fallback
- Backend _parse_material_from_name(): same "Support for" handling for
future profile imports
- Backend assign_spool: prioritize spool.material over lp.filament_type
for generic filament ID lookup
The slicer_binary_path key was left in the settings table from earlier
slicer integration research but is no longer referenced anywhere in the
codebase. Add a startup migration step that deletes orphaned settings
keys so they don't persist in backups.