def _populated_check(self, target, check): if not "type" in check: raise exceptions.UnknownCheckType() result = dict(check) if target == "octoprint": from flask.ext.babel import gettext result["displayName"] = check.get("displayName", gettext("OctoPrint")) result["displayVersion"] = check.get("displayVersion", "{octoprint_version}") from octoprint._version import get_versions versions = get_versions() if check["type"] == "github_commit": result["current"] = versions.get("full-revisionid", versions.get("full", "unknown")) else: result["current"] = versions["version"] else: result["displayName"] = check.get("displayName", target) result["displayVersion"] = check.get("displayVersion", check.get("current", "unknown")) if check["type"] in ("github_commit"): result["current"] = check.get("current", None) else: result["current"] = check.get("current", check.get("displayVersion", None)) return result
def _load_version_cache(self): if not os.path.isfile(self._version_cache_path): return import yaml try: with open(self._version_cache_path) as f: data = yaml.safe_load(f) except: self._logger.exception("Error while loading version cache from disk") else: try: if not isinstance(data, dict): self._logger.info("Version cache was created in a different format, not using it") return if "__version" in data: data_version = data["__version"] else: self._logger.info("Can't determine version of OctoPrint version cache was created for, not using it") return from octoprint._version import get_versions octoprint_version = get_versions()["version"] if data_version != octoprint_version: self._logger.info("Version cache was created for another version of OctoPrint, not using it") return self._version_cache = data self._version_cache_dirty = False self._logger.info("Loaded version cache from disk") except: self._logger.exception("Error parsing in version cache data")
def get_current_versions(self, check_targets=None, force=False): """ Retrieves the current version information for all defined check_targets. Will retrieve information for all available targets by default. :param check_targets: an iterable defining the targets to check, if not supplied defaults to all targets """ checks = self._get_configured_checks() if check_targets is None: check_targets = checks.keys() update_available = False update_possible = False information = dict() for target, check in checks.items(): if not target in check_targets: continue try: populated_check = self._populated_check(target, check) target_information, target_update_available, target_update_possible = self._get_current_version( target, populated_check, force=force) if target_information is None: target_information = dict() except exceptions.UnknownCheckType: self._logger.warn( "Unknown update check type for target {}: {}".format( target, check.get("type", "<n/a>"))) continue target_information = dict_merge( dict(local=dict(name="unknown", value="unknown"), remote=dict(name="unknown", value="unknown")), target_information) update_available = update_available or target_update_available update_possible = update_possible or (target_update_possible and target_update_available) from octoprint._version import get_versions octoprint_version = get_versions()["version"] local_name = target_information["local"]["name"] local_value = target_information["local"]["value"] information[target] = dict( updateAvailable=target_update_available, updatePossible=target_update_possible, information=target_information, displayName=populated_check["displayName"], displayVersion=populated_check["displayVersion"].format( octoprint_version=octoprint_version, local_name=local_name, local_value=local_value), check=populated_check) if self._version_cache_dirty: self._save_version_cache() return information, update_available, update_possible
def _get_version_checker(self, target, check): """ Retrieves the version checker to use for given target and check configuration. Will raise an UnknownCheckType if version checker cannot be determined. """ if not "type" in check: raise exceptions.ConfigurationInvalid("no check type defined") if target == "octoprint": from octoprint._version import get_versions from flask.ext.babel import gettext check["displayName"] = gettext("OctoPrint") check["displayVersion"] = "{octoprint_version}" check["current"] = get_versions()["version"] check_type = check["type"] if check_type == "github_release": return version_checks.github_release elif check_type == "github_commit": return version_checks.github_commit elif check_type == "git_commit": return version_checks.git_commit elif check_type == "commandline": return version_checks.commandline elif check_type == "python_checker": return version_checks.python_checker else: raise exceptions.UnknownCheckType()
def _load_version_cache(self): if not os.path.isfile(self._version_cache_path): return import yaml try: with open(self._version_cache_path) as f: data = yaml.safe_load(f) timestamp = os.stat(self._version_cache_path).st_mtime except: self._logger.exception("Error while loading version cache from disk") else: try: if not isinstance(data, dict): self._logger.info("Version cache was created in a different format, not using it") return if "__version" in data: data_version = data["__version"] else: self._logger.info("Can't determine version of OctoPrint version cache was created for, not using it") return from octoprint._version import get_versions octoprint_version = get_versions()["version"] if data_version != octoprint_version: self._logger.info("Version cache was created for another version of OctoPrint, not using it") return self._version_cache = data self._version_cache_dirty = False self._version_cache_timestamp = timestamp self._logger.info("Loaded version cache from disk") except: self._logger.exception("Error parsing in version cache data")
def _populated_check(self, target, check): if not "type" in check: raise exceptions.UnknownCheckType() result = dict(check) if target == "octoprint": from flask.ext.babel import gettext result["displayName"] = check.get("displayName", gettext("OctoPrint")) result["displayVersion"] = check.get("displayVersion", "{octoprint_version}") from octoprint._version import get_versions versions = get_versions() if check["type"] == "github_commit": result["current"] = versions.get( "full-revisionid", versions.get("full", "unknown")) else: result["current"] = versions["version"] else: result["displayName"] = check.get("displayName", target) result["displayVersion"] = check.get( "displayVersion", check.get("current", "unknown")) if check["type"] in ("github_commit"): result["current"] = check.get("current", None) else: result["current"] = check.get( "current", check.get("displayVersion", None)) return result
def _populated_check(self, target, check): result = dict(check) if target == "octoprint": from flask.ext.babel import gettext result["displayName"] = check.get("displayName", gettext("Due Raster")) result["displayVersion"] = check.get("displayVersion", gettext("1.2.2")) from octoprint._version import get_versions versions = get_versions() if check["type"] == "github_commit": result["current"] = check.get("current", None) # result["current"] = versions.get("full-revisionid", versions.get("full", "unknown")) else: result["current"] = versions["version"] else: result["displayName"] = check.get("displayName", target) result["displayVersion"] = check.get( "displayVersion", check.get("current", "unknown")) if check["type"] in ("github_commit"): result["current"] = check.get("current", None) else: result["current"] = check.get( "current", check.get("displayVersion", None)) return result
def get_current_versions(self, check_targets=None, force=False): """ Retrieves the current version information for all defined check_targets. Will retrieve information for all available targets by default. :param check_targets: an iterable defining the targets to check, if not supplied defaults to all targets """ checks = self._get_configured_checks() if check_targets is None: check_targets = checks.keys() update_available = False update_possible = False information = dict() for target, check in checks.items(): if not target in check_targets: continue try: target_information, target_update_available, target_update_possible = self._get_current_version( target, check, force=force ) if target_information is None: continue except exceptions.UnknownCheckType: self._logger.warn("Unknown update check type for %s" % target) continue target_information = dict_merge( dict(local=dict(name="unknown", value="unknown"), remote=dict(name="unknown", value="unknown")), target_information, ) update_available = update_available or target_update_available update_possible = update_possible or (target_update_possible and target_update_available) information[target] = dict( updateAvailable=target_update_available, updatePossible=target_update_possible, information=target_information, ) if "displayName" in check: information[target]["displayName"] = check["displayName"] if "displayVersion" in check: from octoprint._version import get_versions octoprint_version = get_versions()["version"] local_name = target_information["local"]["name"] local_value = target_information["local"]["value"] information[target]["displayVersion"] = check["displayVersion"].format( octoprint_version=octoprint_version, local_name=local_name, local_value=local_value ) if self._version_cache_dirty: self._save_version_cache() return information, update_available, update_possible
def _save_version_cache(self): import yaml from octoprint.util import atomic_write from octoprint._version import get_versions octoprint_version = get_versions()["version"] self._version_cache["__version"] = octoprint_version with atomic_write(self._version_cache_path) as file_obj: yaml.safe_dump(self._version_cache, stream=file_obj, default_flow_style=False, indent=" ", allow_unicode=True) self._version_cache_dirty = False self._logger.info("Saved version cache to disk")
def get_assets(self): from octoprint._version import get_versions octoprint_version = self._parse_version(get_versions()["version"]) settings_max_version = self._parse_version( self._settings.get(["octoprint_max_version"])) default_max_version = self._parse_version(self.octoprint_max_version) if octoprint_version < default_max_version: self._settings.set(["octoprint_max_version"], None) elif settings_max_version is not None and settings_max_version != '': if octoprint_version > settings_max_version: return dict(js=["js/squishsettings.js"]) else: return dict(js=["js/squishsettings.js"]) return dict(js=["js/squish.js"], css=["css/squish.css"])
def get_assets(self): from octoprint._version import get_versions octoprint_version = self._parse_version(get_versions()["version"]) settings_max_version = self._parse_version(self._settings.get(["octoprint_max_version"])) default_max_version = self._parse_version(self.octoprint_max_version) if octoprint_version < default_max_version: self._settings.set(["octoprint_max_version"], None) elif settings_max_version is not None and settings_max_version != '': if octoprint_version > settings_max_version: return dict(js=["js/squishsettings.js"]) else: return dict(js=["js/squishsettings.js"]) return dict( js=["js/squish.js"], css=["css/squish.css"] )
def _load_version_cache(self): if not os.path.isfile(self._version_cache_path): return import yaml try: with open(self._version_cache_path) as f: data = yaml.safe_load(f) except: self._logger.exception("Error while loading version cache from disk") else: try: if ( "octoprint" in data and len(data["octoprint"]) == 4 and "local" in data["octoprint"][1] and "value" in data["octoprint"][1]["local"] ): data_version = data["octoprint"][1]["local"]["value"] else: self._logger.info( "Can't determine version of OctoPrint version cache was created for, not using it" ) return from octoprint._version import get_versions octoprint_version = get_versions()["version"] if data_version != octoprint_version: self._logger.info("Version cache was created for another version of OctoPrint, not using it") return self._version_cache = data self._version_cache_dirty = False self._logger.info("Loaded version cache from disk") except: self._logger.exception("Error parsing in version cache data")
def _load_version_cache(self): if not os.path.isfile(self._version_cache_path): return import yaml try: with open(self._version_cache_path) as f: data = yaml.safe_load(f) except: self._logger.exception( "Error while loading version cache from disk") else: try: if "octoprint" in data and len( data["octoprint"] ) == 4 and "local" in data["octoprint"][1] and "value" in data[ "octoprint"][1]["local"]: data_version = data["octoprint"][1]["local"]["value"] else: self._logger.info( "Can't determine version of OctoPrint version cache was created for, not using it" ) return from octoprint._version import get_versions octoprint_version = get_versions()["version"] if data_version != octoprint_version: self._logger.info( "Version cache was created for another version of OctoPrint, not using it" ) return self._version_cache = data self._version_cache_dirty = False self._logger.info("Loaded version cache from disk") except: self._logger.exception("Error parsing in version cache data")
def _processIncoming(self): next_wait_timeout = time.time() + self._waitInterval buf = "" while self.incoming is not None and not self._killed: self._simulateTemps() try: data = self.incoming.get(timeout=0.01) self.incoming.task_done() except Queue.Empty: if self._sendWait and time.time() > next_wait_timeout: self._output("wait") next_wait_timeout = time.time() + self._waitInterval continue buf += data if "\n" in buf: data = buf[:buf.find("\n") + 1] buf = buf[buf.find("\n") + 1:] else: continue next_wait_timeout = time.time() + self._waitInterval if data is None: continue if self._dont_answer: self._dont_answer = False continue data = data.strip() # strip checksum if "*" in data: checksum = int(data[data.rfind("*") + 1:]) data = data[:data.rfind("*")] if not checksum == self._calculate_checksum(data): self._triggerResend(expected=self.currentLine + 1) continue self.currentLine += 1 elif settings().getBoolean( ["devel", "virtualPrinter", "forceChecksum"]): self._output("Error: Missing checksum") continue # track N = N + 1 if data.startswith("N") and "M110" in data: linenumber = int(re.search("N([0-9]+)", data).group(1)) self.lastN = linenumber self.currentLine = linenumber self._triggerResendAt100 = True self._triggerResendWithTimeoutAt105 = True self._sendOk() continue elif data.startswith("N"): linenumber = int(re.search("N([0-9]+)", data).group(1)) expected = self.lastN + 1 if linenumber != expected: self._triggerResend(actual=linenumber) continue elif linenumber == 100 and self._triggerResendAt100: # simulate a resend at line 100 self._triggerResendAt100 = False self._triggerResend(expected=100) continue elif linenumber == 105 and self._triggerResendWithTimeoutAt105 and not self._writingToSd: # simulate a resend with timeout at line 105 self._triggerResendWithTimeoutAt105 = False self._triggerResend(expected=105) self._dont_answer = True self.lastN = linenumber continue else: self.lastN = linenumber data = data.split(None, 1)[1].strip() data += "\n" # shortcut for writing to SD if self._writingToSdHandle is not None and not "M29" in data: self._writingToSdHandle.write(data) self._sendOk() continue if data.strip() == "version": from octoprint._version import get_versions self._output("OctoPrint VirtualPrinter v" + get_versions()["version"]) continue elif data.startswith("!!DEBUG:"): self._debugTrigger(data[len("!!DEBUG:"):].strip()) continue if len(data.strip()) > 0 and self._okBeforeCommandOutput: self._sendOk() #print "Send: %s" % (data.rstrip()) if 'M104' in data or 'M109' in data: wait = support_r = 'M109' in data self._parseHotendCommand(data, wait=wait, support_r=support_r) if 'M140' in data or 'M190' in data: wait = support_r = 'M190' in data self._parseBedCommand(data, wait=wait, support_r=support_r) if 'M105' in data: self._processTemperatureQuery() continue elif 'M20' in data: if self._sdCardReady: self._listSd() elif 'M21' in data: self._sdCardReady = True self._output("SD card ok") elif 'M22' in data: self._sdCardReady = False elif 'M23' in data: if self._sdCardReady: filename = data.split(None, 1)[1].strip() self._selectSdFile(filename) elif 'M24' in data: if self._sdCardReady: self._startSdPrint() elif 'M25' in data: if self._sdCardReady: self._pauseSdPrint() elif 'M26' in data: if self._sdCardReady: pos = int(re.search("S([0-9]+)", data).group(1)) self._setSdPos(pos) elif 'M27' in data: if self._sdCardReady: self._reportSdStatus() elif 'M28' in data: if self._sdCardReady: filename = data.split(None, 1)[1].strip() self._writeSdFile(filename) elif 'M29' in data: if self._sdCardReady: self._finishSdFile() if self._brokenM29: continue elif 'M30' in data: if self._sdCardReady: filename = data.split(None, 1)[1].strip() self._deleteSdFile(filename) elif "M114" in data: # send dummy position report output = "X:10.00 Y:3.20 Z:5.20 E:1.24 Count: A:1000 B:320 C:1040" if not self._okBeforeCommandOutput: output = "ok " + output self._output(output) continue elif "M117" in data: # we'll just use this to echo a message, to allow playing around with pause triggers if self._echoOnM117: self._output("echo:%s" % re.search("M117\s+(.*)", data).group(1)) elif "M999" in data: # mirror Marlin behaviour self._output("Resend: 1") elif data.startswith("T"): self.currentExtruder = int(re.search("T(\d+)", data).group(1)) self._output("Active Extruder: %d" % self.currentExtruder) elif "G20" in data: self._unitModifier = 1.0 / 2.54 if self._lastX is not None: self._lastX *= 2.54 if self._lastY is not None: self._lastY *= 2.54 if self._lastZ is not None: self._lastZ *= 2.54 if self._lastE is not None: self._lastE *= 2.54 elif "G21" in data: self._unitModifier = 1.0 if self._lastX is not None: self._lastX /= 2.54 if self._lastY is not None: self._lastY /= 2.54 if self._lastZ is not None: self._lastZ /= 2.54 if self._lastE is not None: self._lastE /= 2.54 elif "G90" in data: self._relative = False elif "G91" in data: self._relative = True elif "G92" in data: self._setPosition(data) elif data.startswith("G28"): self._performMove(data) elif data.startswith("G0") or data.startswith( "G1") or data.startswith("G2") or data.startswith("G3"): # simulate reprap buffered commands via a Queue with maxsize which internally simulates the moves self.buffered.put(data) if len(self._sleepAfter) or len(self._sleepAfterNext): command_match = VirtualPrinter.command_regex.match(data) if command_match is not None: command = command_match.group(0) interval = None if command in self._sleepAfter: interval = self._sleepAfter[command] elif command in self._sleepAfterNext: interval = self._sleepAfterNext[command] del self._sleepAfterNext[command] if interval is not None: self._output( "// sleeping for {interval} seconds".format( interval=interval)) time.sleep(interval) if len(data.strip()) > 0 and not self._okBeforeCommandOutput: self._sendOk() self._logger.info("Closing down read loop")
def _get_octoprint_version(self): from octoprint._version import get_versions return get_versions()["version"]
def __init__(self): self.octoprint_version = get_versions()["version"] roboprinter.printer_instance._logger.info( "Initialized Printer Jog, Octoprint Version is: " + str(self.octoprint_version))
def _processIncoming(self): next_wait_timeout = time.time() + self._waitInterval while self.incoming is not None: self._simulateTemps() try: data = self.incoming.get(timeout=0.01) except Queue.Empty: if self._sendWait and time.time() > next_wait_timeout: self.outgoing.put("wait") next_wait_timeout = time.time() + self._waitInterval continue next_wait_timeout = time.time() + self._waitInterval if data is None: continue if self._dont_answer: self._dont_answer = False continue data = data.strip() # strip checksum if "*" in data: data = data[:data.rfind("*")] self.currentLine += 1 elif settings().getBoolean(["devel", "virtualPrinter", "forceChecksum"]): self.outgoing.put("Error: Missing checksum") continue # track N = N + 1 if data.startswith("N") and "M110" in data: linenumber = int(re.search("N([0-9]+)", data).group(1)) self.lastN = linenumber self.currentLine = linenumber self._sendOk() continue elif data.startswith("N"): linenumber = int(re.search("N([0-9]+)", data).group(1)) expected = self.lastN + 1 if linenumber != expected: self._triggerResend(actual=linenumber) continue elif self.currentLine == 101: # simulate a resend at line 100 self._triggerResend(expected=100) continue else: self.lastN = linenumber data = data.split(None, 1)[1].strip() data += "\n" # shortcut for writing to SD if self._writingToSd and not self._selectedSdFile is None and not "M29" in data: with open(self._selectedSdFile, "a") as f: f.write(data) self._sendOk() continue if data.strip() == "version": from octoprint._version import get_versions self.outgoing.put("OctoPrint VirtualPrinter v" + get_versions()["version"]) continue elif data.startswith("!!DEBUG:"): self._debugTrigger(data[len("!!DEBUG:"):].strip()) continue if len(data.strip()) > 0 and self._okBeforeCommandOutput: self._sendOk() #print "Send: %s" % (data.rstrip()) if 'M104' in data or 'M109' in data: self._parseHotendCommand(data) if 'M140' in data or 'M190' in data: self._parseBedCommand(data) if 'M105' in data: self._processTemperatureQuery() continue elif 'M20' in data: if self._sdCardReady: self._listSd() elif 'M21' in data: self._sdCardReady = True self.outgoing.put("SD card ok") elif 'M22' in data: self._sdCardReady = False elif 'M23' in data: if self._sdCardReady: filename = data.split(None, 1)[1].strip() self._selectSdFile(filename) elif 'M24' in data: if self._sdCardReady: self._startSdPrint() elif 'M25' in data: if self._sdCardReady: self._pauseSdPrint() elif 'M26' in data: if self._sdCardReady: pos = int(re.search("S([0-9]+)", data).group(1)) self._setSdPos(pos) elif 'M27' in data: if self._sdCardReady: self._reportSdStatus() elif 'M28' in data: if self._sdCardReady: filename = data.split(None, 1)[1].strip() self._writeSdFile(filename) elif 'M29' in data: if self._sdCardReady: self._finishSdFile() elif 'M30' in data: if self._sdCardReady: filename = data.split(None, 1)[1].strip() self._deleteSdFile(filename) elif "M114" in data: # send dummy position report output = "C: X:10.00 Y:3.20 Z:5.20 E:1.24" if not self._okBeforeCommandOutput: output = "ok " + output self.outgoing.put(output) continue elif "M117" in data: # we'll just use this to echo a message, to allow playing around with pause triggers self.outgoing.put("echo:%s" % re.search("M117\s+(.*)", data).group(1)) elif "M999" in data: # mirror Marlin behaviour self.outgoing.put("Resend: 1") elif data.startswith("T"): self.currentExtruder = int(re.search("T(\d+)", data).group(1)) self.outgoing.put("Active Extruder: %d" % self.currentExtruder) elif "G20" in data: self._unitModifier = 1.0 / 2.54 if self._lastX is not None: self._lastX *= 2.54 if self._lastY is not None: self._lastY *= 2.54 if self._lastZ is not None: self._lastZ *= 2.54 if self._lastE is not None: self._lastE *= 2.54 elif "G21" in data: self._unitModifier = 1.0 if self._lastX is not None: self._lastX /= 2.54 if self._lastY is not None: self._lastY /= 2.54 if self._lastZ is not None: self._lastZ /= 2.54 if self._lastE is not None: self._lastE /= 2.54 elif "G90" in data: self._relative = False elif "G91" in data: self._relative = True elif "G92" in data: self._setPosition(data) elif data.startswith("G0") or data.startswith("G1") or data.startswith("G2") or data.startswith("G3") \ or data.startswith("G28") or data.startswith("G29") or data.startswith("G30") \ or data.startswith("G31") or data.startswith("G32"): # simulate reprap buffered commands via a Queue with maxsize which internally simulates the moves self.buffered.put(data) if len(self._sleepAfter) or len(self._sleepAfterNext): command_match = VirtualPrinter.command_regex.match(data) if command_match is not None: command = command_match.group(0) interval = None if command in self._sleepAfter: interval = self._sleepAfter[command] elif command in self._sleepAfterNext: interval = self._sleepAfterNext[command] del self._sleepAfterNext[command] if interval is not None: self.outgoing.put("// sleeping for {interval} seconds".format(interval=interval)) time.sleep(interval) if len(data.strip()) > 0 and not self._okBeforeCommandOutput: self._sendOk()
def _processIncoming(self): next_wait_timeout = time.time() + self._waitInterval buf = "" while self.incoming is not None and not self._killed: self._simulateTemps() try: data = self.incoming.get(timeout=0.01) self.incoming.task_done() except queue.Empty: if self._sendWait and time.time() > next_wait_timeout: self._send("wait") next_wait_timeout = time.time() + self._waitInterval continue buf += data if "\n" in buf: data = buf[:buf.find("\n") + 1] buf = buf[buf.find("\n") + 1:] else: continue next_wait_timeout = time.time() + self._waitInterval if data is None: continue if self._dont_answer: self._dont_answer = False continue data = data.strip() # strip checksum if "*" in data: checksum = int(data[data.rfind("*") + 1:]) data = data[:data.rfind("*")] if not checksum == self._calculate_checksum(data): self._triggerResend(expected=self.currentLine + 1) continue self.currentLine += 1 elif settings().getBoolean( ["devel", "virtualPrinter", "forceChecksum"]): self._send("Error: Missing checksum") continue # track N = N + 1 if data.startswith("N") and "M110" in data: linenumber = int(re.search("N([0-9]+)", data).group(1)) self.lastN = linenumber self.currentLine = linenumber self._triggerResendAt100 = True self._triggerResendWithTimeoutAt105 = True self._sendOk() continue elif data.startswith("N"): linenumber = int(re.search("N([0-9]+)", data).group(1)) expected = self.lastN + 1 if linenumber != expected: self._triggerResend(actual=linenumber) continue elif linenumber == 100 and self._triggerResendAt100: # simulate a resend at line 100 self._triggerResendAt100 = False self._triggerResend(expected=100) continue elif linenumber == 105 and self._triggerResendWithTimeoutAt105 and not self._writingToSd: # simulate a resend with timeout at line 105 self._triggerResendWithTimeoutAt105 = False self._triggerResend(expected=105) self._dont_answer = True self.lastN = linenumber continue else: self.lastN = linenumber data = data.split(None, 1)[1].strip() data += "\n" # shortcut for writing to SD if self._writingToSdHandle is not None and not "M29" in data: self._writingToSdHandle.write(data) self._sendOk() continue if data.strip() == "version": from octoprint._version import get_versions self._send("OctoPrint VirtualPrinter v" + get_versions()["version"]) continue elif data.startswith("!!DEBUG:") or data.strip() == "!!DEBUG": debug_command = "" if data.startswith("!!DEBUG:"): debug_command = data[len("!!DEBUG:"):].strip() self._debugTrigger(debug_command) continue # if we are sending oks before command output, send it now if len(data.strip()) > 0 and self._okBeforeCommandOutput: self._sendOk() # actual command handling command_match = VirtualPrinter.command_regex.match(data) if command_match is not None: command = command_match.group(0) letter = command_match.group(1) try: # if we have a method _gcode_G, _gcode_M or _gcode_T, execute that first letter_handler = "_gcode_{}".format(letter) if hasattr(self, letter_handler): code = command_match.group(2) handled = getattr(self, letter_handler)(code, data) if handled: continue # then look for a method _gcode_<command> and execute that if it exists command_handler = "_gcode_{}".format(command) if hasattr(self, command_handler): handled = getattr(self, command_handler)(data) if handled: continue finally: # make sure that the debug sleepAfter and sleepAfterNext stuff works even # if we continued above if len(self._sleepAfter) or len(self._sleepAfterNext): interval = None if command in self._sleepAfter: interval = self._sleepAfter[command] elif command in self._sleepAfterNext: interval = self._sleepAfterNext[command] del self._sleepAfterNext[command] if interval is not None: self._send( "// sleeping for {interval} seconds".format( interval=interval)) time.sleep(interval) # if we are sending oks after command output, send it now if len(data.strip()) > 0 and not self._okBeforeCommandOutput: self._sendOk() self._logger.info("Closing down read loop")
def _processIncoming(self): next_wait_timeout = time.time() + self._waitInterval buf = "" while self.incoming is not None and not self._killed: self._simulateTemps() try: data = self.incoming.get(timeout=0.01) self.incoming.task_done() except queue.Empty: if self._sendWait and time.time() > next_wait_timeout: self._send("wait") next_wait_timeout = time.time() + self._waitInterval continue buf += data if "\n" in buf: data = buf[:buf.find("\n") + 1] buf = buf[buf.find("\n") + 1:] else: continue next_wait_timeout = time.time() + self._waitInterval if data is None: continue if self._dont_answer: self._dont_answer = False continue data = data.strip() # strip checksum if "*" in data: checksum = int(data[data.rfind("*") + 1:]) data = data[:data.rfind("*")] if not checksum == self._calculate_checksum(data): self._triggerResend(expected=self.currentLine + 1) continue self.currentLine += 1 elif settings().getBoolean(["devel", "virtualPrinter", "forceChecksum"]): self._send("Error: Missing checksum") continue # track N = N + 1 if data.startswith("N") and "M110" in data: linenumber = int(re.search("N([0-9]+)", data).group(1)) self.lastN = linenumber self.currentLine = linenumber self._triggerResendAt100 = True self._triggerResendWithTimeoutAt105 = True self._sendOk() continue elif data.startswith("N"): linenumber = int(re.search("N([0-9]+)", data).group(1)) expected = self.lastN + 1 if linenumber != expected: self._triggerResend(actual=linenumber) continue elif linenumber == 100 and self._triggerResendAt100: # simulate a resend at line 100 self._triggerResendAt100 = False self._triggerResend(expected=100) continue elif linenumber == 105 and self._triggerResendWithTimeoutAt105 and not self._writingToSd: # simulate a resend with timeout at line 105 self._triggerResendWithTimeoutAt105 = False self._triggerResend(expected=105) self._dont_answer = True self.lastN = linenumber continue else: self.lastN = linenumber data = data.split(None, 1)[1].strip() data += "\n" # shortcut for writing to SD if self._writingToSdHandle is not None and not "M29" in data: self._writingToSdHandle.write(data) self._sendOk() continue if data.strip() == "version": from octoprint._version import get_versions self._send("OctoPrint VirtualPrinter v" + get_versions()["version"]) continue elif data.startswith("!!DEBUG:") or data.strip() == "!!DEBUG": debug_command = "" if data.startswith("!!DEBUG:"): debug_command = data[len("!!DEBUG:"):].strip() self._debugTrigger(debug_command) continue # if we are sending oks before command output, send it now if len(data.strip()) > 0 and self._okBeforeCommandOutput: self._sendOk() # actual command handling command_match = VirtualPrinter.command_regex.match(data) if command_match is not None: command = command_match.group(0) letter = command_match.group(1) try: # if we have a method _gcode_G, _gcode_M or _gcode_T, execute that first letter_handler = "_gcode_{}".format(letter) if hasattr(self, letter_handler): code = command_match.group(2) handled = getattr(self, letter_handler)(code, data) if handled: continue # then look for a method _gcode_<command> and execute that if it exists command_handler = "_gcode_{}".format(command) if hasattr(self, command_handler): handled = getattr(self, command_handler)(data) if handled: continue finally: # make sure that the debug sleepAfter and sleepAfterNext stuff works even # if we continued above if len(self._sleepAfter) or len(self._sleepAfterNext): interval = None if command in self._sleepAfter: interval = self._sleepAfter[command] elif command in self._sleepAfterNext: interval = self._sleepAfterNext[command] del self._sleepAfterNext[command] if interval is not None: self._send("// sleeping for {interval} seconds".format(interval=interval)) time.sleep(interval) # if we are sending oks after command output, send it now if len(data.strip()) > 0 and not self._okBeforeCommandOutput: self._sendOk() self._logger.info("Closing down read loop")