Skip to content

Commit

Permalink
0.1.8rc7
Browse files Browse the repository at this point in the history
* update pybambu module from upstream HA project, groundwork for fixing new cloud authorization process, #59
* potential fix for stuck progress/canceled printing status, #52
  • Loading branch information
jneilliii committed Nov 9, 2024
1 parent 5633d6f commit e3fda73
Show file tree
Hide file tree
Showing 10 changed files with 305 additions and 103 deletions.
5 changes: 5 additions & 0 deletions octoprint_bambu_printer/bambu_print_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,11 @@ def get_settings_defaults(self):
"ams_current_tray": 255,
}

def on_settings_save(self, data):
if data.get("local_mqtt", False) is True:
data["auth_token"] = ""
octoprint.plugin.SettingsPlugin.on_settings_save(self, data)

def is_api_adminonly(self):
return True

Expand Down
8 changes: 4 additions & 4 deletions octoprint_bambu_printer/printer/bambu_virtual_printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,21 +345,21 @@ def remove_project_selection(self):
self._selected_project_file = None

def select_project_file(self, file_path: str) -> bool:
self._log.debug(f"Select project file: {file_path}")
file_info = self._project_files_view.get_file_by_stem(
file_path, [".gcode", ".3mf"]
)
file_info = self._project_files_view.get_file_by_name(file_path)
if (
self._selected_project_file is not None
and file_info is not None
and self._selected_project_file.path == file_info.path
):
self._log.debug(f"File already selected: {file_path}")
return True

if file_info is None:
self._log.error(f"Cannot select non-existent file: {file_path}")
return False

self._log.debug(f"Select project file: {file_path}")

self._selected_project_file = file_info
self._send_file_selected_message()
return True
Expand Down
32 changes: 16 additions & 16 deletions octoprint_bambu_printer/printer/file_system/cached_file_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ def list_all_views(self):
result: list[FileInfo] = []

with self.file_system.get_ftps_client() as ftp:
for filter in self.folder_view.keys():
result.extend(self.file_system.list_files(*filter, ftp, existing_files))
for key in self.folder_view.keys():
result.extend(self.file_system.list_files(*key, ftp, existing_files))
return result

def update(self):
Expand All @@ -56,6 +56,9 @@ def get_all_info(self):
def get_all_cached_info(self):
return list(self._file_data_cache.values())

def get_keys_as_list(self):
return list(self._file_data_cache.keys()) + list(self._file_alias_cache.keys())

def get_file_data(self, file_path: str | Path) -> FileInfo | None:
file_data = self.get_file_data_cached(file_path)
if file_data is None:
Expand All @@ -73,22 +76,19 @@ def get_file_data_cached(self, file_path: str | Path) -> FileInfo | None:
file_path = self._file_alias_cache.get(file_path, file_path)
return self._file_data_cache.get(file_path, None)

def get_file_by_stem(self, file_stem: str, allowed_suffixes: list[str]):
if file_stem == "":
def get_file_by_name(self, file_name: str):
if file_name == "":
return None

file_stem = Path(file_stem).with_suffix("").stem
file_data = self._get_file_by_stem_cached(file_stem, allowed_suffixes)
file_list = self.get_keys_as_list()
if not file_name in file_list:
if f"{file_name}.3mf" in file_list:
file_name = f"{file_name}.3mf"
elif f"{file_name}.gcode.3mf" in file_list:
file_name = f"{file_name}.gcode.3mf"

file_data = self.get_file_data_cached(file_name)
if file_data is None:
self.update()
file_data = self._get_file_by_stem_cached(file_stem, allowed_suffixes)
return self.get_file_by_name(file_name)
return file_data

def _get_file_by_stem_cached(self, file_stem: str, allowed_suffixes: list[str]):
for file_path_str in list(self._file_data_cache.keys()) + list(self._file_alias_cache.keys()):
file_path = Path(file_path_str)
if file_stem == file_path.with_suffix("").stem and any(
suffix in allowed_suffixes for suffix in file_path.suffixes
):
return self.get_file_data_cached(file_path)
return None
42 changes: 28 additions & 14 deletions octoprint_bambu_printer/printer/pybambu/bambu_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import asyncio
import queue
import json
import math
Expand Down Expand Up @@ -36,6 +37,7 @@ def __init__(self, client):
self._stop_event = threading.Event()
self._last_received_data = time.time()
super().__init__()
self.daemon = True
self.setName(f"{self._client._device.info.device_type}-Watchdog-{threading.get_native_id()}")

def stop(self):
Expand Down Expand Up @@ -70,6 +72,7 @@ def __init__(self, client):
self._client = client
self._stop_event = threading.Event()
super().__init__()
self.daemon = True
self.setName(f"{self._client._device.info.device_type}-Chamber-{threading.get_native_id()}")

