comm: More resilience against garbage on the line during connect
* leading and trailing null bytes will now be stripped
* while connecting, a "wait" will also trigger switch to connected
state - relevant when connecting without reset and initial "ok" for
M110 gets mangled
* extended virtual printer by new options to test the above:
* mangled "ok" can now be injected via "preparedOks" setting and
prepare_ok DEBUG command
* simulated reset lines on beginning ("start" etc) now only sent
if new setting "simulateReset" is true
Should fix #1770
This commit is contained in:
parent
b8cbe02b7a
commit
e1eaf4eb8e
3 changed files with 33 additions and 10 deletions
|
|
@ -25,6 +25,7 @@ class VirtualPrinter(object):
|
|||
sleep_after_regex = re.compile("sleep_after ([GMTF]\d+) (\d+)")
|
||||
sleep_after_next_regex = re.compile("sleep_after_next ([GMTF]\d+) (\d+)")
|
||||
custom_action_regex = re.compile("action_custom ([a-zA-Z0-9_]+)(\s+.*)?")
|
||||
prepare_ok_regex = re.compile("prepare_ok (.*)?")
|
||||
|
||||
def __init__(self, seriallog_handler=None, read_timeout=5.0, write_timeout=10.0):
|
||||
import logging
|
||||
|
|
@ -50,8 +51,15 @@ class VirtualPrinter(object):
|
|||
self.outgoing = queue.Queue()
|
||||
self.buffered = queue.Queue(maxsize=settings().getInt(["devel", "virtualPrinter", "commandBuffer"]))
|
||||
|
||||
for item in ['start\n', 'Marlin: Virtual Marlin!\n', '\x80\n', 'SD card ok\n']:
|
||||
self._send(item)
|
||||
if settings().getBoolean(["devel", "virtualPrinter", "simulateReset"]):
|
||||
for item in ['start\n', 'Marlin: Virtual Marlin!\n', '\x80\n', 'SD card ok\n']:
|
||||
self._send(item)
|
||||
|
||||
self._prepared_oks = []
|
||||
prepared = settings().get(["devel", "virtualPrinter", "preparedOks"])
|
||||
if prepared and isinstance(prepared, list):
|
||||
for prep in prepared:
|
||||
self._prepared_oks.append(prep)
|
||||
|
||||
self.currentExtruder = 0
|
||||
self.extruderCount = settings().getInt(["devel", "virtualPrinter", "numExtruders"])
|
||||
|
|
@ -385,7 +393,7 @@ class VirtualPrinter(object):
|
|||
def _gcode_M114(self, data):
|
||||
output = "X:{} Y:{} Z:{} E:{} Count: A:{} B:{} C:{}".format(self._lastX, self._lastY, self._lastZ, self._lastE, int(self._lastX*100), int(self._lastY*100), int(self._lastZ*100))
|
||||
if not self._okBeforeCommandOutput:
|
||||
output = "ok " + output
|
||||
output = "{} {}".format(self._ok(), output)
|
||||
self._send(output)
|
||||
return True
|
||||
|
||||
|
|
@ -498,7 +506,7 @@ class VirtualPrinter(object):
|
|||
|
||||
def request_resend():
|
||||
self._send("Resend:%d" % expected)
|
||||
self._send("ok")
|
||||
self._send(self._ok())
|
||||
|
||||
if settings().getBoolean(["devel", "virtualPrinter", "repetierStyleResends"]):
|
||||
request_resend()
|
||||
|
|
@ -538,6 +546,9 @@ class VirtualPrinter(object):
|
|||
| Triggers a resend error with a checksum mismatch
|
||||
drop_connection
|
||||
| Drops the serial connection
|
||||
prepare_ok <broken ok>
|
||||
| Will cause <broken ok> to be enqueued for use,
|
||||
| will be used instead of actual "ok"
|
||||
|
||||
# Reply Timing / Sleeping
|
||||
|
||||
|
|
@ -546,7 +557,7 @@ class VirtualPrinter(object):
|
|||
sleep_after <str:command> <int:seconds>
|
||||
| Sleeps <seconds> s after each execution of <command>
|
||||
sleep_after_next <str:command> <int:seconds>
|
||||
| Sleeps <seconds> s after execution of <command>
|
||||
| Sleeps <seconds> s after execution of next <command>
|
||||
"""
|
||||
for line in usage.split("\n"):
|
||||
self._send("echo: {}".format(line.strip()))
|
||||
|
|
@ -575,6 +586,7 @@ class VirtualPrinter(object):
|
|||
sleep_after_match = VirtualPrinter.sleep_after_regex.match(data)
|
||||
sleep_after_next_match = VirtualPrinter.sleep_after_next_regex.match(data)
|
||||
custom_action_match = VirtualPrinter.custom_action_regex.match(data)
|
||||
prepare_ok_match = VirtualPrinter.prepare_ok_regex.match(data)
|
||||
|
||||
if sleep_match is not None:
|
||||
interval = int(sleep_match.group(1))
|
||||
|
|
@ -595,6 +607,9 @@ class VirtualPrinter(object):
|
|||
params = custom_action_match.group(2)
|
||||
params = params.strip() if params is not None else ""
|
||||
self._send("// action:{action} {params}".format(**locals()).strip())
|
||||
elif prepare_ok_match is not None:
|
||||
ok = prepare_ok_match.group(1)
|
||||
self._prepared_oks.append(ok)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
@ -684,7 +699,7 @@ class VirtualPrinter(object):
|
|||
output += " @:64\n"
|
||||
|
||||
if includeOk:
|
||||
output = "ok " + output
|
||||
output = "{} {}".format(self._ok(), output)
|
||||
self._send(output)
|
||||
|
||||
def _parseHotendCommand(self, line, wait=False, support_r=False):
|
||||
|
|
@ -1060,9 +1075,9 @@ class VirtualPrinter(object):
|
|||
return
|
||||
|
||||
if settings().getBoolean(["devel", "virtualPrinter", "okWithLinenumber"]):
|
||||
self._send("ok %d" % self.lastN)
|
||||
self._send("{} {}".format(self._ok(), self.lastN))
|
||||
else:
|
||||
self._send("ok")
|
||||
self._send(self._ok())
|
||||
|
||||
def _sendWaitAfterTimeout(self, timeout=5):
|
||||
time.sleep(timeout)
|
||||
|
|
@ -1073,6 +1088,12 @@ class VirtualPrinter(object):
|
|||
if self.outgoing is not None:
|
||||
self.outgoing.put(line)
|
||||
|
||||
def _ok(self):
|
||||
ok = "ok"
|
||||
if self._prepared_oks:
|
||||
ok = self._prepared_oks.pop(0)
|
||||
return ok
|
||||
|
||||
class CharCountingQueue(queue.Queue):
|
||||
|
||||
def __init__(self, maxsize, name=None):
|
||||
|
|
|
|||
|
|
@ -359,6 +359,8 @@ default_settings = {
|
|||
"firmwareName": "Virtual Marlin 1.0",
|
||||
"sharedNozzle": False,
|
||||
"sendBusy": False,
|
||||
"simulateReset": True,
|
||||
"preparedOks": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ class MachineCom(object):
|
|||
def convert_line(line):
|
||||
if line is None:
|
||||
return None, None
|
||||
stripped_line = line.strip()
|
||||
stripped_line = line.strip().strip("\0")
|
||||
return stripped_line, stripped_line.lower()
|
||||
|
||||
##~~ Error handling
|
||||
|
|
@ -1383,7 +1383,7 @@ class MachineCom(object):
|
|||
if "start" in line and not startSeen:
|
||||
startSeen = True
|
||||
self.sayHello()
|
||||
elif line.startswith("ok"):
|
||||
elif line.startswith("ok") or (supportWait and line == "wait"):
|
||||
self._onConnected()
|
||||
elif time.time() > self._timeout:
|
||||
self._log("There was a timeout while trying to connect to the printer")
|
||||
|
|
|
|||
Loading…
Reference in a new issue