All notable changes to Bambuddy will be documented in this file.
orcaslicer://open?file= protocol. Default remains Bambu Studio for backward compatibility..orca_filament, .bbscfg, .bbsflmt, .zip, and .json exports. Resolves OrcaSlicer inheritance chains by fetching base Bambu profiles from GitHub (cached locally with 7-day TTL). Stores presets in the database with extracted core fields (material type, vendor, nozzle temps, pressure advance, compatible printers). New "Local Profiles" tab on the Profiles page with drag-and-drop import, 3-column layout (Filament/Process/Printer), search, and expandable preset details. Local filament presets appear in AMS slot configuration alongside cloud presets. Includes smart profile type detection (explicit type field, ZIP path hints, settings ID keys, content heuristics, and name-based patterns) and material/vendor extraction from preset names as fallback.printer.local, my-printer.home.lan) in addition to IPv4 addresses. Updated backend validation, frontend forms, and all locale labels.SkipObjectsModal component shared across PrintersPage and both camera views.tray_uuid over tag_uid for spool identification.HA_URL and HA_TOKEN environment variables for zero-configuration add-on deployments. Auto-enables when both variables are set. UI fields become read-only with lock icons when env-managed. Database values preserved as fallback.Spoolman Fill Level for AMS Lite / External Spools (#293) — AMS Lite (no weight sensor) always reported 0% fill level. Now uses Spoolman's remaining weight as a fallback when AMS reports 0%. External spools also show fill level from Spoolman data. Fill bars and hover cards indicate "(Spoolman)" when the data source is Spoolman rather than AMS.
Extended Support Bundle Diagnostics — Support bundle now collects comprehensive diagnostic data for faster issue resolution: printer connectivity and firmware versions, integration status (Spoolman, MQTT, Home Assistant), network interfaces (subnets only), Python package versions, database health checks, Docker environment details, WebSocket connections, and log file info. All data properly anonymized — no IPs, names, or serials included. Privacy disclosure updated on System Info page.
active_extruder, replacing the misleading "Docked" label.firmware:read and firmware:update permissions. Translations added in all 4 locales.ja.ts from a divergent format (different key structure, 12 structural conflicts, 1,366 missing translations) to match the English/German locale structure exactly. Translated all 2,083 keys into Japanese, achieving full parity with EN/DE. Zero structural divergences, zero missing keys.h2d), causing firmware checks to offer H2D firmware instead of H2C firmware. H2C has its own firmware track (01.01.x.x vs H2D's 01.02.x.x). Added separate h2c API key mapping. Also added missing H2C/H2S entries to printer model ID and 3MF model maps.invert() filter. The filter was intended for monochrome preset icons but was incorrectly applied to user-uploaded images (e.g., full-color logos). Removed the invert filter from custom icon rendering in the sidebar and the add/edit link modal.[Errno 104] Connection reset by peer while the small verify_job always succeeded. The _handle_data_connection callback returned immediately, allowing the asyncio server-handler task to complete while the data connection was still in active use. The passive port listener also stayed open during transfers, risking duplicate data connections. Fixed by keeping the callback alive until the transfer completes (_transfer_done event), closing the passive listener after accepting the connection, and rejecting duplicate data connections. Also added a 5-second drain timeout to MQTT status pushes to prevent blocking when the slicer is busy uploading.remote_interface_ip setting (network interface override) was only used in proxy mode, but users with multiple network interfaces (LAN + Tailscale, Docker bridges) also needed it in server modes (immediate/review/print_queue). Auto-detected IP from _get_local_ip() followed the OS default route, causing wrong IP in TLS certificate SAN (handshake failures) and SSDP broadcasts (slicer can't discover printer). Now the interface override applies to all modes: included in certificate SAN, passed to SSDP server as advertise IP, and triggers service restart on change. UI dropdown shown for all modes when enabled (not just proxy).subtask_name and never invalidated between prints, so a cache hit returned the stale first-print thumbnail. Now the cover cache is cleared on every print start./usr/etc/print/auto_cali_for_user.gcode) and other internal printer files under /usr/ are now detected and skipped during print start.sendBeacon) failed with 401 Unauthorized when authentication was enabled because sendBeacon cannot send auth headers. Replaced with fetch + keepalive: true which supports Authorization headers while remaining reliable during page unload.filament_used_grams by print quantity, even though the value already represents the total for the entire job. A 26-object print using 126g was counted as 3,276g. Removed the erroneous multiplier from three aggregations in FilamentTrends.tsx.homeassistant_service was not configured with HA URL/token before querying plug energy data, causing it to silently return nothing.use_ams: 1 (integer) as a nozzle index, routing filament to the deputy nozzle instead of the main nozzle. Bambu Studio sends use_ams: true (boolean) while using integers for other fields. Fixed by keeping use_ams as boolean for all printers including H2D series.ams_unit_count: 0 because it expected raw_data["ams"] to be a nested dict ({"ams": [...]}) but the MQTT handler stores it as a flat list. Now handles both formats.latest_version, since there is nothing to compare against.ams_id * 4 + tray_id (= 512), but AMS-HT uses the raw ams_id (128) since it has a single tray. The backend then misidentified 512 as an external spool. Fixed in frontend tray ID calculation, backend ams_mapping2 builder, print scheduler, and Spoolman tracking.id - 16). Filament colors and materials were missing because the H2C uses different MQTT field names (color_m, fila_id, sn, tm) than the H2D (filament_colour, filament_id, serial_number, max_temp). Added fallback field name resolution. Also fixed nozzle rack layout breaking on medium card size by allowing the temperature row to wrap.mock_ftp_server.py) implements implicit TLS, custom AVBL command, and per-command failure injectiontransfercmd(), progress callbacks, 553/550/552 error handlingerror_perm hierarchy, diagnose_storage CWD propagation, injection count decrementpyOpenSSL to requirements-dev.txt for Docker test image compatibilitydiagnose_storage() was running before every upload, and its CWD failures (ftplib.error_perm) were not caught because error_perm is not a subclass of error_replydiagnose_storage() from the upload hot pathexcept (OSError, ftplib.error_reply) to except (OSError, ftplib.Error) to catch all FTP error types/api/v1/archives/{id}/reprint and /api/v1/library/files/{id}/print caused by the FTP failure above/api/v1/printers/{id}/cover when FTP download returned 0 bytes but reported success; now retries and falls back to 4040.1.8.1 for hotfixes without incrementing the minor versionxml.etree.ElementTree with defusedxml across all 3MF parsing code../ sequences.codeql/python-bambuddy.qls, .codeql/javascript-bambuddy.qls) with documented accepted-risk exclusions%s style across all backend filesexcept Exception blocks to specific types (OSError, KeyError, ValueError, zipfile.BadZipFile, sqlalchemy.exc.OperationalError, etc.)str(e) with generic error messages in HTTP responses (updates.py)homeassistant.py)tasmota.py)usedforsecurity=False to non-security hash calls (MD5 for AMS fingerprinting, SHA1 for git blob format)test_security.sh uses --threads=0 for all CodeQL commands (auto-detects CPU cores).trivyignore to suppress accepted Dockerfile USER directive findingAmbientCapabilities=CAP_NET_BIND_SERVICE capabilityfilament_used_grams field already contains the total for the entire print job* quantity multiplication from archive stats, Prometheus metrics, and FilamentTrends charttray_info_idx (filament type identifier)tray_info_idx (e.g., "GFA00" for generic PLA) identifies filament TYPE, not unique spoolsfind() which always returned the first match regardless of colorstorbinary() with manual chunked transfer using transfercmd()storbinary() waiting for completion responsePUID=$(id -u) PGID=$(id -g) docker compose up -dstart_bambuddy.bat for Windows users - double-click to run, no installation required.portable\ folder for easy cleanupstart_bambuddy.bat (launch), start_bambuddy.bat update (update deps), start_bambuddy.bat reset (clean start)set PORT=9000 & start_bambuddy.batRequirePermissionIfAuthEnabled() for permission checks<img> tags which cannot send Authorization headers/api/v1/spoolman/spools/linked endpoint returning map of linked spool tags to IDsscript.* entities; now shows all HA entities with toggle enabledfilament_used_grams by quantity/archives/stats) and Prometheus metrics also fixedfetch() without Authorization headerformatDateInput, parseDateInput, getDatePlaceholderformatTimeInput, parseTimeInput, getTimePlaceholderproject relationship not eagerly loaded in get_archive() service methodSecurity Release: This release addresses critical security vulnerabilities. Users running authentication-enabled instances should upgrade immediately.
JWT_SECRET_KEY environment variable (recommended for production).jwt_secret file in data directory with secure permissions (0600)/api/ routes when auth is enabled*_own and *_all variants:queue:update_own / queue:update_allqueue:delete_own / queue:delete_allarchives:update_own / archives:update_allarchives:delete_own / archives:delete_allarchives:reprint_own / archives:reprint_alllibrary:update_own / library:update_alllibrary:delete_own / library:delete_all*_all permissions (can modify any items)*_own permissions (can only modify their own items)*_all permissioncreated_by_id columns to print_archives, library_files, and print_queue tablesprinters:ams_rfid permission for re-reading AMS RFID tagsqueue:create permission for users with restricted access?fps=30 parameter to control camera frame rate (1-30, default 15)?camera=false parameter to hide camera and show only status overlay on black backgroundlibrary:read permission for File Manager endpoints:
library:read permission check to all list/view endpoints (files, folders, stats)library:upload permission check to upload and folder creation endpointsqueue:create permission check to add-to-queue endpointprinters:control permission check to direct print endpointlibrary:read permission can no longer view files in the File Manager*_all permissions<img> don't send Authorization headersams_mapping2 slot_id handling that caused AMS mapping failuresskip_session_reuse to ImplicitFTP_TLSsliced_for_model column that was missing in some upgrade paths/overlay/:printerId combining camera feed with status overlay?size=small|medium|large and ?show=progress,layers,eta,filename,status,printerpower_l1, data.power)GET /api/v1/printers/usb-cameras)GET /api/v1/metrics (Prometheus text format)/api/settings for Home Assistant rest_command compatibility (Issue #152)/ to search paths when looking for 3MF files/cachetray_exist_bits bitmask to detect and clear empty slotsGET /api/v1/smart-plugs/ha/sensors to list available energy sensors{finish_photo_url} template variable for print_complete, print_failed, print_stopped eventscompleted_at - started_at) instead of slicer estimates; cancelled prints only count time actually printed (Issue #137){"text": "..."} instead of custom fields (Issue #133)library_file_id directlyselectedFolderId from useEffect dependency array that was causing a reset looptray_info_idx from the preset's base_id when filament_id is null