Browse Source

fix: inventory spool weight_used reset by AMS remain% sync

The on_ams_change() handler recalculated weight_used from the AMS
remain% sensor on every status update, overwriting precise values
from the usage tracker. For small prints on large spools (e.g. 1.6g
on 1000g), the integer-resolution sensor (10g steps) still reported
100% remain, resetting weight_used back to 0. The sync now only
increases weight_used, never decreases it.
maziggy 3 months ago
parent
commit
d67f1a1c03
2 changed files with 7 additions and 3 deletions
  1. 1 0
      CHANGELOG.md
  2. 6 3
      backend/app/main.py

+ 1 - 0
CHANGELOG.md

@@ -25,6 +25,7 @@ All notable changes to Bambuddy will be documented in this file.
 - **AMS Slot Configuration Overwrites RFID Spool State** — Configuring an AMS slot for an RFID-detected Bambu Lab spool sent `ams_set_filament_setting`, which replaced the firmware's RFID-managed filament config with a manual one — causing the slicer's "eye" icon to change to a "pen" icon. Now detects RFID spools and skips the filament setting command, only sending K-profile selection.
 - **K-Profile Selection Corrupts Existing Profiles on X1C/P1S** — The `extrusion_cali_sel` command included a `setting_id` field that BambuStudio never sends, causing firmware to mislink calibration data. The `extrusion_cali_set` command was sent unconditionally, overwriting existing profile metadata. Now `setting_id` is removed from selection commands, and `extrusion_cali_set` is only sent when no existing profile is selected (`cali_idx < 0`).
 - **AMS Slot Configure — Black Filament Color Not Pre-Populated** — When re-opening the Configure AMS Slot modal for a slot with black filament, the color field was empty despite the preset and K-profile being correctly pre-selected. The color pre-population logic excluded hex `000000` (black) as a guard against empty slots, but empty slots already skip color data entirely. Removed the unnecessary check so black is now pre-populated like any other color.
+- **Inventory Spool Weight Resets After Print Completes** — After a print, the usage tracker correctly updated `weight_used` (e.g., +1.6g), but periodic AMS status updates recalculated `weight_used` from the AMS remain% sensor and overwrote the precise value. For small prints on large spools (e.g., 1.6g on 1000g), the AMS remain% stays at 100% (integer resolution = 10g steps), resetting `weight_used` back to 0. The AMS weight sync now only increases `weight_used`, never decreases it, preserving precise values from the usage tracker.
 
 ### Improved
 - **SQLite WAL Mode for Database Reliability** — Database now uses Write-Ahead Logging (WAL) mode with a 5-second busy timeout, reducing "database is locked" errors under concurrent access. WAL mode allows simultaneous reads during writes, improving responsiveness for multi-printer setups. Automatically enabled on startup.

+ 6 - 3
backend/app/main.py

@@ -675,7 +675,9 @@ async def on_ams_change(printer_id: int, ams_data: list):
                         )
                         existing_assignment = existing.scalar_one_or_none()
                         if existing_assignment:
-                            # Sync spool weight_used from AMS remain if valid
+                            # Sync spool weight_used from AMS remain — only INCREASE, never decrease.
+                            # The AMS remain% is low-resolution (integer %, i.e. 10g steps for 1kg spool)
+                            # and must not overwrite precise values from the usage tracker (3MF/G-code).
                             remain_raw = tray.get("remain")
                             if remain_raw is not None and existing_assignment.spool:
                                 try:
@@ -685,11 +687,12 @@ async def on_ams_change(printer_id: int, ams_data: list):
                                 if 0 <= remain_val <= 100:
                                     lw = existing_assignment.spool.label_weight or 1000
                                     new_used = round(lw * (100 - remain_val) / 100.0, 1)
-                                    if abs((existing_assignment.spool.weight_used or 0) - new_used) > 1:
+                                    current_used = existing_assignment.spool.weight_used or 0
+                                    if new_used > current_used + 1:
                                         logger.info(
                                             "Weight sync: spool %d weight_used %s -> %s (remain=%d)",
                                             existing_assignment.spool_id,
-                                            existing_assignment.spool.weight_used,
+                                            current_used,
                                             new_used,
                                             remain_val,
                                         )