From 5bf5e336eca92b6b52aa1198ea047bea74fefcd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 8 Jul 2016 12:54:58 +0200 Subject: [PATCH] Extend payload in various events Added name and path various event print job events and the upload event, deprecated the file property. Had to move event triggering of the print job events to the printer implementation, since the file manager is not available in the comm layer. Added new callbacks to the PrinterInterface to allow for that to be possible. --- docs/events/index.rst | 102 +++++++++++++++++++++++------ src/octoprint/printer/standard.py | 104 +++++++++++++++++++++++++++--- src/octoprint/server/api/files.py | 7 +- src/octoprint/util/comm.py | 82 ++++++----------------- 4 files changed, 204 insertions(+), 91 deletions(-) diff --git a/docs/events/index.rst b/docs/events/index.rst index 22a31c5c..455b0b8a 100644 --- a/docs/events/index.rst +++ b/docs/events/index.rst @@ -152,8 +152,15 @@ Upload A file has been uploaded. Payload: - * ``file``: the file's name - * ``target``: the target to which the file was uploaded, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``target``: the target storage location to which the file was uploaded, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's path within its storage location + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. UpdatedFiles A file list was modified. @@ -201,19 +208,26 @@ MetadataAnalysisFinished Still available for reasons of backwards compatibility. Will be removed with 1.4.0. FileSelected - A GCODE file has been selected for printing. + A file has been selected for printing. Payload: - * ``file``: the full path to the file - * ``filename``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. FileDeselected No file is selected any more for printing. TransferStarted - A GCODE file transfer to SD has started. + A file transfer to the printer's SD has started. Payload: @@ -223,7 +237,7 @@ TransferStarted **Note:** Name changed in version 1.1.0 TransferDone - A GCODE file transfer to SD has finished. + A file transfer to the printer's SD has finished. Payload: @@ -239,49 +253,97 @@ PrintStarted Payload: - * ``file``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. PrintFailed A print failed. Payload: - * ``file``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. PrintDone A print completed successfully. Payload: - * ``file``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` * ``time``: the time needed for the print, in seconds (float) + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. + PrintCancelled The print has been cancelled via the cancel button. Payload: - * ``file``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. PrintPaused The print has been paused. Payload: - * ``file``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. PrintResumed The print has been resumed. Payload: - * ``file``: the file's name - * ``origin``: the origin of the file, either ``local`` or ``sdcard`` + * ``name``: the file's name + * ``path``: the file's path within its storage location + * ``origin``: the origin storage location of the file, either ``local`` or ``sdcard`` + + .. deprecated:: 1.3.0 + + * ``file``: the file's full path on disk (``local``) or within its storage (``sdcard``) + * ``filename``: the file's name + + Still available for reasons of backwards compatibility. Will be removed with 1.4.0. GCODE processing ---------------- diff --git a/src/octoprint/printer/standard.py b/src/octoprint/printer/standard.py index 4833942e..51bad831 100644 --- a/src/octoprint/printer/standard.py +++ b/src/octoprint/printer/standard.py @@ -97,6 +97,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): job_data={ "file": { "name": None, + "path": None, "size": None, "origin": None, "date": None @@ -232,7 +233,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): for command in commands: self._comm.sendCommand(command) - def script(self, name, context=None): + def script(self, name, context=None, must_be_set=True): if self._comm is None: return @@ -240,7 +241,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): raise ValueError("name must be set") result = self._comm.sendGcodeScript(name, replacements=context) - if not result: + if not result and must_be_set: raise UnknownScript(name) def jog(self, axes, relative=True, speed=None, *args, **kwargs): @@ -719,13 +720,15 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): def _setJobData(self, filename, filesize, sd): if filename is not None: if sd: - path_in_storage = filename - if path_in_storage.startswith("/"): - path_in_storage = path_in_storage[1:] + name_in_storage = filename + if name_in_storage.startswith("/"): + name_in_storage = name_in_storage[1:] + path_in_storage = name_in_storage path_on_disk = None else: path_in_storage = self._fileManager.path_in_storage(FileDestinations.LOCAL, filename) path_on_disk = self._fileManager.path_on_disk(FileDestinations.LOCAL, filename) + _, name_in_storage = self._fileManager.split_path(FileDestinations.LOCAL, path_in_storage) self._selectedFile = { "filename": path_in_storage, "filesize": filesize, @@ -737,6 +740,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): self._stateMonitor.set_job_data({ "file": { "name": None, + "path": None, "origin": None, "size": None, "date": None @@ -784,7 +788,8 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): self._stateMonitor.set_job_data({ "file": { - "name": path_in_storage, + "name": name_in_storage, + "path": path_in_storage, "origin": FileDestinations.SDCARD if sd else FileDestinations.LOCAL, "size": filesize, "date": date @@ -804,7 +809,7 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): "messages": list(self._messages) }) callback.on_printer_send_initial_data(data) - except Exception, err: + except Exception as err: import sys sys.stderr.write("ERROR: %s\n" % str(err)) pass @@ -892,19 +897,67 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): eventManager().fire(Events.UPDATED_FILES, {"type": "gcode"}) self._sdFilelistAvailable.set() - def on_comm_file_selected(self, filename, filesize, sd): - self._setJobData(filename, filesize, sd) + def on_comm_file_selected(self, full_path, size, sd): + if full_path is not None: + payload = self._payload_for_print_job_event(location=FileDestinations.SDCARD if sd else FileDestinations.LOCAL, + print_job_file=full_path) + eventManager().fire(Events.FILE_SELECTED, payload) + else: + eventManager().fire(Events.FILE_DESELECTED) + + self._setJobData(full_path, size, sd) self._stateMonitor.set_state({"text": self.get_state_string(), "flags": self._getStateFlags()}) if self._printAfterSelect: self.start_print(pos=self._posAfterSelect) + def on_comm_print_job_started(self): + payload = self._payload_for_print_job_event() + if payload: + eventManager().fire(Events.PRINT_STARTED, payload) + def on_comm_print_job_done(self): + payload = self._payload_for_print_job_event() + if payload: + payload["time"] = self._comm.getPrintTime() + eventManager().fire(Events.PRINT_DONE, payload) + self.script("afterPrintDone", + context=dict(event=payload), + must_be_set=False) + self._fileManager.log_print(FileDestinations.SDCARD if self._selectedFile["sd"] else FileDestinations.LOCAL, self._selectedFile["filename"], time.time(), self._comm.getPrintTime(), True, self._printerProfileManager.get_current_or_default()["id"]) self._setProgressData(completion=1.0, filepos=self._selectedFile["filesize"], printTime=self._comm.getPrintTime(), printTimeLeft=0) self._stateMonitor.set_state({"text": self.get_state_string(), "flags": self._getStateFlags()}) self._fileManager.delete_recovery_data() + def on_comm_print_job_failed(self): + payload = self._payload_for_print_job_event() + eventManager().fire(Events.PRINT_FAILED, payload) + + def on_comm_print_job_cancelled(self): + payload = self._payload_for_print_job_event() + if payload: + eventManager().fire(Events.PRINT_CANCELLED, payload) + self.script("afterPrintCancelled", + context=dict(event=payload), + must_be_set=False) + + def on_comm_print_job_paused(self): + payload = self._payload_for_print_job_event() + if payload: + eventManager().fire(Events.PRINT_PAUSED, payload) + self.script("afterPrintPaused", + context=dict(event=payload), + must_be_set=False) + + def on_comm_print_job_resumed(self): + payload = self._payload_for_print_job_event() + if payload: + eventManager().fire(Events.PRINT_RESUMED, payload) + self.script("beforePrintResumed", + context=dict(event=payload), + must_be_set=False) + def on_comm_file_transfer_started(self, filename, filesize): self._sdStreaming = True @@ -936,6 +989,39 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): except: self._logger.exception("Error while trying to persist print recovery data") + def _payload_for_print_job_event(self, location=None, print_job_file=None): + if print_job_file is None: + selected_file = self._selectedFile + if not selected_file: + return dict() + + print_job_file = selected_file.get("filename", None) + location = FileDestinations.LOCAL if selected_file.get("sd", False) else FileDestinations.SDCARD + + if not print_job_file or not location: + return dict() + + if location == FileDestinations.SDCARD: + full_path = print_job_file + name = full_path + path = "" + origin = FileDestinations.SDCARD + + else: + full_path = self._fileManager.path_on_disk(FileDestinations.LOCAL, print_job_file) + path = self._fileManager.path_in_storage(FileDestinations.LOCAL, print_job_file) + _, name = self._fileManager.split_path(FileDestinations.LOCAL, path) + origin = FileDestinations.LOCAL + + return dict(name=name, + path=path, + origin=origin, + + # TODO deprecated, remove in 1.4.0 + file=full_path, + filename=name) + + class StateMonitor(object): def __init__(self, interval=0.5, on_update=None, on_add_temperature=None, on_add_log=None, on_add_message=None, on_get_progress=None): self._interval = interval diff --git a/src/octoprint/server/api/files.py b/src/octoprint/server/api/files.py index 91cde75a..036c40f0 100644 --- a/src/octoprint/server/api/files.py +++ b/src/octoprint/server/api/files.py @@ -287,7 +287,12 @@ def uploadGcodeFile(target): if isinstance(filename, tuple): filename, sdFilename = filename - eventManager.fire(Events.UPLOAD, {"file": filename, "target": target}) + eventManager.fire(Events.UPLOAD, {"name": futureFilename, + "path": filename, + "target": target, + + # TODO deprecated, remove in 1.4.0 + "file": filename}) files = {} location = url_for(".readGcodeFile", target=FileDestinations.LOCAL, filename=filename, _external=True) diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 9728dfc8..29f6569b 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -575,14 +575,7 @@ class MachineCom(object): self._sdFileList = [] if printing: - payload = None - if self._currentFile is not None: - payload = { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation() - } - eventManager().fire(Events.PRINT_FAILED, payload) + self._callback.on_comm_print_job_failed() def setTemperatureOffset(self, offsets): self._tempOffsets.update(offsets) @@ -676,13 +669,7 @@ class MachineCom(object): self.resetLineNumbers() - payload = { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation() - } - eventManager().fire(Events.PRINT_STARTED, payload) - self.sendGcodeScript("beforePrintStarted", replacements=dict(event=payload)) + self._callback.on_comm_print_job_started() if self.isSdFileSelected(): #self.sendCommand("M26 S0") # setting the sd pos apparently sometimes doesn't work, so we re-select @@ -743,11 +730,6 @@ class MachineCom(object): self.sendCommand("M23 %s" % filename) else: self._currentFile = PrintingGcodeFileInformation(filename, offsets_callback=self.getOffsets, current_tool_callback=self.getCurrentTool) - eventManager().fire(Events.FILE_SELECTED, { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation() - }) self._callback.on_comm_file_selected(filename, self._currentFile.getFilesize(), False) def unselectFile(self): @@ -755,7 +737,6 @@ class MachineCom(object): return self._currentFile = None - eventManager().fire(Events.FILE_DESELECTED) self._callback.on_comm_file_selected(None, None, False) def cancelPrint(self, firmware_error=None): @@ -778,16 +759,7 @@ class MachineCom(object): pass self._recordFilePosition() - - payload = { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation(), - "firmwareError": firmware_error - } - - self.sendGcodeScript("afterPrintCancelled", replacements=dict(event=payload)) - eventManager().fire(Events.PRINT_CANCELLED, payload) + self._callback.on_comm_print_job_cancelled() def setPause(self, pause): if self.isStreaming(): @@ -796,20 +768,13 @@ class MachineCom(object): if not self._currentFile: return - payload = { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation() - } - if not pause and self.isPaused(): if self._pauseWaitStartTime: self._pauseWaitTimeLost = self._pauseWaitTimeLost + (time.time() - self._pauseWaitStartTime) self._pauseWaitStartTime = None self._changeState(self.STATE_PRINTING) - - self.sendGcodeScript("beforePrintResumed", replacements=dict(event=payload)) + self._callback.on_comm_print_job_resumed() if self.isSdFileSelected(): self.sendCommand("M24") @@ -822,7 +787,6 @@ class MachineCom(object): # now make sure we actually do something, up until now we only filled up the queue self._sendFromQueue() - eventManager().fire(Events.PRINT_RESUMED, payload) elif pause and self.isPrinting(): if not self._pauseWaitStartTime: self._pauseWaitStartTime = time.time() @@ -830,9 +794,9 @@ class MachineCom(object): self._changeState(self.STATE_PAUSED) if self.isSdFileSelected(): self.sendCommand("M25") # pause print - self.sendGcodeScript("afterPrintPaused", replacements=dict(event=payload)) - eventManager().fire(Events.PRINT_PAUSED, payload) + self._callback.on_comm_print_job_paused() + def getSdFiles(self): return self._sdFiles @@ -1165,10 +1129,6 @@ class MachineCom(object): elif self._currentFile is not None and self.isSdFileSelected(): # final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected" self._callback.on_comm_file_selected(self._currentFile.getFilename(), self._currentFile.getFilesize(), True) - eventManager().fire(Events.FILE_SELECTED, { - "file": self._currentFile.getFilename(), - "origin": self._currentFile.getFileLocation() - }) elif 'Writing to file' in line and self.isStreaming(): self._changeState(self.STATE_PRINTING) elif 'Done printing file' in line and self.isSdPrinting(): @@ -1176,12 +1136,6 @@ class MachineCom(object): self._sdFilePos = 0 self._callback.on_comm_print_job_done() self._changeState(self.STATE_OPERATIONAL) - eventManager().fire(Events.PRINT_DONE, { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation(), - "time": self.getPrintTime() - }) if self._sd_status_timer is not None: try: self._sd_status_timer.cancel() @@ -1637,17 +1591,8 @@ class MachineCom(object): eventManager().fire(Events.TRANSFER_DONE, payload) self.refreshSdFiles() else: - payload = { - "file": self._currentFile.getFilename(), - "filename": os.path.basename(self._currentFile.getFilename()), - "origin": self._currentFile.getFileLocation(), - "time": self.getPrintTime() - } self._callback.on_comm_print_job_done() self._changeState(self.STATE_OPERATIONAL) - eventManager().fire(Events.PRINT_DONE, payload) - - self.sendGcodeScript("afterPrintDone", replacements=dict(event=payload)) return line def _sendNext(self): @@ -2193,9 +2138,24 @@ class MachineComPrintCallback(object): def on_comm_progress(self): pass + def on_comm_print_job_started(self): + pass + + def on_comm_print_job_failed(self): + pass + def on_comm_print_job_done(self): pass + def on_comm_print_job_cancelled(self): + pass + + def on_comm_print_job_paused(self): + pass + + def on_comm_print_job_resumed(self): + pass + def on_comm_z_change(self, newZ): pass