def stop(self):
Expand Down Expand Up @@ -178,7 +181,7 @@ def run(self):

# Reset buffer
img = None
# else:
# else:
# Otherwise we need to continue looping without reseting the buffer to receive the remaining data
# and without delaying.

Expand Down Expand Up @@ -223,6 +226,7 @@ def __init__(self, client):
self._client = client
self._stop_event = threading.Event()
super().__init__()
self.daemon = True
self.setName(f"{self._client._device.info.device_type}-Mqtt-{threading.get_native_id()}")

def stop(self):
Expand Down Expand Up @@ -282,7 +286,7 @@ class BambuClient:
_usage_hours: float

def __init__(self, device_type: str, serial: str, host: str, local_mqtt: bool, region: str, email: str,
username: str, auth_token: str, access_code: str, usage_hours: float = 0, manual_refresh_mode: bool = False):
username: str, auth_token: str, access_code: str, usage_hours: float = 0, manual_refresh_mode: bool = False, chamber_image: bool = True):
self.callback = None
self.host = host
self._local_mqtt = local_mqtt
Expand All @@ -299,6 +303,7 @@ def __init__(self, device_type: str, serial: str, host: str, local_mqtt: bool, r
self._device = Device(self)
self.bambu_cloud = BambuCloud(region, email, username, auth_token)
self.slicer_settings = SlicerSettings(self)
self.use_chamber_image = chamber_image

@property
def connected(self):
Expand All @@ -319,6 +324,10 @@ async def set_manual_refresh_mode(self, on):
# Reconnect normally
self.connect(self.callback)

def setup_tls(self):
self.client.tls_set(tls_version=ssl.PROTOCOL_TLS, cert_reqs=ssl.CERT_NONE)
self.client.tls_insecure_set(True)

def connect(self, callback):
"""Connect to the MQTT Broker"""
self.client = mqtt.Client()
Expand All @@ -329,8 +338,9 @@ def connect(self, callback):
# Set aggressive reconnect polling.
self.client.reconnect_delay_set(min_delay=1, max_delay=1)

self.client.tls_set(tls_version=ssl.PROTOCOL_TLS, cert_reqs=ssl.CERT_NONE)
self.client.tls_insecure_set(True)
# Run the blocking tls_set method in a separate thread
self.setup_tls()

self._port = 8883
if self._local_mqtt:
self.client.username_pw_set("bblp", password=self._access_code)
Expand Down Expand Up @@ -369,10 +379,14 @@ def _on_connect(self):
self._watchdog = WatchdogThread(self)
self._watchdog.start()

if self._device.supports_feature(Features.CAMERA_IMAGE):
LOGGER.debug("Starting Chamber Image thread")
self._camera = ChamberImageThread(self)
self._camera.start()
if not self._device.supports_feature(Features.CAMERA_RTSP):
if self._device.supports_feature(Features.CAMERA_IMAGE):
if self.use_chamber_image:
LOGGER.debug("Starting Chamber Image thread")
self._camera = ChamberImageThread(self)
self._camera.start()
elif (self.host == "") or (self._access_code == ""):
LOGGER.debug("Skipping camera setup as local access details not provided.")

def try_on_connect(self,
client_: mqtt.Client,
Expand All @@ -396,7 +410,7 @@ def on_disconnect(self,
"""Called when MQTT Disconnects"""
LOGGER.warn(f"On Disconnect: Printer disconnected with error code: {result_code}")
self._on_disconnect()

def _on_disconnect(self):
LOGGER.debug("_on_disconnect: Lost connection to the printer")
self._connected = False
Expand Down Expand Up @@ -451,9 +465,7 @@ def on_message(self, client, userdata, message):
LOGGER.debug("Got Version Data")
self._device.info_update(data=json_data.get("info"))
except Exception as e:
LOGGER.error("An exception occurred processing a message:")
LOGGER.error(f"Exception type: {type(e)}")
LOGGER.error(f"Exception data: {e}")
LOGGER.error("An exception occurred processing a message:", exc_info=e)

def subscribe(self):
"""Subscribe to report topic"""
Expand Down Expand Up @@ -516,8 +528,10 @@ def on_message(client, userdata, message):
self.client.on_disconnect = self.on_disconnect
self.client.on_message = on_message

self.client.tls_set(tls_version=ssl.PROTOCOL_TLS, cert_reqs=ssl.CERT_NONE)
self.client.tls_insecure_set(True)
# Run the blocking tls_set method in a separate thread
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, self.setup_tls)

if self._local_mqtt:
self.client.username_pw_set("bblp", password=self._access_code)
else:
Expand Down
Loading

0 comments on commit e3fda73

Please sign in to comment.