Merge branch 'experimental' of git://github.com/kenaaker/Printrun into experimental
commit
3826dd1732
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
250
gcoder.py
250
gcoder.py
|
@ -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()
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'),
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
229
pronsole.py
229
pronsole.py
|
@ -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()
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue