Allow specification of known long running commands through settings
This should allow users to adjust the behaviour of the communication stack more granularly in case the regular settings which only consider G4, G28, G29, G30, G32 to be real long runners without output are not sufficient.
This commit is contained in:
parent
d2bca10ac9
commit
b714c59004
7 changed files with 45 additions and 24 deletions
|
|
@ -153,7 +153,8 @@
|
|||
``python setup.py sdist``
|
||||
* [#330](https://github.com/foosel/OctoPrint/issues/330) - Ping pong sending to fix potential acknowledgement errors.
|
||||
Also affects [#166](https://github.com/foosel/OctoPrint/issues/166), [#470](https://github.com/foosel/OctoPrint/issues/470)
|
||||
and [#490](https://github.com/foosel/OctoPrint/issues/490).
|
||||
and [#490](https://github.com/foosel/OctoPrint/issues/490). A big thank you to all people involved in these tickets
|
||||
in getting to the ground of this.
|
||||
* [#825](https://github.com/foosel/OctoPrint/issues/825) - Fixed "please visualize" button of large GCODE files
|
||||
* Various fixes of bugs in newly introduced features and improvements:
|
||||
* [#625](https://github.com/foosel/OctoPrint/pull/625) - Newly added GCODE files were not being added to the analysis
|
||||
|
|
|
|||
|
|
@ -80,7 +80,8 @@ def getSettings():
|
|||
"timeoutTemperature": s.getFloat(["serial", "timeout", "temperature"]),
|
||||
"timeoutSdStatus": s.getFloat(["serial", "timeout", "sdStatus"]),
|
||||
"log": s.getBoolean(["serial", "log"]),
|
||||
"additionalPorts": s.get(["serial", "additionalPorts"])
|
||||
"additionalPorts": s.get(["serial", "additionalPorts"]),
|
||||
"longRunningCommands": s.get(["serial", "longRunningCommands"])
|
||||
},
|
||||
"folder": {
|
||||
"uploads": s.getBaseFolder("uploads"),
|
||||
|
|
@ -192,6 +193,7 @@ def setSettings():
|
|||
if "timeoutTemperature" in data["serial"].keys(): s.setFloat(["serial", "timeout", "temperature"], data["serial"]["timeoutTemperature"])
|
||||
if "timeoutSdStatus" in data["serial"].keys(): s.setFloat(["serial", "timeout", "sdStatus"], data["serial"]["timeoutSdStatus"])
|
||||
if "additionalPorts" in data["serial"] and isinstance(data["serial"]["additionalPorts"], (list, tuple)): s.set(["serial", "additionalPorts"], data["serial"]["additionalPorts"])
|
||||
if "longRunningCommands" in data["serial"] and isinstance(data["serial"]["longRunningCommands"], (list, tuple)): s.set(["serial", "longRunningCommands"], data["serial"]["longRunningCommands"])
|
||||
|
||||
oldLog = s.getBoolean(["serial", "log"])
|
||||
if "log" in data["serial"].keys(): s.setBoolean(["serial", "log"], data["serial"]["log"])
|
||||
|
|
|
|||
|
|
@ -82,7 +82,8 @@ default_settings = {
|
|||
"temperature": 5,
|
||||
"sdStatus": 1
|
||||
},
|
||||
"additionalPorts": []
|
||||
"additionalPorts": [],
|
||||
"longRunningCommands": ["G4", "G28", "G29", "G30", "G32"]
|
||||
},
|
||||
"server": {
|
||||
"host": "0.0.0.0",
|
||||
|
|
|
|||
|
|
@ -447,3 +447,17 @@ function showConfirmationDialog(message, onacknowledge) {
|
|||
});
|
||||
confirmationDialog.modal("show");
|
||||
}
|
||||
|
||||
function commentableLinesToArray(lines) {
|
||||
return splitTextToArray(lines, "\n", true, function(item) {return !_.startsWith(item, "#")});
|
||||
}
|
||||
|
||||
function splitTextToArray(text, sep, stripEmpty, filter) {
|
||||
return _.filter(
|
||||
_.map(
|
||||
text.split(sep),
|
||||
function(item) { return (item) ? item.trim() : ""; }
|
||||
),
|
||||
function(item) { return (stripEmpty ? item : true) && (filter ? filter(item) : true); }
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ $(function() {
|
|||
self.serial_timeoutSdStatus = ko.observable(undefined);
|
||||
self.serial_log = ko.observable(undefined);
|
||||
self.serial_additionalPorts = ko.observable(undefined);
|
||||
self.serial_longRunningCommands = ko.observable(undefined);
|
||||
|
||||
self.folder_uploads = ko.observable(undefined);
|
||||
self.folder_timelapse = ko.observable(undefined);
|
||||
|
|
@ -385,6 +386,7 @@ $(function() {
|
|||
self.serial_timeoutSdStatus(response.serial.timeoutSdStatus);
|
||||
self.serial_log(response.serial.log);
|
||||
self.serial_additionalPorts(response.serial.additionalPorts.join("\n"));
|
||||
self.serial_longRunningCommands(response.serial.longRunningCommands.join(", "));
|
||||
|
||||
self.folder_uploads(response.folder.uploads);
|
||||
self.folder_timelapse(response.folder.timelapse);
|
||||
|
|
@ -462,13 +464,8 @@ $(function() {
|
|||
"timeoutTemperature": self.serial_timeoutTemperature(),
|
||||
"timeoutSdStatus": self.serial_timeoutSdStatus(),
|
||||
"log": self.serial_log(),
|
||||
"additionalPorts": _.filter(
|
||||
_.map(
|
||||
self.serial_additionalPorts().split("\n"),
|
||||
function(item) { return (item) ? item.trim() : ""; }
|
||||
),
|
||||
function(item) { return item && !_.startsWith(item, "#"); }
|
||||
)
|
||||
"additionalPorts": commentableLinesToArray(self.serial_additionalPorts()),
|
||||
"longRunningCommands": splitTextToArray(self.serial_longRunningCommands(), ",", true)
|
||||
},
|
||||
"folder": {
|
||||
"uploads": self.folder_uploads(),
|
||||
|
|
|
|||
|
|
@ -70,6 +70,13 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="settings-serialLongRunningCommands">{{ _('Long running commands') }}</label>
|
||||
<div class="controls">
|
||||
<input type="text" class="input-block-level" id="settings-serialLongRunningCommands" data-bind="value: serial_longRunningCommands">
|
||||
<span class="help-inline">{{ _('Use this to specify the commands known to take a long time to complete without output from your printer and hence might cause timeout issues. Just the G or M code, comma separated.')|format(glob_url="http://docs.python.org/2/library/glob.html") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="settings-serialAdditionalPorts">{{ _('Additional serial ports') }}</label>
|
||||
<div class="controls">
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ class MachineCom(object):
|
|||
self._pauseWaitTimeLost = 0.0
|
||||
self._currentTool = 0
|
||||
|
||||
self._blocking_command = False
|
||||
self._long_running_command = False
|
||||
self._heating = False
|
||||
|
||||
self._timeout = None
|
||||
|
|
@ -218,7 +218,7 @@ class MachineCom(object):
|
|||
self._regex_repetierTempExtr = re.compile("TargetExtr([0-9]+):(%s)" % positiveFloatPattern)
|
||||
self._regex_repetierTempBed = re.compile("TargetBed:(%s)" % positiveFloatPattern)
|
||||
|
||||
self._blocking_commands = ("G28", "G29", "G30", "G32")
|
||||
self._long_running_commands = settings().get(["serial", "longRunningCommands"])
|
||||
|
||||
# multithreading locks
|
||||
self._sendNextLock = threading.Lock()
|
||||
|
|
@ -883,7 +883,7 @@ class MachineCom(object):
|
|||
##~~ process oks
|
||||
if line.strip().startswith("ok") or (self.isPrinting() and supportWait and line.strip().startswith("wait")):
|
||||
self._clear_to_send.set()
|
||||
self._blocking_command = False
|
||||
self._long_running_command = False
|
||||
|
||||
##~~ Temperature processing
|
||||
if ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:') or ' B:' in line or line.startswith('B:'):
|
||||
|
|
@ -1088,12 +1088,12 @@ class MachineCom(object):
|
|||
### Printing
|
||||
elif self._state == self.STATE_PRINTING:
|
||||
if line == "" and time.time() > self._timeout:
|
||||
if not self._blocking_command:
|
||||
if not self._long_running_command:
|
||||
self._log("Communication timeout during printing, forcing a line")
|
||||
self._sendCommand("M105")
|
||||
self._clear_to_send.set()
|
||||
else:
|
||||
self._logger.debug("Ran into a communication timeout, but a blocking command is currently active")
|
||||
self._logger.debug("Ran into a communication timeout, but a command known to be a long runner is currently active")
|
||||
|
||||
if "ok" in line or (supportWait and "wait" in line):
|
||||
# a wait while printing means our printer's buffer ran out, probably due to some ok getting
|
||||
|
|
@ -1161,22 +1161,22 @@ class MachineCom(object):
|
|||
"""
|
||||
Polls the temperature after the temperature timeout, re-enqueues itself.
|
||||
|
||||
If the printer is not operational, not printing from sd, busy with a blocking command or heating, no poll
|
||||
If the printer is not operational, not printing from sd, busy with a long running command or heating, no poll
|
||||
will be done.
|
||||
"""
|
||||
|
||||
if self.isOperational() and not self.isStreaming() and not self._blocking_command and not self._heating:
|
||||
if self.isOperational() and not self.isStreaming() and not self._long_running_command and not self._heating:
|
||||
self.sendCommand("M105", cmd_type="temperature_poll")
|
||||
|
||||
def _poll_sd_status(self):
|
||||
"""
|
||||
Polls the sd printing status after the sd status timeout, re-enqueues itself.
|
||||
|
||||
If the printer is not operational, not printing from sd, busy with a blocking command or heating, no poll
|
||||
If the printer is not operational, not printing from sd, busy with a long running command or heating, no poll
|
||||
will be done.
|
||||
"""
|
||||
|
||||
if self.isOperational() and self.isSdPrinting() and not self._blocking_command and not self._heating:
|
||||
if self.isOperational() and self.isSdPrinting() and not self._long_running_command and not self._heating:
|
||||
self.sendCommand("M27", cmd_type="sd_status_poll")
|
||||
|
||||
def _onConnected(self):
|
||||
|
|
@ -1693,13 +1693,13 @@ class MachineCom(object):
|
|||
|
||||
def _gcode_M109_sent(self, cmd, cmd_type=None):
|
||||
self._heatupWaitStartTime = time.time()
|
||||
self._blocking_command = True
|
||||
self._long_running_command = True
|
||||
self._heating = True
|
||||
self._gcode_M104_sent(cmd, cmd_type)
|
||||
|
||||
def _gcode_M190_sent(self, cmd, cmd_type=None):
|
||||
self._heatupWaitStartTime = time.time()
|
||||
self._blocking_command = True
|
||||
self._long_running_command = True
|
||||
self._heating = True
|
||||
self._gcode_M140_sent(cmd, cmd_type)
|
||||
|
||||
|
|
@ -1737,13 +1737,12 @@ class MachineCom(object):
|
|||
# dwell time is specified in seconds
|
||||
_timeout = float(cmd[s_idx+1:])
|
||||
self._timeout = get_new_timeout("communication") + _timeout
|
||||
self._blocking_command = True
|
||||
|
||||
##~~ command phase handlers
|
||||
|
||||
def _command_phase_sending(self, cmd, cmd_type=None, gcode=None):
|
||||
if gcode is not None and gcode in self._blocking_commands:
|
||||
self._blocking_command = True
|
||||
if gcode is not None and gcode in self._long_running_commands:
|
||||
self._long_running_command = True
|
||||
|
||||
### MachineCom callback ################################################################################################
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue