2011-06-09 14:43:03 +00:00
#!/usr/bin/env python
2011-05-26 22:16:57 +00:00
import cmd , printcore , sys
import glob , os , time
2011-09-26 04:57:04 +00:00
import sys , subprocess
2011-12-01 01:33:55 +00:00
import math
2011-11-04 10:49:05 +00:00
from math import sqrt
2011-12-21 08:12:40 +00:00
import gettext
if os . path . exists ( ' /usr/share/pronterface/locale ' ) :
gettext . install ( ' pronterface ' , ' /usr/share/pronterface/locale ' , unicode = 1 )
else :
gettext . install ( ' pronterface ' , ' ./locale ' , unicode = 1 )
2011-12-01 01:33:55 +00:00
2011-05-30 09:09:04 +00:00
if os . name == " nt " :
try :
import _winreg
except :
pass
READLINE = True
try :
import readline
try :
2011-05-30 09:53:45 +00:00
readline . rl . mode . show_all_if_ambiguous = " on " #config pyreadline on windows
2011-05-30 09:09:04 +00:00
except :
2011-05-30 09:53:45 +00:00
pass
except :
READLINE = False #neither readline module is available
2011-05-26 22:16:57 +00:00
2011-05-28 17:08:22 +00:00
def dosify ( name ) :
2011-05-31 15:08:23 +00:00
return os . path . split ( name ) [ 1 ] . split ( " . " ) [ 0 ] [ : 8 ] + " .g "
2011-08-27 06:51:01 +00:00
def measurements ( g ) :
2011-12-01 01:33:55 +00:00
Xcur = 0.0
Ycur = 0.0
Zcur = 0.0
Xmin = 1000000
Ymin = 1000000
Zmin = 1000000
Xmax = - 1000000
Ymax = - 1000000
Zmax = - 1000000
Xtot = 0
Ytot = 0
Ztot = 0
for i in g :
if " X " in i and ( " G1 " in i or " G0 " in i ) :
try :
Xcur = float ( i . split ( " X " ) [ 1 ] . split ( " " ) [ 0 ] )
if Xcur < Xmin and Xcur > 5.0 : Xmin = Xcur
if Xcur > Xmax : Xmax = Xcur
except :
pass
if " Y " in i and ( " G1 " in i or " G0 " in i ) :
try :
Ycur = float ( i . split ( " Y " ) [ 1 ] . split ( " " ) [ 0 ] )
if Ycur < Ymin and Ycur > 5.0 : Ymin = Ycur
if Ycur > Ymax : Ymax = Ycur
except :
pass
if " Z " in i and ( " G1 " in i or " G0 " in i ) :
try :
Zcur = float ( i . split ( " Z " ) [ 1 ] . split ( " " ) [ 0 ] )
if Zcur < Zmin : Zmin = Zcur
if Zcur > Zmax : Zmax = Zcur
except :
pass
Xtot = Xmax - Xmin
Ytot = Ymax - Ymin
Ztot = Zmax - Zmin
return ( Xtot , Ytot , Ztot , Xmin , Xmax , Ymin , Ymax , Zmin , Zmax )
2011-05-28 17:08:22 +00:00
2011-08-06 12:48:10 +00:00
def totalelength ( g ) :
tot = 0
cur = 0
for i in g :
if " E " in i and ( " G1 " in i or " G0 " in i ) :
try :
cur = float ( i . split ( " E " ) [ 1 ] . split ( " " ) [ 0 ] )
except :
pass
elif " G92 " in i and " E0 " in i :
tot + = cur
return tot
2011-11-04 10:49:05 +00:00
def get_coordinate_value ( axis , parts ) :
for i in parts :
if ( axis in i ) :
return float ( i [ 1 : ] )
return None
2011-12-01 01:33:55 +00:00
def hypot3d ( X1 , Y1 , Z1 , X2 = 0.0 , Y2 = 0.0 , Z2 = 0.0 ) :
return math . hypot ( X2 - X1 , math . hypot ( Y2 - Y1 , Z2 - Z1 ) )
2011-11-04 10:49:05 +00:00
def estimate_duration ( g ) :
2011-12-01 01:33:55 +00:00
lastx = lasty = lastz = laste = lastf = 0.0
x = y = z = e = f = 0.0
currenttravel = 0.0
totaltravel = 0.0
moveduration = 0.0
totalduration = 0.0
acceleration = 1500.0 #mm/s/s ASSUMING THE DEFAULT FROM SPRINTER !!!!
layerduration = 0.0
layerbeginduration = 0.0
2011-12-09 23:50:09 +00:00
layercount = 0
2011-12-01 01:33:55 +00:00
#TODO:
# get device caps from firmware: max speed, acceleration/axis (including extruder)
# calculate the maximum move duration accounting for above ;)
2011-12-09 23:50:09 +00:00
# print ".... estimating ...."
2011-11-29 04:36:04 +00:00
for i in g :
2011-12-09 19:11:56 +00:00
i = i . split ( " ; " ) [ 0 ]
2011-12-01 01:33:55 +00:00
if " G4 " in i or " G1 " in i :
if " G4 " in i :
parts = i . split ( " " )
moveduration = get_coordinate_value ( " P " , parts [ 1 : ] )
if moveduration is None :
continue
else :
moveduration / = 1000.0
if " G1 " in i :
parts = i . split ( " " )
x = get_coordinate_value ( " X " , parts [ 1 : ] )
if x is None : x = lastx
y = get_coordinate_value ( " Y " , parts [ 1 : ] )
if y is None : y = lasty
z = get_coordinate_value ( " Z " , parts [ 1 : ] )
if z is None : z = lastz
e = get_coordinate_value ( " E " , parts [ 1 : ] )
if e is None : e = laste
f = get_coordinate_value ( " F " , parts [ 1 : ] )
if f is None : f = lastf
else : f / = 60.0 # mm/s vs mm/m
# given last feedrate and current feedrate calculate the distance needed to achieve current feedrate.
# if travel is longer than req'd distance, then subtract distance to achieve full speed, and add the time it took to get there.
# then calculate the time taken to complete the remaining distance
currenttravel = hypot3d ( x , y , z , lastx , lasty , lastz )
distance = 2 * ( ( lastf + f ) * ( f - lastf ) * 0.5 ) / acceleration #2x because we have to accelerate and decelerate
if distance < = currenttravel :
moveduration = 2 * distance / ( lastf + f )
currenttravel - = distance
moveduration + = currenttravel / f
else :
moveduration = math . sqrt ( 2 * distance / acceleration )
totalduration + = moveduration
if z > lastz :
2011-12-09 23:50:09 +00:00
layercount + = 1
#print "layer z: ", lastz, " will take: ", time.strftime('%H:%M:%S', time.gmtime(totalduration-layerbeginduration))
2011-12-01 01:33:55 +00:00
layerbeginduration = totalduration
lastx = x
lasty = y
lastz = z
laste = e
lastf = f
2011-11-04 10:49:05 +00:00
2011-12-09 23:50:09 +00:00
#print "Total Duration: " #, time.strftime('%H:%M:%S', time.gmtime(totalduration))
return " {0:d} layers, " . format ( int ( layercount ) ) + time . strftime ( ' % H: % M: % S ' , time . gmtime ( totalduration ) )
2011-11-04 10:49:05 +00:00
2011-06-29 18:50:09 +00:00
class Settings :
#def _temperature_alias(self): return {"pla":210,"abs":230,"off":0}
#def _temperature_validate(self,v):
# if v < 0: raise ValueError("You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0.")
#def _bedtemperature_alias(self): return {"pla":60,"abs":110,"off":0}
def _baudrate_list ( self ) : return [ " 2400 " , " 9600 " , " 19200 " , " 38400 " , " 57600 " , " 115200 " ]
def __init__ ( self ) :
# defaults here.
# the initial value determines the type
self . port = " "
2011-06-29 19:23:20 +00:00
self . baudrate = 115200
2011-10-25 19:56:44 +00:00
self . bedtemp_abs = 110
2011-12-20 11:48:23 +00:00
self . bedtemp_pla = 60
self . temperature_abs = 230
self . temperature_pla = 185
2011-06-29 19:23:20 +00:00
self . xy_feedrate = 3000
self . z_feedrate = 200
self . e_feedrate = 300
2011-11-18 08:52:16 +00:00
self . slicecommand = " python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s "
self . sliceoptscommand = " python skeinforge/skeinforge_application/skeinforge.py "
2011-12-20 11:48:23 +00:00
2011-06-29 18:50:09 +00:00
def _set ( self , key , value ) :
try :
value = getattr ( self , " _ %s _alias " % key ) ( ) [ value ]
except KeyError :
pass
except AttributeError :
pass
try :
getattr ( self , " _ %s _validate " % key ) ( value )
except AttributeError :
pass
setattr ( self , key , type ( getattr ( self , key ) ) ( value ) )
try :
getattr ( self , " _ %s _cb " % key ) ( key , value )
except AttributeError :
pass
return value
def _tabcomplete ( self , key ) :
try :
return getattr ( self , " _ %s _list " % key ) ( )
except AttributeError :
pass
try :
return getattr ( self , " _ %s _alias " % key ) ( ) . keys ( )
except AttributeError :
pass
return [ ]
2011-07-26 16:19:45 +00:00
def _all_settings ( self ) :
return dict ( [ ( k , getattr ( self , k ) ) for k in self . __dict__ . keys ( ) if not k . startswith ( " _ " ) ] )
2011-05-26 22:16:57 +00:00
class pronsole ( cmd . Cmd ) :
def __init__ ( self ) :
cmd . Cmd . __init__ ( self )
2011-05-30 09:09:04 +00:00
if not READLINE :
self . completekey = None
2011-05-26 22:16:57 +00:00
self . p = printcore . printcore ( )
2011-05-30 13:47:01 +00:00
self . p . recvcb = self . recvcb
self . recvlisteners = [ ]
2011-05-26 22:16:57 +00:00
self . prompt = " PC> "
self . p . onlinecb = self . online
self . f = None
2011-05-30 13:47:01 +00:00
self . listing = 0
self . sdfiles = [ ]
2011-05-26 22:16:57 +00:00
self . paused = False
2011-06-01 12:32:45 +00:00
self . sdprinting = 0
2011-08-27 08:16:35 +00:00
self . temps = { " pla " : " 185 " , " abs " : " 230 " , " off " : " 0 " }
2011-05-31 15:08:23 +00:00
self . bedtemps = { " pla " : " 60 " , " abs " : " 110 " , " off " : " 0 " }
2011-06-01 12:32:45 +00:00
self . percentdone = 0
self . tempreadings = " "
2011-06-07 14:31:43 +00:00
self . macros = { }
2011-07-04 09:02:30 +00:00
self . rc_loaded = False
2011-06-07 14:31:43 +00:00
self . processing_rc = False
2011-07-04 09:02:30 +00:00
self . processing_args = False
2011-06-29 18:50:09 +00:00
self . settings = Settings ( )
self . settings . _port_list = self . scanserial
self . settings . _temperature_abs_cb = self . set_temp_preset
self . settings . _temperature_pla_cb = self . set_temp_preset
self . settings . _bedtemp_abs_cb = self . set_temp_preset
self . settings . _bedtemp_pla_cb = self . set_temp_preset
2011-06-09 14:01:23 +00:00
self . monitoring = 0
2011-12-20 11:48:23 +00:00
self . helpdict = { }
self . helpdict [ " baudrate " ] = _ ( " Communications Speed (default: 115200) " )
self . helpdict [ " bedtemp_abs " ] = _ ( " Heated Build Platform temp for ABS (default: 110 deg C) " )
self . helpdict [ " bedtemp_pla " ] = _ ( " Heated Build Platform temp for PLA (default: 60 deg C) " )
self . helpdict [ " e_feedrate " ] = _ ( " Feedrate for Control Panel Moves in Extrusions (default: 300mm/min) " )
self . helpdict [ " port " ] = _ ( " Port used to communicate with printer " )
self . helpdict [ " slicecommand " ] = _ ( " Feedrate for Control Panel Moves in Extrusions. \n default: \n python skeinforge/skeinforge_application/skeinforge_utilities/skeinforge_craft.py $s) " )
self . helpdict [ " sliceoptscommand " ] = _ ( " Feedrate for Control Panel Moves in Extrusions. \n default: \n python skeinforge/skeinforge_application/skeinforge.py " )
self . helpdict [ " temperature_abs " ] = _ ( " Extruder temp for ABS (default: 230 deg C) " )
self . helpdict [ " temperature_pla " ] = _ ( " Extruder temp for PLA (default: 185 deg C) " )
self . helpdict [ " xy_feedrate " ] = _ ( " Feedrate for Control Panel Moves in X and Y (default: 3000mm/min) " )
self . helpdict [ " z_feedrate " ] = _ ( " Feedrate for Control Panel Moves in Z (default: 200mm/min) " )
2011-06-29 18:50:09 +00:00
def set_temp_preset ( self , key , value ) :
if not key . startswith ( " bed " ) :
self . temps [ " pla " ] = str ( self . settings . temperature_pla )
self . temps [ " abs " ] = str ( self . settings . temperature_abs )
print " Hotend temperature presets updated, pla: %s , abs: %s " % ( self . temps [ " pla " ] , self . temps [ " abs " ] )
else :
self . bedtemps [ " pla " ] = str ( self . settings . bedtemp_pla )
self . bedtemps [ " abs " ] = str ( self . settings . bedtemp_abs )
print " Bed temperature presets updated, pla: %s , abs: %s " % ( self . bedtemps [ " pla " ] , self . bedtemps [ " abs " ] )
2011-05-26 22:16:57 +00:00
def scanserial ( self ) :
""" scan for available ports. return a list of device names. """
2011-05-30 09:09:04 +00:00
baselist = [ ]
if os . name == " nt " :
try :
key = _winreg . OpenKey ( _winreg . HKEY_LOCAL_MACHINE , " HARDWARE \\ DEVICEMAP \\ SERIALCOMM " )
i = 0
while ( 1 ) :
baselist + = [ _winreg . EnumValue ( key , i ) [ 1 ] ]
i + = 1
except :
pass
return baselist + glob . glob ( ' /dev/ttyUSB* ' ) + glob . glob ( ' /dev/ttyACM* ' ) + glob . glob ( " /dev/tty.* " ) + glob . glob ( " /dev/cu.* " ) + glob . glob ( " /dev/rfcomm* " )
2011-05-26 22:16:57 +00:00
def online ( self ) :
print " Printer is now online "
sys . stdout . write ( self . prompt )
sys . stdout . flush ( )
def help_help ( self , l ) :
self . do_help ( " " )
def do_gcodes ( self , l ) :
self . help_gcodes ( )
def help_gcodes ( self ) :
print " Gcodes are passed through to the printer as they are "
2011-06-07 14:34:56 +00:00
def complete_macro ( self , text , line , begidx , endidx ) :
2011-06-01 17:00:35 +00:00
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
2011-06-07 14:34:56 +00:00
return [ i for i in self . macros . keys ( ) if i . startswith ( text ) ]
2011-06-01 17:00:35 +00:00
elif ( len ( line . split ( ) ) == 3 or ( len ( line . split ( ) ) == 2 and line [ - 1 ] == " " ) ) :
2011-06-29 18:50:09 +00:00
return [ i for i in [ " /D " , " /S " ] + self . completenames ( text ) if i . startswith ( text ) ]
2011-06-01 17:00:35 +00:00
else :
return [ ]
2011-06-07 08:01:41 +00:00
def hook_macro ( self , l ) :
2011-06-08 19:11:59 +00:00
l = l . rstrip ( )
2011-06-07 08:01:41 +00:00
ls = l . lstrip ( )
ws = l [ : len ( l ) - len ( ls ) ] # just leading whitespace
if len ( ws ) == 0 :
2011-06-07 14:31:43 +00:00
self . end_macro ( )
# pass the unprocessed line to regular command processor to not require empty line in .pronsolerc
2011-06-07 08:01:41 +00:00
return self . onecmd ( l )
2011-06-07 14:31:43 +00:00
self . cur_macro_def + = l + " \n "
2011-06-07 08:01:41 +00:00
2011-06-07 14:31:43 +00:00
def end_macro ( self ) :
if self . __dict__ . has_key ( " onecmd " ) : del self . onecmd # remove override
self . prompt = " PC> "
2011-06-08 19:11:59 +00:00
if self . cur_macro_def != " " :
self . macros [ self . cur_macro_name ] = self . cur_macro_def
2011-08-04 11:03:35 +00:00
macro = self . compile_macro ( self . cur_macro_name , self . cur_macro_def )
2011-06-08 19:11:59 +00:00
setattr ( self . __class__ , " do_ " + self . cur_macro_name , lambda self , largs , macro = macro : macro ( self , * largs . split ( ) ) )
setattr ( self . __class__ , " help_ " + self . cur_macro_name , lambda self , macro_name = self . cur_macro_name : self . subhelp_macro ( macro_name ) )
2011-06-26 21:05:22 +00:00
if not self . processing_rc :
2011-06-29 18:50:09 +00:00
print " Macro ' " + self . cur_macro_name + " ' defined "
# save it
2011-07-04 09:02:30 +00:00
if not self . processing_args :
macro_key = " macro " + self . cur_macro_name
macro_def = macro_key
if " \n " in self . cur_macro_def :
macro_def + = " \n "
else :
macro_def + = " "
macro_def + = self . cur_macro_def
self . save_in_rc ( macro_key , macro_def )
2011-06-08 19:11:59 +00:00
else :
2011-06-07 14:31:43 +00:00
print " Empty macro - cancelled "
2011-08-04 11:03:35 +00:00
del self . cur_macro_name , self . cur_macro_def
def compile_macro_line ( self , line ) :
line = line . rstrip ( )
ls = line . lstrip ( )
ws = line [ : len ( line ) - len ( ls ) ] # just leading whitespace
if ls == " " or ls . startswith ( ' # ' ) : return " " # no code
if ls . startswith ( ' ! ' ) :
return ws + ls [ 1 : ] + " \n " # python mode
else :
return ws + ' self.onecmd( " ' + ls + ' " .format(*arg)) \n ' # parametric command mode
def compile_macro ( self , macro_name , macro_def ) :
if macro_def . strip ( ) == " " :
print " Empty macro - cancelled "
return
pycode = " def macro(self,*arg): \n "
if " \n " not in macro_def . strip ( ) :
pycode + = self . compile_macro_line ( " " + macro_def . strip ( ) )
else :
lines = macro_def . split ( " \n " )
for l in lines :
pycode + = self . compile_macro_line ( l )
exec pycode
return macro
2011-06-07 14:31:43 +00:00
2011-07-15 08:12:21 +00:00
def start_macro ( self , macro_name , prev_definition = " " , suppress_instructions = False ) :
if not self . processing_rc and not suppress_instructions :
2011-07-06 21:19:45 +00:00
print " Enter macro using indented lines, end with empty line "
self . cur_macro_name = macro_name
self . cur_macro_def = " "
self . onecmd = self . hook_macro # override onecmd temporarily
self . prompt = " ..> "
2011-07-26 14:34:55 +00:00
def delete_macro ( self , macro_name ) :
if macro_name in self . macros . keys ( ) :
delattr ( self . __class__ , " do_ " + macro_name )
del self . macros [ macro_name ]
print " Macro ' " + macro_name + " ' removed "
if not self . processing_rc and not self . processing_args :
self . save_in_rc ( " macro " + macro_name , " " )
else :
print " Macro ' " + macro_name + " ' is not defined "
2011-06-07 14:31:43 +00:00
def do_macro ( self , args ) :
if args . strip ( ) == " " :
self . print_topics ( " User-defined macros " , self . macros . keys ( ) , 15 , 80 )
2011-06-07 08:01:41 +00:00
return
2011-06-07 14:31:43 +00:00
arglist = args . split ( None , 1 )
macro_name = arglist [ 0 ]
if macro_name not in self . macros and hasattr ( self . __class__ , " do_ " + macro_name ) :
print " Name ' " + macro_name + " ' is being used by built-in command "
2011-06-07 08:01:41 +00:00
return
2011-06-07 14:31:43 +00:00
if len ( arglist ) == 2 :
macro_def = arglist [ 1 ]
if macro_def . lower ( ) == " /d " :
2011-07-26 14:34:55 +00:00
self . delete_macro ( macro_name )
2011-06-07 14:31:43 +00:00
return
if macro_def . lower ( ) == " /s " :
self . subhelp_macro ( macro_name )
return
self . cur_macro_def = macro_def
self . cur_macro_name = macro_name
self . end_macro ( )
2011-06-07 08:01:41 +00:00
return
2011-07-06 21:19:45 +00:00
if self . macros . has_key ( macro_name ) :
self . start_macro ( macro_name , self . macros [ macro_name ] )
else :
self . start_macro ( macro_name )
2011-06-07 08:01:41 +00:00
def help_macro ( self ) :
2011-06-07 14:31:43 +00:00
print " Define single-line macro: macro <name> <definition> "
print " Define multi-line macro: macro <name> "
2011-06-07 08:01:41 +00:00
print " Enter macro definition in indented lines. Use {0} .. {N} to substitute macro arguments "
2011-06-07 14:31:43 +00:00
print " Enter python code, prefixed with ! Use arg[0] .. arg[N] to substitute macro arguments "
print " Delete macro: macro <name> /d "
print " Show macro definition: macro <name> /s "
print " ' macro ' without arguments displays list of defined macros "
2011-06-07 08:01:41 +00:00
2011-06-07 14:31:43 +00:00
def subhelp_macro ( self , macro_name ) :
if macro_name in self . macros . keys ( ) :
macro_def = self . macros [ macro_name ]
if " \n " in macro_def :
print " Macro ' " + macro_name + " ' defined as: "
print self . macros [ macro_name ] + " ---------------- "
else :
print " Macro ' " + macro_name + " ' defined as: ' " + macro_def + " ' "
else :
print " Macro ' " + macro_name + " ' is not defined "
2011-06-29 18:50:09 +00:00
def set ( self , var , str ) :
try :
t = type ( getattr ( self . settings , var ) )
value = self . settings . _set ( var , str )
2011-07-04 09:02:30 +00:00
if not self . processing_rc and not self . processing_args :
2011-06-29 18:50:09 +00:00
self . save_in_rc ( " set " + var , " set %s %s " % ( var , value ) )
except AttributeError :
print " Unknown variable ' %s ' " % var
2011-07-27 18:41:27 +00:00
except ValueError , ve :
2011-07-26 16:19:45 +00:00
print " Bad value for variable ' %s ' , expecting %s ( %s ) " % ( var , repr ( t ) [ 1 : - 1 ] , ve . args [ 0 ] )
2011-06-29 18:50:09 +00:00
def do_set ( self , argl ) :
args = argl . split ( None , 1 )
if len ( args ) < 1 :
for k in [ kk for kk in dir ( self . settings ) if not kk . startswith ( " _ " ) ] :
print " %s = %s " % ( k , str ( getattr ( self . settings , k ) ) )
return
value = getattr ( self . settings , args [ 0 ] )
if len ( args ) < 2 :
try :
print " %s = %s " % ( args [ 0 ] , getattr ( self . settings , args [ 0 ] ) )
except AttributeError :
print " Unknown variable ' %s ' " % args [ 0 ]
return
self . set ( args [ 0 ] , args [ 1 ] )
def help_set ( self ) :
print " Set variable: set <variable> <value> "
print " Show variable: set <variable> "
print " ' set ' without arguments displays all variables "
def complete_set ( self , text , line , begidx , endidx ) :
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
return [ i for i in dir ( self . settings ) if not i . startswith ( " _ " ) and i . startswith ( text ) ]
elif ( len ( line . split ( ) ) == 3 or ( len ( line . split ( ) ) == 2 and line [ - 1 ] == " " ) ) :
return [ i for i in self . settings . _tabcomplete ( line . split ( ) [ 1 ] ) if i . startswith ( text ) ]
else :
return [ ]
2011-06-07 08:01:41 +00:00
2011-05-26 22:16:57 +00:00
def postloop ( self ) :
self . p . disconnect ( )
cmd . Cmd . postloop ( self )
2011-07-04 09:02:30 +00:00
def load_rc ( self , rc_filename ) :
2011-06-07 14:31:43 +00:00
self . processing_rc = True
2011-06-01 13:38:22 +00:00
try :
2011-07-04 09:02:30 +00:00
rc = open ( rc_filename )
self . rc_filename = os . path . abspath ( rc_filename )
2011-06-09 17:03:57 +00:00
for rc_cmd in rc :
if not rc_cmd . lstrip ( ) . startswith ( " # " ) :
self . onecmd ( rc_cmd )
rc . close ( )
2011-08-04 11:03:35 +00:00
if hasattr ( self , " cur_macro_def " ) :
2011-07-04 09:02:30 +00:00
self . end_macro ( )
self . rc_loaded = True
finally :
self . processing_rc = False
def load_default_rc ( self , rc_filename = " .pronsolerc " ) :
try :
try :
self . load_rc ( os . path . join ( os . path . expanduser ( " ~ " ) , rc_filename ) )
except IOError :
self . load_rc ( rc_filename )
2011-06-01 13:38:22 +00:00
except IOError :
2011-07-18 15:25:05 +00:00
# make sure the filename is initialized
self . rc_filename = os . path . abspath ( os . path . join ( os . path . expanduser ( " ~ " ) , rc_filename ) )
2011-06-18 09:54:50 +00:00
2011-06-26 21:05:22 +00:00
def save_in_rc ( self , key , definition ) :
2011-06-29 18:50:09 +00:00
"""
Saves or updates macro or other definitions in . pronsolerc
key is prefix that determines what is being defined / updated ( e . g . ' macro foo ' )
definition is the full definition ( that is written to file ) . ( e . g . ' macro foo move x 10 ' )
Set key as empty string to just add ( and not overwrite )
Set definition as empty string to remove it from . pronsolerc
To delete line from . pronsolerc , set key as the line contents , and definition as empty string
Only first definition with given key is overwritten .
Updates are made in the same file position .
Additions are made to the end of the file .
"""
rci , rco = None , None
if definition != " " and not definition . endswith ( " \n " ) :
definition + = " \n "
try :
written = False
rco = open ( self . rc_filename + " ~new " , " w " )
if os . path . exists ( self . rc_filename ) :
rci = open ( self . rc_filename , " r " )
overwriting = False
for rc_cmd in rci :
l = rc_cmd . rstrip ( )
ls = l . lstrip ( )
ws = l [ : len ( l ) - len ( ls ) ] # just leading whitespace
if overwriting and len ( ws ) == 0 :
overwriting = False
if not written and key != " " and rc_cmd . startswith ( key ) and ( rc_cmd + " \n " ) [ len ( key ) ] . isspace ( ) :
overwriting = True
written = True
rco . write ( definition )
if not overwriting :
rco . write ( rc_cmd )
if not rc_cmd . endswith ( " \n " ) : rco . write ( " \n " )
if not written :
rco . write ( definition )
if rci is not None :
rci . close ( )
if os . path . exists ( self . rc_filename + " ~old " ) :
os . remove ( rci . name + " ~old " )
os . rename ( rci . name , rci . name + " ~old " )
rco . close ( )
os . rename ( rco . name , self . rc_filename )
2011-08-12 05:55:13 +00:00
#if definition != "":
# print "Saved '"+key+"' to '"+self.rc_filename+"'"
#else:
# print "Removed '"+key+"' from '"+self.rc_filename+"'"
2011-07-27 18:41:27 +00:00
except Exception , e :
2011-06-29 18:50:09 +00:00
print " Saving failed for " , key + " : " , str ( e )
finally :
del rci , rco
2011-06-26 21:05:22 +00:00
2011-06-18 09:54:50 +00:00
def preloop ( self ) :
2011-06-01 12:32:45 +00:00
print " Welcome to the printer console! Type \" help \" for a list of available commands. "
2011-05-26 22:16:57 +00:00
cmd . Cmd . preloop ( self )
def do_connect ( self , l ) :
a = l . split ( )
p = self . scanserial ( )
2011-06-29 18:50:09 +00:00
port = self . settings . port
if ( port == " " or port not in p ) and len ( p ) > 0 :
2011-05-28 19:03:57 +00:00
port = p [ 0 ]
2011-06-29 18:50:09 +00:00
baud = self . settings . baudrate or 115200
2011-06-01 21:42:27 +00:00
if ( len ( a ) > 0 ) :
2011-05-26 22:16:57 +00:00
port = a [ 0 ]
2011-06-01 21:42:27 +00:00
if ( len ( a ) > 1 ) :
2011-06-01 12:42:35 +00:00
try :
baud = int ( a [ 1 ] )
except :
2011-06-06 18:43:22 +00:00
print " Bad baud value ' " + a [ 1 ] + " ' ignored "
2011-06-29 18:50:09 +00:00
if len ( p ) == 0 and not port :
2011-05-26 22:16:57 +00:00
print " No serial ports detected - please specify a port "
return
if len ( a ) == 0 :
print " No port specified - connecting to %s at %d bps " % ( port , baud )
2011-06-29 18:50:09 +00:00
if port != self . settings . port :
self . settings . port = port
self . save_in_rc ( " set port " , " set port %s " % port )
if baud != self . settings . baudrate :
self . settings . baudrate = baud
self . save_in_rc ( " set baudrate " , " set baudrate %d " % baud )
2011-05-26 22:16:57 +00:00
self . p . connect ( port , baud )
def help_connect ( self ) :
print " Connect to printer "
print " connect <port> <baudrate> "
print " If port and baudrate are not specified, connects to first detected port at 115200bps "
2011-05-30 09:53:45 +00:00
ports = self . scanserial ( )
if ( len ( ports ) ) :
print " Available ports: " , " " . join ( ports )
else :
print " No serial ports were automatically found. "
2011-05-26 22:16:57 +00:00
def complete_connect ( self , text , line , begidx , endidx ) :
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
return [ i for i in self . scanserial ( ) if i . startswith ( text ) ]
elif ( len ( line . split ( ) ) == 3 or ( len ( line . split ( ) ) == 2 and line [ - 1 ] == " " ) ) :
return [ i for i in [ " 2400 " , " 9600 " , " 19200 " , " 38400 " , " 57600 " , " 115200 " ] if i . startswith ( text ) ]
else :
return [ ]
def do_disconnect ( self , l ) :
self . p . disconnect ( )
def help_disconnect ( self ) :
print " Disconnects from the printer "
def do_load ( self , l ) :
2011-05-28 17:08:22 +00:00
if len ( l ) == 0 :
print " No file name given. "
return
2011-05-26 22:16:57 +00:00
print " Loading file: " + l
if not ( os . path . exists ( l ) ) :
print " File not found! "
return
2011-06-08 14:19:38 +00:00
self . f = [ i . replace ( " \n " , " " ) . replace ( " \r " , " " ) for i in open ( l ) ]
2011-05-26 22:16:57 +00:00
self . filename = l
print " Loaded " , l , " , " , len ( self . f ) , " lines. "
def complete_load ( self , text , line , begidx , endidx ) :
s = line . split ( )
2011-05-28 17:08:22 +00:00
if len ( s ) > 2 :
return [ ]
2011-05-26 22:16:57 +00:00
if ( len ( s ) == 1 and line [ - 1 ] == " " ) or ( len ( s ) == 2 and line [ - 1 ] != " " ) :
if len ( s ) > 1 :
return [ i [ len ( s [ 1 ] ) - len ( text ) : ] for i in glob . glob ( s [ 1 ] + " */ " ) + glob . glob ( s [ 1 ] + " *.g* " ) ]
else :
return glob . glob ( " */ " ) + glob . glob ( " *.g* " )
def help_load ( self ) :
print " Loads a gcode file (with tab-completion) "
2011-05-30 09:09:04 +00:00
2011-05-28 17:08:22 +00:00
def do_upload ( self , l ) :
if len ( l ) == 0 :
print " No file name given. "
return
print " Loading file: " + l . split ( ) [ 0 ]
if not ( os . path . exists ( l . split ( ) [ 0 ] ) ) :
print " File not found! "
return
if not self . p . online :
print " Not connected to printer. "
return
self . f = [ i . replace ( " \n " , " " ) for i in open ( l . split ( ) [ 0 ] ) ]
self . filename = l . split ( ) [ 0 ]
print " Loaded " , l , " , " , len ( self . f ) , " lines. "
tname = " "
if len ( l . split ( ) ) > 1 :
tname = l . split ( ) [ 1 ]
else :
print " please enter target name in 8.3 format. "
return
print " Uploading as " , tname
print ( " Uploading " + self . filename )
self . p . send_now ( " M28 " + tname )
print ( " Press Ctrl-C to interrupt upload. " )
self . p . startprint ( self . f )
try :
sys . stdout . write ( " Progress: 00.0 % " )
sys . stdout . flush ( )
time . sleep ( 1 )
while self . p . printing :
time . sleep ( 1 )
sys . stdout . write ( " \b \b \b \b \b %04.1f %% " % ( 100 * float ( self . p . queueindex ) / len ( self . p . mainqueue ) , ) )
sys . stdout . flush ( )
self . p . send_now ( " M29 " + tname )
2011-05-31 15:08:23 +00:00
self . sleep ( 0.2 )
self . p . clear = 1
2011-05-30 13:47:01 +00:00
self . listing = 0
self . sdfiles = [ ]
self . recvlisteners + = [ self . listfiles ]
self . p . send_now ( " M20 " )
time . sleep ( 0.5 )
2011-05-28 17:08:22 +00:00
print " \b \b \b \b \b 100 % . Upload completed. " , tname , " should now be on the card. "
return
except :
print " ...interrupted! "
self . p . pause ( )
self . p . send_now ( " M29 " + tname )
2011-06-01 21:09:51 +00:00
time . sleep ( 0.2 )
2011-05-31 15:08:23 +00:00
self . p . clear = 1
2011-05-28 17:08:22 +00:00
self . p . startprint ( [ ] )
print " A partial file named " , tname , " may have been written to the sd card. "
def complete_upload ( self , text , line , begidx , endidx ) :
s = line . split ( )
if len ( s ) > 2 :
return [ ]
if ( len ( s ) == 1 and line [ - 1 ] == " " ) or ( len ( s ) == 2 and line [ - 1 ] != " " ) :
if len ( s ) > 1 :
return [ i [ len ( s [ 1 ] ) - len ( text ) : ] for i in glob . glob ( s [ 1 ] + " */ " ) + glob . glob ( s [ 1 ] + " *.g* " ) ]
else :
return glob . glob ( " */ " ) + glob . glob ( " *.g* " )
def help_upload ( self ) :
print " Uploads a gcode file to the sd card "
2011-05-26 22:16:57 +00:00
def help_print ( self ) :
if self . f is None :
print " Send a loaded gcode file to the printer. Load a file with the load command first. "
else :
print " Send a loaded gcode file to the printer. You have " + self . filename + " loaded right now. "
def do_print ( self , l ) :
if self . f is None :
print " No file loaded. Please use load first. "
return
if not self . p . online :
print " Not connected to printer. "
return
print ( " Printing " + self . filename )
2011-06-02 16:47:45 +00:00
print ( " You can monitor the print with the monitor command. " )
2011-05-26 22:16:57 +00:00
self . p . startprint ( self . f )
2011-06-02 16:47:45 +00:00
#self.p.pause()
#self.paused=True
#self.do_resume(None)
def do_pause ( self , l ) :
if self . sdprinting :
self . p . send_now ( " M25 " )
else :
if ( not self . p . printing ) :
print " Not printing, cannot pause. "
return
self . p . pause ( )
2011-06-07 05:46:29 +00:00
#self.p.connect()# This seems to work, but is not a good solution.
2011-05-26 22:16:57 +00:00
self . paused = True
2011-06-02 16:47:45 +00:00
#self.do_resume(None)
2011-06-07 05:46:29 +00:00
def help_pause ( self ) :
2011-06-02 16:47:45 +00:00
print " Pauses a running print "
2011-05-26 22:16:57 +00:00
def do_resume ( self , l ) :
if not self . paused :
print " Not paused, unable to resume. Start a print first. "
return
self . paused = False
2011-06-02 16:47:45 +00:00
if self . sdprinting :
self . p . send_now ( " M24 " )
return
else :
self . p . resume ( )
2011-05-26 22:16:57 +00:00
2011-05-28 17:08:22 +00:00
def help_resume ( self ) :
print " Resumes a paused print. "
2011-05-26 22:16:57 +00:00
def emptyline ( self ) :
pass
def do_shell ( self , l ) :
exec ( l )
2011-05-30 13:47:01 +00:00
def listfiles ( self , line ) :
if " Begin file list " in line :
self . listing = 1
elif " End file list " in line :
self . listing = 0
self . recvlisteners . remove ( self . listfiles )
elif self . listing :
self . sdfiles + = [ line . replace ( " \n " , " " ) . replace ( " \r " , " " ) . lower ( ) ]
def do_ls ( self , l ) :
2011-05-31 07:14:50 +00:00
if not self . p . online :
print " Printer is not online. Try connect to it first. "
return
2011-06-09 14:01:23 +00:00
self . listing = 2
2011-05-30 13:47:01 +00:00
self . sdfiles = [ ]
self . recvlisteners + = [ self . listfiles ]
self . p . send_now ( " M20 " )
time . sleep ( 0.5 )
print " " . join ( self . sdfiles )
def help_ls ( self ) :
print " lists files on the SD card "
2011-05-31 07:14:50 +00:00
def waitforsdresponse ( self , l ) :
if " file.open failed " in l :
print " Opening file failed. "
self . recvlisteners . remove ( self . waitforsdresponse )
return
if " File opened " in l :
print l
if " File selected " in l :
print " Starting print "
self . p . send_now ( " M24 " )
2011-06-01 12:32:45 +00:00
self . sdprinting = 1
2011-05-31 07:14:50 +00:00
#self.recvlisteners.remove(self.waitforsdresponse)
return
if " Done printing file " in l :
print l
2011-06-01 12:32:45 +00:00
self . sdprinting = 0
2011-05-31 07:14:50 +00:00
self . recvlisteners . remove ( self . waitforsdresponse )
return
2011-06-01 12:32:45 +00:00
if " SD printing byte " in l :
#M27 handler
try :
resp = l . split ( )
vals = resp [ - 1 ] . split ( " / " )
self . percentdone = 100.0 * int ( vals [ 0 ] ) / int ( vals [ 1 ] )
except :
pass
2011-05-31 07:14:50 +00:00
2011-06-06 17:46:25 +00:00
def do_reset ( self , l ) :
self . p . reset ( )
def help_reset ( self ) :
print " Resets the printer. "
2011-05-30 13:47:01 +00:00
def do_sdprint ( self , l ) :
2011-05-31 07:14:50 +00:00
if not self . p . online :
2011-07-10 09:57:11 +00:00
print " Printer is not online. Try connect to it first. "
2011-05-31 07:14:50 +00:00
return
2011-06-09 14:01:23 +00:00
self . listing = 2
2011-05-30 13:47:01 +00:00
self . sdfiles = [ ]
self . recvlisteners + = [ self . listfiles ]
self . p . send_now ( " M20 " )
time . sleep ( 0.5 )
if not ( l . lower ( ) in self . sdfiles ) :
print " File is not present on card. Upload it first "
return
2011-05-31 07:14:50 +00:00
self . recvlisteners + = [ self . waitforsdresponse ]
2011-05-30 13:47:01 +00:00
self . p . send_now ( " M23 " + l . lower ( ) )
print " Printing file: " + l . lower ( ) + " from SD card. "
2011-05-31 07:14:50 +00:00
print " Requesting SD print... "
time . sleep ( 1 )
2011-05-30 13:47:01 +00:00
def help_sdprint ( self ) :
print " Print a file from the SD card. Tabcompletes with available file names. "
print " sdprint filename.g "
2011-05-26 22:16:57 +00:00
2011-05-30 13:47:01 +00:00
def complete_sdprint ( self , text , line , begidx , endidx ) :
2011-05-31 07:14:50 +00:00
if self . sdfiles == [ ] and self . p . online :
2011-06-09 14:01:23 +00:00
self . listing = 2
2011-05-30 13:47:01 +00:00
self . recvlisteners + = [ self . listfiles ]
self . p . send_now ( " M20 " )
time . sleep ( 0.5 )
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
return [ i for i in self . sdfiles if i . startswith ( text ) ]
def recvcb ( self , l ) :
2011-06-01 21:09:51 +00:00
if " T: " in l :
2011-06-01 12:32:45 +00:00
self . tempreadings = l
2011-06-09 14:13:17 +00:00
tstring = l . rstrip ( )
2011-06-09 14:01:23 +00:00
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 )
sys . stdout . flush ( )
2011-05-30 13:47:01 +00:00
for i in self . recvlisteners :
i ( l )
2011-05-26 22:16:57 +00:00
def help_shell ( self ) :
print " Executes a python command. Example: "
print " ! os.listdir( ' . ' ) "
def default ( self , l ) :
2011-11-20 18:55:17 +00:00
if ( l [ 0 ] == ' M ' or l [ 0 ] == " G " or l [ 0 ] == ' T ' ) :
2011-05-26 22:16:57 +00:00
if ( self . p and self . p . online ) :
print " SENDING: " + l
self . p . send_now ( l )
2011-05-28 17:08:22 +00:00
else :
print " Printer is not online. "
return
2011-11-20 18:55:17 +00:00
if ( l [ 0 ] == ' m ' or l [ 0 ] == " g " or l [ 0 ] == ' t ' ) :
2011-05-26 22:16:57 +00:00
if ( self . p and self . p . online ) :
print " SENDING: " + l . upper ( )
self . p . send_now ( l . upper ( ) )
2011-05-28 17:08:22 +00:00
else :
print " Printer is not online. "
return
2011-05-26 22:16:57 +00:00
else :
cmd . Cmd . default ( self , l )
2011-05-28 17:08:22 +00:00
def help_help ( self ) :
self . do_help ( " " )
2011-05-31 07:14:50 +00:00
def tempcb ( self , l ) :
2011-06-05 14:04:38 +00:00
if " T: " in l :
2011-05-31 07:14:50 +00:00
print l . replace ( " \r " , " " ) . replace ( " T " , " Hotend " ) . replace ( " B " , " Bed " ) . replace ( " \n " , " " ) . replace ( " ok " , " " )
2011-06-06 17:46:25 +00:00
2011-05-31 07:14:50 +00:00
def do_gettemp ( self , l ) :
if self . p . online :
self . recvlisteners + = [ self . tempcb ]
self . p . send_now ( " M105 " )
2011-06-06 17:46:25 +00:00
time . sleep ( 0.75 )
self . recvlisteners . remove ( self . tempcb )
2011-05-31 07:14:50 +00:00
def help_gettemp ( self ) :
print " Read the extruder and bed temperature. "
def do_settemp ( self , l ) :
try :
2011-06-09 10:54:03 +00:00
l = l . lower ( ) . replace ( " , " , " . " )
for i in self . temps . keys ( ) :
l = l . replace ( i , self . temps [ i ] )
2011-05-31 07:14:50 +00:00
f = float ( l )
if f > = 0 :
if self . p . online :
self . p . send_now ( " M104 S " + l )
print " Setting hotend temperature to " , f , " degrees Celsius. "
else :
print " Printer is not online. "
else :
print " You cannot set negative temperatures. To turn the hotend off entirely, set its temperature to 0. "
except :
print " You must enter a temperature. "
def help_settemp ( self ) :
print " Sets the hotend temperature to the value entered. "
print " Enter either a temperature in celsius or one of the following keywords "
2011-05-31 15:08:23 +00:00
print " , " . join ( [ i + " ( " + self . temps [ i ] + " ) " for i in self . temps . keys ( ) ] )
def complete_settemp ( self , text , line , begidx , endidx ) :
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
return [ i for i in self . temps . keys ( ) if i . startswith ( text ) ]
2011-05-31 07:14:50 +00:00
def do_bedtemp ( self , l ) :
try :
2011-06-09 10:54:03 +00:00
l = l . lower ( ) . replace ( " , " , " . " )
for i in self . bedtemps . keys ( ) :
l = l . replace ( i , self . bedtemps [ i ] )
2011-05-31 07:14:50 +00:00
f = float ( l )
if f > = 0 :
if self . p . online :
self . p . send_now ( " M140 S " + l )
print " Setting bed temperature to " , f , " degrees Celsius. "
else :
print " Printer is not online. "
else :
print " You cannot set negative temperatures. To turn the bed off entirely, set its temperature to 0. "
except :
print " You must enter a temperature. "
def help_bedtemp ( self ) :
print " Sets the bed temperature to the value entered. "
print " Enter either a temperature in celsius or one of the following keywords "
2011-05-31 15:08:23 +00:00
print " , " . join ( [ i + " ( " + self . bedtemps [ i ] + " ) " for i in self . bedtemps . keys ( ) ] )
2011-05-31 07:14:50 +00:00
2011-05-31 15:08:23 +00:00
def complete_bedtemp ( self , text , line , begidx , endidx ) :
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
return [ i for i in self . bedtemps . keys ( ) if i . startswith ( text ) ]
2011-05-31 07:14:50 +00:00
2011-06-01 12:32:45 +00:00
def do_move ( self , l ) :
if ( len ( l . split ( ) ) < 2 ) :
print " No move specified. "
return
if self . p . printing :
print " Printer is currently printing. Please pause the print before you issue manual commands. "
return
if not self . p . online :
print " Printer is not online. Unable to move. "
return
l = l . split ( )
if ( l [ 0 ] . lower ( ) == " x " ) :
2011-06-29 20:13:43 +00:00
feed = self . settings . xy_feedrate
2011-06-01 12:32:45 +00:00
axis = " X "
elif ( l [ 0 ] . lower ( ) == " y " ) :
2011-06-29 20:13:43 +00:00
feed = self . settings . xy_feedrate
2011-06-01 12:32:45 +00:00
axis = " Y "
elif ( l [ 0 ] . lower ( ) == " z " ) :
2011-06-29 18:50:09 +00:00
feed = self . settings . z_feedrate
2011-06-01 12:32:45 +00:00
axis = " Z "
elif ( l [ 0 ] . lower ( ) == " e " ) :
2011-06-29 18:50:09 +00:00
feed = self . settings . e_feedrate
2011-06-01 12:32:45 +00:00
axis = " E "
else :
print " Unknown axis. "
return
dist = 0
try :
dist = float ( l [ 1 ] )
except :
2011-06-09 16:44:57 +00:00
print " Invalid distance "
2011-06-01 12:32:45 +00:00
return
2011-06-09 16:44:57 +00:00
try :
feed = int ( l [ 2 ] )
except :
pass
2011-06-01 12:32:45 +00:00
self . p . send_now ( " G91 " )
self . p . send_now ( " G1 " + axis + str ( l [ 1 ] ) + " F " + str ( feed ) )
self . p . send_now ( " G90 " )
def help_move ( self ) :
print " Move an axis. Specify the name of the axis and the amount. "
2011-06-29 20:13:43 +00:00
print " move X 10 will move the X axis forward by 10mm at " , self . settings . xy_feedrate , " mm/min (default XY speed) "
2011-06-09 16:44:57 +00:00
print " move Y 10 5000 will move the Y axis forward by 10mm at 5000mm/min "
2011-06-29 20:13:43 +00:00
print " move Z -1 will move the Z axis down by 1mm at " , self . settings . z_feedrate , " mm/min (default Z speed) "
2011-06-01 12:32:45 +00:00
print " Common amounts are in the tabcomplete list. "
def complete_move ( self , text , line , begidx , endidx ) :
if ( len ( line . split ( ) ) == 2 and line [ - 1 ] != " " ) or ( len ( line . split ( ) ) == 1 and line [ - 1 ] == " " ) :
return [ i for i in [ " X " , " Y " , " Z " , " E " ] if i . lower ( ) . startswith ( text ) ]
elif ( len ( line . split ( ) ) == 3 or ( len ( line . split ( ) ) == 2 and line [ - 1 ] == " " ) ) :
base = line . split ( ) [ - 1 ]
rlen = 0
if base . startswith ( " - " ) :
rlen = 1
if line [ - 1 ] == " " :
base = " "
return [ i [ rlen : ] for i in [ " -100 " , " -10 " , " -1 " , " -0.1 " , " 100 " , " 10 " , " 1 " , " 0.1 " , " -50 " , " -5 " , " -0.5 " , " 50 " , " 5 " , " 0.5 " , " -200 " , " -20 " , " -2 " , " -0.2 " , " 200 " , " 20 " , " 2 " , " 0.2 " ] if i . startswith ( base ) ]
else :
return [ ]
def do_extrude ( self , l , override = None , overridefeed = 300 ) :
length = 5 #default extrusion length
2011-06-29 20:13:43 +00:00
feed = self . settings . e_feedrate #default speed
2011-06-01 12:32:45 +00:00
if not self . p . online :
print " Printer is not online. Unable to move. "
return
if self . p . printing :
print " Printer is currently printing. Please pause the print before you issue manual commands. "
return
ls = l . split ( )
if len ( ls ) :
try :
length = float ( ls [ 0 ] )
except :
print " Invalid length given. "
2011-06-02 17:59:20 +00:00
if len ( ls ) > 1 :
try :
feed = int ( ls [ 1 ] )
except :
print " Invalid speed given. "
2011-06-01 12:32:45 +00:00
if override is not None :
length = override
feed = overridefeed
if length > 0 :
print " Extruding %f mm of filament. " % ( length , )
elif length < 0 :
print " Reversing %f mm of filament. " % ( - 1 * length , )
else :
" Length is 0, not doing anything. "
self . p . send_now ( " G91 " )
self . p . send_now ( " G1 E " + str ( length ) + " F " + str ( feed ) )
self . p . send_now ( " G90 " )
def help_extrude ( self ) :
print " Extrudes a length of filament, 5mm by default, or the number of mm given as a parameter "
print " extrude - extrudes 5mm of filament at 300mm/min (5mm/s) "
print " extrude 20 - extrudes 20mm of filament at 300mm/min (5mm/s) "
print " extrude -5 - REVERSES 5mm of filament at 300mm/min (5mm/s) "
print " extrude 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s) "
def do_reverse ( self , l ) :
length = 5 #default extrusion length
2011-06-29 20:13:43 +00:00
feed = self . settings . e_feedrate #default speed
2011-06-01 12:32:45 +00:00
if not self . p . online :
print " Printer is not online. Unable to move. "
return
if self . p . printing :
print " Printer is currently printing. Please pause the print before you issue manual commands. "
return
ls = l . split ( )
if len ( ls ) :
try :
length = float ( ls [ 0 ] )
except :
print " Invalid length given. "
if len ( ls ) > 1 :
try :
feed = int ( ls [ 1 ] )
except :
print " Invalid speed given. "
self . do_extrude ( " " , length * - 1.0 , feed )
def help_reverse ( self ) :
print " Reverses the extruder, 5mm by default, or the number of mm given as a parameter "
print " reverse - reverses 5mm of filament at 300mm/min (5mm/s) "
print " reverse 20 - reverses 20mm of filament at 300mm/min (5mm/s) "
print " reverse 10 210 - extrudes 10mm of filament at 210mm/min (3.5mm/s) "
print " reverse -5 - EXTRUDES 5mm of filament at 300mm/min (5mm/s) "
def do_exit ( self , l ) :
print " Disconnecting from printer... "
self . p . disconnect ( )
print " Exiting program. Goodbye! "
return True
def help_exit ( self ) :
print " Disconnects from the printer and exits the program. "
def do_monitor ( self , l ) :
interval = 5
if not self . p . online :
print " Printer is not online. Please connect first. "
return
print " Monitoring printer, use ^C to interrupt. "
if len ( l ) :
try :
interval = float ( l )
except :
print " Invalid period given. "
print " Updating values every %f seconds. " % ( interval , )
2011-06-09 14:01:23 +00:00
self . monitoring = 1
2011-06-01 12:32:45 +00:00
try :
while ( 1 ) :
self . p . send_now ( " M105 " )
if ( self . sdprinting ) :
self . p . send_now ( " M27 " )
2011-06-06 17:46:25 +00:00
time . sleep ( interval )
2011-06-01 12:32:45 +00:00
print ( self . tempreadings . replace ( " \r " , " " ) . replace ( " T " , " Hotend " ) . replace ( " B " , " Bed " ) . replace ( " \n " , " " ) . replace ( " ok " , " " ) )
2011-06-02 16:47:45 +00:00
if ( self . p . printing ) :
print " Print progress: " , 100 * float ( self . p . queueindex ) / len ( self . p . mainqueue ) , " % "
2011-06-01 12:32:45 +00:00
if ( self . sdprinting ) :
print " SD print progress: " , self . percentdone , " % "
2011-06-06 17:46:25 +00:00
2011-06-01 12:32:45 +00:00
except :
print " Done monitoring. "
pass
2011-06-09 14:01:23 +00:00
self . monitoring = 0
2011-06-01 12:32:45 +00:00
def help_monitor ( self ) :
print " Monitor a machine ' s temperatures and an SD print ' s status. "
2011-06-01 12:35:30 +00:00
print " monitor - Reports temperature and SD print status (if SD printing) every 5 seconds "
print " monitor 2 - Reports temperature and SD print status (if SD printing) every 2 seconds "
2011-11-18 08:52:16 +00:00
def expandcommand ( self , c ) :
return c . replace ( " $python " , sys . executable )
2011-06-01 16:27:25 +00:00
def do_skein ( self , l ) :
l = l . split ( )
if len ( l ) == 0 :
print " No file name given. "
return
2011-06-02 16:47:45 +00:00
settings = 0
if ( l [ 0 ] == " set " ) :
settings = 1
else :
print " Skeining file: " + l [ 0 ]
if not ( os . path . exists ( l [ 0 ] ) ) :
print " File not found! "
return
2011-06-01 16:27:25 +00:00
try :
2011-11-18 08:52:16 +00:00
import shlex
2011-06-02 16:47:45 +00:00
if ( settings ) :
2011-12-22 10:07:52 +00:00
param = self . expandcommand ( self . settings . sliceoptscommand ) . replace ( " \\ " , " \\ \\ " ) . encode ( )
2011-11-18 08:52:16 +00:00
print " Entering skeinforge settings: " , param
subprocess . call ( shlex . split ( param ) )
2011-06-02 16:47:45 +00:00
else :
2011-12-22 10:07:52 +00:00
param = self . expandcommand ( self . settings . slicecommand ) . encode ( )
2011-11-18 08:52:16 +00:00
print " Slicing: " , param
2011-12-22 10:07:52 +00:00
params = [ i . replace ( " $s " , l [ 0 ] ) . replace ( " $o " , l [ 0 ] . replace ( " .stl " , " _export.gcode " ) . replace ( " .STL " , " _export.gcode " ) ) . encode ( ) for i in shlex . split ( param . replace ( " \\ " , " \\ \\ " ) . encode ( ) ) ]
subprocess . call ( params )
2011-06-02 16:47:45 +00:00
print " Loading skeined file. "
self . do_load ( l [ 0 ] . replace ( " .stl " , " _export.gcode " ) )
2011-09-26 04:57:04 +00:00
except Exception , e :
print " Skeinforge execution failed: " , e
2011-06-01 16:27:25 +00:00
def complete_skein ( self , text , line , begidx , endidx ) :
s = line . split ( )
if len ( s ) > 2 :
return [ ]
if ( len ( s ) == 1 and line [ - 1 ] == " " ) or ( len ( s ) == 2 and line [ - 1 ] != " " ) :
if len ( s ) > 1 :
return [ i [ len ( s [ 1 ] ) - len ( text ) : ] for i in glob . glob ( s [ 1 ] + " */ " ) + glob . glob ( s [ 1 ] + " *.stl " ) ]
else :
return glob . glob ( " */ " ) + glob . glob ( " *.stl " )
def help_skein ( self ) :
print " Creates a gcode file from an stl model using skeinforge (with tab-completion) "
print " skein filename.stl - create gcode file "
print " skein filename.stl view - create gcode file and view using skeiniso "
2011-06-02 16:47:45 +00:00
print " skein set - adjust skeinforge settings "
2011-06-01 16:27:25 +00:00
2011-06-09 06:01:09 +00:00
def do_home ( self , l ) :
if not self . p . online :
print " Printer is not online. Unable to move. "
return
if self . p . printing :
print " Printer is currently printing. Please pause the print before you issue manual commands. "
return
if " x " in l . lower ( ) :
2011-07-28 10:07:47 +00:00
self . p . send_now ( " G28 X0 " )
2011-06-09 06:01:09 +00:00
if " y " in l . lower ( ) :
2011-07-28 10:07:47 +00:00
self . p . send_now ( " G28 Y0 " )
2011-06-09 06:01:09 +00:00
if " z " in l . lower ( ) :
2011-07-28 10:07:47 +00:00
self . p . send_now ( " G28 Z0 " )
2011-06-11 17:32:11 +00:00
if " e " in l . lower ( ) :
self . p . send_now ( " G92 E0 " )
2011-06-09 06:01:09 +00:00
if not len ( l ) :
2011-06-09 06:48:50 +00:00
self . p . send_now ( " G28 " )
2011-06-11 17:32:11 +00:00
self . p . send_now ( " G92 E0 " )
2011-06-09 06:01:09 +00:00
def help_home ( self ) :
print " Homes the printer "
2011-07-20 13:10:01 +00:00
print " home - homes all axes and zeroes the extruder(Using G28 and G92) "
print " home xy - homes x and y axes (Using G28) "
print " home z - homes z axis only (Using G28) "
2011-06-11 17:32:11 +00:00
print " home e - set extruder position to zero (Using G92) "
2011-07-20 13:10:01 +00:00
print " home xyze - homes all axes and zeroes the extruder (Using G28 and G92) "
2011-06-09 06:01:09 +00:00
2011-07-04 09:02:30 +00:00
def parse_cmdline ( self , args ) :
import getopt
2011-07-04 10:06:42 +00:00
opts , args = getopt . getopt ( args , " c:e:h " , [ " conf= " , " config= " , " help " ] )
2011-07-04 09:02:30 +00:00
for o , a in opts :
#print repr((o,a))
if o in ( " -c " , " --conf " , " --config " ) :
self . load_rc ( a )
2011-07-04 10:06:42 +00:00
elif o in ( " -h " , " --help " ) :
print " Usage: " + sys . argv [ 0 ] + ' [-c filename [-c filename2 ... ] ] [-e " command " ...] '
print " -c | --conf | --config - override startup .pronsolerc file "
print " may chain config files, settings auto-save will go into last file in the chain "
print ' -e <command> - executes command after configuration/.pronsolerc is loaded '
print " macros/settings from these commands are not autosaved "
sys . exit ( )
if not self . rc_loaded :
self . load_default_rc ( )
for o , a in opts :
if o == " -e " :
2011-07-04 09:02:30 +00:00
self . processing_args = True
self . onecmd ( a )
self . processing_args = False
2011-06-09 06:01:09 +00:00
if __name__ == " __main__ " :
interp = pronsole ( )
2011-07-04 09:02:30 +00:00
interp . parse_cmdline ( sys . argv [ 1 : ] )
2011-06-09 06:01:09 +00:00
try :
interp . cmdloop ( )
except :
interp . p . disconnect ( )
2011-06-11 21:03:01 +00:00
#raise
2011-05-31 07:14:50 +00:00