diff --git a/docs/api/connection.rst b/docs/api/connection.rst index 49904369..fc44ff8b 100644 --- a/docs/api/connection.rst +++ b/docs/api/connection.rst @@ -75,6 +75,12 @@ Issue a connection command disconnect Instructs OctoPrint to disconnect from the printer. + fake_ack + Fakes an acknowledgement message for OctoPrint in case one got lost on the serial line and the communication + with the printer since stalled. This should only be used in "emergencies" (e.g. to save prints), the reason + for the lost acknowledgement should always be properly investigated and removed instead of depending on this + "symptom solver". + **Example Connect Request** .. sourcecode:: http @@ -114,7 +120,24 @@ Issue a connection command HTTP/1.1 204 No Content - :json string command: The command to issue, either ``connect`` or ``disconnect`` + **Example FakeAck Request** + + .. sourcecode:: http + + POST /api/connection HTTP/1.1 + Host: example.com + Content-Type: application/json + X-Api-Key: abcdef... + + { + "command": "fake_ack" + } + + .. sourcecode:: http + + HTTP/1.1 204 No Content + + :json string command: The command to issue, either ``connect``, ``disconnect`` or ``fake_ack``. :json string port: ``connect`` command: The port to connect to. If left out either the existing ``portPreference`` will be used, or if that is not available OctoPrint will attempt auto detection. Must be part of the available ports. diff --git a/docs/configuration/config_yaml.rst b/docs/configuration/config_yaml.rst index 11981684..c8640400 100644 --- a/docs/configuration/config_yaml.rst +++ b/docs/configuration/config_yaml.rst @@ -373,10 +373,18 @@ Use the following settings to enable or disable OctoPrint features: # during connect. waitForStartOnConnect: false - # Specifies whether OctoPrint should send linenumber + checksum with every command. Needed for + # Specifies whether OctoPrint should send linenumber + checksum with every printer command. Needed for # successful communication with Repetier firmware alwaysSendChecksum: false + # Specifies whether OctoPrint should also send linenumber + checksum with commands that are *not* + # detected as valid GCODE (as in, they do not match the regular expression "^\s*([GM]\d+|T)"). + sendChecksumWithUnknownCommands: false + + # Specifies whether OctoPrint should also use up acknowledgments ("ok") for commands that are *not* + # detected as valid GCODE (as in, they do not match the regular expression "^\s*([GM]\d+|T)"). + unknownCommandsNeedAck: false + # Whether to ignore the first ok after a resend response. Needed for successful communication with # Repetier firmware swallowOkAfterResend: false diff --git a/src/octoprint/plugin/core.py b/src/octoprint/plugin/core.py index 99ec798f..26d4ca41 100644 --- a/src/octoprint/plugin/core.py +++ b/src/octoprint/plugin/core.py @@ -542,10 +542,11 @@ class PluginManager(object): url=module_pkginfo.home_page, license=module_pkginfo.license )) + package_name = module_pkginfo.name plugin = self._import_plugin_from_module(key, **kwargs) if plugin: - plugin.origin = ("entry_point", group, module_name) + plugin.origin = ("entry_point", group, module_name, package_name) plugin.enabled = False result[key] = plugin diff --git a/src/octoprint/plugin/types.py b/src/octoprint/plugin/types.py index 6349781c..aa4b8fe2 100644 --- a/src/octoprint/plugin/types.py +++ b/src/octoprint/plugin/types.py @@ -181,7 +181,7 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): The right part of the navigation bar located at the top of the UI can be enriched with additional links. Note that with the current implementation, plugins will always be located *to the left* of the existing links. - The included template must be called ``_navbar.jinja2`` (e.g. ``myplugin_navbar.jinja2``) unless + The included template must be called ``_navbar.jinja2`` (e.g. ``myplugin_navbar.jinja2``) unless overridden by the configuration supplied through :func:`get_template_configs`. The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The @@ -192,7 +192,7 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): The left side bar containing Connection, State and Files sections can be enriched with additional sections. Note that with the current implementations, plugins will always be located *beneath* the existing sections. - The included template must be called ``_sidebar.jinja2`` (e.g. ``myplugin_sidebar.jinja2``) unless + The included template must be called ``_sidebar.jinja2`` (e.g. ``myplugin_sidebar.jinja2``) unless overridden by the configuration supplied through :func:`get_template_configs`. The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The @@ -204,7 +204,7 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): plugins. Note that with the current implementation, plugins will always be located *to the right* of the existing tabs. - The included template must be called ``_tab.jinja2`` (e.g. ``myplugin_tab.jinja2``) unless + The included template must be called ``_tab.jinja2`` (e.g. ``myplugin_tab.jinja2``) unless overridden by the configuration supplied through :func:`get_template_configs`. The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The @@ -216,7 +216,7 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): will always be listed beneath the "Plugins" header in the settings link list, ordered alphabetically after their displayed name. - The included template must be called ``_settings.jinja2`` (e.g. ``myplugin_settings.jinja2``) unless + The included template must be called ``_settings.jinja2`` (e.g. ``myplugin_settings.jinja2``) unless overridden by the configuration supplied through :func:`get_template_configs`. The template will be already wrapped into the necessary structure, plugins just need to supply the pure content. The @@ -272,11 +272,11 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): * - template - Name of the template to inject, default value depends on the ``type``: - * ``navbar``: ``_navbar.jinja2`` - * ``sidebar``: ``_sidebar.jinja2`` - * ``tab``: ``_tab.jinja2`` - * ``settings``: ``_settings.jinja2`` - * ``generic``: ``.jinja2`` + * ``navbar``: ``_navbar.jinja2`` + * ``sidebar``: ``_sidebar.jinja2`` + * ``tab``: ``_tab.jinja2`` + * ``settings``: ``_settings.jinja2`` + * ``generic``: ``.jinja2`` * - suffix - Suffix to attach to the component identifier and the div identifier of the injected template. Will be @@ -311,7 +311,7 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): (and the divs will be ``tab_plugin_myplugin_1st`` and ``tab_plugin_myplugin_2nd``). * - div - - Id for the div containing the component. If not provided, defaults to ``_plugin_`` plus + - Id for the div containing the component. If not provided, defaults to ``_plugin_`` plus the ``suffix`` if provided or required. * - replaces - Id of the component this one replaces, might be either one of the core components or a component @@ -370,7 +370,7 @@ class TemplatePlugin(OctoPrintPlugin, ReloadNeedingPlugin): .. note:: As already outlined above, each template type has a default template name (i.e. the default navbar template - of a plugin is called ``_navbar.jinja2``), which may be overridden using the template configuration. + of a plugin is called ``_navbar.jinja2``), which may be overridden using the template configuration. If a plugin needs to include more than one template of a given type, it needs to provide an entry for each of those, since the implicit default template will only be included automatically if no other templates of that type are defined. diff --git a/src/octoprint/plugins/virtual_printer/virtual.py b/src/octoprint/plugins/virtual_printer/virtual.py index 8f54cb28..a94afa93 100644 --- a/src/octoprint/plugins/virtual_printer/virtual.py +++ b/src/octoprint/plugins/virtual_printer/virtual.py @@ -149,6 +149,11 @@ class VirtualPrinter(): self._sendOk() continue + if data.strip() == "version": + from octoprint._version import get_versions + self.outgoing.put("OctoPrint VirtualPrinter v" + get_versions()["version"]) + continue + if len(data.strip()) > 0 and self._okBeforeCommandOutput: self._sendOk() @@ -394,7 +399,6 @@ class VirtualPrinter(): pass if tool >= settings().getInt(["devel", "virtualPrinter", "numExtruders"]): - self._sendOk() return try: @@ -406,7 +410,6 @@ class VirtualPrinter(): self._waitForHeatup("tool%d" % tool) if settings().getBoolean(["devel", "virtualPrinter", "repetierStyleTargetTemperature"]): self.outgoing.put("TargetExtr%d:%d" % (tool, self.targetTemp[tool])) - self._sendOk() def _parseBedCommand(self, line): try: @@ -418,7 +421,6 @@ class VirtualPrinter(): self._waitForHeatup("bed") if settings().getBoolean(["devel", "virtualPrinter", "repetierStyleTargetTemperature"]): self.outgoing.put("TargetBed:%d" % self.bedTargetTemp) - self._sendOk() def _performMove(self, line): matchX = re.search("X([0-9.]+)", line) diff --git a/src/octoprint/printer/__init__.py b/src/octoprint/printer/__init__.py index 3f97deda..e0989a93 100644 --- a/src/octoprint/printer/__init__.py +++ b/src/octoprint/printer/__init__.py @@ -97,6 +97,14 @@ class PrinterInterface(object): """ raise NotImplementedError() + def fake_ack(self): + """ + Fakes an acknowledgement for the communication layer. If the communication between OctoPrint and the printer + gets stuck due to lost "ok" responses from the server due to communication issues, this can be used to get + things going again. + """ + raise NotImplementedError() + def commands(self, commands): """ Sends the provided ``commands`` to the printer. diff --git a/src/octoprint/printer/standard.py b/src/octoprint/printer/standard.py index 03e169cd..48d89cc3 100644 --- a/src/octoprint/printer/standard.py +++ b/src/octoprint/printer/standard.py @@ -212,6 +212,12 @@ class Printer(PrinterInterface, comm.MachineComPrintCallback): return self._comm.getTransport() getTransport = util.deprecated("getTransport has been renamed to get_transport", since="1.2.0-dev-590", includedoc="Replaced by :func:`get_transport`") + def fake_ack(self): + if self._comm is None: + return + + self._comm.fakeOk() + def commands(self, commands): """ Sends one or more gcode commands to the printer. diff --git a/src/octoprint/server/api/connection.py b/src/octoprint/server/api/connection.py index 7f858c7d..75f9b1d8 100644 --- a/src/octoprint/server/api/connection.py +++ b/src/octoprint/server/api/connection.py @@ -33,7 +33,8 @@ def connectionState(): def connectionCommand(): valid_commands = { "connect": [], - "disconnect": [] + "disconnect": [], + "fake_ack": [] } command, data, response = get_json_command_from_request(request, valid_commands) @@ -68,6 +69,8 @@ def connectionCommand(): printer.connect(port=port, baudrate=baudrate, profile=printerProfile) elif command == "disconnect": printer.disconnect() + elif command == "fake_ack": + printer.fake_ack() return NO_CONTENT diff --git a/src/octoprint/settings.py b/src/octoprint/settings.py index 8257cb6a..331b3e8f 100644 --- a/src/octoprint/settings.py +++ b/src/octoprint/settings.py @@ -132,6 +132,8 @@ default_settings = { "temperatureGraph": True, "waitForStartOnConnect": False, "alwaysSendChecksum": False, + "sendChecksumWithUnknownCommands": False, + "unknownCommandsNeedAck": False, "sdSupport": True, "sdAlwaysAvailable": False, "swallowOkAfterResend": True, diff --git a/src/octoprint/static/js/app/viewmodels/terminal.js b/src/octoprint/static/js/app/viewmodels/terminal.js index 235dd0c8..6ce008f6 100644 --- a/src/octoprint/static/js/app/viewmodels/terminal.js +++ b/src/octoprint/static/js/app/viewmodels/terminal.js @@ -173,6 +173,16 @@ $(function() { } }; + self.fakeAck = function() { + $.ajax({ + url: API_BASEURL + "connection", + type: "POST", + dataType: "json", + contentType: "application/json; charset=UTF-8", + data: JSON.stringify({"command": "fake_ack"}) + }); + }; + self.handleKeyDown = function(event) { var keyCode = event.keyCode; diff --git a/src/octoprint/templates/tabs/terminal.jinja2 b/src/octoprint/templates/tabs/terminal.jinja2 index 13a1cc3e..18d2a30a 100644 --- a/src/octoprint/templates/tabs/terminal.jinja2 +++ b/src/octoprint/templates/tabs/terminal.jinja2 @@ -20,3 +20,12 @@ {{ _('Hint: Use the arrow up/down keys to recall commands sent previously') }} + +
+ +
+ + {{ _("If acknowledgements (\"ok\"s) sent by the firmware get lost due to issues with the serial communication to your printer, OctoPrint's communication with it can become stuck. If that happens, this can help. Please be advised that such occurences hint at general communication issues with your printer which will probably negatively influence your printing results and which you should therefore try to resolve!") }} +
+
+ diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py index 88f0e098..15346858 100644 --- a/src/octoprint/util/comm.py +++ b/src/octoprint/util/comm.py @@ -155,6 +155,8 @@ class MachineCom(object): self._timeout = None self._alwaysSendChecksum = settings().getBoolean(["feature", "alwaysSendChecksum"]) + self._sendChecksumWithUnknownCommands = settings().getBoolean(["feature", "sendChecksumWithUnknownCommands"]) + self._unknownCommandsNeedAck = settings().getBoolean(["feature", "unknownCommandsNeedAck"]) self._currentLine = 1 self._resendDelta = None self._lastLines = deque([], 50) @@ -410,6 +412,9 @@ class MachineCom(object): def setTemperatureOffset(self, offsets): self._tempOffsets.update(offsets) + def fakeOk(self): + self._clear_to_send.set() + def sendCommand(self, cmd, cmd_type=None, processed=False): cmd = cmd.encode('ascii', 'replace') if not processed: @@ -420,7 +425,7 @@ class MachineCom(object): if self.isPrinting() and not self.isSdFileSelected(): self._commandQueue.put((cmd, cmd_type)) elif self.isOperational(): - self._sendCommand((cmd, cmd_type)) + self._sendCommand(cmd, cmd_type=cmd_type) def sendGcodeScript(self, scriptName, replacements=None): context = dict() @@ -520,7 +525,7 @@ class MachineCom(object): self.sendCommand(line) # now make sure we actually do something, up until now we only filled up the queue - self._sendFromQueue(sendChecksum=True) + self._sendFromQueue() except: self._logger.exception("Error while trying to start printing") self._errorValue = get_exception_string() @@ -621,7 +626,7 @@ class MachineCom(object): self.sendCommand(line) # now make sure we actually do something, up until now we only filled up the queue - self._sendFromQueue(sendChecksum=True) + self._sendFromQueue() eventManager().fire(Events.PRINT_RESUMED, payload) elif pause and self.isPrinting(): @@ -786,12 +791,12 @@ class MachineCom(object): #Start monitoring the serial port. self._timeout = get_new_timeout("communication") - startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"]) + startSeen = False supportRepetierTargetTemp = settings().getBoolean(["feature", "repetierTargetTemp"]) # enqueue an M105 first thing - self._sendCommand("M105") - if startSeen: + if not settings().getBoolean(["feature", "waitForStartOnConnect"]): + self._sendCommand("M110") self._clear_to_send.set() while self._monitoring_active: @@ -1013,7 +1018,7 @@ class MachineCom(object): self._baudrateDetectRetry -= 1 self._serial.write('\n') self._log("Baudrate test retry: %d" % (self._baudrateDetectRetry)) - self._sendCommand("M105") + self._sendCommand("M110") self._clear_to_send.set() else: baudrate = self._baudrateDetectList.pop(0) @@ -1024,11 +1029,11 @@ class MachineCom(object): self._baudrateDetectRetry = 5 self._timeout = get_new_timeout("communication") self._serial.write('\n') - self._sendCommand("M105") + self._sendCommand("M110") self._clear_to_send.set() except: self._log("Unexpected error while setting baudrate: %d %s" % (baudrate, get_exception_string())) - elif 'start' in line or ('ok' in line and 'T:' in line): + elif 'start' in line or 'ok' in line: self._onConnected() self._clear_to_send.set() @@ -1036,8 +1041,9 @@ class MachineCom(object): elif self._state == self.STATE_CONNECTING: if "start" in line and not startSeen: startSeen = True + self._sendCommand("M110") self._clear_to_send.set() - elif "ok" in line and startSeen: + elif "ok" in line: self._onConnected() elif time.time() > self._timeout: self.close() @@ -1074,7 +1080,7 @@ class MachineCom(object): self._resendNextCommand() else: - if self._sendFromQueue(sendChecksum=True): + if self._sendFromQueue(): pass elif not self.isSdPrinting(): self._sendNext() @@ -1164,9 +1170,18 @@ class MachineCom(object): eventManager().fire(Events.CONNECTED, payload) self.sendGcodeScript("afterPrinterConnected", replacements=dict(event=payload)) - def _sendFromQueue(self, sendChecksum=False): + def _sendFromQueue(self): if not self._commandQueue.empty() and not self.isStreaming(): - self._sendCommand(self._commandQueue.get(), sendChecksum) + entry = self._commandQueue.get() + if isinstance(entry, tuple): + if not len(entry) == 2: + return False + cmd, cmd_type = entry + else: + cmd = entry + cmd_type = None + + self._sendCommand(cmd, cmd_type=cmd_type) return True else: return False @@ -1325,7 +1340,7 @@ class MachineCom(object): with self._sendNextLock: line = self._getNext() if line is not None: - self._sendCommand(line, True) + self._sendCommand(line) self._callback.on_comm_progress() def _handleResendRequest(self, line): @@ -1385,64 +1400,53 @@ class MachineCom(object): self._lastResendNumber = None self._currentResendCount = 0 - def _sendCommand(self, cmd_tuple, sendChecksum=False): - if isinstance(cmd_tuple, tuple): - cmd, cmd_type = cmd_tuple - else: - cmd = cmd_tuple - cmd_type = None - + def _sendCommand(self, cmd, cmd_type=None): # Make sure we are only handling one sending job at a time with self._sendingLock: if self._serial is None: return if not self.isStreaming(): - for hook in self._gcode_hooks: - hook_cmd = self._gcode_hooks[hook](self, cmd, cmd_type=cmd_type, send_checksum=sendChecksum) + for name, hook in self._gcode_hooks.items(): + hook_cmd = hook(self, cmd, cmd_type=cmd_type) + + if hook_cmd is None: + cmd = None # hook might have returned (cmd, sendChecksum) or (cmd, sendChecksum, cmd_type), split that - if isinstance(hook_cmd, tuple): + elif isinstance(hook_cmd, tuple): if len(hook_cmd) == 2: hook_cmd, cmd_type = hook_cmd elif len(hook_cmd) == 3: - hook_cmd, cmd_type, sendChecksum = hook_cmd - - # hook might have returned None for cmd, if so stop processing, we won't send this command - # to the printer - if hook_cmd is None: - cmd = None - break + # legacy hook handler, ignore returned send_checksum + hook_cmd, cmd_type, _ = hook_cmd # if hook_cmd is a string, we'll replace cmd with it (it's been rewritten by the hook handler - elif isinstance(hook_cmd, basestring): + if isinstance(hook_cmd, basestring): cmd = hook_cmd + else: + self._logger.warn("Hook {name} returned unintelligible result, ignoring it: {hook_cmd!r}".format(**locals())) + continue + + if cmd is None: + break + # try to parse the cmd and extract the gcode type - gcode = self._regex_command.search(cmd) - if gcode: - gcode = gcode.group(1) + if cmd is not None: + gcode = self._regex_command.search(cmd) + if gcode: + gcode = gcode.group(1) - # fire events if necessary - if gcode in gcodeToEvent: - eventManager().fire(gcodeToEvent[gcode]) + # fire events if necessary + if gcode in gcodeToEvent: + eventManager().fire(gcodeToEvent[gcode]) - # send it through the specific handler if it exists - gcodeHandler = "_gcode_" + gcode - if hasattr(self, gcodeHandler): - cmd = getattr(self, gcodeHandler)(cmd) + # send it through the specific handler if it exists + cmd = self._process_command_phase("queue", cmd, gcode=gcode) if cmd is not None: - self._doSend(cmd, send_checksum=sendChecksum, cmd_type=cmd_type) - - def _doSend(self, cmd, send_checksum=False, cmd_type=None): - if send_checksum or self._alwaysSendChecksum: - lineNumber = self._currentLine - self._addToLastLines(cmd) - self._currentLine += 1 - self._enqueue_for_sending(cmd, linenumber=lineNumber, command_type=cmd_type) - else: - self._enqueue_for_sending(cmd, command_type=cmd_type) + self._enqueue_for_sending(cmd, command_type=cmd_type) def gcode_command_for_cmd(self, cmd): """ @@ -1497,20 +1501,62 @@ class MachineCom(object): if not self._send_queue_active: break - # fetch command and optional linenumber from queue, send it + # fetch command and optional linenumber from queue command, linenumber, _ = entry + + # some firmwares (e.g. Smoothie) might support additional in-band communication that will not + # stick to the acknowledgement behaviour of GCODE, so we check here if we have a GCODE command + # at hand here and only clear our clear_to_send flag later if that's the case + gcode_match = self._regex_command.search(command) + is_gcode = gcode_match is not None + + if is_gcode: + # trigger "sending" phase + command = self._process_command_phase("sending", command, gcode=gcode_match.group(1)) + if linenumber is not None: + # line number predetermined, use that self._doSendWithChecksum(command, linenumber) else: - self._doSendWithoutChecksum(command) + if (is_gcode or self._sendChecksumWithUnknownCommands) and (self.isPrinting() or self._alwaysSendChecksum): + linenumber = self._currentLine + self._addToLastLines(command) + self._currentLine += 1 + self._doSendWithChecksum(command, linenumber) + else: + self._doSendWithoutChecksum(command) - # we just used up one ok, clear it, wait for the next clear - self._clear_to_send.clear() + use_up_clear = not self._unknownCommandsNeedAck + if is_gcode: + # trigger "sent" phase and use up one "ok" + self._process_command_phase("sent", command, gcode=gcode_match.group(1)) + use_up_clear = True + + # if we need to use up a clear, do that now + if use_up_clear: + self._clear_to_send.clear() + + # wait for the next clear self._clear_to_send.wait() except: self._logger.exception("Caught an exception in the send loop") self._log("Closing down send loop") + def _process_command_phase(self, phase, command, gcode=None): + if gcode is None: + gcode_match = self._regex_command.search(command) + if gcode_match is None: + return command + + gcode = gcode.group(1) + + # send it through the specific handler if it exists + gcodeHandler = "_gcode_" + gcode + "_" + phase + if hasattr(self, gcodeHandler): + command = getattr(self, gcodeHandler)(command) + + return command + ##~~ actual sending via serial def _doSendWithChecksum(self, cmd, lineNumber): @@ -1538,13 +1584,13 @@ class MachineCom(object): ##~~ command handlers - def _gcode_T(self, cmd): + def _gcode_T_sent(self, cmd): toolMatch = self._regex_paramTInt.search(cmd) if toolMatch: self._currentTool = int(toolMatch.group(1)) return cmd - def _gcode_G0(self, cmd): + def _gcode_G0_sent(self, cmd): if 'Z' in cmd: match = self._regex_paramZFloat.search(cmd) if match: @@ -1556,14 +1602,14 @@ class MachineCom(object): except ValueError: pass return cmd - _gcode_G1 = _gcode_G0 + _gcode_G0_sent = _gcode_G0_sent - def _gcode_M0(self, cmd): + def _gcode_M0_queue(self, cmd): self.setPause(True) - return "M105" # Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause. - _gcode_M1 = _gcode_M0 + return None # Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause. + _gcode_M1_queued = _gcode_M0_queue - def _gcode_M104(self, cmd): + def _gcode_M104_sent(self, cmd): toolNum = self._currentTool toolMatch = self._regex_paramTInt.search(cmd) if toolMatch: @@ -1581,7 +1627,7 @@ class MachineCom(object): pass return cmd - def _gcode_M140(self, cmd): + def _gcode_M140_sent(self, cmd): match = self._regex_paramSInt.search(cmd) if match: try: @@ -1595,19 +1641,19 @@ class MachineCom(object): pass return cmd - def _gcode_M109(self, cmd): + def _gcode_M109_sent(self, cmd): self._heatupWaitStartTime = time.time() self._blocking_command = True self._heating = True - return self._gcode_M104(cmd) + return self._gcode_M104_sent(cmd) - def _gcode_M190(self, cmd): + def _gcode_M190_sent(self, cmd): self._heatupWaitStartTime = time.time() self._blocking_command = True self._heating = True - return self._gcode_M140(cmd) + return self._gcode_M140_sent(cmd) - def _gcode_M110(self, cmd): + def _gcode_M110_sending(self, cmd): newLineNumber = None match = self._regex_paramNInt.search(cmd) if match: @@ -1619,20 +1665,19 @@ class MachineCom(object): newLineNumber = 0 # send M110 command with new line number - self._enqueue_for_sending(cmd, linenumber=newLineNumber) - self._currentLine = newLineNumber + 1 + self._currentLine = newLineNumber # after a reset of the line number we have no way to determine what line exactly the printer now wants self._lastLines.clear() self._resendDelta = None - return None + return cmd - def _gcode_M112(self, cmd): # It's an emergency what todo? Canceling the print should be the minimum + def _gcode_M112_queue(self, cmd): # It's an emergency what todo? Canceling the print should be the minimum self.cancelPrint() return cmd - def _gcode_G4(self, cmd): + def _gcode_G4_sent(self, cmd): # we are intending to dwell for a period of time, increase the timeout to match cmd = cmd.upper() p_idx = cmd.find('P') @@ -1648,12 +1693,12 @@ class MachineCom(object): self._blocking_command = True return cmd - def _gcode_G28(self, cmd): + def _gcode_G28_sending(self, cmd): self._blocking_command = True return cmd - _gcode_G29 = _gcode_G28 - _gcode_G30 = _gcode_G28 - _gcode_G32 = _gcode_G28 + _gcode_G29_sending = _gcode_G28_sending + _gcode_G30_sending = _gcode_G28_sending + _gcode_G32_sending = _gcode_G28_sending ### MachineCom callback ################################################################################################