Merge branch 'experimental' of git://github.com/kenaaker/Printrun into experimental

master
Ken Aaker 2013-03-28 11:43:50 -05:00
commit 3826dd1732
10 changed files with 520 additions and 117 deletions

BIN
P-face.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

250
gcoder.py
View File

@ -16,6 +16,17 @@
import sys
import re
import math
def deltalen(a,b):
d = object()
d.x = b.x - a.x
d.y = b.y - a.y
d.z = b.z - a.z
return math.sqrt((d.x*d.x)+(d.y*d.y)+(d.z*d.z))
class Line(object):
def __init__(self,l):
@ -29,6 +40,7 @@ class Line(object):
self.raw = l.upper().lstrip()
self.imperial = False
self.relative = False
self.relative_e = False
if ";" in self.raw:
self.raw = self.raw.split(";")[0]
@ -77,53 +89,55 @@ class Line(object):
return ""
def _get_float(self,which):
return float(self.regex.findall(self.raw.split(which)[1])[0])
try:
return float(self.regex.findall(self.raw.split(which)[1])[0])
except:
return None
def _parse_coordinates(self):
if "X" in self.raw:
self._x = self._get_float("X")
try:
if "X" in self.raw:
self._x = self._get_float("X")
except:
pass
try:
if "Y" in self.raw:
self._y = self._get_float("Y")
except:
pass
try:
if "Z" in self.raw:
self._z = self._get_float("Z")
except:
pass
try:
if "E" in self.raw:
self.e = self._get_float("E")
except:
pass
try:
if "F" in self.raw:
self.f = self._get_float("F")
except:
pass
if "Y" in self.raw:
self._y = self._get_float("Y")
if "Z" in self.raw:
self._z = self._get_float("Z")
if "E" in self.raw:
self.e = self._get_float("E")
if "F" in self.raw:
self.f = self._get_float("F")
def is_move(self):
return "G1" in self.raw or "G0" in self.raw
return self.command() and ("G1" in self.raw or "G0" in self.raw)
def __str__(self):
return self.raw
class Layer(object):
def __init__(self,lines):
self.lines = lines
class GCode(object):
def __init__(self,data):
self.lines = [Line(i) for i in data]
self._preprocess()
def _preprocess(self):
#checks for G20, G21, G90 and G91, sets imperial and relative flags
imperial = False
relative = False
for line in self.lines:
if line.command() == "G20":
imperial = True
elif line.command() == "G21":
imperial = False
elif line.command() == "G90":
relative = False
elif line.command() == "G91":
relative = True
elif line.is_move():
line.imperial = imperial
line.relative = relative
def measure(self):
xmin = 999999999
ymin = 999999999
@ -132,7 +146,8 @@ class GCode(object):
ymax = -999999999
zmax = -999999999
relative = False
relative_e = False
current_x = 0
current_y = 0
current_z = 0
@ -147,13 +162,13 @@ class GCode(object):
x = line.x
y = line.y
z = line.z
if line.relative:
x = current_x + (x or 0)
y = current_y + (y or 0)
z = current_z + (z or 0)
if x and line.e:
if x < xmin:
xmin = x
@ -169,22 +184,137 @@ class GCode(object):
zmin = z
if z > zmax:
zmax = z
current_x = x or current_x
current_y = y or current_y
current_z = z or current_z
self.xmin = xmin
self.ymin = ymin
self.zmin = zmin
self.xmax = xmax
self.ymax = ymax
self.zmax = zmax
self.width = xmax-xmin
self.depth = ymax-ymin
self.height = zmax-zmin
return ( (xmin,xmax),(ymin,ymax),(zmin,zmax) )
class GCode(object):
def __init__(self,data):
self.lines = [Line(i) for i in data]
self._preprocess()
self._create_layers()
def _preprocess(self):
#checks for G20, G21, G90 and G91, sets imperial and relative flags
imperial = False
relative = False
relative_e = False
for line in self.lines:
if line.command() == "G20":
imperial = True
elif line.command() == "G21":
imperial = False
elif line.command() == "G90":
relative = False
relative_e = False
elif line.command() == "G91":
relative = True
relative_e = True
elif line.command() == "M82":
relative_e = False
elif line.command() == "M83":
relative_e = True
elif line.is_move():
line.imperial = imperial
line.relative = relative
line.relative_e = relative_e
def _create_layers(self):
self.layers = []
prev_z = None
cur_z = 0
cur_lines = []
layer_index = []
temp_layers = {}
for line in self.lines:
if line.command() == "G92" and line.z != None:
cur_z = line.z
elif line.is_move():
if line.z != None:
if line.relative:
cur_z += line.z
else:
cur_z = line.z
if cur_z != prev_z:
old_lines = temp_layers.pop(prev_z,[])
old_lines += cur_lines
temp_layers[prev_z] = old_lines
if not prev_z in layer_index:
layer_index.append(prev_z)
cur_lines = []
cur_lines.append(line)
prev_z = cur_z
old_lines = temp_layers.pop(prev_z,[])
old_lines += cur_lines
temp_layers[prev_z] = old_lines
if not prev_z in layer_index:
layer_index.append(prev_z)
layer_index.sort()
for idx in layer_index:
cur_lines = temp_layers[idx]
has_movement = False
for l in cur_lines:
if l.is_move() and l.e != None:
has_movement = True
break
if has_movement:
self.layers.append(Layer(cur_lines))
def num_layers(self):
return len(self.layers)
def measure(self):
xmin = 999999999
ymin = 999999999
zmin = 0
xmax = -999999999
ymax = -999999999
zmax = -999999999
for l in self.layers:
xd,yd,zd = l.measure()
if xd[0] < xmin:
xmin = xd[0]
if xd[1] > xmax:
xmax = xd[1]
if yd[0] < ymin:
ymin = yd[0]
if yd[1] > ymax:
ymax = yd[1]
if zd[0] < zmin:
zmin = zd[0]
if zd[1] > zmax:
zmax = zd[1]
self.xmin = xmin
self.xmax = xmax
self.ymin = ymin
self.ymax = ymax
self.zmin = zmin
self.zmax = zmax
self.width = xmax - xmin
self.depth = ymax - ymin
self.height = zmax - zmin
def filament_length(self):
total_e = 0
@ -196,7 +326,7 @@ class GCode(object):
total_e += cur_e
cur_e = line.e
elif line.is_move() and line.e:
if line.relative:
if line.relative_e:
cur_e += line.e
else:
cur_e = line.e
@ -210,6 +340,8 @@ def main():
print "usage: %s filename.gcode" % sys.argv[0]
return
# d = [i.replace("\n","") for i in open(sys.argv[1])]
# gcode = GCode(d)
gcode = GCode(list(open(sys.argv[1])))
gcode.measure()
@ -219,6 +351,8 @@ def main():
print "\tY: %0.02f - %0.02f (%0.02f)" % (gcode.ymin,gcode.ymax,gcode.depth)
print "\tZ: %0.02f - %0.02f (%0.02f)" % (gcode.zmin,gcode.zmax,gcode.height)
print "Filament used: %0.02fmm" % gcode.filament_length()
print "Number of layers: %d" % gcode.num_layers()
if __name__ == '__main__':
main()

