From e2fb1cc931635ad770c1b455c3a41e2ddcbf1040 Mon Sep 17 00:00:00 2001 From: Eric Callahan Date: Tue, 21 Dec 2021 20:08:30 -0500 Subject: [PATCH] octoprint_compat: add support for "print on start" Cura's Octoprint plugin does not set the 'start' flag on uploads when UFP is enabled. Instead it waits for the upload to finish then issues Octoprint's "file command" request. Add limited support for this API, mimicing how uploads are normally handled. Singed-off-by: Eric Callahan --- .../components/file_manager/file_manager.py | 3 + moonraker/components/octoprint_compat.py | 58 ++++++++++++++++++- 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/moonraker/components/file_manager/file_manager.py b/moonraker/components/file_manager/file_manager.py index aad4e99..bfbe55d 100644 --- a/moonraker/components/file_manager/file_manager.py +++ b/moonraker/components/file_manager/file_manager.py @@ -202,6 +202,9 @@ class FileManager: file_path = os.path.join(root_dir, filename) return os.path.exists(file_path) + def upload_queue_enabled(self) -> bool: + return self.queue_gcodes + def sync_inotify_event(self, path: str) -> Optional[NotifySyncLock]: if self.notify_sync_lock is None or \ not self.notify_sync_lock.check_need_sync(path): diff --git a/moonraker/components/octoprint_compat.py b/moonraker/components/octoprint_compat.py index e7d5e3e..642c192 100644 --- a/moonraker/components/octoprint_compat.py +++ b/moonraker/components/octoprint_compat.py @@ -17,8 +17,9 @@ from typing import ( if TYPE_CHECKING: from confighelper import ConfigHelper from websockets import WebRequest - from . import klippy_apis - APIComp = klippy_apis.KlippyAPI + from .klippy_apis import KlippyAPI as APIComp + from .file_manager.file_manager import FileManager + from .job_queue import JobQueue OCTO_VERSION = '1.5.0' @@ -97,7 +98,10 @@ class OctoprintCompat: # Upload Handlers self.server.register_upload_handler( - "/api/files/local", location_prefix="api/moonraker/files/") + "/api/files/local", location_prefix="api/files/moonraker") + self.server.register_endpoint( + "/api/files/moonraker/(?P.+)", ['POST'], + self._select_file, transports=['http'], wrap_result=False) # System # TODO: shutdown/reboot/restart operations @@ -328,6 +332,54 @@ class OctoprintCompat: } } + async def _select_file(self, + web_request: WebRequest + ) -> None: + command: str = web_request.get('command') + rel_path: str = web_request.get('relative_path') + root, filename = rel_path.strip("/").split("/", 1) + fmgr: FileManager = self.server.lookup_component('file_manager') + if command == "select": + start_print: bool = web_request.get('print', False) + if not start_print: + # No-op, selecting a file has no meaning in Moonraker + return + if root != "gcodes": + raise self.server.error( + "File must be located in the 'gcodes' root", 400) + if not fmgr.check_file_exists(root, filename): + raise self.server.error("File does not exist") + try: + ret = await self.klippy_apis.query_objects( + {'print_stats': None}) + pstate: str = ret['print_stats']['state'] + except self.server.error: + pstate = "not_avail" + started: bool = False + if pstate not in ["printing", "paused", "not_avail"]: + try: + await self.klippy_apis.start_print(filename) + except self.server.error: + started = False + else: + logging.debug(f"Job '{filename}' started via Octoprint API") + started = True + if not started: + if fmgr.upload_queue_enabled(): + job_queue: JobQueue = self.server.lookup_component( + 'job_queue') + await job_queue.queue_job(filename, check_exists=False) + # Fire the file_manager's upload_queued event for + # compatibility. We assume that this endpoint is + # requests by Cura after a file has been uploaded. + self.server.send_event("file_manager:upload_queued", + filename) + logging.debug(f"Job '{filename}' queued via Octoprint API") + else: + raise self.server.error("Conflict", 409) + else: + raise self.server.error(f"Unsupported Command: {command}") + def load_component(config: ConfigHelper) -> OctoprintCompat: return OctoprintCompat(config)