Improved handshake procedure on comm layer

"Hello" command sent to printer to trigger initial handshake can now be
configured. Commands that _always_ necessitate to be sent with checksum/
line number (e.g. M110 on Marlin) can be configured as such too.

Also fixed an issue causing the "Hello" command to not be actually enqueued
first thing on opening a connection. Seems to not have caused harm in the
wild, but was unintentional.
This commit is contained in:
Gina Häußge 2015-08-13 13:07:18 +02:00
parent ac3409a223
commit 5c2ae378e1
3 changed files with 53 additions and 14 deletions

View file

@ -613,8 +613,30 @@ Use the following settings to configure the serial connection to the printer:
# Use this to define additional baud rates to offer for connecting to serial ports. Must be a
# valid integer. Defaults to not set
additionalBaudrates:
- 123456
# Commands which are known to take a long time to be acknowledged by the firmware. E.g.
# homing, dwelling, auto leveling etc. Defaults to the below commands.
longRunningCommands:
- G4
- G28
- G29
- G30
- G32
- M400
- M226
# Commands which need to always be send with a checksum. Defaults to only M110
checksumRequiringCommands:
- M110
# Command to send in order to initiate a handshake with the printer.
# Defaults to "M110 N0" which simply resets the line numbers in the firmware and which
# should be acknowledged with a simple "ok".
helloCommand:
- M110 N0
.. _sec-configuration-config_yaml-server:
Server

View file

@ -84,7 +84,9 @@ default_settings = {
},
"additionalPorts": [],
"additionalBaudrates": [],
"longRunningCommands": ["G4", "G28", "G29", "G30", "G32", "M400", "M226"]
"longRunningCommands": ["G4", "G28", "G29", "G30", "G32", "M400", "M226"],
"checksumRequiringCommands": ["M110"],
"helloCommand": "M110 N0"
},
"server": {
"host": "0.0.0.0",

View file

@ -165,6 +165,8 @@ class MachineCom(object):
self._timeout = None
self._hello_command = settings().get(["serial", "helloCommand"])
self._alwaysSendChecksum = settings().getBoolean(["feature", "alwaysSendChecksum"])
self._sendChecksumWithUnknownCommands = settings().getBoolean(["feature", "sendChecksumWithUnknownCommands"])
self._unknownCommandsNeedAck = settings().getBoolean(["feature", "unknownCommandsNeedAck"])
@ -175,6 +177,7 @@ class MachineCom(object):
self._lastResendNumber = None
self._currentResendCount = 0
self._resendSwallowNextOk = False
self._checksum_requiring_commands = settings().get(["serial", "checksumRequiringCommands"])
self._clear_to_send = CountedEvent(max=10, name="comm.clear_to_send")
self._send_queue = TypedQueue()
@ -478,7 +481,7 @@ class MachineCom(object):
def fakeOk(self):
self._clear_to_send.set()
def sendCommand(self, cmd, cmd_type=None, processed=False):
def sendCommand(self, cmd, cmd_type=None, processed=False, force=False):
cmd = cmd.encode('ascii', 'replace')
if not processed:
cmd = process_gcode_line(cmd)
@ -487,7 +490,7 @@ class MachineCom(object):
if self.isPrinting() and not self.isSdFileSelected():
self._commandQueue.put((cmd, cmd_type))
elif self.isOperational():
elif self.isOperational() or force:
self._sendCommand(cmd, cmd_type=cmd_type)
def sendGcodeScript(self, scriptName, replacements=None):
@ -559,7 +562,7 @@ class MachineCom(object):
self._changeState(self.STATE_PRINTING)
self.sendCommand("M110 N0")
self.resetLineNumbers()
payload = {
"file": self._currentFile.getFilename(),
@ -757,6 +760,16 @@ class MachineCom(object):
self._callback.on_comm_sd_state_change(self._sdAvailable)
self._callback.on_comm_sd_files(self._sdFiles)
def sayHello(self):
self.sendCommand(self._hello_command, force=True)
self._clear_to_send.set()
def resetLineNumbers(self, number=0):
if not self.isOperational():
return
self.sendCommand("M110 N%d" % number)
##~~ communication monitoring and handling
def _parseTemperatures(self, line):
@ -865,10 +878,9 @@ class MachineCom(object):
connection_timeout = settings().getFloat(["serial", "timeout", "connection"])
detection_timeout = settings().getFloat(["serial", "timeout", "detection"])
# enqueue an M105 first thing
# enqueue the "hello command" first thing
if try_hello:
self._sendCommand("M110")
self._clear_to_send.set()
self.sayHello()
while self._monitoring_active:
try:
@ -1089,8 +1101,7 @@ class MachineCom(object):
self._baudrateDetectRetry -= 1
self._serial.write('\n')
self._log("Baudrate test retry: %d" % (self._baudrateDetectRetry))
self._sendCommand("M110")
self._clear_to_send.set()
self.sayHello()
elif len(self._baudrateDetectList) > 0:
baudrate = self._baudrateDetectList.pop(0)
try:
@ -1101,8 +1112,7 @@ class MachineCom(object):
self._baudrateDetectRetry = 5
self._timeout = get_new_timeout("communication")
self._serial.write('\n')
self._sendCommand("M110")
self._clear_to_send.set()
self.sayHello()
except:
self._log("Unexpected error while setting baudrate: %d %s" % (baudrate, get_exception_string()))
else:
@ -1118,8 +1128,7 @@ 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()
self.sayHello()
elif "ok" in line:
self._onConnected()
elif time.time() > self._timeout:
@ -1241,6 +1250,8 @@ class MachineCom(object):
self._changeState(self.STATE_OPERATIONAL)
self.resetLineNumbers()
if self._sdAvailable:
self.refreshSdFiles()
else:
@ -1588,7 +1599,11 @@ class MachineCom(object):
continue
# now comes the part where we increase line numbers and send stuff - no turning back now
if (gcode is not None or self._sendChecksumWithUnknownCommands) and (self.isPrinting() or self._alwaysSendChecksum):
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 = self.isPrinting() or self._alwaysSendChecksum
if command_requiring_checksum or (command_allowing_checksum and checksum_enabled):
linenumber = self._currentLine
self._addToLastLines(command)
self._currentLine += 1