BIN
plater.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -222,6 +222,7 @@ class printcore():
def pause(self):
"""Pauses the print, saving the current position.
"""
if not self.printing: return False
self.paused = True
self.printing = False
self.print_thread.join()
@ -230,6 +231,7 @@ class printcore():
def resume(self):
"""Resumes a paused print.
"""
if not self.paused: return False
self.paused = False
self.printing = True
self.print_thread = Thread(target = self._print)
@ -287,6 +289,8 @@ class printcore():
self.sentlines = {}
self.log = []
self.sent = []
self.print_thread.join()
self.print_thread = None
if self.endcb:
#callback for printing done
try: self.endcb()

View File

@ -223,7 +223,7 @@ class MainToolbar(wx.BoxSizer):
root.serialport = wx.ComboBox(root.panel, -1,
choices = root.scanserial(),
style = wx.CB_DROPDOWN, size = (100, 25))
style = wx.CB_DROPDOWN, size = (150, 25))
root.serialport.SetToolTip(wx.ToolTip("Select Port Printer is connected to"))
root.rescanports()
self.Add(root.serialport)

View File

@ -23,7 +23,7 @@ from printrun.printrun_utils import configfile, imagefile, sharedfile
users = {}
def PrintHeader():
return '<html>\n<head>\n<title>Pronterface-Web</title>\n<link rel = "stylesheet" type = "text/css" href = "/css/style.css" type = "text/css"></link>\n</head>\n<body>\n'
return '<html>\n<head>\n<title>Pronterface-Web</title>\n<link rel = "stylesheet" type = "text/css" href = "/css/style.css" type = "text/css"></link>\n<script src="/js/asyncCommand.js"></script>\n</head>\n<body>\n'
def PrintMenu():
return '<div id = "mainmenu"><ul><li><a href = "/">home</a></li><li><a href = "/settings">settings</a></li><li><a href = "/console">console</a></li><li><a href = "/status">status (XML)</a></li></ul></div>'
@ -284,14 +284,14 @@ class WebInterface(object):
pageText = PrintHeader()+self.name+PrintMenu()
pageText+="<div id='content'>\n"
pageText+="<div id='controls'>\n"
pageText+="<ul><li><a href='/connect'>Connect</a></li>\n"
pageText+="<li><a href='/disconnect'>Disconnect</a></li>\n"
pageText+="<li><a href='/reset'>Reset</a></li>\n"
pageText+="<li><a href='/printbutton'>Print</a></li>\n"
pageText+="<li><a href='/pausebutton'>Pause</a></li>\n"
pageText+="<ul><li><a class='command' href='/connect'>Connect</a></li>\n"
pageText+="<li><a class='command' href='/disconnect'>Disconnect</a></li>\n"
pageText+="<li><a class='command' href='/reset'>Reset</a></li>\n"
pageText+="<li><a class='command' href='/printbutton'>Print</a></li>\n"
pageText+="<li><a class='command' href='/pausebutton'>Pause</a></li>\n"
for i in gPronterPtr.cpbuttons:
pageText+="<li><a href='/custom/button/"+i[1]+"'>"+i[0]+"</a></li>\n"
pageText+="<li><a class='command' href='/custom/button/"+i.command+"'>"+i.label+"</a></li>\n"
#for i in gPronterPtr.custombuttons:
# print(str(i));
@ -303,38 +303,38 @@ class WebInterface(object):
pageText+="<img src='/images/control_xy.png' usemap='#xymap'/>"
pageText+='<map name = "xymap">'
pageText+='<area shape = "rect" coords = "8, 5, 51, 48" href = "/home/axis/x" alt = "X Home" title = "X Home" />'
pageText+='<area shape = "rect" coords = "195, 6, 236, 46" href = "/home/axis/y" alt = "Y Home" title = "Y Home" />'
pageText+='<area shape = "rect" coords = "7, 192, 48, 232" href = "/home/axis/all" alt = "All Home" title = "All Home" />'
pageText+='<area shape = "rect" coords = "194, 192, 235, 232" href = "/home/axis/z" alt = "Z Home" title = "Z Home" />'
pageText+='<area shape = "rect" coords = "62, 7, 185, 34" href = "/move/axis/y/100" alt = "Y 100" title = "Y 100" />'
pageText+='<area shape = "rect" coords = "68, 34, 175, 61" href = "/move/axis/y/10" alt = "Y 10" title = "Y 10" />'
pageText+='<area shape = "rect" coords = "80, 60, 163, 84" href = "/move/axis/y/1" alt = "Y 1" title = "Y 1" />'
pageText+='<area shape = "rect" coords = "106, 83, 138, 107" href = "/move/axis/y/.1" alt = "Y .1" title = "Y .1" />'
pageText+='<area shape = "rect" coords = "110, 135, 142, 159" href = "/move/axis/y/-.1" alt = "Y -.1" title = "Y -.1" />'
pageText+='<area shape = "rect" coords = "81, 157, 169, 181" href = "/move/axis/y/-1" alt = "Y -1" title = "Y -1" />'
pageText+='<area shape = "rect" coords = "69, 180, 178, 206" href = "/move/axis/y/-10" alt = "Y -10" title = "Y -10" />'
pageText+='<area shape = "rect" coords = "60, 205, 186, 231" href = "/move/axis/y/-100" alt = "Y -100" title = "Y -100" />'
pageText+='<area shape = "rect" coords = "11, 53, 37, 179" href = "/move/axis/x/-100" alt = "X -100" title = "X -100" />'
pageText+='<area shape = "rect" coords = "210, 59, 236, 185" href = "/move/axis/x/100" alt = "X 100" title = "X 100" />'
pageText+='<area shape = "rect" coords = "38, 60, 64, 172" href = "/move/axis/x/-10" alt = "X -10" title = "X -10" />'
pageText+='<area shape = "rect" coords = "185, 66, 211, 178" href = "/move/axis/x/10" alt = "X 10" title = "X 10" />'
pageText+='<area shape = "rect" coords = "62, 84, 83, 157" href = "/move/axis/x/-1" alt = "X -1" title = "X -1" />'
pageText+='<area shape = "rect" coords = "163, 87, 187, 160" href = "/move/axis/x/1" alt = "X 1" title = "X 1" />'
pageText+='<area shape = "rect" coords = "82, 104, 110, 139" href = "/move/axis/x/-.1" alt = "X -.1" title = "X -.1" />'
pageText+='<area shape = "rect" coords = "137, 105, 165, 140" href = "/move/axis/x/.1" alt = "X .1" title = "X .1" />'
pageText+='<area shape = "rect" class="command" coords = "8, 5, 51, 48" href = "/home/axis/x" alt = "X Home" title = "X Home" />'
pageText+='<area shape = "rect" class="command" coords = "195, 6, 236, 46" href = "/home/axis/y" alt = "Y Home" title = "Y Home" />'
pageText+='<area shape = "rect" class="command" coords = "7, 192, 48, 232" href = "/home/axis/all" alt = "All Home" title = "All Home" />'
pageText+='<area shape = "rect" class="command" coords = "194, 192, 235, 232" href = "/home/axis/z" alt = "Z Home" title = "Z Home" />'
pageText+='<area shape = "rect" class="command" coords = "62, 7, 185, 34" href = "/move/axis/y/100" alt = "Y 100" title = "Y 100" />'
pageText+='<area shape = "rect" class="command" coords = "68, 34, 175, 61" href = "/move/axis/y/10" alt = "Y 10" title = "Y 10" />'
pageText+='<area shape = "rect" class="command" coords = "80, 60, 163, 84" href = "/move/axis/y/1" alt = "Y 1" title = "Y 1" />'
pageText+='<area shape = "rect" class="command" coords = "106, 83, 138, 107" href = "/move/axis/y/.1" alt = "Y .1" title = "Y .1" />'
pageText+='<area shape = "rect" class="command" coords = "110, 135, 142, 159" href = "/move/axis/y/-.1" alt = "Y -.1" title = "Y -.1" />'
pageText+='<area shape = "rect" class="command" coords = "81, 157, 169, 181" href = "/move/axis/y/-1" alt = "Y -1" title = "Y -1" />'
pageText+='<area shape = "rect" class="command" coords = "69, 180, 178, 206" href = "/move/axis/y/-10" alt = "Y -10" title = "Y -10" />'
pageText+='<area shape = "rect" class="command" coords = "60, 205, 186, 231" href = "/move/axis/y/-100" alt = "Y -100" title = "Y -100" />'
pageText+='<area shape = "rect" class="command" coords = "11, 53, 37, 179" href = "/move/axis/x/-100" alt = "X -100" title = "X -100" />'
pageText+='<area shape = "rect" class="command" coords = "210, 59, 236, 185" href = "/move/axis/x/100" alt = "X 100" title = "X 100" />'
pageText+='<area shape = "rect" class="command" coords = "38, 60, 64, 172" href = "/move/axis/x/-10" alt = "X -10" title = "X -10" />'
pageText+='<area shape = "rect" class="command" coords = "185, 66, 211, 178" href = "/move/axis/x/10" alt = "X 10" title = "X 10" />'
pageText+='<area shape = "rect" class="command" coords = "62, 84, 83, 157" href = "/move/axis/x/-1" alt = "X -1" title = "X -1" />'
pageText+='<area shape = "rect" class="command" coords = "163, 87, 187, 160" href = "/move/axis/x/1" alt = "X 1" title = "X 1" />'
pageText+='<area shape = "rect" class="command" coords = "82, 104, 110, 139" href = "/move/axis/x/-.1" alt = "X -.1" title = "X -.1" />'
pageText+='<area shape = "rect" class="command" coords = "137, 105, 165, 140" href = "/move/axis/x/.1" alt = "X .1" title = "X .1" />'
pageText+="</map>"
pageText+="</div>\n" #endxy
pageText+="<div id='control_z'>"
pageText+="<img src='/images/control_z.png' usemap='#zmap'/>"
pageText+='<map name = "zmap">'
pageText+='<area shape = "rect" coords = "4, 35, 54, 64" href = "/move/axis/z/10" alt = "Z 10" title = "Z 10" />'
pageText+='<area shape = "rect" coords = "4, 60, 54, 89" href = "/move/axis/z/1" alt = "Z 1" title = "Z 1" />'
pageText+='<area shape = "rect" coords = "4, 87, 54, 116" href = "/move/axis/z/.1" alt = "Z .1" title = "Z .1" />'
pageText+='<area shape = "rect" coords = "4, 121, 54, 150" href = "/move/axis/z/-.1" alt = "Z -.1" title = "Z -.1" />'
pageText+='<area shape = "rect" coords = "4, 147, 54, 176" href = "/move/axis/z/-1" alt = "Z -1" title = "Z -1" />'
pageText+='<area shape = "rect" coords = "4, 173, 54, 202" href = "/move/axis/z/-10" alt = "Z -10" title = "Z -10" />'
pageText+='<area shape = "rect" class="command" coords = "4, 35, 54, 64" href = "/move/axis/z/10" alt = "Z 10" title = "Z 10" />'
pageText+='<area shape = "rect" class="command" coords = "4, 60, 54, 89" href = "/move/axis/z/1" alt = "Z 1" title = "Z 1" />'
pageText+='<area shape = "rect" class="command" coords = "4, 87, 54, 116" href = "/move/axis/z/.1" alt = "Z .1" title = "Z .1" />'
pageText+='<area shape = "rect" class="command" coords = "4, 121, 54, 150" href = "/move/axis/z/-.1" alt = "Z -.1" title = "Z -.1" />'
pageText+='<area shape = "rect" class="command" coords = "4, 147, 54, 176" href = "/move/axis/z/-1" alt = "Z -1" title = "Z -1" />'
pageText+='<area shape = "rect" class="command" coords = "4, 173, 54, 202" href = "/move/axis/z/-10" alt = "Z -10" title = "Z -10" />'
pageText+="</map>"
#TODO Map Z Moves
pageText+="</div>\n" #endz
@ -374,11 +374,14 @@ def KillWebInterfaceThread():
cherrypy.engine.exit()
def StartWebInterfaceThread(webInterface):
current_dir = os.path.dirname(os.path.abspath(__file__))
current_dir = os.path.dirname(os.path.abspath(__file__))
cherrypy.config.update({'engine.autoreload_on':False})
cherrypy.config.update(configfile(webInterface.pface.web_config or "http.config"))
conf = {'/css/style.css': {'tools.staticfile.on': True,
'tools.staticfile.filename': sharedfile('css/style.css'),
'tools.staticfile.filename': sharedfile('web/css/style.css'),
},
'/js/asyncCommand.js': {'tools.staticfile.on': True,
'tools.staticfile.filename': sharedfile('web/js/asyncCommand.js'),
},
'/images/control_xy.png': {'tools.staticfile.on': True,
'tools.staticfile.filename': imagefile('control_xy.png'),

BIN
pronsole.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -131,6 +131,14 @@ def estimate_duration(g):
#print "Total Duration: " #, time.strftime('%H:%M:%S', time.gmtime(totalduration))
return "{0:d} layers, ".format(int(layercount)) + str(datetime.timedelta(seconds = int(totalduration)))
def confirm():
y_or_n = raw_input("y/n: ")
if y_or_n == "y":
return True
elif y_or_n != "n":
return confirm()
return False
class Settings:
#def _temperature_alias(self): return {"pla":210, "abs":230, "off":0}
#def _temperature_validate(self, v):
@ -183,15 +191,46 @@ class Settings:
def _all_settings(self):
return dict([(k, getattr(self, k)) for k in self.__dict__.keys() if not k.startswith("_")])
class Status:
def __init__(self):
self.extruder_temp = 0
self.extruder_temp_target = 0
self.bed_temp = 0
self.bed_temp_target = 0
self.print_job = None
self.print_job_progress = 1.0
def update_tempreading(self, tempstr):
r = tempstr.split()
# eg. r = ["ok", "T:20.5", "/0.0", "B:0.0", "/0.0", "@:0"]
if len(r) == 6:
self.extruder_temp = float(r[1][2:])
self.extruder_temp_target = float(r[2][1:])
self.bed_temp = float(r[3][2:])
self.bed_temp_target = float(r[4][1:])
@property
def bed_enabled(self):
return self.bed_temp != 0
@property
def extruder_enabled(self):
return self.extruder_temp != 0
class pronsole(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
if not READLINE:
self.completekey = None
self.status = Status()
self.dynamic_temp = False
self.p = printcore.printcore()
self.p.recvcb = self.recvcb
self.recvlisteners = []
self.prompt = "PC>"
self.in_macro = False
self.p.onlinecb = self.online
self.f = None
self.listing = 0
@ -230,6 +269,55 @@ class pronsole(cmd.Cmd):
self.webrequested = False
self.web_config = None
self.web_auth_config = None
self.promptstrs = {"offline" : "%(bold)suninitialized>%(normal)s ",
"fallback" : "%(bold)sPC>%(normal)s ",
"macro" : "%(bold)s..>%(normal)s ",
"online" : "%(bold)sT:%(extruder_temp_fancy)s %(progress_fancy)s >%(normal)s "}
def promptf(self):
"""A function to generate prompts so that we can do dynamic prompts. """
if self.in_macro:
promptstr = self.promptstrs["macro"]
elif not self.p.online:
promptstr = self.promptstrs["offline"]
elif self.status.extruder_enabled:
promptstr = self.promptstrs["online"]
else:
promptstr = self.promptstrs["fallback"]
if not "%" in promptstr:
return promptstr
else:
specials = {}
specials["extruder_temp"] = str(int(self.status.extruder_temp))
specials["extruder_temp_target"] = str(int(self.status.extruder_temp_target))
if self.status.extruder_temp_target == 0:
specials["extruder_temp_fancy"] = str(int(self.status.extruder_temp))
else:
specials["extruder_temp_fancy"] = "%s/%s" % (str(int(self.status.extruder_temp)), str(int(self.status.extruder_temp_target)))
if self.p.printing:
progress = int(1000*float(self.p.queueindex)/len(self.p.mainqueue)) / 10
elif self.sdprinting:
progress = self.percentdone
else:
progress = 0.0
specials["progress"] = str(progress)
if self.p.printing or self.sdprinting:
specials["progress_fancy"] = str(progress) +"%"
else:
specials["progress_fancy"] = "?%"
specials["bold"] = "\033[01m"
specials["normal"] = "\033[00m"
return promptstr % specials
def postcmd(self, stop, line):
""" A hook we override to generate prompts after
each command is executed, for the next prompt.
We also use it to send M105 commands so that
temp info gets updated for the prompt."""
if self.p.online and self.dynamic_temp:
self.p.send_now("M105")
self.prompt = self.promptf()
return stop
def set_temp_preset(self, key, value):
if not key.startswith("bed"):
@ -257,8 +345,8 @@ class pronsole(cmd.Cmd):
return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') +glob.glob("/dev/tty.*")+glob.glob("/dev/cu.*")+glob.glob("/dev/rfcomm*")
def online(self):
print "Printer is now online"
sys.stdout.write(self.prompt)
print "\rPrinter is now online"
sys.stdout.write(self.promptf())
sys.stdout.flush()
def help_help(self, l):
@ -290,7 +378,8 @@ class pronsole(cmd.Cmd):
def end_macro(self):
if self.__dict__.has_key("onecmd"): del self.onecmd # remove override
self.prompt = "PC>"
self.in_macro = False
self.prompt = self.promptf()
if self.cur_macro_def!="":
self.macros[self.cur_macro_name] = self.cur_macro_def
macro = self.compile_macro(self.cur_macro_name, self.cur_macro_def)
@ -342,7 +431,8 @@ class pronsole(cmd.Cmd):
self.cur_macro_name = macro_name
self.cur_macro_def = ""
self.onecmd = self.hook_macro # override onecmd temporarily
self.prompt = "..>"
self.in_macro = False
self.prompt = self.promptf()
def delete_macro(self, macro_name):
if macro_name in self.macros.keys():
@ -520,6 +610,7 @@ class pronsole(cmd.Cmd):
def preloop(self):
print "Welcome to the printer console! Type \"help\" for a list of available commands."
self.prompt = self.promptf()
cmd.Cmd.preloop(self)
def do_connect(self, l):
@ -813,10 +904,13 @@ class pronsole(cmd.Cmd):
def recvcb(self, l):
if "T:" in l:
self.tempreadings = l
self.status.update_tempreading(l)
tstring = l.rstrip()
if(tstring!="ok" and not tstring.startswith("ok T") and not tstring.startswith("T:") and not self.listing and not self.monitoring):
print tstring
sys.stdout.write(self.prompt)
if tstring[:5] == "echo:":
tstring = tstring[5:].lstrip()
print "\r" + tstring.ljust(15)
sys.stdout.write(self.promptf())
sys.stdout.flush()
for i in self.recvlisteners:
i(l)
@ -848,16 +942,17 @@ class pronsole(cmd.Cmd):
def help_help(self):
self.do_help("")
def tempcb(self, l):
if "T:" in l:
print l.replace("\r", "").replace("T", "Hotend").replace("B", "Bed").replace("\n", "").replace("ok ", "")
def do_gettemp(self, l):
if "dynamic" in l:
self.dynamic_temp = True
if self.p.online:
self.recvlisteners+=[self.tempcb]
self.p.send_now("M105")
time.sleep(0.75)
self.recvlisteners.remove(self.tempcb)
if not self.status.bed_enabled:
print "Hotend: %s/%s" % (self.status.extruder_temp, self.status.extruder_temp_target)
else:
print "Hotend: %s/%s" % (self.status.extruder_temp, self.status.extruder_temp_target)
print "Bed: %s/%s" % (self.status.bed_temp, self.status.bed_temp_target)
def help_gettemp(self):
print "Read the extruder and bed temperature."
@ -869,6 +964,10 @@ class pronsole(cmd.Cmd):
l = l.replace(i, self.temps[i])
f = float(l)
if f>=0:
if f > 250:
print f, " is a high temperature to set your extruder to. Are you sure you want to do that?"
if not confirm():
return
if self.p.online:
self.p.send_now("M104 S"+l)
print "Setting hotend temperature to ", f, " degrees Celsius."
@ -1045,9 +1144,22 @@ class pronsole(cmd.Cmd):
print "reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s)"
def do_exit(self, l):
if self.status.extruder_temp_target != 0:
print "Setting extruder temp to 0"
self.p.send_now("M104 S0.0")
if self.status.bed_enabled:
if self.status.bed_temp_taret != 0:
print "Setting bed temp to 0"
self.p.send_now("M140 S0.0")
print "Disconnecting from printer..."
self.p.disconnect()
print self.p.printing
if self.p.printing:
print "Are you sure you want to exit while printing?"
print "(this will terminate the print)."
if not confirm():
return False
print "Exiting program. Goodbye!"
self.p.disconnect()
return True
def help_exit(self):
@ -1058,6 +1170,9 @@ class pronsole(cmd.Cmd):
if not self.p.online:
print "Printer is not online. Please connect first."
return
if not (self.p.printing or self.sdprinting):
print "Printer not printing. Please print something before monitoring."
return
print "Monitoring printer, use ^C to interrupt."
if len(l):
try:
@ -1066,22 +1181,27 @@ class pronsole(cmd.Cmd):
print "Invalid period given."
print "Updating values every %f seconds."%(interval,)
self.monitoring = 1
prev_msg_len = 0
try:
while(1):
while True:
self.p.send_now("M105")
if(self.sdprinting):
self.p.send_now("M27")
time.sleep(interval)
#print (self.tempreadings.replace("\r", "").replace("T", "Hotend").replace("B", "Bed").replace("\n", "").replace("ok ", ""))
if(self.p.printing):
print "Print progress: ", 100*float(self.p.queueindex)/len(self.p.mainqueue), "%"
if(self.sdprinting):
print "SD print progress: ", self.percentdone, "%"
except:
if self.p.printing:
preface = "Print progress: "
progress = 100*float(self.p.queueindex)/len(self.p.mainqueue)
elif self.sdprinting:
preface = "Print progress: "
progress = self.percentdone
progress = int(progress*10)/10.0 #limit precision
prev_msg = preface + str(progress) + "%"
sys.stdout.write("\r" + prev_msg.ljust(prev_msg_len))
sys.stdout.flush()
prev_msg_len = len(prev_msg)
except KeyboardInterrupt:
print "Done monitoring."
pass
self.monitoring = 0
def help_monitor(self):
@ -1193,6 +1313,69 @@ class pronsole(cmd.Cmd):
self.onecmd(a)
self.processing_args = False
# We replace this function, defined in cmd.py .
# It's default behavior with reagrds to Ctr-C
# and Ctr-D doesn't make much sense...
def cmdloop(self, intro=None):
"""Repeatedly issue a prompt, accept input, parse an initial prefix
off the received input, and dispatch to action methods, passing them
the remainder of the line as argument.
"""
self.preloop()
if self.use_rawinput and self.completekey:
try:
import readline
self.old_completer = readline.get_completer()
readline.set_completer(self.complete)
readline.parse_and_bind(self.completekey+": complete")
except ImportError:
pass
try:
if intro is not None:
self.intro = intro
if self.intro:
self.stdout.write(str(self.intro)+"\n")
stop = None
while not stop:
if self.cmdqueue:
line = self.cmdqueue.pop(0)
else:
if self.use_rawinput:
try:
line = raw_input(self.prompt)
except EOFError:
print ""
should_exit = self.do_exit("")
if should_exit:
exit()
except KeyboardInterrupt:
print ""
line = ""
else:
self.stdout.write(self.prompt)
self.stdout.flush()
line = self.stdin.readline()
if not len(line):
line = ""
else:
line = line.rstrip('\r\n')
line = self.precmd(line)
stop = self.onecmd(line)
stop = self.postcmd(stop, line)
self.postloop()
finally:
if self.use_rawinput and self.completekey:
try:
import readline
readline.set_completer(self.old_completer)
except ImportError:
pass
if __name__ == "__main__":
interp = pronsole()

79
web/js/asyncCommand.js Normal file
View File

@ -0,0 +1,79 @@
function pronterfaceWebInterface_setup(){
pronterfaceWebInterface_attachAsync();
}
function pronterfaceWebInterface_attachAsync(){
var list = [];
if(document.getElementsByClassName){
list = document.getElementsByClassName('command');
}else if(document.getElementsByTagName){
list = document.getElementsByTagName('a');
list.concat( document.getElementsByTagName('area') );
//TODO filter list via checking the className attributes
}else{
console && console.error && console.error('unable to gather list of elements');
return false;
}
for(var i=0; i < list.length; i++){
list[i].addEventListener && list[i].addEventListener( 'click', function(e){return pronterfaceWebInterface_asyncCommand(null, e);}, true );
list[i].attachEvent && list[i].attachEvent( 'onclick', function(e){return pronterfaceWebInterface_asyncCommand(null, e);} );
}
return true;
}
function pronterfaceWebInterface_asyncCommand( urlOrElement, event ){
if( ! urlOrElement && event.target)
urlOrElement = event.target;
var url = null;
if( typeof urlOrElement == 'string' ){
url = urlOrElement;
}else{
url = urlOrElement&&urlOrElement.href;
}
if( typeof url != 'string' ){
console && console.error && console.error('url not a string', urlOrElement, url);
return true;
}
var httpRequest;
if (window.XMLHttpRequest) { // Mozilla, Safari, ...
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) { // IE 8 and older
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
if( ! httpRequest ){
alert('no AJAX available?');
// follow link
return true;
}
//onreadystatechange
//onerror
httpRequest.open( 'GET', url, true);
httpRequest.send(null);
// don't follow link
if( event ){
event.stopImmediatePropagation && event.stopImmediatePropagation();
event.defaultPrevented = true;
event.preventDefault && event.preventDefault();
}
return false;
}
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", pronterfaceWebInterface_setup, false);
} else if (document.attachEvent) {
document.attachEvent("onreadystatechange", pronterfaceWebInterface_setup);
} else {
document.onload = pronterfaceWebInterface_setup;
}