Merge branch 'experimental' into connection-rework

Conflicts:
	printrun/printcore.py
	pronsole.py
	pronterface.py
master
Guillaume Seguin 2012-09-05 09:56:16 +02:00
commit bff5a8ff51
7 changed files with 280 additions and 81 deletions

143
README.md
View File

@ -5,80 +5,44 @@ Printrun consists of printcore, pronsole and pronterface, and a small collection
* pronterface.py is a graphical host software with the same functionality as pronsole
* webinterface.py is a browser-usable remote control function for Pronterface
# INSTALLING DEPENDENCIES
# GETTING PRINTRUN
This section suggests using precompiled binaries, this way you get everything bundled into one single package for an easy installation.
If you want the newest, shiniest features, you can run Printrun from source using the instructions further down this README.
## Windows
A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
Download the following, and install in this order:
## Mac OS X
1. http://python.org/ftp/python/2.7.2/python-2.7.2.msi
2. http://pypi.python.org/packages/any/p/pyserial/pyserial-2.5.win32.exe
3. http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.0-py27.exe
4. http://launchpad.net/pyreadline/1.7/1.7/+download/pyreadline-1.7.win32.exe
5. http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
For the last one, you will need to unpack it, open a command terminal,
go into the the directory you unpacked it in and run
`python setup.py install`
## Linux
### Ubuntu/Debian
You can run Printrun directly from source, as there are no packages available yet. Fetch and install the dependencies using
## Ubuntu/Debian
`sudo apt-get install python-serial python-wxgtk2.8 python-pyglet`
## Fedora 15
### Fedora 15 and newer
You can run Printrun directly from source, as there are no packages available yet. Fetch and install the dependencies using
`sudo yum install pyserial wxpython pyglet`
## Mac OS X Lion
### Archlinux
A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
Packages are available in AUR. Just run
1. Ensure that the active Python is the system version. (`brew uninstall python` or other appropriate incantations)
2. Download an install [wxPython2.8-osx-unicode] matching to your python version (most likely 2.7 on Lion,
check with: python --version) from: http://wxpython.org/download.php#stable
Known to work PythonWX: http://superb-sea2.dl.sourceforge.net/project/wxpython/wxPython/2.8.12.1/wxPython2.8-osx-unicode-2.8.12.1-universal-py2.7.dmg
3. Download and unpack pyserial from http://pypi.python.org/packages/source/p/pyserial/pyserial-2.5.tar.gz
4. In a terminal, change to the folder you unzipped to, then type in: `sudo python setup.py install`
5. Repeat 4. with http://http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
`yaourt printrun`
The tools will probably run just fine in 64bit on Lion, you don't need to mess
with any of the 32bit settings. In case they don't, try
5. export VERSIONER_PYTHON_PREFER_32_BIT=yes
in a terminal before running Pronterface
## Mac OS X (pre Lion)
A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
1. Download and install http://downloads.sourceforge.net/wxpython/wxPython2.8-osx-unicode-2.8.12.0-universal-py2.6.dmg
2. Grab the source for pyserial from http://pypi.python.org/packages/source/p/pyserial/pyserial-2.5.tar.gz
3. Unzip pyserial to a folder. Then, in a terminal, change to the folder you unzipped to, then type in:
`defaults write com.apple.versioner.python Prefer-32-Bit -bool yes`
`sudo python setup.py install`
Alternatively, you can run python in 32 bit mode by setting the following environment variable before running the setup.py command:
This alternative approach is confirmed to work on Mac OS X 10.6.8.
`export VERSIONER_PYTHON_PREFER_32_BIT=yes`
`sudo python setup.py install`
Then repeat the same with http://http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
and enjoy the `pronterface`, `pronsole`, ... commands directly.
# USING PRONTERFACE
To use pronterface, you need:
* python (ideally 2.6.x or 2.7.x),
* pyserial (or python-serial on ubuntu/debian),
* pyglet
* pyreadline (not needed on Linux) and
* wxPython
Download and install the above, and start pronterface.py
When you're done setting up Printrun, you can start pronterface.py in the directory you unpacked it.
Select the port name you are using from the first drop-down, select your baud rate, and hit connect.
Load an STL (see the note on skeinforge below) or GCODE file, and you can upload it to SD or print it directly.
The "monitor printer" function, when enabled, checks the printer state (temperatures, SD print progress) every 3 seconds.
@ -133,6 +97,73 @@ sender, or the following code example:
p.resume()
p.disconnect()
# RUNNING FROM SOURCE
Run Printrun for source if you want to test out the latest features.
## Dependencies
To use pronterface, you need:
* python (ideally 2.6.x or 2.7.x),
* pyserial (or python-serial on ubuntu/debian),
* pyglet
* pyreadline (not needed on Linux) and
* wxPython
Please see specific instructions for Windows and Mac OS X below. Under Linux, you should use your package manager directly (see the "GETTING PRINTRUN" section)
## Windows
Download the following, and install in this order:
1. http://python.org/ftp/python/2.7.2/python-2.7.2.msi
2. http://pypi.python.org/packages/any/p/pyserial/pyserial-2.5.win32.exe
3. http://downloads.sourceforge.net/wxpython/wxPython2.8-win32-unicode-2.8.12.0-py27.exe
4. http://launchpad.net/pyreadline/1.7/1.7/+download/pyreadline-1.7.win32.exe
5. http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
For the last one, you will need to unpack it, open a command terminal,
go into the the directory you unpacked it in and run
`python setup.py install`
## Mac OS X Lion
1. Ensure that the active Python is the system version. (`brew uninstall python` or other appropriate incantations)
2. Download an install [wxPython2.8-osx-unicode] matching to your python version (most likely 2.7 on Lion,
check with: python --version) from: http://wxpython.org/download.php#stable
Known to work PythonWX: http://superb-sea2.dl.sourceforge.net/project/wxpython/wxPython/2.8.12.1/wxPython2.8-osx-unicode-2.8.12.1-universal-py2.7.dmg
3. Download and unpack pyserial from http://pypi.python.org/packages/source/p/pyserial/pyserial-2.5.tar.gz
4. In a terminal, change to the folder you unzipped to, then type in: `sudo python setup.py install`
5. Repeat 4. with http://http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
The tools will probably run just fine in 64bit on Lion, you don't need to mess
with any of the 32bit settings. In case they don't, try
5. export VERSIONER_PYTHON_PREFER_32_BIT=yes
in a terminal before running Pronterface
## Mac OS X (pre Lion)
A precompiled version is available at http://koti.kapsi.fi/~kliment/printrun/
1. Download and install http://downloads.sourceforge.net/wxpython/wxPython2.8-osx-unicode-2.8.12.0-universal-py2.6.dmg
2. Grab the source for pyserial from http://pypi.python.org/packages/source/p/pyserial/pyserial-2.5.tar.gz
3. Unzip pyserial to a folder. Then, in a terminal, change to the folder you unzipped to, then type in:
`defaults write com.apple.versioner.python Prefer-32-Bit -bool yes`
`sudo python setup.py install`
Alternatively, you can run python in 32 bit mode by setting the following environment variable before running the setup.py command:
This alternative approach is confirmed to work on Mac OS X 10.6.8.
`export VERSIONER_PYTHON_PREFER_32_BIT=yes`
`sudo python setup.py install`
Then repeat the same with http://http://pyglet.googlecode.com/files/pyglet-1.1.4.zip
# LICENSE
```

View File

@ -1,17 +1,6 @@
# Sample .pronsolerc file - copy this into your home directory and rename it to .pronsolerc
!print "Loaded " + self.rc_filename
macro loud
!if self.p.loud:
!self.p.loud = 0
!if hasattr(self,"cur_button") and self.cur_button is not None:
!self.onecmd('button %d "loud (off)" /c green loud' % self.cur_button)
!else:
!self.p.loud = 1
!if hasattr(self,"cur_button") and self.cur_button is not None:
!self.onecmd('button %d "loud (on)" /c yellow loud' % self.cur_button)
button 0 "loud (off)" /c "green" loud
macro fan
!global _fan
!if '_fan' in globals() and _fan:
@ -24,4 +13,4 @@ macro fan
M106
!if hasattr(self,"cur_button") and self.cur_button is not None:
!self.onecmd('button %d "fan (on)" /c yellow fan' % self.cur_button)
button 1 "fan (off)" /c "green" fan
button 0 "fan (off)" /c "green" fan

View File

@ -35,7 +35,7 @@ from printrun.printrun_utils import pixmapfile
glview = False
if "-nogl" not in sys.argv:
try:
import stlview
from printrun import stlview
glview = True
except:
pass

View File

@ -179,14 +179,19 @@ class printcore():
#callback for errors
try: self.errorcb(line)
except: pass
# Teststrings for resend parsing # Firmware exp. result
# line="rs N2 Expected checksum 67" # Teacup 2
if line.lower().startswith("resend") or line.startswith("rs"):
toresend = self.resendfrom
try:
toresend = int(line.replace("N:", " ").replace("N", " ").replace(":", " ").split()[-1])
except:
if line.startswith("rs"):
toresend = int(line.split()[1])
self.resendfrom = toresend
line = line.replace("N:"," ").replace("N"," ").replace(":"," ")
linewords = line.split()
while len(linewords) != 0:
try:
toresend = int(linewords.pop(0))
self.resendfrom = toresend
#print str(toresend)
break
except:
pass
self.clear = True
self.clear = True

View File

@ -621,9 +621,12 @@ class pronsole(cmd.Cmd):
def help_disconnect(self):
print "Disconnects from the printer"
def do_load(self,l):
self._do_load(l)
def do_load(self, l):
if len(l) == 0:
def _do_load(self,l):
if len(l)==0:
print "No file name given."
return
print "Loading file:"+l
@ -874,14 +877,16 @@ class pronsole(cmd.Cmd):
def default(self, l):
if(l[0] in self.commandprefixes.upper()):
if(self.p and self.p.online):
print "SENDING:"+l
if(not self.p.loud):
print "SENDING:"+l
self.p.send_now(l)
else:
print "Printer is not online."
return
elif(l[0] in self.commandprefixes.lower()):
if(self.p and self.p.online):
print "SENDING:"+l.upper()
if(not self.p.loud):
print "SENDING:"+l.upper()
self.p.send_now(l.upper())
else:
print "Printer is not online."

View File

@ -183,6 +183,8 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
self.webInterface = None
except:
print _("CherryPy is not installed. Web Interface Disabled.")
if self.filename is not None:
self.do_load(self.filename)
def startcb(self):
self.starttime = time.time()
@ -402,9 +404,13 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
self.capture_skip[pat] -= 1
self.capture_skip_newline = True
return
<<<<<<< HEAD
wx.CallAfter(self.logbox.AppendText, l)
if self.webInterface:
self.webInterface.AppendLog(l)
=======
wx.CallAfter(self.addtexttolog,l);
>>>>>>> experimental
def scanserial(self):
"""scan for available ports. return a list of device names."""
@ -420,10 +426,17 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
pass
return baselist+glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + glob.glob("/dev/tty.*") + glob.glob("/dev/cu.*") + glob.glob("/dev/rfcomm*")
<<<<<<< HEAD
def project(self, event):
import projectlayer
if self.p.online:
projectlayer.setframe(self, self.p).Show()
=======
def project(self,event):
from printrun import projectlayer
if(self.p.online):
projectlayer.setframe(self,self.p).Show()
>>>>>>> experimental
else:
print _("Printer is not online.")
if self.webInterface:
@ -447,7 +460,22 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
self.Bind(wx.EVT_MENU, self.new_macro, self.macros_menu.Append(-1, _("<&New...>")))
self.Bind(wx.EVT_MENU, lambda *e:options(self), m.Append(-1, _("&Options"), _(" Options dialog")))
<<<<<<< HEAD
self.Bind(wx.EVT_MENU, lambda x: threading.Thread(target = lambda:self.do_skein("set")).start(), m.Append(-1, _("Slicing Settings"), _(" Adjust slicing settings")))
=======
self.Bind(wx.EVT_MENU, lambda x:threading.Thread(target=lambda :self.do_skein("set")).start(), m.Append(-1,_("Slicing Settings"),_(" Adjust slicing settings")))
mItem = m.AppendCheckItem(-1, _("Debug G-code"),
_("Print all G-code sent to and received from the printer."))
m.Check(mItem.GetId(), self.p.loud)
self.Bind(wx.EVT_MENU, self.setloud, mItem)
#try:
# from SkeinforgeQuickEditDialog import SkeinforgeQuickEditDialog
# self.Bind(wx.EVT_MENU, lambda *e:SkeinforgeQuickEditDialog(self), m.Append(-1,_("SFACT Quick Settings"),_(" Quickly adjust SFACT settings for active profile")))
#except:
# pass
>>>>>>> experimental
self.menustrip.Append(m, _("&Settings"))
self.update_macros_menu()
@ -547,16 +575,27 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
uts = self.uppertopsizer = wx.BoxSizer(wx.HORIZONTAL)
self.rescanbtn = wx.Button(self.panel,-1, _("Port"), size = buttonSize)
self.rescanbtn.SetToolTip(wx.ToolTip("Communication Settings\nClick to rescan ports"))
<<<<<<< HEAD
self.rescanbtn.Bind(wx.EVT_BUTTON, self.rescanports)
uts.Add(self.rescanbtn, 0, wx.TOP|wx.LEFT, 0)
=======
self.rescanbtn.Bind(wx.EVT_BUTTON,self.rescanports)
uts.Add(self.rescanbtn,0,wx.TOP|wx.LEFT,0)
>>>>>>> experimental
self.serialport = wx.ComboBox(self.panel, -1,
choices = self.scanserial(),
style = wx.CB_DROPDOWN, size = (100, 25))
self.serialport.SetToolTip(wx.ToolTip("Select Port Printer is connected to"))
self.rescanports()
uts.Add(self.serialport)
<<<<<<< HEAD
uts.Add(wx.StaticText(self.panel,-1, "@"), 0, wx.RIGHT|wx.ALIGN_CENTER, 0)
=======
uts.Add(wx.StaticText(self.panel,-1,"@"),0,wx.RIGHT|wx.ALIGN_CENTER,0)
>>>>>>> experimental
self.baud = wx.ComboBox(self.panel, -1,
choices = ["2400", "9600", "19200", "38400", "57600", "115200", "250000"],
style = wx.CB_DROPDOWN, size = (100, 25))
@ -567,6 +606,7 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
except:
pass
uts.Add(self.baud)
<<<<<<< HEAD
self.connectbtn = wx.Button(self.panel,-1, _("Connect"), size = buttonSize)
uts.Add(self.connectbtn)
self.connectbtn.SetToolTip(wx.ToolTip("Connect to the printer"))
@ -582,6 +622,25 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
#uts.Add((15,-1), flag = wx.EXPAND)
#uts.Add(self.minibtn, 0, wx.ALIGN_CENTER)
=======
self.connectbtn=wx.Button(self.panel,-1,_("Connect"), size=buttonSize)
self.connectbtn.SetToolTip(wx.ToolTip("Connect to the printer"))
self.connectbtn.Bind(wx.EVT_BUTTON,self.connect)
uts.Add(self.connectbtn)
self.resetbtn=wx.Button(self.panel,-1,_("Reset"),style=wx.BU_EXACTFIT,size=(-1,buttonSize[1]))
self.resetbtn.Bind(wx.EVT_BUTTON,self.reset)
self.resetbtn.SetToolTip(wx.ToolTip("Reset the printer"))
uts.Add(self.resetbtn)
#uts.Add((25,-1))
#uts.Add((15,-1),flag=wx.EXPAND)
#self.minibtn=wx.Button(self.panel,-1,_("Mini mode"),style=wx.BU_EXACTFIT)
#self.minibtn.Bind(wx.EVT_BUTTON,self.toggleview)
#uts.Add(self.minibtn,0,wx.ALIGN_CENTER)
>>>>>>> experimental
#SECOND ROW
ubs = self.upperbottomsizer = uts#wx.BoxSizer(wx.HORIZONTAL)
@ -791,8 +850,13 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
self.gviz.showall = 1
try:
raise ""
<<<<<<< HEAD
import printrun.stlview
self.gwindow = printrun.stlview.GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size = (600, 600))
=======
from printrun import stlview
self.gwindow=stlview.GCFrame(None, wx.ID_ANY, 'Gcode view, shift to move view, mousewheel to set layer', size=(600,600))
>>>>>>> experimental
except:
self.gwindow = gviz.window([],
build_dimensions = self.build_dimensions_list,
@ -1323,6 +1387,7 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
else:
wx.CallAfter(self.graph.StopPlotting)
<<<<<<< HEAD
def sendline(self, e):
command = self.commandbox.GetValue()
if not len(command):
@ -1330,6 +1395,25 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
wx.CallAfter(self.logbox.AppendText, ">>>"+command+"\n")
if self.webInterface:
self.webInterface.AppendLog(">>>"+command+"\n")
=======
def addtexttolog(self,text):
try:
self.logbox.AppendText(text)
except:
print "attempted to write invalid text to console"
pass
if self.webInterface:
self.webInterface.AppendLog(text)
def setloud(self,e):
self.p.loud=e.IsChecked()
def sendline(self,e):
command=self.commandbox.GetValue()
if not len(command):
return
wx.CallAfter(self.addtexttolog,">>>"+command+"\n");
>>>>>>> experimental
self.onecmd(str(command))
self.commandbox.SetSelection(0, len(command))
self.commandbox.history+=[command]
@ -1417,10 +1501,14 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
traceback.print_exc()
tstring = l.rstrip()
#print tstring
if (tstring!="ok") and (tstring!="wait") and ("ok T:" not in tstring):
if (tstring!="ok") and (tstring!="wait") and ("ok T:" not in tstring) and (not self.p.loud):
# print "*"+tstring+"*"
# print "[" + time.strftime('%H:%M:%S',time.localtime(time.time())) + "] " + tstring
<<<<<<< HEAD
wx.CallAfter(self.logbox.AppendText, tstring+"\n")
=======
wx.CallAfter(self.addtexttolog,tstring+"\n");
>>>>>>> experimental
for i in self.recvlisteners:
i(l)
@ -1534,6 +1622,7 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
def skein(self, filename):
wx.CallAfter(self.loadbtn.SetLabel, _("Cancel"))
print _("Slicing ") + filename
<<<<<<< HEAD
self.cout = StringIO.StringIO()
self.filename = filename
self.stopsf = 0
@ -1542,6 +1631,22 @@ class PronterWindow(wx.Frame, pronsole.pronsole):
threading.Thread(target = self.skein_monitor).start()
def loadfile(self, event, filename = None):
=======
self.cout=StringIO.StringIO()
self.filename=filename
self.stopsf=0
self.skeining=1
thread(target=self.skein_func).start()
thread(target=self.skein_monitor).start()
def do_load(self,l):
if hasattr(self, 'skeining'):
self.loadfile(None, l)
else:
self._do_load(l)
def loadfile(self,event,filename=None):
>>>>>>> experimental
if self.skeining and self.skeinp is not None:
self.skeinp.terminate()
return

View File

@ -0,0 +1,64 @@
(Created by G-code exporter)
(Fri Apr 27 22:20:09 2012)
(Board size: 100.00 x 130.00 mm)
(---------------------------------)
G21
G90
G0 X14.392 Y30.94113 Z1.
G4
M104 S255
G1 Z-0.2 F60
G1 X14.05334 Y30.60247
G1 X12.02134 Y30.60247
G1 X11.598 Y30.85647
G1 X11.00534 Y31.5338
G1 X10.074 Y32.5498
G1 X9.98933 Y34.41247
G0 Z1.
(RepRap Gen7 v1.4)
G0 Z1.
(R)
G0 X9.9753 Y6.9723
G1 Z-0.20 F60
G1 X11.4761 Y6.9723 F250
G1 X11.8514 Y6.5971
G1 X11.8514 Y5.8467
G1 X11.4761 Y5.4715
G1 X10.3505 Y5.4715
G1 X11.8514 Y3.9456
G0 Z1.
G0 X10.3505 Y6.9723
G1 Z-0.20 F60
G1 X10.3505 Y3.9456 F250
G0 Z1.
(e)
G0 X12.7519 Y4.696
G1 Z-0.20 F60
G1 X14.2778 Y4.696 F250
G1 X14.2778 Y5.0962
G1 X13.9025 Y5.4715
G1 X13.1271 Y5.4715
G1 X12.7519 Y5.0962
G1 X12.7519 Y4.3208
G1 X13.1271 Y3.9456
G1 X14.2778 Y3.9456
G0 Z1.
(p)
G0 X15.5535 Y2.8199
G1 Z-0.20 F60
G1 X15.5535 Y5.0962 F250
G1 X15.1783 Y5.4715
G1 X15.5535 Y5.0962
G1 X15.9287 Y5.4715
G1 X16.6792 Y5.4715
G1 X17.0544 Y5.0962
G1 X17.0544 Y4.3208
G1 X16.6792 Y3.9456
G1 X15.9287 Y3.9456
G1 X15.5535 Y4.3208
G0 Z1.
G4
M104 S0
(tool change position)
G1 X2. Y2. Z40. F400
M2