def __init__(self, **kwargs): self.initializing = True self.max_w_val = 0 pronsole.pronsole.__init__(self) EventEmitter.__init__(self) self.settings.sensor_names = {'T': 'extruder', 'B': 'bed'} self.settings.sensor_poll_rate = 1 # seconds self.p.loud = kwargs['loud'] self.dry_run = kwargs['dry_run'] == True self.stdout = sys.stdout self.load_default_rc() self.p.sendcb = self.sendcb self.initializing = False dir = os.path.dirname(__file__) self.server = ConstructServer( printer=self, settings=dict( pause_between_prints=self.settings.pause_between_prints, sensor_poll_rate=self.settings.sensor_poll_rate * 1000), components=dict( temps=["e0", "b"], fans=["f0"], conveyors=["c0"], axes=[] # In the far off future we may have axes like these for position data: # axes= ["x", "y", "z"] ), server_settings=dict( template_path=os.path.join(dir, "printrun", "server", "templates"), static_path=os.path.join(dir, "printrun", "server", "static"), debug=True), routes=[(r"/", RootHandler), (r"/inspect", InspectHandler)])
def __init__(self, **kwargs): self.initializing = True self.max_w_val = 0 pronsole.pronsole.__init__(self) EventEmitter.__init__(self) self.settings.sensor_names = {'T': 'extruder', 'B': 'bed'} self.settings.sensor_poll_rate = 1 # seconds self.p.loud = kwargs['loud'] self.dry_run = kwargs['dry_run'] self.heaptrace = kwargs['heaptrace'] self.stdout = sys.stdout self.load_default_rc() self.p.sendcb = self.sendcb self.initializing = False dir = os.path.dirname(__file__) self.server = ConstructServer( printer= self, settings= dict( pause_between_prints = self.settings.pause_between_prints, sensor_poll_rate = self.settings.sensor_poll_rate * 1000 ), components= dict( temps= ["e0", "b"], fans= ["f0"], conveyors= ["c0"], axes= [] # In the far off future we may have axes like these for position data: # axes= ["x", "y", "z"] ), server_settings= dict( template_path= os.path.join(dir, "server", "templates"), static_path= os.path.join(dir, "server", "static"), debug= True ), routes= [ (r"/", RootHandler), (r"/inspect", InspectHandler) ] )
class Prontserve(pronsole.pronsole, EventEmitter): def __init__(self, **kwargs): self.initializing = True self.max_w_val = 0 pronsole.pronsole.__init__(self) EventEmitter.__init__(self) self.settings.sensor_names = {'T': 'extruder', 'B': 'bed'} self.settings.sensor_poll_rate = 1 # seconds self.p.loud = kwargs['loud'] self.dry_run = kwargs['dry_run'] == True self.stdout = sys.stdout self.load_default_rc() self.p.sendcb = self.sendcb self.initializing = False dir = os.path.dirname(__file__) self.server = ConstructServer( printer=self, settings=dict( pause_between_prints=self.settings.pause_between_prints, sensor_poll_rate=self.settings.sensor_poll_rate * 1000), components=dict( temps=["e0", "b"], fans=["f0"], conveyors=["c0"], axes=[] # In the far off future we may have axes like these for position data: # axes= ["x", "y", "z"] ), server_settings=dict( template_path=os.path.join(dir, "printrun", "server", "templates"), static_path=os.path.join(dir, "printrun", "server", "static"), debug=True), routes=[(r"/", RootHandler), (r"/inspect", InspectHandler)]) def display_startup_padding(self): if self.dry_run: for i in range(0, 7): sys.stdout.write("\x1B[0;33m Dry Run \x1B[0m") print "" def display_startup_message(self): welcome = textwrap.dedent(u""" +---+ \x1B[0;32mProntserve: Your printer just got a whole lot better. \x1B[0m| \u2713 | Ready to print. +---+ More details at http://localhost:8888/""") print "\n" + "-" * 80 self.display_startup_padding() sys.stdout.write(welcome) print "\n" self.display_startup_padding() print "-" * 80 + "\n" def start(self): try: if self.dry_run == False: # Attempt to connect to the printer self.do_connect("") if self.p.printer == None: sys.exit(1) print "Connecting to printer..." # Wait for the attempt to succeed or timeout for x in range(0, 50 - 1): if self.p.online == True: break sys.stdout.write(".") sys.stdout.flush() time.sleep(0.1) print "" if self.p.online == False: print "Unable to connect to printer: Connection timed-out." sys.exit(1) # Wait for the printer to finish connecting and then reset it time.sleep(2) self.reset() # Start the server, display the startup message and start the ioloop self.server.start() self.display_startup_message() self.server.ioloop.start() except Exception as ex: print traceback.format_exc() if args.heaptrace: print hpy().heap() self.p.disconnect() exit() def is_online(self): return self.p.online == True def is_printing(self): return self.p.printing == False and self.p.online def post_process_print_job(self, filename, filebody): return FastGCode(filebody.split("\n")) def current_print_line(self): if (self.p.printing): return (self.p.queueindex) return 0 def total_print_lines(self, job_body): return len(job_body) def start_print_job(self, job): self.p.startprint(job['body']) self.p.paused = False def do_home(self, *args, **kwargs): pronsole.pronsole.do_home(self, " ".join(args)) def do_move(self, **kwargs): # Convert mm/s to mm/minute if "at" in kwargs: speed_multiplier = float(kwargs['at'].replace("%", "")) * 0.01 else: speed_multiplier = 1 for k, v in kwargs.iteritems(): if k == "at": continue # Getting the feedrate if k in ["z", "e"]: prefix = k else: prefix = "xy" speed = getattr(self.settings, "%s_feedrate" % prefix) * speed_multiplier # Creating the pronsole axial move command args = {"axis": k, "dist": v, "speed": speed} cmd = "%(axis)s %(dist)s %(speed)s" % args print "move %s" % cmd pronsole.pronsole.do_move(self, cmd) def do_stop_move(self): raise Exception("Continuous movement not supported") def do_estop(self): self.reset() print "Emergency Stop!" # Not thread safe; must be run from the ioloop thread. def reset(self): self. async (self.server.set_blocking_temps, []) # pause the print job if any is printing if self.p.printing: pronsole.pronsole.do_pause(self, "") # Prevent the sensor from polling for 2 seconds while the firmware # restarts self.server.set_reset_timeout(time.time() + 2) self.server.set_sensor_update_received(True) # restart the firmware pronsole.pronsole.do_reset(self, "") self.p.printing = False def on_temp_target_change(self, parent_path, component, value): target = parent_path[0] gcode = "M104" if target == "b": gcode = "M140" if not target in ["b", "e0"]: gcode += " p%i" % (int(target[1:])) gcode += " S%f" % float(value) self.p.send_now(gcode) def on_fan_enabled_change(self, parent_path, component, value): update_fan(component) def on_fan_speed_change(self, parent_path, component, value): update_fan(component) def update_fan(self, component): speed = int(component['speed']) if component['enabled'] == False: speed = 0 print "M106 S%i" % speed self.p.send_now("M106 S%i" % speed) def on_motors_enabled_change(self, parent_path, component, value): self.p.send_now({True: "M17", False: "M18"}[value]) def request_sensor_update(self): if self.dry_run: return self._receive_sensor_update( "ok T:%i B:%i" % (random.randint(30, 60), random.randint(30, 60))) if self.p.online: self.p.send_now("M105") def recvcb(self, l): """ Parses a line of output from the printer via printcore """ l = l.rstrip() #print l if self.server.waiting_to_reach_temp and ("ok" in l): self. async (self.server.set_blocking_temps, []) if ("T:" in l): self. async (self._receive_sensor_update, l) if l != "ok" and not l.startswith("ok T") and not l.startswith("T:"): self. async (self._receive_printer_error, l) def sendcb(self, l): # Monitor the sent commands for new extruder target temperatures if ("M109" in l) or ("M104" in l) or ("M140" in l) or ("M190" in l): temp = float(re.search('S([0-9]+)', l).group(1)) if ("M109" in l) or ("M104" in l): target = "e0" if " P" in l: target = "e%i" % (int(re.search(' P([0-9]+)', l).group(1))) else: target = "b" self. async (self.server.c_set, [target, "target_temp"], temp, internal=True) if ("M109" in l) or ("M190" in l) or ("M116" in l): if ("M116" in l): target = "e0" self. async (self.server.set_blocking_temps, [target]) # Adds a callback to the ioloop to run a method later on in the server thread def async (self, *args, **kwargs): self.server.ioloop.add_callback(*args, **kwargs) def _receive_sensor_update(self, l): try: self. async (self.server.set_sensor_update_received, True) words = filter(lambda s: s.find(":") > 0, l.lower().split(" ")) d = dict([s.split(":") for s in words]) for key, value in d.iteritems(): if key == "t": key = "e0" if not key in self.server.components: continue self.server.c_set([key, "current_temp"], float(value), internal=True) # Fire a event if the extruder is giving us a countdown till it's online # see: TEMP_RESIDENCY_TIME (via the googles) # see: https://github.com/ErikZalm/Marlin/blob/Marlin_v1/Marlin/Marlin_main.cpp#L1191 if ("w" in d) and (not d["w"] == "?"): w = float(d["w"]) * 1000 for target in (self.server.blockers): self.server.c_set([target, "target_temp_countdown"], w, internal=True) except Exception as ex: print traceback.format_exc() def log(self, *msg): msg = ''.join(str(i) for i in msg) msg.replace("\r", "") print msg # self.server.broadcast([ # dict(type= "log", data= dict(msg= msg, level= "debug")) # ]) def logError(self, *msg): print u"".join(unicode(i) for i in msg) if self.initializing == False: raise Exception(u"".join(unicode(i) for i in msg)) def write_prompt(self): None def confirm(self): True
class Prontserve(pronsole.pronsole, EventEmitter): def __init__(self, **kwargs): self.initializing = True self.max_w_val = 0 pronsole.pronsole.__init__(self) EventEmitter.__init__(self) self.settings.sensor_names = {'T': 'extruder', 'B': 'bed'} self.settings.sensor_poll_rate = 1 # seconds self.p.loud = kwargs['loud'] self.dry_run = kwargs['dry_run'] == True self.stdout = sys.stdout self.load_default_rc() self.p.sendcb = self.sendcb self.initializing = False dir = os.path.dirname(__file__) self.server = ConstructServer( printer= self, settings= dict( pause_between_prints = self.settings.pause_between_prints, sensor_poll_rate = self.settings.sensor_poll_rate * 1000 ), components= dict( temps= ["e0", "b"], fans= ["f0"], conveyors= ["c0"], axes= [] # In the far off future we may have axes like these for position data: # axes= ["x", "y", "z"] ), server_settings= dict( template_path= os.path.join(dir, "printrun", "server", "templates"), static_path= os.path.join(dir, "printrun", "server", "static"), debug= True ), routes= [ (r"/", RootHandler), (r"/inspect", InspectHandler) ] ) def display_startup_padding(self): if self.dry_run: for i in range(0,7): sys.stdout.write("\x1B[0;33m Dry Run \x1B[0m") print "" def display_startup_message(self): welcome = textwrap.dedent(u""" +---+ \x1B[0;32mProntserve: Your printer just got a whole lot better. \x1B[0m| \u2713 | Ready to print. +---+ More details at http://localhost:8888/""") print "\n"+"-"*80 self.display_startup_padding() sys.stdout.write(welcome) print "\n" self.display_startup_padding() print "-"*80 + "\n" def start(self): try: if self.dry_run == False: # Attempt to connect to the printer self.do_connect("") if self.p.printer == None: sys.exit(1) print "Connecting to printer..." # Wait for the attempt to succeed or timeout for x in range(0,50-1): if self.p.online == True: break sys.stdout.write(".") sys.stdout.flush() time.sleep(0.1) print "" if self.p.online == False: print "Unable to connect to printer: Connection timed-out." sys.exit(1) # Wait for the printer to finish connecting and then reset it time.sleep(2) self.reset() # Start the server, display the startup message and start the ioloop self.server.start() self.display_startup_message() self.server.ioloop.start() except Exception as ex: print traceback.format_exc() if args.heaptrace: print hpy().heap() self.p.disconnect() exit() def is_online(self): return self.p.online == True def is_printing(self): return self.p.printing == False and self.p.online def post_process_print_job(self, filename, filebody): return FastGCode(filebody.split("\n")) def current_print_line(self): if(self.p.printing): return (self.p.queueindex) return 0 def total_print_lines(self, job_body): return len(job_body) def start_print_job(self, job): self.p.startprint(job['body']) self.p.paused = False def do_home(self, *args, **kwargs): pronsole.pronsole.do_home(self, " ".join(args)) def do_move(self, **kwargs): # Convert mm/s to mm/minute if "at" in kwargs: speed_multiplier = float(kwargs['at'].replace("%",""))*0.01 else: speed_multiplier = 1 for k, v in kwargs.iteritems(): if k == "at": continue # Getting the feedrate if k in ["z", "e"]: prefix = k else: prefix = "xy" speed = getattr(self.settings, "%s_feedrate"%prefix) * speed_multiplier # Creating the pronsole axial move command args = {"axis" : k, "dist" : v, "speed" : speed } cmd = "%(axis)s %(dist)s %(speed)s" % args print "move %s"%cmd pronsole.pronsole.do_move(self, cmd ) def do_stop_move(self): raise Exception("Continuous movement not supported") def do_estop(self): self.reset() print "Emergency Stop!" # Not thread safe; must be run from the ioloop thread. def reset(self): self.async(self.server.set_blocking_temps, []) # pause the print job if any is printing if self.p.printing: pronsole.pronsole.do_pause(self, "") # Prevent the sensor from polling for 2 seconds while the firmware # restarts self.server.set_reset_timeout(time.time() + 2) self.server.set_sensor_update_received(True) # restart the firmware pronsole.pronsole.do_reset(self, "") self.p.printing = False def on_temp_target_change(self, parent_path, component, value): target = parent_path[0] gcode = "M104" if target == "b": gcode = "M140" if not target in ["b", "e0"]: gcode += " p%i"%(int(target[1:])) gcode += " S%f"%float(value) self.p.send_now(gcode) def on_fan_enabled_change(self, parent_path, component, value): update_fan(component) def on_fan_speed_change(self, parent_path, component, value): update_fan(component) def update_fan(self, component): speed = int(component['speed']) if component['enabled'] == False: speed = 0 print "M106 S%i"%speed self.p.send_now("M106 S%i"%speed) def on_motors_enabled_change(self, parent_path, component, value): self.p.send_now({True: "M17", False: "M18"}[value]) def request_sensor_update(self): if self.dry_run: return self._receive_sensor_update( "ok T:%i B:%i"%(random.randint(30, 60), random.randint(30, 60)) ) if self.p.online: self.p.send_now("M105") def recvcb(self, l): """ Parses a line of output from the printer via printcore """ l = l.rstrip() #print l if self.server.waiting_to_reach_temp and ("ok" in l): self.async(self.server.set_blocking_temps, []) if ("T:" in l): self.async(self._receive_sensor_update, l) if l!="ok" and not l.startswith("ok T") and not l.startswith("T:"): self.async(self._receive_printer_error, l) def sendcb(self, l): # Monitor the sent commands for new extruder target temperatures if ("M109" in l) or ("M104" in l) or ("M140" in l) or ("M190" in l): temp = float(re.search('S([0-9]+)', l).group(1)) if ("M109" in l) or ("M104" in l): target = "e0" if " P" in l: target = "e%i"%(int(re.search(' P([0-9]+)', l).group(1))) else: target = "b" self.async(self.server.c_set, [target, "target_temp"], temp, internal=True) if ("M109" in l) or ("M190" in l) or ("M116" in l): if ("M116" in l): target = "e0" self.async(self.server.set_blocking_temps, [target]) # Adds a callback to the ioloop to run a method later on in the server thread def async(self, *args, **kwargs): self.server.ioloop.add_callback(*args, **kwargs)