Made settings module more flexible regarding variable path lengths to needed values, made speed for printer movement configurable
parent
b64662c460
commit
f03056c1b2
|
@ -20,8 +20,8 @@ def getConnectionOptions():
|
|||
return {
|
||||
"ports": comm.serialList(),
|
||||
"baudrates": comm.baudrateList(),
|
||||
"portPreference": settings().get("serial", "port"),
|
||||
"baudratePreference": settings().getInt("serial", "baudrate")
|
||||
"portPreference": settings().get(["serial", "port"]),
|
||||
"baudratePreference": settings().getInt(["serial", "baudrate"])
|
||||
}
|
||||
|
||||
class Printer():
|
||||
|
|
|
@ -29,9 +29,9 @@ printer = Printer(gcodeManager)
|
|||
def index():
|
||||
return render_template(
|
||||
"index.html",
|
||||
webcamStream=settings().get("webcam", "stream"),
|
||||
enableTimelapse=(settings().get("webcam", "snapshot") is not None and settings().get("webcam", "ffmpeg") is not None),
|
||||
enableGCodeVisualizer=settings().get("feature", "gCodeVisualizer")
|
||||
webcamStream=settings().get(["webcam", "stream"]),
|
||||
enableTimelapse=(settings().get(["webcam", "snapshot"]) is not None and settings().get(["webcam", "ffmpeg"]) is not None),
|
||||
enableGCodeVisualizer=settings().get(["feature", "gCodeVisualizer"])
|
||||
)
|
||||
|
||||
#~~ Printer state
|
||||
|
@ -111,13 +111,13 @@ def connectionOptions():
|
|||
def connect():
|
||||
port = None
|
||||
baudrate = None
|
||||
if request.values.has_key("port"):
|
||||
if "port" in request.values.keys():
|
||||
port = request.values["port"]
|
||||
if request.values.has_key("baudrate"):
|
||||
if "baudrate" in request.values.keys():
|
||||
baudrate = request.values["baudrate"]
|
||||
if request.values.has_key("save"):
|
||||
settings().set("serial", "port", port)
|
||||
settings().set("serial", "baudrate", baudrate)
|
||||
if "save" in request.values.keys():
|
||||
settings().set(["serial", "port"], port)
|
||||
settings().setInt(["serial", "baudrate"], baudrate)
|
||||
settings().save()
|
||||
printer.connect(port=port, baudrate=baudrate)
|
||||
return jsonify(state="Connecting")
|
||||
|
@ -181,21 +181,22 @@ def setTargetTemperature():
|
|||
@app.route(BASEURL + "control/jog", methods=["POST"])
|
||||
def jog():
|
||||
if not printer.isOperational() or printer.isPrinting():
|
||||
# do not jog when a print job is running or we don"t have a connection
|
||||
# do not jog when a print job is running or we don't have a connection
|
||||
return jsonify(SUCCESS)
|
||||
|
||||
(movementSpeedX, movementSpeedY, movementSpeedZ, movementSpeedE) = settings().get(["printerParameters", "movementSpeed", ["x", "y", "z", "e"]])
|
||||
if "x" in request.values.keys():
|
||||
# jog x
|
||||
x = request.values["x"]
|
||||
printer.commands(["G91", "G1 X" + x + " F3000", "G90"])
|
||||
printer.commands(["G91", "G1 X%s F%d" % (x, movementSpeedX), "G90"])
|
||||
if "y" in request.values.keys():
|
||||
# jog y
|
||||
y = request.values["y"]
|
||||
printer.commands(["G91", "G1 Y" + y + " F3000", "G90"])
|
||||
printer.commands(["G91", "G1 Y%s F%d" % (y, movementSpeedY), "G90"])
|
||||
if "z" in request.values.keys():
|
||||
# jog z
|
||||
z = request.values["z"]
|
||||
printer.commands(["G91", "G1 Z" + z + " F200", "G90"])
|
||||
printer.commands(["G91", "G1 Z%s F%d" % (z, movementSpeedZ), "G90"])
|
||||
if "homeXY" in request.values.keys():
|
||||
# home x/y
|
||||
printer.command("G28 X0 Y0")
|
||||
|
@ -205,7 +206,7 @@ def jog():
|
|||
if "extrude" in request.values.keys():
|
||||
# extrude/retract
|
||||
length = request.values["extrude"]
|
||||
printer.commands(["G91", "G1 E" + length + " F300", "G90"])
|
||||
printer.commands(["G91", "G1 E%s F%d" % (length, movementSpeedE), "G90"])
|
||||
|
||||
return jsonify(SUCCESS)
|
||||
|
||||
|
@ -227,7 +228,7 @@ def speed():
|
|||
|
||||
@app.route(BASEURL + "control/custom", methods=["GET"])
|
||||
def getCustomControls():
|
||||
customControls = settings().getObject("controls")
|
||||
customControls = settings().get(["controls"])
|
||||
return jsonify(controls=customControls)
|
||||
|
||||
#~~ GCODE file handling
|
||||
|
@ -393,8 +394,8 @@ def initLogging():
|
|||
def main():
|
||||
from optparse import OptionParser
|
||||
|
||||
defaultHost = settings().get("server", "host")
|
||||
defaultPort = settings().get("server", "port")
|
||||
defaultHost = settings().get(["server", "host"])
|
||||
defaultPort = settings().get(["server", "port"])
|
||||
|
||||
parser = OptionParser(usage="usage: %prog [options]")
|
||||
parser.add_option("-d", "--debug", action="store_true", dest="debug",
|
||||
|
|
|
@ -45,9 +45,19 @@ old_default_settings = {
|
|||
|
||||
default_settings = old_default_settings.copy()
|
||||
default_settings.update({
|
||||
"controls": []
|
||||
"controls": [],
|
||||
"printerParameters": {
|
||||
"movementSpeed": {
|
||||
"x": 6000,
|
||||
"y": 6000,
|
||||
"z": 200,
|
||||
"e": 300
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
valid_boolean_trues = ["true", "yes", "y", "1"]
|
||||
|
||||
class Settings(object):
|
||||
|
||||
def __init__(self):
|
||||
|
@ -56,10 +66,10 @@ class Settings(object):
|
|||
self._config = None
|
||||
self._dirty = False
|
||||
|
||||
self.init_settings_dir()
|
||||
self._init_settings_dir()
|
||||
self.load()
|
||||
|
||||
def init_settings_dir(self):
|
||||
def _init_settings_dir(self):
|
||||
self.settings_dir = _resolveSettingsDir(APPNAME)
|
||||
|
||||
# migration due to rename
|
||||
|
@ -67,6 +77,8 @@ class Settings(object):
|
|||
if os.path.exists(old_settings_dir) and os.path.isdir(old_settings_dir) and not os.path.exists(self.settings_dir):
|
||||
os.rename(old_settings_dir, self.settings_dir)
|
||||
|
||||
#~~ load and save
|
||||
|
||||
def load(self):
|
||||
filename = os.path.join(self.settings_dir, "config.yaml")
|
||||
oldFilename = os.path.join(self.settings_dir, "config.ini")
|
||||
|
@ -102,29 +114,48 @@ class Settings(object):
|
|||
self._dirty = False
|
||||
self.load()
|
||||
|
||||
def getObject(self, key):
|
||||
if key not in default_settings.keys():
|
||||
#~~ getter
|
||||
|
||||
def get(self, path):
|
||||
if len(path) == 0:
|
||||
return None
|
||||
|
||||
if key in self._config.keys():
|
||||
return self._config[key]
|
||||
config = self._config
|
||||
defaults = default_settings
|
||||
|
||||
return default_settings[key]
|
||||
|
||||
def get(self, section, key):
|
||||
if section not in default_settings.keys():
|
||||
while len(path) > 1:
|
||||
key = path.pop(0)
|
||||
if key in config.keys() and key in defaults.keys():
|
||||
config = config[key]
|
||||
defaults = defaults[key]
|
||||
elif key in defaults.keys():
|
||||
config = {}
|
||||
defaults = defaults[key]
|
||||
else:
|
||||
return None
|
||||
|
||||
if self._config.has_key(section) and self._config[section].has_key(key):
|
||||
return self._config[section][key]
|
||||
k = path.pop(0)
|
||||
if not isinstance(k, (list, tuple)):
|
||||
keys = [k]
|
||||
else:
|
||||
keys = k
|
||||
|
||||
if default_settings.has_key(section) and default_settings[section].has_key(key):
|
||||
return default_settings[section][key]
|
||||
results = []
|
||||
for key in keys:
|
||||
if key in config.keys():
|
||||
results.append(config[key])
|
||||
elif key in defaults:
|
||||
results.append(defaults[key])
|
||||
else:
|
||||
results.append(None)
|
||||
|
||||
return None
|
||||
if not isinstance(k, (list, tuple)):
|
||||
return results.pop()
|
||||
else:
|
||||
return results
|
||||
|
||||
def getInt(self, section, key):
|
||||
value = self.get(section, key)
|
||||
def getInt(self, path):
|
||||
value = self.get(path)
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
|
@ -133,19 +164,19 @@ class Settings(object):
|
|||
except ValueError:
|
||||
return None
|
||||
|
||||
def getBoolean(self, section, key):
|
||||
value = self.get(section, key)
|
||||
def getBoolean(self, path):
|
||||
value = self.get(path)
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
return value.lower() in ["true", "yes", "y", "1"]
|
||||
return value.lower() in valid_boolean_trues
|
||||
|
||||
def getBaseFolder(self, type):
|
||||
if type not in old_default_settings["folder"].keys():
|
||||
return None
|
||||
|
||||
folder = self.get("folder", type)
|
||||
folder = self.get(["folder", type])
|
||||
if folder is None:
|
||||
folder = os.path.join(self.settings_dir, type.replace("_", os.path.sep))
|
||||
|
||||
|
@ -154,26 +185,50 @@ class Settings(object):
|
|||
|
||||
return folder
|
||||
|
||||
def set(self, section, key, value):
|
||||
if section not in default_settings.keys():
|
||||
#~~ setter
|
||||
|
||||
def set(self, path, value):
|
||||
if len(path) == 0:
|
||||
return
|
||||
|
||||
if self._config.has_key(section):
|
||||
sectionConfig = self._config[section]
|
||||
config = self._config
|
||||
defaults = default_settings
|
||||
|
||||
while len(path) > 1:
|
||||
key = path.pop(0)
|
||||
if key in config.keys():
|
||||
config = config[key]
|
||||
elif key in defaults.keys():
|
||||
config[key] = {}
|
||||
config = config[key]
|
||||
else:
|
||||
sectionConfig = {}
|
||||
|
||||
sectionConfig[key] = value
|
||||
self._config[section] = sectionConfig
|
||||
self._dirty = True
|
||||
|
||||
def setObject(self, key, value):
|
||||
if key not in default_settings.keys():
|
||||
return
|
||||
|
||||
self._config[key] = value
|
||||
key = path.pop(0)
|
||||
config[key] = value
|
||||
self._dirty = True
|
||||
|
||||
def setInt(self, path, value):
|
||||
if value is None:
|
||||
return
|
||||
|
||||
try:
|
||||
intValue = int(value)
|
||||
except ValueError:
|
||||
return
|
||||
|
||||
self.set(path, intValue)
|
||||
|
||||
def setBoolean(self, path, value):
|
||||
if value is None:
|
||||
return
|
||||
elif isinstance(value, bool):
|
||||
self.set(path, value)
|
||||
elif value.lower() in valid_boolean_trues:
|
||||
self.set(path, True)
|
||||
else:
|
||||
self.set(path, False)
|
||||
|
||||
def _resolveSettingsDir(applicationName):
|
||||
# taken from http://stackoverflow.com/questions/1084697/how-do-i-store-desktop-application-data-in-a-cross-platform-way-for-python
|
||||
if sys.platform == "darwin":
|
||||
|
|
|
@ -31,7 +31,7 @@ class Timelapse(object):
|
|||
|
||||
self._captureDir = settings().getBaseFolder("timelapse_tmp")
|
||||
self._movieDir = settings().getBaseFolder("timelapse")
|
||||
self._snapshotUrl = settings().get("webcam", "snapshot")
|
||||
self._snapshotUrl = settings().get(["webcam", "snapshot"])
|
||||
|
||||
self._renderThread = None
|
||||
self._captureMutex = threading.Lock()
|
||||
|
@ -79,8 +79,8 @@ class Timelapse(object):
|
|||
urllib.urlretrieve(self._snapshotUrl, filename)
|
||||
|
||||
def _createMovie(self):
|
||||
ffmpeg = settings().get("webcam", "ffmpeg")
|
||||
bitrate = settings().get("webcam", "bitrate")
|
||||
ffmpeg = settings().get(["webcam", "ffmpeg"])
|
||||
bitrate = settings().get(["webcam", "bitrate"])
|
||||
if ffmpeg is None or bitrate is None:
|
||||
return
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ def serialList():
|
|||
except:
|
||||
pass
|
||||
baselist = baselist + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/cu.*") + glob.glob("/dev/rfcomm*")
|
||||
prev = settings().get("serial", "port")
|
||||
prev = settings().get(["serial", "port"])
|
||||
if prev in baselist:
|
||||
baselist.remove(prev)
|
||||
baselist.insert(0, prev)
|
||||
|
@ -48,7 +48,7 @@ def serialList():
|
|||
|
||||
def baudrateList():
|
||||
ret = [250000, 230400, 115200, 57600, 38400, 19200, 9600]
|
||||
prev = settings().getInt("serial", "baudrate")
|
||||
prev = settings().getInt(["serial", "baudrate"])
|
||||
if prev in ret:
|
||||
ret.remove(prev)
|
||||
ret.insert(0, prev)
|
||||
|
@ -144,9 +144,9 @@ class MachineCom(object):
|
|||
|
||||
def __init__(self, port = None, baudrate = None, callbackObject = None):
|
||||
if port == None:
|
||||
port = settings().get("serial", "port")
|
||||
port = settings().get(["serial", "port"])
|
||||
if baudrate == None:
|
||||
settingsBaudrate = settings().getInt("serial", "baudrate")
|
||||
settingsBaudrate = settings().getInt(["serial", "baudrate"])
|
||||
if settingsBaudrate is None:
|
||||
baudrate = 0
|
||||
else:
|
||||
|
|
Loading…
Reference in New Issue