Verbessere die MQTT-Verbindung und Statusverarbeitung in BambuVirtualPrinter mit robusteren Wiederverbindungsversuchen und erweiterter Statusverarbeitung für unbekannte Druckzustände.

This commit is contained in:
Manuel Weiser 2025-03-02 16:26:50 +01:00
parent 8dafb9fa5a
commit fd9ce76275

View File

@ -114,6 +114,14 @@ class BambuMqttBridgeClient:
self._log.warning(f"Disconnected from MQTT broker with code: {rc}")
self.connected = False
# Add reconnection attempt
if rc != 0: # Non-zero means unexpected disconnect
self._log.info("Attempting to reconnect to MQTT broker...")
try:
self._mqtt_client.reconnect()
except Exception as e:
self._log.error(f"Failed to reconnect to MQTT broker: {str(e)}", exc_info=True)
if hasattr(self, 'on_disconnect') and callable(self.on_disconnect):
self.on_disconnect(client, userdata, rc)
@ -217,6 +225,16 @@ class BambuMqttBridgeClient:
# Wait a bit for the connection to establish
time.sleep(1)
# If not connected after waiting, try again
if not self.connected:
self._log.warning("Initial connection attempt failed, retrying...")
try:
self._mqtt_client.reconnect()
time.sleep(2) # Wait a bit longer for retry
except Exception as e:
self._log.error(f"Reconnection failed: {str(e)}", exc_info=True)
return self.connected
except Exception as e:
self._log.error(f"Failed to connect to MQTT broker: {str(e)}", exc_info=True)
@ -392,14 +410,13 @@ class BambuVirtualPrinter:
self._log.debug(f"Current temperatures - Nozzle: {self._telemetry.temp[0]}/{self._telemetry.targetTemp[0]}, " +
f"Bed: {self._telemetry.bedTemp}/{self._telemetry.bedTargetTemp}, " +
f"Chamber: {self._telemetry.chamberTemp}")
if print_job_state == "IDLE" or print_job_state == "FAILED":
self.change_state(self._state_idle)
elif print_job_state == "RUNNING" or print_job_state == "PREPARE":
self.change_state(self._state_printing)
elif print_job_state == "PAUSE":
self.change_state(self._state_paused)
# Process the printer state even if it's "unknown"
if print_job_state:
self._process_print_state(print_job_state)
else:
self._log.warn(f"Unknown print job state: {print_job_state}")
self._log.debug("No printer state received, skipping state processing")
elif event_type == "event_hms_errors":
self._log.debug("Received event_hms_errors")
bambu_printer = self.bambu_client.get_device()
@ -643,8 +660,9 @@ class BambuVirtualPrinter:
# oder andere Werte haben als die, die wir erwarten
print_job_state = print_job_state.upper() if print_job_state else "UNKNOWN"
# Normalisieren des Status, falls er 'unknown' ist oder nicht erkannt wird
if print_job_state in ["UNKNOWN", ""]:
# Explicitly handle "unknown" state (both upper and lowercase)
if print_job_state in ["UNKNOWN", ""] or print_job_state.upper() == "UNKNOWN":
self._log.debug("Detected 'unknown' printer state, trying to determine actual state")
# Wenn wir keinen erkannten Status haben, versuchen wir ihn aus anderen Daten abzuleiten
# Prüfe ob Druckfortschritt vorhanden ist
if self.current_print_job and self.current_print_job.print_percentage > 0:
@ -654,6 +672,9 @@ class BambuVirtualPrinter:
elif self._telemetry.targetTemp[0] > 150 or self._telemetry.bedTargetTemp > 40:
print_job_state = "PREPARE"
self._log.debug(f"Changed unknown state to PREPARE based on target temperatures")
else:
self._log.debug("Keeping state as IDLE since no indicators for print activity were found")
print_job_state = "IDLE" # Default to IDLE if we can't determine state
# Status im PrintJob aktualisieren
if self.current_print_job is None and print_job_state in ["RUNNING", "PREPARE", "PAUSE"]:
@ -704,6 +725,8 @@ class BambuVirtualPrinter:
self._bambu_client.device.print_job.gcode_state = print_job_state
except Exception as e:
self._log.error(f"Error processing print state: {e}", exc_info=True)
# Default to a safe state in case of errors
self.change_state(self._state_idle)
def _process_direct_temperature_data(self, print_data):
"""Verarbeitet Temperaturdaten direkt aus dem print-Objekt"""
@ -866,8 +889,33 @@ class BambuVirtualPrinter:
bambu_client.on_disconnect = self.on_disconnect(bambu_client.on_disconnect)
bambu_client.on_connect = self.on_connect(bambu_client.on_connect)
bambu_client.connect(callback=self.new_update)
self._log.info(f"bambu connection status: {bambu_client.connected}")
# Add more robust connection retry logic
connection_attempts = 0
max_attempts = 3
retry_delay = 2
while connection_attempts < max_attempts:
try:
self._log.info(f"Connection attempt {connection_attempts + 1}/{max_attempts}...")
bambu_client.connect(callback=self.new_update)
# Wait a moment to verify connection
time.sleep(retry_delay)
if bambu_client.connected:
self._log.info(f"Bambu connection successful: {bambu_client.connected}")
break
self._log.warning("Connection attempt failed, retrying...")
connection_attempts += 1
time.sleep(retry_delay)
except Exception as e:
self._log.error(f"Error during connection attempt {connection_attempts + 1}: {str(e)}", exc_info=True)
connection_attempts += 1
if connection_attempts < max_attempts:
time.sleep(retry_delay)
self.sendOk()
self._bambu_client = bambu_client
@ -1272,32 +1320,44 @@ class BambuVirtualPrinter:
def close(self):
"""Safely close all connections."""
try:
# Log that we're starting to close connections
self._log.debug("Starting to close all connections...")
if self._mqtt_client and self._mqtt_connected:
self._log.debug("Stopping MQTT client loop and disconnecting...")
self._mqtt_client.loop_stop()
self._mqtt_client.disconnect()
self._mqtt_connected = False
self._custom_connected = False
self._log.debug("MQTT client disconnected")
# Sicherstellen, dass wir keinen AttributError bekommen, wenn wir den BambuClient trennen
if self._bambu_client:
self._log.debug("Disconnecting BambuClient...")
try:
self._bambu_client.disconnect()
self._log.debug("BambuClient disconnected successfully")
except AttributeError:
# BambuClient hat keinen client-Attribut oder die disconnect-Methode funktioniert nicht wie erwartet
self._log.warning("BambuClient disconnect failed, cleaning up manually")
# Manuell aufräumen
if hasattr(self._bambu_client, '_mqtt_client') and self._bambu_client._mqtt_client:
try:
self._log.debug("Manually stopping BambuClient's MQTT client...")
self._bambu_client._mqtt_client.loop_stop()
self._bambu_client._mqtt_client.disconnect()
except:
pass
self._log.debug("BambuClient's MQTT client manually disconnected")
except Exception as ex:
self._log.error(f"Error during manual MQTT client cleanup: {str(ex)}")
except Exception as e:
self._log.error(f"Error during close: {e}", exc_info=True)
finally:
# Immer in einen sicheren Zustand zurückkehren
self._log.debug("Final cleanup in close() method")
self.change_state(self._state_idle)
self._serial_io.close()
self.stop()
self._log.debug("Connection cleanup completed")
def stop(self):
self._running = False