aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/klippy.py
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2016-05-25 11:37:40 -0400
committerKevin O'Connor <kevin@koconnor.net>2016-05-25 11:37:40 -0400
commitf582a36e4df16d5709943f7df17a900c8bcc12ab (patch)
tree628d927c4f3e19e54618f7f47c7a44af66bf0c2f /klippy/klippy.py
parent37a91e9c10648208de002c75df304e23ca89e256 (diff)
downloadkutter-f582a36e4df16d5709943f7df17a900c8bcc12ab.tar.gz
kutter-f582a36e4df16d5709943f7df17a900c8bcc12ab.tar.xz
kutter-f582a36e4df16d5709943f7df17a900c8bcc12ab.zip
Initial commit of source code.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/klippy.py')
-rw-r--r--klippy/klippy.py163
1 files changed, 163 insertions, 0 deletions
diff --git a/klippy/klippy.py b/klippy/klippy.py
new file mode 100644
index 00000000..143dd762
--- /dev/null
+++ b/klippy/klippy.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python
+# Main code for host side printer firmware
+#
+# Copyright (C) 2016 Kevin O'Connor <kevin@koconnor.net>
+#
+# This file may be distributed under the terms of the GNU GPLv3 license.
+import sys, optparse, ConfigParser, logging, time, threading
+import gcode, cartesian, util, mcu, fan, heater, reactor
+
+class ConfigWrapper:
+ def __init__(self, printer, section):
+ self.printer = printer
+ self.section = section
+ def get(self, option, default=None):
+ if not self.printer.fileconfig.has_option(self.section, option):
+ return default
+ return self.printer.fileconfig.get(self.section, option)
+ def getint(self, option, default=None):
+ if not self.printer.fileconfig.has_option(self.section, option):
+ return default
+ return self.printer.fileconfig.getint(self.section, option)
+ def getfloat(self, option, default=None):
+ if not self.printer.fileconfig.has_option(self.section, option):
+ return default
+ return self.printer.fileconfig.getfloat(self.section, option)
+ def getboolean(self, option, default=None):
+ if not self.printer.fileconfig.has_option(self.section, option):
+ return default
+ return self.printer.fileconfig.getboolean(self.section, option)
+ def getsection(self, section):
+ return ConfigWrapper(self.printer, section)
+
+class Printer:
+ def __init__(self, conffile, debuginput=None):
+ self.fileconfig = ConfigParser.RawConfigParser()
+ self.fileconfig.read(conffile)
+ self.reactor = reactor.Reactor()
+
+ self._pconfig = ConfigWrapper(self, 'printer')
+ ptty = self._pconfig.get('pseudo_tty', '/tmp/printer')
+ if debuginput is None:
+ pseudo_tty = util.create_pty(ptty)
+ else:
+ pseudo_tty = debuginput.fileno()
+
+ self.gcode = gcode.GCodeParser(
+ self, pseudo_tty, inputfile=debuginput is not None)
+ self.mcu = None
+ self.stat_timer = None
+
+ self.objects = {}
+ if self.fileconfig.has_section('fan'):
+ self.objects['fan'] = fan.PrinterFan(
+ self, ConfigWrapper(self, 'fan'))
+ if self.fileconfig.has_section('heater_nozzle'):
+ self.objects['heater_nozzle'] = heater.PrinterHeater(
+ self, ConfigWrapper(self, 'heater_nozzle'))
+ if self.fileconfig.has_section('heater_bed'):
+ self.objects['heater_bed'] = heater.PrinterHeater(
+ self, ConfigWrapper(self, 'heater_bed'))
+ self.objects['kinematics'] = cartesian.CartKinematics(
+ self, self._pconfig)
+
+ def stats(self, eventtime):
+ out = []
+ out.append(self.gcode.stats(eventtime))
+ out.append(self.objects['kinematics'].stats(eventtime))
+ out.append(self.mcu.stats(eventtime))
+ logging.info("Stats %.0f: %s" % (eventtime, ' '.join(out)))
+ return eventtime + 1.
+ def build_config(self):
+ for oname in sorted(self.objects.keys()):
+ self.objects[oname].build_config()
+ self.gcode.build_config()
+ self.mcu.build_config()
+ def connect(self):
+ self.mcu = mcu.MCU(self, ConfigWrapper(self, 'mcu'))
+ self.mcu.connect()
+ self.build_config()
+ self.stats_timer = self.reactor.register_timer(
+ self.stats, self.reactor.NOW)
+ def connect_debug(self, debugoutput):
+ self.mcu = mcu.DummyMCU(debugoutput)
+ self.mcu.connect()
+ self.build_config()
+ def connect_file(self, output, dictionary):
+ self.mcu = mcu.MCU(self, ConfigWrapper(self, 'mcu'))
+ self.mcu.connect_file(output, dictionary)
+ self.build_config()
+ def run(self):
+ self.gcode.run()
+ # If gcode exits, then exit the MCU
+ self.stats(time.time())
+ self.mcu.disconnect()
+ self.stats(time.time())
+ def shutdown(self):
+ self.gcode.shutdown()
+
+
+######################################################################
+# Startup
+######################################################################
+
+def read_dictionary(filename):
+ dfile = open(filename, 'rb')
+ dictionary = dfile.read()
+ dfile.close()
+ return dictionary
+
+def store_dictionary(filename, printer):
+ f = open(filename, 'wb')
+ f.write(printer.mcu.serial.msgparser.raw_identify_data)
+ f.close()
+
+def main():
+ usage = "%prog [options] <config file>"
+ opts = optparse.OptionParser(usage)
+ opts.add_option("-o", "--debugoutput", dest="outputfile",
+ help="write output to file instead of to serial port")
+ opts.add_option("-i", "--debuginput", dest="inputfile",
+ help="read commands from file instead of from tty port")
+ opts.add_option("-l", "--logfile", dest="logfile",
+ help="write log to file instead of stderr")
+ opts.add_option("-v", action="store_true", dest="verbose",
+ help="enable debug messages")
+ opts.add_option("-d", dest="read_dictionary",
+ help="file to read for mcu protocol dictionary")
+ opts.add_option("-D", dest="write_dictionary",
+ help="file to write mcu protocol dictionary")
+ options, args = opts.parse_args()
+ if len(args) != 1:
+ opts.error("Incorrect number of arguments")
+ conffile = args[0]
+
+ debuginput = debugoutput = None
+
+ debuglevel = logging.INFO
+ if options.verbose:
+ debuglevel = logging.DEBUG
+ if options.inputfile:
+ debuginput = open(options.inputfile, 'rb')
+ if options.outputfile:
+ debugoutput = open(options.outputfile, 'wb')
+ if options.logfile:
+ logoutput = open(options.logfile, 'wb')
+ logging.basicConfig(stream=logoutput, level=debuglevel)
+ else:
+ logging.basicConfig(level=debuglevel)
+ logging.info("Starting Klippy...")
+
+ # Start firmware
+ printer = Printer(conffile, debuginput=debuginput)
+ if debugoutput:
+ proto_dict = read_dictionary(options.read_dictionary)
+ printer.connect_file(debugoutput, proto_dict)
+ else:
+ printer.connect()
+ if options.write_dictionary:
+ store_dictionary(options.write_dictionary, printer)
+ printer.run()
+
+if __name__ == '__main__':
+ main()