User thread lock instead of boolean to ensure only one concurrent sending thread, introduced wait flag for repetier printers
parent
48a2fd71a7
commit
f050567a1c
|
@ -360,6 +360,7 @@ def getSettings():
|
||||||
"feature": {
|
"feature": {
|
||||||
"gcodeViewer": s.getBoolean(["feature", "gCodeVisualizer"]),
|
"gcodeViewer": s.getBoolean(["feature", "gCodeVisualizer"]),
|
||||||
"waitForStart": s.getBoolean(["feature", "waitForStartOnConnect"]),
|
"waitForStart": s.getBoolean(["feature", "waitForStartOnConnect"]),
|
||||||
|
"waitForWaitAfterStart": s.getBoolean(["feature", "waitForWaitAfterStartOnConnect"]),
|
||||||
"alwaysSendChecksum": s.getBoolean(["feature", "alwaysSendChecksum"]),
|
"alwaysSendChecksum": s.getBoolean(["feature", "alwaysSendChecksum"]),
|
||||||
"resetLineNumbersWithPrefixedN": s.getBoolean(["feature", "resetLineNumbersWithPrefixedN"])
|
"resetLineNumbersWithPrefixedN": s.getBoolean(["feature", "resetLineNumbersWithPrefixedN"])
|
||||||
},
|
},
|
||||||
|
@ -403,6 +404,7 @@ def setSettings():
|
||||||
if "feature" in data.keys():
|
if "feature" in data.keys():
|
||||||
if "gcodeViewer" in data["feature"].keys(): s.setBoolean(["feature", "gCodeVisualizer"], data["feature"]["gcodeViewer"])
|
if "gcodeViewer" in data["feature"].keys(): s.setBoolean(["feature", "gCodeVisualizer"], data["feature"]["gcodeViewer"])
|
||||||
if "waitForStart" in data["feature"].keys(): s.setBoolean(["feature", "waitForStartOnConnect"], data["feature"]["waitForStart"])
|
if "waitForStart" in data["feature"].keys(): s.setBoolean(["feature", "waitForStartOnConnect"], data["feature"]["waitForStart"])
|
||||||
|
if "waitForWait" in data["feature"].keys(): s.setBoolean(["feature", "waitForWaitOnConnect"], data["feature"]["waitForWait"]),
|
||||||
if "alwaysSendChecksum" in data["feature"].keys(): s.setBoolean(["feature", "alwaysSendChecksum"], data["feature"]["alwaysSendChecksum"])
|
if "alwaysSendChecksum" in data["feature"].keys(): s.setBoolean(["feature", "alwaysSendChecksum"], data["feature"]["alwaysSendChecksum"])
|
||||||
if "resetLineNumbersWithPrefixedN" in data["feature"].keys(): s.setBoolean(["feature", "resetLineNumbersWithPrefixedN"], data["feature"]["resetLineNumbersWithPrefixedN"])
|
if "resetLineNumbersWithPrefixedN" in data["feature"].keys(): s.setBoolean(["feature", "resetLineNumbersWithPrefixedN"], data["feature"]["resetLineNumbersWithPrefixedN"])
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ default_settings = {
|
||||||
"feature": {
|
"feature": {
|
||||||
"gCodeVisualizer": True,
|
"gCodeVisualizer": True,
|
||||||
"waitForStartOnConnect": False,
|
"waitForStartOnConnect": False,
|
||||||
|
"waitForWaitOnConnect": False,
|
||||||
"alwaysSendChecksum": False,
|
"alwaysSendChecksum": False,
|
||||||
"resetLineNumbersWithPrefixedN": False
|
"resetLineNumbersWithPrefixedN": False
|
||||||
},
|
},
|
||||||
|
|
|
@ -618,6 +618,7 @@ function TerminalViewModel() {
|
||||||
if (!self.log)
|
if (!self.log)
|
||||||
self.log = []
|
self.log = []
|
||||||
self.log = self.log.concat(data)
|
self.log = self.log.concat(data)
|
||||||
|
self.log = self.log.slice(-300)
|
||||||
self.updateOutput();
|
self.updateOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,6 +960,7 @@ function SettingsViewModel() {
|
||||||
|
|
||||||
self.feature_gcodeViewer = ko.observable(undefined);
|
self.feature_gcodeViewer = ko.observable(undefined);
|
||||||
self.feature_waitForStart = ko.observable(undefined);
|
self.feature_waitForStart = ko.observable(undefined);
|
||||||
|
self.feature_waitForWait = ko.observable(undefined);
|
||||||
self.feature_alwaysSendChecksum = ko.observable(undefined);
|
self.feature_alwaysSendChecksum = ko.observable(undefined);
|
||||||
self.feature_resetLineNumbersWithPrefixedN = ko.observable(undefined);
|
self.feature_resetLineNumbersWithPrefixedN = ko.observable(undefined);
|
||||||
|
|
||||||
|
@ -1005,6 +1007,7 @@ function SettingsViewModel() {
|
||||||
|
|
||||||
self.feature_gcodeViewer(response.feature.gcodeViewer);
|
self.feature_gcodeViewer(response.feature.gcodeViewer);
|
||||||
self.feature_waitForStart(response.feature.waitForStart);
|
self.feature_waitForStart(response.feature.waitForStart);
|
||||||
|
self.feature_waitForWait(response.feature.waitForWait);
|
||||||
self.feature_alwaysSendChecksum(response.feature.alwaysSendChecksum);
|
self.feature_alwaysSendChecksum(response.feature.alwaysSendChecksum);
|
||||||
self.feature_resetLineNumbersWithPrefixedN(response.feature.resetLineNumbersWithPrefixedN);
|
self.feature_resetLineNumbersWithPrefixedN(response.feature.resetLineNumbersWithPrefixedN);
|
||||||
|
|
||||||
|
@ -1040,6 +1043,7 @@ function SettingsViewModel() {
|
||||||
"feature": {
|
"feature": {
|
||||||
"gcodeViewer": self.feature_gcodeViewer(),
|
"gcodeViewer": self.feature_gcodeViewer(),
|
||||||
"waitForStart": self.feature_waitForStart(),
|
"waitForStart": self.feature_waitForStart(),
|
||||||
|
"waitForWait": self.feature_waitForWait(),
|
||||||
"alwaysSendChecksum": self.feature_alwaysSendChecksum(),
|
"alwaysSendChecksum": self.feature_alwaysSendChecksum(),
|
||||||
"resetLineNumbersWithPrefixedN": self.feature_resetLineNumbersWithPrefixedN()
|
"resetLineNumbersWithPrefixedN": self.feature_resetLineNumbersWithPrefixedN()
|
||||||
},
|
},
|
||||||
|
|
|
@ -102,21 +102,28 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input type="checkbox" data-bind="checked: feature_waitForStart" id="settings-featureWaitForStart"> Wait for start on connect
|
<input type="checkbox" data-bind="checked: feature_waitForStart" id="settings-featureWaitForStart"> Wait for <code>start</code> on connect
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input type="checkbox" data-bind="checked: feature_alwaysSendChecksum" id="settings-featureAlwaysSendChecksum"> Send a checksum with <strong>every</strong> command
|
<input type="checkbox" data-bind="checked: feature_waitForWait" id="settings-featureWaitForWait"> Wait for <code>wait</code> on connect <span class="label">Repetier</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<label class="checkbox">
|
<label class="checkbox">
|
||||||
<input type="checkbox" data-bind="checked: feature_resetLineNumbersWithPrefixedN" id="settings-resetLineNumbersWithPrefixedN"> Send M110 commands with target line number as N-prefix
|
<input type="checkbox" data-bind="checked: feature_alwaysSendChecksum" id="settings-featureAlwaysSendChecksum"> Send a checksum with <strong>every</strong> command <span class="label">Repetier</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="control-group">
|
||||||
|
<div class="controls">
|
||||||
|
<label class="checkbox">
|
||||||
|
<input type="checkbox" data-bind="checked: feature_resetLineNumbersWithPrefixedN" id="settings-resetLineNumbersWithPrefixedN"> Send M110 commands with target line number as N-prefix <span class="label">Repetier</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -66,6 +66,9 @@ class VirtualPrinter():
|
||||||
|
|
||||||
self.currentLine = 0
|
self.currentLine = 0
|
||||||
|
|
||||||
|
waitThread = threading.Thread(target=self._sendWaitAfterTimeout)
|
||||||
|
waitThread.start()
|
||||||
|
|
||||||
def write(self, data):
|
def write(self, data):
|
||||||
if self.readList is None:
|
if self.readList is None:
|
||||||
return
|
return
|
||||||
|
@ -125,6 +128,10 @@ class VirtualPrinter():
|
||||||
def close(self):
|
def close(self):
|
||||||
self.readList = None
|
self.readList = None
|
||||||
|
|
||||||
|
def _sendWaitAfterTimeout(self, timeout=5):
|
||||||
|
time.sleep(timeout)
|
||||||
|
self.readList.append("wait")
|
||||||
|
|
||||||
class MachineComPrintCallback(object):
|
class MachineComPrintCallback(object):
|
||||||
def mcLog(self, message):
|
def mcLog(self, message):
|
||||||
pass
|
pass
|
||||||
|
@ -197,7 +204,9 @@ class MachineCom(object):
|
||||||
self._currentLine = 1
|
self._currentLine = 1
|
||||||
self._resendDelta = None
|
self._resendDelta = None
|
||||||
self._lastLines = []
|
self._lastLines = []
|
||||||
self._sending = False
|
|
||||||
|
self._sendingLock = threading.Lock()
|
||||||
|
|
||||||
self.thread = threading.Thread(target=self._monitor)
|
self.thread = threading.Thread(target=self._monitor)
|
||||||
self.thread.daemon = True
|
self.thread.daemon = True
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
@ -338,6 +347,7 @@ class MachineCom(object):
|
||||||
timeout = time.time() + 5
|
timeout = time.time() + 5
|
||||||
tempRequestTimeout = timeout
|
tempRequestTimeout = timeout
|
||||||
startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
|
startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
|
||||||
|
waitSeen = not settings().getBoolean(["feature", "waitForWaitOnConnect"])
|
||||||
while True:
|
while True:
|
||||||
line = self._readline()
|
line = self._readline()
|
||||||
if line == None:
|
if line == None:
|
||||||
|
@ -429,13 +439,13 @@ class MachineCom(object):
|
||||||
|
|
||||||
### Connection attempt
|
### Connection attempt
|
||||||
elif self._state == self.STATE_CONNECTING:
|
elif self._state == self.STATE_CONNECTING:
|
||||||
#if (line == "" or "wait" in line) and startSeen:
|
if line == "" and startSeen and waitSeen:
|
||||||
#This modification allows more reliable initial connection.
|
|
||||||
if ("wait" in line) and startSeen:
|
|
||||||
self._sendCommand("M105")
|
self._sendCommand("M105")
|
||||||
elif "start" in line:
|
elif "start" in line:
|
||||||
startSeen = True
|
startSeen = True
|
||||||
elif "ok" in line and startSeen:
|
elif "wait" in line:
|
||||||
|
waitSeen = True
|
||||||
|
elif "ok" in line and startSeen and waitSeen:
|
||||||
self._changeState(self.STATE_OPERATIONAL)
|
self._changeState(self.STATE_OPERATIONAL)
|
||||||
elif time.time() > timeout:
|
elif time.time() > timeout:
|
||||||
self.close()
|
self.close()
|
||||||
|
@ -444,8 +454,16 @@ class MachineCom(object):
|
||||||
elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
|
elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
|
||||||
#Request the temperature on comm timeout (every 5 seconds) when we are not printing.
|
#Request the temperature on comm timeout (every 5 seconds) when we are not printing.
|
||||||
if line == "" or "wait" in line:
|
if line == "" or "wait" in line:
|
||||||
|
if self._resendDelta is not None:
|
||||||
|
self._resendNextCommand()
|
||||||
|
elif not self._commandQueue.empty():
|
||||||
|
self._sendCommand(self._commandQueue.get())
|
||||||
|
else:
|
||||||
self._sendCommand("M105")
|
self._sendCommand("M105")
|
||||||
tempRequestTimeout = time.time() + 5
|
tempRequestTimeout = time.time() + 5
|
||||||
|
# resend -> start resend procedure from requested line
|
||||||
|
elif "resend" in line.lower() or "rs" in line:
|
||||||
|
self._handleResendRequest(line)
|
||||||
|
|
||||||
### Printing
|
### Printing
|
||||||
elif self._state == self.STATE_PRINTING:
|
elif self._state == self.STATE_PRINTING:
|
||||||
|
@ -468,6 +486,10 @@ class MachineCom(object):
|
||||||
self._sendNext()
|
self._sendNext()
|
||||||
# resend -> start resend procedure from requested line
|
# resend -> start resend procedure from requested line
|
||||||
elif "resend" in line.lower() or "rs" in line:
|
elif "resend" in line.lower() or "rs" in line:
|
||||||
|
self._handleResendRequest(line)
|
||||||
|
self._log("Connection closed, closing down monitor")
|
||||||
|
|
||||||
|
def _handleResendRequest(self, line):
|
||||||
lineToResend = None
|
lineToResend = None
|
||||||
try:
|
try:
|
||||||
lineToResend = int(line.replace("N:"," ").replace("N"," ").replace(":"," ").split()[-1])
|
lineToResend = int(line.replace("N:"," ").replace("N"," ").replace(":"," ").split()[-1])
|
||||||
|
@ -483,7 +505,6 @@ class MachineCom(object):
|
||||||
self._logger.warn(self._errorValue)
|
self._logger.warn(self._errorValue)
|
||||||
else:
|
else:
|
||||||
self._resendNextCommand()
|
self._resendNextCommand()
|
||||||
self._log("Connection closed, closing down monitor")
|
|
||||||
|
|
||||||
def _log(self, message):
|
def _log(self, message):
|
||||||
self._callback.mcLog(message)
|
self._callback.mcLog(message)
|
||||||
|
@ -527,6 +548,8 @@ class MachineCom(object):
|
||||||
self.close()
|
self.close()
|
||||||
|
|
||||||
def _resendNextCommand(self):
|
def _resendNextCommand(self):
|
||||||
|
# Make sure we are only handling one sending job at a time
|
||||||
|
with self._sendingLock:
|
||||||
self._logger.debug("Resending line %d, delta is %d, history log is %s items strong" % (self._currentLine - self._resendDelta, self._resendDelta, len(self._lastLines)))
|
self._logger.debug("Resending line %d, delta is %d, history log is %s items strong" % (self._currentLine - self._resendDelta, self._resendDelta, len(self._lastLines)))
|
||||||
cmd = self._lastLines[-self._resendDelta]
|
cmd = self._lastLines[-self._resendDelta]
|
||||||
lineNumber = self._currentLine - self._resendDelta
|
lineNumber = self._currentLine - self._resendDelta
|
||||||
|
@ -538,11 +561,10 @@ class MachineCom(object):
|
||||||
self._resendDelta = None
|
self._resendDelta = None
|
||||||
|
|
||||||
def _sendCommand(self, cmd, sendChecksum=False):
|
def _sendCommand(self, cmd, sendChecksum=False):
|
||||||
|
# Make sure we are only handling one sending job at a time
|
||||||
|
with self._sendingLock:
|
||||||
cmd = cmd.upper()
|
cmd = cmd.upper()
|
||||||
#Wait for current send to finish.
|
|
||||||
while self._sending:
|
|
||||||
pass
|
|
||||||
self._sending = True
|
|
||||||
if self._serial is None:
|
if self._serial is None:
|
||||||
return
|
return
|
||||||
if 'M109' in cmd or 'M190' in cmd:
|
if 'M109' in cmd or 'M190' in cmd:
|
||||||
|
@ -570,11 +592,11 @@ class MachineCom(object):
|
||||||
|
|
||||||
if settings().getBoolean(["feature", "resetLineNumbersWithPrefixedN"]) and newLineNumber is not None:
|
if settings().getBoolean(["feature", "resetLineNumbersWithPrefixedN"]) and newLineNumber is not None:
|
||||||
# let's rewrite the M110 command to fit repetier syntax
|
# let's rewrite the M110 command to fit repetier syntax
|
||||||
self._doSendWithChecksum("M110", newLineNumber)
|
|
||||||
self._addToLastLines(cmd)
|
self._addToLastLines(cmd)
|
||||||
self._currentLine = newLineNumber + 1
|
self._doSendWithChecksum("M110", newLineNumber)
|
||||||
else:
|
else:
|
||||||
self._doSend(cmd, sendChecksum)
|
self._doSend(cmd, sendChecksum)
|
||||||
|
|
||||||
if newLineNumber is not None:
|
if newLineNumber is not None:
|
||||||
self._currentLine = newLineNumber + 1
|
self._currentLine = newLineNumber + 1
|
||||||
|
|
||||||
|
@ -596,17 +618,15 @@ class MachineCom(object):
|
||||||
lineNumber = self._currentLine
|
lineNumber = self._currentLine
|
||||||
else:
|
else:
|
||||||
lineNumber = self._gcodePos
|
lineNumber = self._gcodePos
|
||||||
self._doSendWithChecksum(cmd, lineNumber)
|
|
||||||
self._addToLastLines(cmd)
|
self._addToLastLines(cmd)
|
||||||
self._currentLine += 1
|
self._currentLine += 1
|
||||||
|
self._doSendWithChecksum(cmd, lineNumber)
|
||||||
else:
|
else:
|
||||||
self._doSendWithoutChecksum(cmd)
|
self._doSendWithoutChecksum(cmd)
|
||||||
|
|
||||||
def _doSendWithChecksum(self, cmd, lineNumber=None):
|
def _doSendWithChecksum(self, cmd, lineNumber):
|
||||||
self._logger.debug("Sending cmd '%s' with lineNumber %r" % (cmd, lineNumber))
|
self._logger.debug("Sending cmd '%s' with lineNumber %r" % (cmd, lineNumber))
|
||||||
|
|
||||||
if lineNumber is None:
|
|
||||||
lineNumber = self._currentLine
|
|
||||||
checksum = reduce(lambda x,y:x^y, map(ord, "N%d%s" % (lineNumber, cmd)))
|
checksum = reduce(lambda x,y:x^y, map(ord, "N%d%s" % (lineNumber, cmd)))
|
||||||
commandToSend = "N%d%s*%d" % (lineNumber, cmd, checksum)
|
commandToSend = "N%d%s*%d" % (lineNumber, cmd, checksum)
|
||||||
self._doSendWithoutChecksum(commandToSend)
|
self._doSendWithoutChecksum(commandToSend)
|
||||||
|
@ -627,8 +647,6 @@ class MachineCom(object):
|
||||||
self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
|
self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
|
||||||
self._errorValue = getExceptionString()
|
self._errorValue = getExceptionString()
|
||||||
self.close(True)
|
self.close(True)
|
||||||
#clear sending flag
|
|
||||||
self._sending = False
|
|
||||||
|
|
||||||
def _sendNext(self):
|
def _sendNext(self):
|
||||||
if self._gcodePos >= len(self._gcodeList):
|
if self._gcodePos >= len(self._gcodeList):
|
||||||
|
|
Loading…
Reference in New Issue