Added timeout settings for serial communiction, initial connection and baudrate detection

Closes #126
master
Gina Häußge 2013-07-04 21:26:53 +02:00
parent 3ffaaa19be
commit 6d3e3221b8
6 changed files with 96 additions and 15 deletions

View File

@ -518,6 +518,9 @@ def getSettings():
"portOptions": connectionOptions["ports"], "portOptions": connectionOptions["ports"],
"baudrateOptions": connectionOptions["baudrates"], "baudrateOptions": connectionOptions["baudrates"],
"autoconnect": s.getBoolean(["serial", "autoconnect"]), "autoconnect": s.getBoolean(["serial", "autoconnect"]),
"timeoutConnection": s.getFloat(["serial", "timeout", "connection"]),
"timeoutDetection": s.getFloat(["serial", "timeout", "detection"]),
"timeoutCommunication": s.getFloat(["serial", "timeout", "communication"]),
"log": s.getBoolean(["serial", "log"]) "log": s.getBoolean(["serial", "log"])
}, },
"folder": { "folder": {
@ -576,6 +579,9 @@ def setSettings():
if "autoconnect" in data["serial"].keys(): s.setBoolean(["serial", "autoconnect"], data["serial"]["autoconnect"]) if "autoconnect" in data["serial"].keys(): s.setBoolean(["serial", "autoconnect"], data["serial"]["autoconnect"])
if "port" in data["serial"].keys(): s.set(["serial", "port"], data["serial"]["port"]) if "port" in data["serial"].keys(): s.set(["serial", "port"], data["serial"]["port"])
if "baudrate" in data["serial"].keys(): s.setInt(["serial", "baudrate"], data["serial"]["baudrate"]) if "baudrate" in data["serial"].keys(): s.setInt(["serial", "baudrate"], data["serial"]["baudrate"])
if "timeoutConnection" in data["serial"].keys(): s.setFloat(["serial", "timeout", "connection"], data["serial"]["timeoutConnection"])
if "timeoutDetection" in data["serial"].keys(): s.setFloat(["serial", "timeout", "detection"], data["serial"]["timeoutDetection"])
if "timeoutCommunication" in data["serial"].keys(): s.setFloat(["serial", "timeout", "communication"], data["serial"]["timeoutCommunication"])
oldLog = s.getBoolean(["serial", "log"]) oldLog = s.getBoolean(["serial", "log"])
if "log" in data["serial"].keys(): s.setBoolean(["serial", "log"], data["serial"]["log"]) if "log" in data["serial"].keys(): s.setBoolean(["serial", "log"], data["serial"]["log"])

View File

@ -27,7 +27,12 @@ default_settings = {
"port": None, "port": None,
"baudrate": None, "baudrate": None,
"autoconnect": False, "autoconnect": False,
"log": False "log": False,
"timeout": {
"detection": 0.5,
"connection": 2,
"communication": 5
}
}, },
"server": { "server": {
"host": "0.0.0.0", "host": "0.0.0.0",
@ -199,6 +204,17 @@ class Settings(object):
self._logger.warn("Could not convert %r to a valid integer when getting option %r" % (value, path)) self._logger.warn("Could not convert %r to a valid integer when getting option %r" % (value, path))
return None return None
def getFloat(self, path):
value = self.get(path)
if value is None:
return None
try:
return float(value)
except ValueError:
self._logger.warn("Could not convert %r to a valid integer when getting option %r" % (value, path))
return None
def getBoolean(self, path): def getBoolean(self, path):
value = self.get(path) value = self.get(path)
if value is None: if value is None:
@ -288,6 +304,19 @@ class Settings(object):
self.set(path, intValue, force) self.set(path, intValue, force)
def setFloat(self, path, value, force=False):
if value is None:
self.set(path, None, force)
return
try:
floatValue = float(value)
except ValueError:
self._logger.warn("Could not convert %r to a valid integer when setting option %r" % (value, path))
return
self.set(path, floatValue, force)
def setBoolean(self, path, value, force=False): def setBoolean(self, path, value, force=False):
if value is None or isinstance(value, bool): if value is None or isinstance(value, bool):
self.set(path, value, force) self.set(path, value, force)

View File

@ -1363,6 +1363,9 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) {
self.serial_portOptions = ko.observableArray([]); self.serial_portOptions = ko.observableArray([]);
self.serial_baudrateOptions = ko.observableArray([]); self.serial_baudrateOptions = ko.observableArray([]);
self.serial_autoconnect = ko.observable(undefined); self.serial_autoconnect = ko.observable(undefined);
self.serial_timeoutConnection = ko.observable(undefined);
self.serial_timeoutDetection = ko.observable(undefined);
self.serial_timeoutCommunication = ko.observable(undefined);
self.serial_log = ko.observable(undefined); self.serial_log = ko.observable(undefined);
self.folder_uploads = ko.observable(undefined); self.folder_uploads = ko.observable(undefined);
@ -1421,6 +1424,9 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) {
self.serial_portOptions(response.serial.portOptions); self.serial_portOptions(response.serial.portOptions);
self.serial_baudrateOptions(response.serial.baudrateOptions); self.serial_baudrateOptions(response.serial.baudrateOptions);
self.serial_autoconnect(response.serial.autoconnect); self.serial_autoconnect(response.serial.autoconnect);
self.serial_timeoutConnection(response.serial.timeoutConnection);
self.serial_timeoutDetection(response.serial.timeoutDetection);
self.serial_timeoutCommunication(response.serial.timeoutCommunication);
self.serial_log(response.serial.log); self.serial_log(response.serial.log);
self.folder_uploads(response.folder.uploads); self.folder_uploads(response.folder.uploads);
@ -1468,6 +1474,9 @@ function SettingsViewModel(loginStateViewModel, usersViewModel) {
"port": self.serial_port(), "port": self.serial_port(),
"baudrate": self.serial_baudrate(), "baudrate": self.serial_baudrate(),
"autoconnect": self.serial_autoconnect(), "autoconnect": self.serial_autoconnect(),
"timeoutConnection": self.serial_timeoutConnection(),
"timeoutDetection": self.serial_timeoutDetection(),
"timeoutCommunication": self.serial_timeoutCommunication(),
"log": self.serial_log() "log": self.serial_log()
}, },
"folder": { "folder": {

View File

@ -21,14 +21,14 @@
<div class="tab-pane active" id="settings_serialConnection"> <div class="tab-pane active" id="settings_serialConnection">
<form class="form-horizontal"> <form class="form-horizontal">
<div class="control-group"> <div class="control-group">
<label class="control-label" for="settings-serialPort">Serial Port</label>
<div class="controls"> <div class="controls">
<label for="settings-serialPort">Serial Port</label>
<select id="settings-serialPort" data-bind="options: serial_portOptions, optionsCaption: 'AUTO', value: serial_port"></select> <select id="settings-serialPort" data-bind="options: serial_portOptions, optionsCaption: 'AUTO', value: serial_port"></select>
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label class="control-label" for="settings-baudrate">Baudrate</label>
<div class="controls"> <div class="controls">
<label for="settings-baudrate">Baudrate</label>
<select id="settings-baudrate" data-bind="options: serial_baudrateOptions, optionsCaption: 'AUTO', value: serial_baudrate"></select> <select id="settings-baudrate" data-bind="options: serial_baudrateOptions, optionsCaption: 'AUTO', value: serial_baudrate"></select>
</div> </div>
</div> </div>
@ -39,6 +39,33 @@
</label> </label>
</div> </div>
</div> </div>
<div class="control-group">
<label class="control-label" for="settings-movementSpeedE">Communication timeout</label>
<div class="controls">
<div class="input-append">
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutCommunication" id="settings-serialTimeoutCommunication">
<span class="add-on">s</span>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label" for="settings-movementSpeedE">Connection timeout</label>
<div class="controls">
<div class="input-append">
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutConnection" id="settings-serialTimeoutConnection">
<span class="add-on">s</span>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label" for="settings-movementSpeedE">Autodetection timeout</label>
<div class="controls">
<div class="input-append">
<input type="number" step="any" min="0" class="input-mini text-right" data-bind="value: serial_timeoutDetection" id="settings-serialTimeoutDetection">
<span class="add-on">s</span>
</div>
</div>
</div>
<div class="control-group"> <div class="control-group">
<div class="controls"> <div class="controls">
<label class="checkbox"> <label class="checkbox">

View File

@ -2,11 +2,12 @@
__author__ = "Gina Häußge <osd@foosel.net>" __author__ = "Gina Häußge <osd@foosel.net>"
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html' __license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
import re
import os import os
import traceback import traceback
import sys import sys
import time
from octoprint.settings import settings
def getFormattedSize(num): def getFormattedSize(num):
""" """
@ -79,3 +80,12 @@ def getGitInfo():
head = f.readline().strip() head = f.readline().strip()
return (branch, head) return (branch, head)
def getNewTimeout(type):
now = time.time()
if type not in ["connection", "detection", "communication"]:
return now # timeout immediately for unknown timeout type
return now + settings().getFloat(["serial", "timeout", type])

View File

@ -19,7 +19,7 @@ from octoprint.util.avr_isp import ispBase
from octoprint.settings import settings from octoprint.settings import settings
from octoprint.events import eventManager from octoprint.events import eventManager
from octoprint.util import isDevVersion, getExceptionString from octoprint.util import isDevVersion, getExceptionString, getNewTimeout
from octoprint.util.virtual import VirtualPrinter from octoprint.util.virtual import VirtualPrinter
try: try:
@ -467,7 +467,7 @@ class MachineCom(object):
if self._baudrate == 0: if self._baudrate == 0:
self._serial = serial.Serial(str(self._port), 115200, timeout=0.1, writeTimeout=10000) self._serial = serial.Serial(str(self._port), 115200, timeout=0.1, writeTimeout=10000)
else: else:
self._serial = serial.Serial(str(self._port), self._baudrate, timeout=2, writeTimeout=10000) self._serial = serial.Serial(str(self._port), self._baudrate, timeout=settings().getFloat(["serial", "timeout", "connection"]), writeTimeout=10000)
except: except:
self._log("Unexpected error while connecting to serial port: %s %s" % (self._port, getExceptionString())) self._log("Unexpected error while connecting to serial port: %s %s" % (self._port, getExceptionString()))
if self._serial == None: if self._serial == None:
@ -483,7 +483,7 @@ class MachineCom(object):
self._changeState(self.STATE_CONNECTING) self._changeState(self.STATE_CONNECTING)
#Start monitoring the serial port. #Start monitoring the serial port.
timeout = time.time() + 5 timeout = getNewTimeout("communication")
tempRequestTimeout = timeout tempRequestTimeout = timeout
sdStatusRequestTimeout = timeout sdStatusRequestTimeout = timeout
startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"]) startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
@ -623,11 +623,11 @@ class MachineCom(object):
baudrate = self._baudrateDetectList.pop(0) baudrate = self._baudrateDetectList.pop(0)
try: try:
self._serial.baudrate = baudrate self._serial.baudrate = baudrate
self._serial.timeout = 0.5 self._serial.timeout = getNewTimeout("detection")
self._log("Trying baudrate: %d" % (baudrate)) self._log("Trying baudrate: %d" % (baudrate))
self._baudrateDetectRetry = 5 self._baudrateDetectRetry = 5
self._baudrateDetectTestOk = 0 self._baudrateDetectTestOk = 0
timeout = time.time() + 5 timeout = getNewTimeout("communication")
self._serial.write('\n') self._serial.write('\n')
self._sendCommand("M105") self._sendCommand("M105")
self._testingBaudrate = True self._testingBaudrate = True
@ -640,7 +640,7 @@ class MachineCom(object):
self._sendCommand("M105") self._sendCommand("M105")
else: else:
self._sendCommand("M999") self._sendCommand("M999")
self._serial.timeout = 2 self._serial.timeout = getNewTimeout("connection")
self._changeState(self.STATE_OPERATIONAL) self._changeState(self.STATE_OPERATIONAL)
if self._sdAvailable: if self._sdAvailable:
self.refreshSdFiles() self.refreshSdFiles()
@ -672,7 +672,7 @@ class MachineCom(object):
self._sendCommand(self._commandQueue.get()) self._sendCommand(self._commandQueue.get())
else: else:
self._sendCommand("M105") self._sendCommand("M105")
tempRequestTimeout = time.time() + 5 tempRequestTimeout = getNewTimeout("communication")
# 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._handleResendRequest(line)
@ -686,22 +686,22 @@ class MachineCom(object):
if self.isSdPrinting(): if self.isSdPrinting():
if time.time() > tempRequestTimeout and not heatingUp: if time.time() > tempRequestTimeout and not heatingUp:
self._sendCommand("M105") self._sendCommand("M105")
tempRequestTimeout = time.time() + 5 tempRequestTimeout = getNewTimeout("communication")
if time.time() > sdStatusRequestTimeout and not heatingUp: if time.time() > sdStatusRequestTimeout and not heatingUp:
self._sendCommand("M27") self._sendCommand("M27")
sdStatusRequestTimeout = time.time() + 1 sdStatusRequestTimeout = time.time() + 1
if 'ok' or 'SD printing byte' in line: if 'ok' or 'SD printing byte' in line:
timeout = time.time() + 5 timeout = getNewTimeout("communication")
else: else:
# Even when printing request the temperature every 5 seconds. # Even when printing request the temperature every 5 seconds.
if time.time() > tempRequestTimeout and not self.isStreaming(): if time.time() > tempRequestTimeout and not self.isStreaming():
self._commandQueue.put("M105") self._commandQueue.put("M105")
tempRequestTimeout = time.time() + 5 tempRequestTimeout = getNewTimeout("communication")
if 'ok' in line: if 'ok' in line:
timeout = time.time() + 5 timeout = getNewTimeout("communication")
if self._resendDelta is not None: if self._resendDelta is not None:
self._resendNextCommand() self._resendNextCommand()
elif not self._commandQueue.empty() and not self.isStreaming(): elif not self._commandQueue.empty() and not self.isStreaming():