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