Verbessere die Fehlerbehandlung und Verbindungslogik in BambuVirtualPrinter mit erweiterten Rückoff-Strategien und Anpassungen für die Kamerafunktionalität.

This commit is contained in:
Manuel Weiser 2025-03-02 16:36:17 +01:00
parent c5c6ed037e
commit a8cf4957ec

View File

@ -335,6 +335,16 @@ class BambuVirtualPrinter:
self._mqtt_connected = False self._mqtt_connected = False
self._bambu_client = None self._bambu_client = None
self._custom_connected = False self._custom_connected = False
# Store initial connection errors to avoid logging the same errors repeatedly
self._connection_error_logged = False
self._camera_error_logged = False
self._last_connection_attempt = 0
self._connection_retry_backoff = 10 # Start with 10 seconds between retries
# Track if we should disable camera functionality due to persistent errors
self._disable_camera = self._settings.get_boolean(["disable_camera"]) or False
self._bambu_client: BambuClient = self._create_client_connection_async() self._bambu_client: BambuClient = self._create_client_connection_async()
@property @property
@ -458,6 +468,12 @@ class BambuVirtualPrinter:
client.subscribe(device_topic) client.subscribe(device_topic)
self._log.debug(f"Subscribed to topic: {device_topic}") self._log.debug(f"Subscribed to topic: {device_topic}")
self._log.info(f"MQTT connection successful. Connected: {self.is_connected}") self._log.info(f"MQTT connection successful. Connected: {self.is_connected}")
# Try to patch client for better error handling after successful connection
try:
self._patch_bambu_client_for_connection_errors()
except Exception as e:
self._log.warning(f"Failed to patch BambuClient for better error handling: {str(e)}")
else: else:
self._mqtt_connected = False self._mqtt_connected = False
self._custom_connected = False self._custom_connected = False
@ -871,21 +887,43 @@ class BambuVirtualPrinter:
self._log.debug( self._log.debug(
f"Creating standard BambuClient with local_mqtt: {self._settings.get_boolean(['local_mqtt'])}" f"Creating standard BambuClient with local_mqtt: {self._settings.get_boolean(['local_mqtt'])}"
) )
bambu_client = BambuClient(
device_type=self._settings.get(["device_type"]), # Set up client parameters
serial=self._settings.get(["serial"]), client_params = {
host=self._settings.get(["host"]), "device_type": self._settings.get(["device_type"]),
username=( "serial": self._settings.get(["serial"]),
"host": self._settings.get(["host"]),
"username": (
"bblp" "bblp"
if self._settings.get_boolean(["local_mqtt"]) if self._settings.get_boolean(["local_mqtt"])
else self._settings.get(["username"]) else self._settings.get(["username"])
), ),
access_code=self._settings.get(["access_code"]), "access_code": self._settings.get(["access_code"]),
local_mqtt=self._settings.get_boolean(["local_mqtt"]), "local_mqtt": self._settings.get_boolean(["local_mqtt"]),
region=self._settings.get(["region"]), "region": self._settings.get(["region"]),
email=self._settings.get(["email"]), "email": self._settings.get(["email"]),
auth_token=self._settings.get(["auth_token"]), "auth_token": self._settings.get(["auth_token"]),
) }
# Add disable_camera parameter if it's enabled in settings
if self._disable_camera:
self._log.info("Camera functionality is disabled in settings")
client_params["disable_camera"] = True
client_params["enable_camera_stream"] = False
try:
bambu_client = BambuClient(**client_params)
except TypeError as e:
# Handle the case where pybambu doesn't support these parameters yet
if "disable_camera" in str(e) or "enable_camera_stream" in str(e):
self._log.warning("This version of pybambu doesn't support camera disabling parameters, trying without them")
if "disable_camera" in client_params:
del client_params["disable_camera"]
if "enable_camera_stream" in client_params:
del client_params["enable_camera_stream"]
bambu_client = BambuClient(**client_params)
else:
raise
bambu_client.on_disconnect = self.on_disconnect(bambu_client.on_disconnect) bambu_client.on_disconnect = self.on_disconnect(bambu_client.on_disconnect)
bambu_client.on_connect = self.on_connect(bambu_client.on_connect) bambu_client.on_connect = self.on_connect(bambu_client.on_connect)
@ -898,6 +936,15 @@ class BambuVirtualPrinter:
while connection_attempts < max_attempts: while connection_attempts < max_attempts:
try: try:
self._log.info(f"Connection attempt {connection_attempts + 1}/{max_attempts}...") self._log.info(f"Connection attempt {connection_attempts + 1}/{max_attempts}...")
# Check if we need to wait based on backoff
current_time = time.time()
if current_time - self._last_connection_attempt < self._connection_retry_backoff:
wait_time = self._connection_retry_backoff - (current_time - self._last_connection_attempt)
self._log.debug(f"Waiting {wait_time:.1f}s before retry due to backoff")
time.sleep(wait_time)
self._last_connection_attempt = time.time()
bambu_client.connect(callback=self.new_update) bambu_client.connect(callback=self.new_update)
# Wait a moment to verify connection # Wait a moment to verify connection
@ -905,14 +952,27 @@ class BambuVirtualPrinter:
if bambu_client.connected: if bambu_client.connected:
self._log.info(f"Bambu connection successful: {bambu_client.connected}") self._log.info(f"Bambu connection successful: {bambu_client.connected}")
# Reset connection error flags on successful connection
self._connection_error_logged = False
self._connection_retry_backoff = 10 # Reset backoff on success
break break
self._log.warning("Connection attempt failed, retrying...") self._log.warning("Connection attempt failed, retrying...")
connection_attempts += 1 connection_attempts += 1
# Increase backoff time for future connection attempts
self._connection_retry_backoff = min(300, self._connection_retry_backoff * 2) # Cap at 5 minutes
time.sleep(retry_delay) time.sleep(retry_delay)
except Exception as e: except Exception as e:
self._log.error(f"Error during connection attempt {connection_attempts + 1}: {str(e)}", exc_info=True) if not self._connection_error_logged:
self._log.error(f"Error during connection attempt {connection_attempts + 1}: {str(e)}", exc_info=True)
self._connection_error_logged = True
else:
self._log.debug(f"Repeated connection error during attempt {connection_attempts + 1}: {str(e)}")
connection_attempts += 1 connection_attempts += 1
# Increase backoff time for future connection attempts
self._connection_retry_backoff = min(300, self._connection_retry_backoff * 2)
if connection_attempts < max_attempts: if connection_attempts < max_attempts:
time.sleep(retry_delay) time.sleep(retry_delay)
@ -922,6 +982,40 @@ class BambuVirtualPrinter:
self._log.info(f"Custom connection status: {self.is_connected}") self._log.info(f"Custom connection status: {self.is_connected}")
self.sendOk() self.sendOk()
def _patch_bambu_client_for_connection_errors(self):
"""Patch the BambuClient instance to handle connection errors gracefully"""
if not self._bambu_client:
return
# If we need to modify how the library handles connection errors, particularly
# for the Chamber Image functionality, we can patch the relevant methods here
# Check if the client has chamber image functionality and it's causing errors
if hasattr(self._bambu_client, '_chamber_image_thread') and self._bambu_client._chamber_image_thread:
original_run = None
# Find the run function in the thread class
if hasattr(self._bambu_client._chamber_image_thread, 'run'):
original_run = self._bambu_client._chamber_image_thread.run
# Create a wrapper that catches connection errors
def patched_run(*args, **kwargs):
try:
return original_run(*args, **kwargs)
except ConnectionRefusedError as e:
# Only log first occurrence to avoid log spam
if not self._camera_error_logged:
self._log.warning(f"Chamber image connection refused: {str(e)}. Further errors will be suppressed.")
self._camera_error_logged = True
return None
except Exception as e:
self._log.error(f"Chamber image error: {str(e)}", exc_info=True)
return None
# Apply the patched method
self._bambu_client._chamber_image_thread.run = patched_run
self._log.debug("Patched chamber image thread to handle connection errors")
def publish_mqtt(self, topic, payload): def publish_mqtt(self, topic, payload):
"""Publish a message to the MQTT broker""" """Publish a message to the MQTT broker"""
if self._mqtt_client and self._mqtt_connected: if self._mqtt_client and self._mqtt_connected: