From 0de0e4ea9bd5fec2abea17f9dc86b6c3700d9ef0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gina=20H=C3=A4u=C3=9Fge?= Date: Fri, 24 Nov 2017 13:11:23 +0100 Subject: [PATCH] Handling of non gcode SD file transfers No guarantees however that transporting anything BUT gcode via the usual M28/M29 interface will even remotely work. Note that it most likely won't work if the transferred file contains an M29 (= end transfer), just like with transferred GCODE files. Also note that stuff like config files or some such that might be transferred might contain lines that are too large to fit into the buffer of the printer. This is really just to enable plugins to maybe do some nifty stuff, no official support of streaming arbitrary files to the printer's SD (for that we'd need WAY more firmware support first). See jneilliii/OctoPrint-SmoothiewareConfig#1 --- src/octoprint/printer/standard.py | 14 +++++++++----- src/octoprint/util/comm.py | 30 +++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/octoprint/printer/standard.py b/src/octoprint/printer/standard.py index 1976b750..7a619c45 100644 --- a/src/octoprint/printer/standard.py +++ b/src/octoprint/printer/standard.py @@ -595,12 +595,16 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): self.refresh_sd_files(blocking=True) existingSdFiles = map(lambda x: x[0], self._comm.getSdFiles()) - remoteName = util.get_dos_filename(filename, - existing_filenames=existingSdFiles, - extension="gco", - whitelisted_extensions=["gco", "g"]) + if valid_file_type(filename, "gcode"): + remoteName = util.get_dos_filename(filename, + existing_filenames=existingSdFiles, + extension="gco", + whitelisted_extensions=["gco", "g"]) + else: + # probably something else added through a plugin, use it's basename as-is + remoteName = os.path.basename(filename) self._timeEstimationData = TimeEstimationHelper() - self._comm.startFileTransfer(absolutePath, filename, "/" + remoteName) + self._comm.startFileTransfer(absolutePath, filename, "/" + remoteName, special=not valid_file_type(filename, "gcode")) return remoteName diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 44a6605a..425b54d8 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -877,7 +877,7 @@ class MachineCom(object): self._changeState(self.STATE_ERROR) eventManager().fire(Events.ERROR, {"error": self.getErrorString()}) - def startFileTransfer(self, filename, localFilename, remoteFilename): + def startFileTransfer(self, filename, localFilename, remoteFilename, special=False): if not self.isOperational() or self.isBusy(): self._logger.info("Printer is not operational or busy") return @@ -885,7 +885,10 @@ class MachineCom(object): with self._jobLock: self.resetLineNumbers() - self._currentFile = StreamingGcodeFileInformation(filename, localFilename, remoteFilename) + if special: + self._currentFile = SpecialStreamingGcodeFileInformation(filename, localFilename, remoteFilename) + else: + self._currentFile = StreamingGcodeFileInformation(filename, localFilename, remoteFilename) self._currentFile.start() self.sendCommand("M28 %s" % remoteFilename) @@ -2356,7 +2359,7 @@ class MachineCom(object): # now comes the part where we increase line numbers and send stuff - no turning back now command_requiring_checksum = gcode is not None and gcode in self._checksum_requiring_commands command_allowing_checksum = gcode is not None or self._sendChecksumWithUnknownCommands - checksum_enabled = not self._neverSendChecksum and (self.isPrinting() or + checksum_enabled = not self._neverSendChecksum and ((self.isPrinting() and self._currentFile and self._currentFile.checksum) or self._alwaysSendChecksum or not self._firmware_info_received) @@ -2825,6 +2828,8 @@ class PrintingFileInformation(object): value between 0 and 1. """ + checksum = True + def __init__(self, filename): self._logger = logging.getLogger(__name__) self._filename = filename @@ -2879,6 +2884,8 @@ class PrintingSdFileInformation(PrintingFileInformation): Encapsulates information regarding an ongoing print from SD. """ + checksum = False + def __init__(self, filename, size): PrintingFileInformation.__init__(self, filename) self._size = size @@ -3025,6 +3032,23 @@ class StreamingGcodeFileInformation(PrintingGcodeFileInformation): self._logger.info("Finished in {duration:.3f} s. Approx. transfer rate of {rate:.3f} lines/s or {time_per_line:.3f} ms per line".format(**stats)) +class SpecialStreamingGcodeFileInformation(StreamingGcodeFileInformation): + """ + For streaming files to the printer that aren't GCODE. + + Difference to regular StreamingGcodeFileInformation: no checksum requirement, only rudimentary line processing + (stripping of whitespace from the end and ignoring of empty lines) + """ + + checksum = False + + def _process(self, line, offsets, current_tool): + line = line.rstrip() + if not len(line): + return None + return line + + class SendQueue(PrependableQueue): def __init__(self, maxsize=0):