Merge branch 'maintenance' into devel
This commit is contained in:
commit
bac972de53
11 changed files with 252 additions and 34 deletions
|
|
@ -133,6 +133,12 @@ mapped from the same fields in ``config.yaml`` unless otherwise noted:
|
|||
-
|
||||
* - ``feature.modelSizeDetection``
|
||||
-
|
||||
* - ``feature.firmwareDetection``
|
||||
-
|
||||
* - ``feature.printCancelConfirmation``
|
||||
-
|
||||
* - ``feature.blockWhileDwelling``
|
||||
-
|
||||
* - ``folder.uploads``
|
||||
-
|
||||
* - ``folder.timelapse``
|
||||
|
|
|
|||
|
|
@ -519,6 +519,23 @@ Use the following settings to enable or disable OctoPrint features:
|
|||
# If ignoredIdenticalResends is true, how many consecutive identical resends to ignore
|
||||
identicalResendsCount: 7
|
||||
|
||||
# Whether to support F on its own as a valid GCODE command (true) or not (false)
|
||||
supportFAsCommand: false
|
||||
|
||||
# Whether to enable model size detection and warning (true) or not (false)
|
||||
modelSizeDetection: true
|
||||
|
||||
# Whether to attempt to auto detect the firmware of the printer and adjust settings
|
||||
# accordingly (true) or not and rely on manual configuration (false)
|
||||
firmwareDetection: true
|
||||
|
||||
# Whether to show a confirmation on print cancelling (true) or not (false)
|
||||
printCancelConfirmation: true
|
||||
|
||||
# Whether to block all sending to the printer while a G4 (dwell) command is active (true, repetier)
|
||||
# or not (false)
|
||||
blockWhileDwelling: false
|
||||
|
||||
.. _sec-configuration-config_yaml-folder:
|
||||
|
||||
Folder
|
||||
|
|
@ -565,6 +582,45 @@ Use the following settings to set custom paths for folders used by OctoPrint:
|
|||
# Absolute path where to store (GCODE) scripts
|
||||
scripts: /path/to/scripts/folder
|
||||
|
||||
.. _sec-configuration-config_yaml-gcodeanalysis:
|
||||
|
||||
GCODE Analysis
|
||||
--------------
|
||||
|
||||
Settings pertaining to the server side GCODE analysis implementation.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Maximum number of extruders to support/to sanity check for
|
||||
maxExtruders: 10
|
||||
|
||||
# Pause between each processed GCODE line in normal priority mode, seconds
|
||||
throttle_normalprio: 0.01
|
||||
|
||||
# Pause between each processed GCODE line in high priority mode (e.g. on fresh
|
||||
# uploads), seconds
|
||||
throttle_highprio: 0.0
|
||||
|
||||
.. _sec-configuration-config_yaml-gcodeviewer:
|
||||
|
||||
GCODE Viewer
|
||||
------------
|
||||
|
||||
Settings pertaining to the built in GCODE Viewer.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Whether to enable the GCODE viewer in the UI
|
||||
enabled: true
|
||||
|
||||
# Maximum size a GCODE file may have on mobile devices to automatically be loaded
|
||||
# into the viewer, defaults to 2MB
|
||||
mobileSizeThreshold: 2097152
|
||||
|
||||
# Maximum size a GCODE file may have to automatically be loaded into the viewer,
|
||||
# defaults to 20MB
|
||||
sizeThreshold: 20971520
|
||||
|
||||
.. _sec-configuration-config_yaml-plugins:
|
||||
|
||||
Plugin settings
|
||||
|
|
@ -679,8 +735,34 @@ Use the following settings to configure the serial connection to the printer:
|
|||
connection: 2
|
||||
|
||||
# Timeout during serial communication, in seconds.
|
||||
# Defaults to 5 sec
|
||||
communication: 5
|
||||
# Defaults to 30 sec
|
||||
communication: 30
|
||||
|
||||
# Timeout after which to query temperature when no target is set
|
||||
temperature: 5
|
||||
|
||||
# Timeout after which to query temperature when a target is set
|
||||
temperatureTargetSet: 2
|
||||
|
||||
# Timeout after which to query the SD status while SD printing
|
||||
sdStatus: 1
|
||||
|
||||
# Maximum number of consecutive communication timeouts after which the printer will be considered
|
||||
# dead and OctoPrint disconnects with an error.
|
||||
maxCommunicationTimeouts:
|
||||
|
||||
# max. timeouts when the printer is idle
|
||||
idle: 2
|
||||
|
||||
# max. timeouts when the printer is printing
|
||||
printing: 5
|
||||
|
||||
# max. timeouts when a long running command is active
|
||||
long: 5
|
||||
|
||||
# Maximum number of write attempts to serial during which nothing can be written before the communication
|
||||
# with the printer is considered dead and OctoPrint will disconnect with an error
|
||||
maxWritePasses:
|
||||
|
||||
# Use this to define additional patterns to consider for serial port listing. Must be a valid
|
||||
# "glob" pattern (see http://docs.python.org/2/library/glob.html). Defaults to not set.
|
||||
|
|
@ -702,6 +784,7 @@ Use the following settings to configure the serial connection to the printer:
|
|||
- G32
|
||||
- M400
|
||||
- M226
|
||||
- M600
|
||||
|
||||
# Commands which need to always be send with a checksum. Defaults to only M110
|
||||
checksumRequiringCommands:
|
||||
|
|
@ -944,10 +1027,12 @@ Use `Javascript regular expressions <https://developer.mozilla.org/en/docs/Web/J
|
|||
|
||||
# A list of filters to display in the terminal tab. Defaults to the filters shown below
|
||||
terminalFilters:
|
||||
- name: Suppress M105 requests/responses
|
||||
regex: '(Send: M105)|(Recv: ok T:)'
|
||||
- name: Suppress M27 requests/responses
|
||||
regex: '(Send: M27)|(Recv: SD printing byte)'
|
||||
- name: Suppress temperature messages
|
||||
regex: '(Send: (N\d+\s+)?M105)|(Recv: ok T:)'
|
||||
- name: Suppress SD status messages
|
||||
regex: '(Send: (N\d+\s+)?M27)|(Recv: SD printing byte)'
|
||||
- name: Suppress wait responses
|
||||
regex: 'Recv: wait'
|
||||
|
||||
.. _sec-configuration-config_yaml-webcam:
|
||||
|
||||
|
|
@ -981,22 +1066,42 @@ Use the following settings to configure webcam support:
|
|||
# Whether to include a "created with OctoPrint" watermark in the generated timelapse movies
|
||||
watermark: true
|
||||
|
||||
# Whether to flip the webcam horizontally
|
||||
flipH: false
|
||||
|
||||
# Whether to flip the webcam vertically
|
||||
flipV: false
|
||||
|
||||
# Whether to rotate the webcam 90° counter clockwise
|
||||
rotate90: false
|
||||
|
||||
# The default timelapse settings.
|
||||
timelapse:
|
||||
|
||||
# The timelapse type. Can be either "off", "zchange" or "timed". Defaults to "off"
|
||||
type: timed
|
||||
|
||||
# The framerate at which to render the movie
|
||||
fps: 25
|
||||
|
||||
# The number of seconds in the rendered video to add after a finished print. The exact way how the
|
||||
# additional images will be recorded depends on timelapse type. Timed timelapses continue to
|
||||
# record just like at the beginning, so the recording will continue another
|
||||
# fps * postRoll * interval seconds. Zchange timelapses will take one final picture and add it fps * postRoll
|
||||
postRoll: 0
|
||||
|
||||
# Additional options depending on the timelapse type. All timelapses take a postRoll and an fps setting.
|
||||
options:
|
||||
# The number of seconds in the rendered video to add after a finished print. The exact way how the
|
||||
# additional images will be recorded depends on timelapse type. Timed timelapses continue to
|
||||
# record just like at the beginning, so the recording will continue another
|
||||
# fps * postRoll * interval seconds. Zchange timelapses will take one final picture and add it fps * postRoll
|
||||
postRoll: 0
|
||||
|
||||
# The framerate at which to render the movie
|
||||
fps: 25
|
||||
|
||||
# Timed timelapses only: The interval which to leave between images in seconds
|
||||
interval: 2
|
||||
|
||||
# Timed timelapses only: Whether to capture the snapshots for the post roll (true) or just copy
|
||||
# the last captured snapshot from the print over and over again (false)
|
||||
capturePostRoll: true
|
||||
|
||||
# ZChange timelapses only: Z-hop height during retractions to ignore for capturing snapshots
|
||||
retractionZHop: 0.0
|
||||
|
||||
# After how many days unrendered timelapses will be deleted
|
||||
cleanTmpAfterDays: 7
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
|
@ -92,6 +100,7 @@ class VirtualPrinter(object):
|
|||
self._supportF = settings().getBoolean(["devel", "virtualPrinter", "supportF"])
|
||||
|
||||
self._sendWait = settings().getBoolean(["devel", "virtualPrinter", "sendWait"])
|
||||
self._sendBusy = settings().getBoolean(["devel", "virtualPrinter", "sendBusy"])
|
||||
self._waitInterval = settings().getFloat(["devel", "virtualPrinter", "waitInterval"])
|
||||
|
||||
self._echoOnM117 = settings().getBoolean(["devel", "virtualPrinter", "echoOnM117"])
|
||||
|
|
@ -384,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
|
||||
|
||||
|
|
@ -451,6 +460,24 @@ class VirtualPrinter(object):
|
|||
_gcode_G2 = _gcode_G0
|
||||
_gcode_G3 = _gcode_G0
|
||||
|
||||
def _gcode_G4(self, data):
|
||||
matchS = re.search('S([0-9]+)', data)
|
||||
matchP = re.search('P([0-9]+)', data)
|
||||
|
||||
_timeout = 0
|
||||
if matchP:
|
||||
_timeout = float(matchP.group(1)) / 1000.0
|
||||
elif matchS:
|
||||
_timeout = float(matchS.group(1))
|
||||
|
||||
if self._sendBusy:
|
||||
until = time.time() + _timeout
|
||||
while time.time() < until:
|
||||
time.sleep(1.0)
|
||||
self._send("busy:processing")
|
||||
else:
|
||||
time.sleep(_timeout)
|
||||
|
||||
##~~ further helpers
|
||||
|
||||
def _calculate_checksum(self, line):
|
||||
|
|
@ -479,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()
|
||||
|
|
@ -519,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
|
||||
|
||||
|
|
@ -527,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()))
|
||||
|
|
@ -556,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))
|
||||
|
|
@ -576,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
|
||||
|
||||
|
|
@ -665,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):
|
||||
|
|
@ -1041,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)
|
||||
|
|
@ -1054,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):
|
||||
|
|
|
|||
|
|
@ -126,7 +126,8 @@ def getSettings():
|
|||
"ignoreIdenticalResends": s.getBoolean(["feature", "ignoreIdenticalResends"]),
|
||||
"modelSizeDetection": s.getBoolean(["feature", "modelSizeDetection"]),
|
||||
"firmwareDetection": s.getBoolean(["feature", "firmwareDetection"]),
|
||||
"printCancelConfirmation": s.getBoolean(["feature", "printCancelConfirmation"])
|
||||
"printCancelConfirmation": s.getBoolean(["feature", "printCancelConfirmation"]),
|
||||
"blockWhileDwelling": s.getBoolean(["feature", "blockWhileDwelling"])
|
||||
},
|
||||
"serial": {
|
||||
"port": connectionOptions["portPreference"],
|
||||
|
|
@ -311,6 +312,7 @@ def _saveSettings(data):
|
|||
if "modelSizeDetection" in data["feature"]: s.setBoolean(["feature", "modelSizeDetection"], data["feature"]["modelSizeDetection"])
|
||||
if "firmwareDetection" in data["feature"]: s.setBoolean(["feature", "firmwareDetection"], data["feature"]["firmwareDetection"])
|
||||
if "printCancelConfirmation" in data["feature"]: s.setBoolean(["feature", "printCancelConfirmation"], data["feature"]["printCancelConfirmation"])
|
||||
if "blockWhileDwelling" in data["feature"]: s.setBoolean(["feature", "blockWhileDwelling"], data["feature"]["blockWhileDwelling"])
|
||||
|
||||
if "serial" in data.keys():
|
||||
if "autoconnect" in data["serial"].keys(): s.setBoolean(["serial", "autoconnect"], data["serial"]["autoconnect"])
|
||||
|
|
|
|||
|
|
@ -168,7 +168,6 @@ default_settings = {
|
|||
"options": {},
|
||||
"postRoll": 0,
|
||||
"fps": 25,
|
||||
"capturePostRoll": True
|
||||
},
|
||||
"cleanTmpAfterDays": 7
|
||||
},
|
||||
|
|
@ -203,7 +202,8 @@ default_settings = {
|
|||
"supportFAsCommand": False,
|
||||
"modelSizeDetection": True,
|
||||
"firmwareDetection": True,
|
||||
"printCancelConfirmation": True
|
||||
"printCancelConfirmation": True,
|
||||
"blockWhileDwelling": False
|
||||
},
|
||||
"folder": {
|
||||
"uploads": None,
|
||||
|
|
@ -357,7 +357,10 @@ default_settings = {
|
|||
"brokenM29": True,
|
||||
"supportF": False,
|
||||
"firmwareName": "Virtual Marlin 1.0",
|
||||
"sharedNozzle": False
|
||||
"sharedNozzle": False,
|
||||
"sendBusy": False,
|
||||
"simulateReset": True,
|
||||
"preparedOks": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -883,3 +883,36 @@ var getQueryParameterByName = function(name, url) {
|
|||
if (!results[2]) return '';
|
||||
return decodeURIComponent(results[2].replace(/\+/g, " "));
|
||||
};
|
||||
|
||||
/**
|
||||
* Escapes unprintable ASCII characters in the provided string.
|
||||
*
|
||||
* E.g. turns a null byte in the string into "\x00".
|
||||
*
|
||||
* Only characters 0 to 31, 127 and 255 will be escaped, that
|
||||
* should leave printable characters and unicode alone.
|
||||
*
|
||||
* Originally based on
|
||||
* https://gist.github.com/mathiasbynens/1243213#gistcomment-53590
|
||||
*
|
||||
* @param str The string to escape
|
||||
* @returns {string}
|
||||
*/
|
||||
var escapeUnprintableCharacters = function(str) {
|
||||
var result = "";
|
||||
var index = 0;
|
||||
var charCode;
|
||||
|
||||
while (!isNaN(charCode = str.charCodeAt(index))) {
|
||||
if (charCode < 32 || charCode == 127 || charCode == 255) {
|
||||
// special hex chars
|
||||
result += "\\x" + (charCode > 15 ? "" : "0") + charCode.toString(16)
|
||||
} else {
|
||||
// anything else
|
||||
result += str[index];
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -139,6 +139,7 @@ $(function() {
|
|||
self.feature_modelSizeDetection = ko.observable(undefined);
|
||||
self.feature_firmwareDetection = ko.observable(undefined);
|
||||
self.feature_printCancelConfirmation = ko.observable(undefined);
|
||||
self.feature_blockWhileDwelling = ko.observable(undefined);
|
||||
|
||||
self.serial_port = ko.observable();
|
||||
self.serial_baudrate = ko.observable();
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ $(function() {
|
|||
if (type == undefined) {
|
||||
type = "line";
|
||||
}
|
||||
return {line: line, type: type}
|
||||
return {line: escapeUnprintableCharacters(line), type: type}
|
||||
};
|
||||
|
||||
self._processStateData = function(data) {
|
||||
|
|
|
|||
|
|
@ -88,6 +88,13 @@
|
|||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: feature_blockWhileDwelling" id="settings-featureBlockWhileDwelling"> {{ _('Actively pause communication during <code>G4</code> dwell command') }} <span class="label">{{ _('Repetier') }}</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group">
|
||||
<label class="control-label">{{ _('Send a checksum with the command')}}</label>
|
||||
<div class="controls">
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" title="{{ _('Time after which the communication with your printer will be considered timed out if nothing was sent by your printer (and an attempt to get it talking again will be done). Increase this if your printer takes longer than this for some moves. This is also the interval in which the temperature will be polled from the printer while not printing.') }}">
|
||||
<div class="control-group" title="{{ _('Time after which the communication with your printer will be considered timed out if nothing was sent by your printer (and an attempt to get it talking again will be done). Increase this if your printer takes longer than this for some moves.') }}">
|
||||
<label class="control-label" for="settings-serialTimeoutCommunication">{{ _('Communication timeout') }}</label>
|
||||
<div class="controls">
|
||||
<div class="input-append">
|
||||
|
|
@ -138,25 +138,28 @@
|
|||
</div>
|
||||
<div class="controls">
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" data-bind="checked: serial_supportResendsWithoutOk" id="settings-supportResendsWithoutOk"> {{ _('Simulate an additional `ok` for resend requests') }}
|
||||
<input type="checkbox" data-bind="checked: serial_supportResendsWithoutOk" id="settings-supportResendsWithoutOk"> {{ _('Simulate an additional <code>ok</code> for resend requests') }}
|
||||
</label>
|
||||
</div>
|
||||
<div class="control-group" title="{{ _('Maximum consecutive communication timeouts while idle. More than this and the printer will be considered to be gone. Set to 0 to disable.') }}">
|
||||
<label class="control-label" for="settings-serialMaxTimeoutsIdle">{{ _('Max. consecutive timeouts while idle') }}</label>
|
||||
<div class="controls">
|
||||
<input type="number" min="0" class="input-mini text-right" id="settings-serialMaxTimeoutsIdle" data-bind="value: serial_maxTimeoutsIdle">
|
||||
<span class="help-block">{{ _('Set to 0 to disable consecutive timeout detection and handling.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" title="{{ _('Maximum consecutive communication timeouts while printing. More than this and the printer will be considered to be gone. Set to 0 to disable.') }}">
|
||||
<label class="control-label" for="settings-serialMaxTimeoutsPrinting">{{ _('Max. consecutive timeouts while printing') }}</label>
|
||||
<div class="controls">
|
||||
<input type="number" min="0" class="input-mini text-right" id="settings-serialMaxTimeoutsPrinting" data-bind="value: serial_maxTimeoutsPrinting">
|
||||
<span class="help-block">{{ _('Set to 0 to disable consecutive timeout detection and handling.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="control-group" title="{{ _('Maximum consecutive communication timeouts while a long running command is active. More than this and the printer will be considered to be gone. Set to 0 to disable.') }}">
|
||||
<label class="control-label" for="settings-serialMaxTimeoutsLong">{{ _('Max. consecutive timeouts during long running commands') }}</label>
|
||||
<div class="controls">
|
||||
<input type="number" min="0" class="input-mini text-right" id="settings-serialMaxTimeoutsLong" data-bind="value: serial_maxTimeoutsLong">
|
||||
<span class="help-block">{{ _('Set to 0 to disable consecutive timeout detection and handling.') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -285,6 +285,7 @@ class MachineCom(object):
|
|||
|
||||
self._long_running_command = False
|
||||
self._heating = False
|
||||
self._dwelling_until = False
|
||||
self._connection_closing = False
|
||||
|
||||
self._timeout = None
|
||||
|
|
@ -316,6 +317,7 @@ class MachineCom(object):
|
|||
self._unknownCommandsNeedAck = settings().getBoolean(["feature", "unknownCommandsNeedAck"])
|
||||
self._sdAlwaysAvailable = settings().getBoolean(["feature", "sdAlwaysAvailable"])
|
||||
self._sdRelativePath = settings().getBoolean(["feature", "sdRelativePath"])
|
||||
self._blockWhileDwelling = settings().getBoolean(["feature", "blockWhileDwelling"])
|
||||
self._currentLine = 1
|
||||
self._line_mutex = threading.RLock()
|
||||
self._resendDelta = None
|
||||
|
|
@ -1059,6 +1061,7 @@ class MachineCom(object):
|
|||
self.sayHello()
|
||||
|
||||
while self._monitoring_active:
|
||||
now = time.time()
|
||||
try:
|
||||
line = self._readline()
|
||||
if line is None:
|
||||
|
|
@ -1067,6 +1070,9 @@ class MachineCom(object):
|
|||
self._consecutive_timeouts = 0
|
||||
self._timeout = get_new_timeout("communication", self._timeout_intervals)
|
||||
|
||||
if self._dwelling_until and now > self._dwelling_until:
|
||||
self._dwelling_until = False
|
||||
|
||||
##~~ debugging output handling
|
||||
if line.startswith("//"):
|
||||
debugging_output = line[2:].strip()
|
||||
|
|
@ -1095,7 +1101,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
|
||||
|
|
@ -1148,7 +1154,7 @@ class MachineCom(object):
|
|||
handled = True
|
||||
|
||||
# process timeouts
|
||||
elif line == "" and time.time() > self._timeout:
|
||||
elif line == "" and (not self._blockWhileDwelling or not self._dwelling_until or now > self._dwelling_until) and now > self._timeout:
|
||||
# timeout only considered handled if the printer is printing
|
||||
self._handle_timeout()
|
||||
handled = self.isPrinting()
|
||||
|
|
@ -1238,6 +1244,7 @@ class MachineCom(object):
|
|||
|
||||
self._alwaysSendChecksum = True
|
||||
self._resendSwallowRepetitions = True
|
||||
self._blockWhileDwelling = True
|
||||
supportRepetierTargetTemp = True
|
||||
disable_external_heatup_detection = True
|
||||
|
||||
|
|
@ -1377,7 +1384,10 @@ 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"):
|
||||
if line == "wait":
|
||||
# if it was a wait we probably missed an ok, so let's simulate that now
|
||||
self._handle_ok()
|
||||
self._onConnected()
|
||||
elif time.time() > self._timeout:
|
||||
self._log("There was a timeout while trying to connect to the printer")
|
||||
|
|
@ -1551,7 +1561,7 @@ class MachineCom(object):
|
|||
command or heating, no poll will be done.
|
||||
"""
|
||||
|
||||
if self.isOperational() and not self._connection_closing and not self.isStreaming() and not self._long_running_command and not self._heating and not self._manualStreaming:
|
||||
if self.isOperational() and not self._connection_closing and not self.isStreaming() and not self._long_running_command and not self._heating and not self._dwelling_until and not self._manualStreaming:
|
||||
self.sendCommand("M105", cmd_type="temperature_poll")
|
||||
|
||||
def _poll_sd_status(self):
|
||||
|
|
@ -1562,7 +1572,7 @@ class MachineCom(object):
|
|||
command or heating, no poll will be done.
|
||||
"""
|
||||
|
||||
if self.isOperational() and not self._connection_closing and self.isSdPrinting() and not self._long_running_command and not self._heating:
|
||||
if self.isOperational() and not self._connection_closing and self.isSdPrinting() and not self._long_running_command and not self._dwelling_until and not self._heating:
|
||||
self.sendCommand("M27", cmd_type="sd_status_poll")
|
||||
|
||||
def _onConnected(self):
|
||||
|
|
@ -2019,6 +2029,12 @@ class MachineCom(object):
|
|||
if not self._send_queue_active:
|
||||
break
|
||||
|
||||
# sleep if we are dwelling
|
||||
now = time.time()
|
||||
if self._blockWhileDwelling and self._dwelling_until and now < self._dwelling_until:
|
||||
time.sleep(self._dwelling_until - now)
|
||||
self._dwelling_until = False
|
||||
|
||||
# fetch command, command type and optional linenumber and sent callback from queue
|
||||
command, linenumber, command_type, on_sent = entry
|
||||
|
||||
|
|
@ -2423,7 +2439,9 @@ class MachineCom(object):
|
|||
_timeout = float(p_match.group("value")) / 1000.0
|
||||
elif s_match:
|
||||
_timeout = float(s_match.group("value"))
|
||||
|
||||
self._timeout = get_new_timeout("communication", self._timeout_intervals) + _timeout
|
||||
self._dwelling_until = time.time() + _timeout
|
||||
|
||||
##~~ command phase handlers
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue