Browse Source

Added debug logging for printer's hour counter and current active AMS slot mapping

maziggy 4 months ago
parent
commit
53eff03fb5

+ 33 - 0
backend/app/api/routes/printers.py

@@ -1299,3 +1299,36 @@ async def refresh_ams_slot(
         raise HTTPException(400, message)
 
     return {"success": True, "message": message}
+
+
+@router.get("/{printer_id}/runtime-debug")
+async def get_runtime_debug(
+    printer_id: int,
+    db: AsyncSession = Depends(get_db),
+):
+    """Debug endpoint: Get runtime tracking status for a printer."""
+    result = await db.execute(select(Printer).where(Printer.id == printer_id))
+    printer = result.scalar_one_or_none()
+    if not printer:
+        raise HTTPException(404, "Printer not found")
+
+    state = printer_manager.get_status(printer_id)
+
+    return {
+        "printer_name": printer.name,
+        "runtime_seconds": printer.runtime_seconds,
+        "runtime_hours": printer.runtime_seconds / 3600.0 if printer.runtime_seconds else 0,
+        "print_hours_offset": printer.print_hours_offset,
+        "total_hours": (printer.runtime_seconds / 3600.0 if printer.runtime_seconds else 0)
+        + (printer.print_hours_offset or 0),
+        "last_runtime_update": printer.last_runtime_update.isoformat() if printer.last_runtime_update else None,
+        "mqtt_state": {
+            "connected": state.connected if state else False,
+            "state": state.state if state else None,
+            "progress": state.progress if state else None,
+            "gcode_file": state.gcode_file if state else None,
+        }
+        if state
+        else None,
+        "is_active": printer.is_active,
+    }

+ 18 - 1
backend/app/main.py

@@ -1597,7 +1597,11 @@ async def track_printer_runtime():
                 for printer in printers:
                     # Get current state from printer manager
                     state = printer_manager.get_status(printer.id)
-                    if not state or not state.connected:
+                    if not state:
+                        logger.debug(f"[{printer.name}] Runtime tracking: no state available")
+                        continue
+                    if not state.connected:
+                        logger.debug(f"[{printer.name}] Runtime tracking: not connected")
                         continue
 
                     # Check if printer is in an active state (RUNNING or PAUSE)
@@ -1610,14 +1614,27 @@ async def track_printer_runtime():
                                 printer.runtime_seconds += int(elapsed)
                                 updated_count += 1
                                 needs_commit = True
+                                logger.debug(
+                                    f"[{printer.name}] Runtime tracking: added {int(elapsed)}s, "
+                                    f"total={printer.runtime_seconds}s ({printer.runtime_seconds/3600:.2f}h)"
+                                )
+                            else:
+                                logger.warning(
+                                    f"[{printer.name}] Runtime tracking: skipped elapsed={elapsed:.1f}s "
+                                    f"(outside valid range 0-{RUNTIME_TRACKING_INTERVAL * 2}s)"
+                                )
                         else:
                             # First time seeing printer active - need to commit to save timestamp
                             needs_commit = True
+                            logger.debug(f"[{printer.name}] Runtime tracking: first active detection")
 
                         printer.last_runtime_update = now
                     else:
                         # Printer is idle/offline - clear last_runtime_update
                         if printer.last_runtime_update is not None:
+                            logger.debug(
+                                f"[{printer.name}] Runtime tracking: state={state.state}, clearing last_runtime_update"
+                            )
                             printer.last_runtime_update = None
                             needs_commit = True
 

+ 16 - 3
backend/app/services/bambu_mqtt.py

@@ -862,11 +862,24 @@ class BambuMQTTClient:
             logger.warning(f"[{self.serial_number}] Unexpected AMS data format: {type(ams_data)}")
             return
 
-        # Store AMS data in raw_data so it's accessible via API
-        self.state.raw_data["ams"] = ams_list
+        # Merge AMS data instead of replacing, to handle partial updates
+        # During prints, the printer may only send updates for active AMS units
+        existing_ams = self.state.raw_data.get("ams", [])
+        existing_by_id = {ams.get("id"): ams for ams in existing_ams if ams.get("id") is not None}
+
+        # Update existing units with new data, add new units
+        for ams_unit in ams_list:
+            ams_id = ams_unit.get("id")
+            if ams_id is not None:
+                existing_by_id[ams_id] = ams_unit
+
+        # Convert back to list, sorted by ID for consistent ordering
+        merged_ams = sorted(existing_by_id.values(), key=lambda x: x.get("id", 0))
+        self.state.raw_data["ams"] = merged_ams
+
         # Update timestamp for RFID refresh detection (frontend can detect "new data arrived")
         self.state.last_ams_update = time.time()
-        logger.debug(f"[{self.serial_number}] Stored AMS data with {len(ams_list)} units")
+        logger.debug(f"[{self.serial_number}] Merged AMS data: {len(ams_list)} new units, {len(merged_ams)} total")
 
         # Extract ams_extruder_map from each AMS unit's info field
         # According to OpenBambuAPI: info field bit 8 indicates which extruder (0=right, 1=left)

File diff suppressed because it is too large
+ 0 - 0
icons/5f21bc794a4e4521b72c6564029ed5d9.svg


File diff suppressed because it is too large
+ 0 - 0
icons/fc3b0d1fbe8b4815b0f7dbd92f3b68fd.svg


Some files were not shown because too many files changed in this diff