2012-12-05 12:14:06 +00:00
# coding=utf-8
from __future__ import absolute_import
import threading
import re
import subprocess
import sys
import time
import platform
2012-12-20 12:03:22 +00:00
import os
2012-12-07 08:29:41 +00:00
import power
2012-12-05 12:14:06 +00:00
import wx
from wx . lib import buttons
2012-12-06 17:28:37 +00:00
from Cura . gui . util import webcam
from Cura . gui . util import taskbar
2012-12-06 13:51:55 +00:00
from Cura . util import machineCom
from Cura . util import gcodeInterpreter
from Cura . util . resources import getPathForImage
2012-12-05 12:14:06 +00:00
printWindowMonitorHandle = None
def printFile ( filename ) :
global printWindowMonitorHandle
2012-12-27 08:22:02 +00:00
if printWindowMonitorHandle is None :
2012-12-05 12:14:06 +00:00
printWindowMonitorHandle = printProcessMonitor ( )
printWindowMonitorHandle . loadFile ( filename )
def startPrintInterface ( filename ) :
#startPrintInterface is called from the main script when we want the printer interface to run in a seperate process.
# It needs to run in a seperate process, as any running python code blocks the GCode sender pyton code (http://wiki.python.org/moin/GlobalInterpreterLock).
app = wx . App ( False )
printWindowHandle = printWindow ( )
printWindowHandle . Show ( True )
printWindowHandle . Raise ( )
printWindowHandle . OnConnect ( None )
t = threading . Thread ( target = printWindowHandle . LoadGCodeFile , args = ( filename , ) )
t . daemon = True
t . start ( )
app . MainLoop ( )
class printProcessMonitor ( ) :
def __init__ ( self ) :
self . handle = None
def loadFile ( self , filename ) :
2012-12-27 08:22:02 +00:00
if self . handle is None :
2012-12-20 12:03:22 +00:00
if platform . system ( ) == " Darwin " and hasattr ( sys , ' frozen ' ) :
cmdList = [ os . path . join ( os . path . dirname ( sys . executable ) , ' Cura ' ) ]
else :
2012-12-27 08:22:02 +00:00
cmdList = [ sys . executable , ' -m ' , ' Cura.cura ' ]
2012-12-20 12:03:22 +00:00
cmdList . append ( ' -r ' )
cmdList . append ( filename )
2012-10-11 15:00:29 +00:00
if platform . system ( ) == " Darwin " :
if platform . machine ( ) == ' i386 ' :
cmdList . insert ( 0 , ' arch ' )
cmdList . insert ( 1 , ' -i386 ' )
2012-12-05 12:14:06 +00:00
self . handle = subprocess . Popen ( cmdList , stdin = subprocess . PIPE , stdout = subprocess . PIPE ,
stderr = subprocess . PIPE )
self . thread = threading . Thread ( target = self . Monitor )
self . thread . start ( )
else :
self . handle . stdin . write ( filename + ' \n ' )
def Monitor ( self ) :
p = self . handle
line = p . stdout . readline ( )
2012-12-27 08:22:02 +00:00
while len ( line ) > 0 :
print line . rstrip ( )
2012-12-05 12:14:06 +00:00
line = p . stdout . readline ( )
p . communicate ( )
self . handle = None
self . thread = None
class PrintCommandButton ( buttons . GenBitmapButton ) :
def __init__ ( self , parent , commandList , bitmapFilename , size = ( 20 , 20 ) ) :
self . bitmap = wx . Bitmap ( getPathForImage ( bitmapFilename ) )
super ( PrintCommandButton , self ) . __init__ ( parent . directControlPanel , - 1 , self . bitmap , size = size )
self . commandList = commandList
self . parent = parent
self . SetBezelWidth ( 1 )
self . SetUseFocusIndicator ( False )
self . Bind ( wx . EVT_BUTTON , self . OnClick )
def OnClick ( self , e ) :
2012-12-27 08:22:02 +00:00
if self . parent . machineCom is None or self . parent . machineCom . isPrinting ( ) :
2012-12-05 12:14:06 +00:00
return ;
for cmd in self . commandList :
self . parent . machineCom . sendCommand ( cmd )
e . Skip ( )
class printWindow ( wx . Frame ) :
" Main user interface window "
def __init__ ( self ) :
super ( printWindow , self ) . __init__ ( None , - 1 , title = ' Printing ' )
self . machineCom = None
self . gcode = None
self . gcodeList = None
self . sendList = [ ]
self . temp = None
self . bedTemp = None
self . bufferLineCount = 4
self . sendCnt = 0
self . feedrateRatioOuterWall = 1.0
self . feedrateRatioInnerWall = 1.0
self . feedrateRatioFill = 1.0
self . feedrateRatioSupport = 1.0
self . pause = False
self . termHistory = [ ]
self . termHistoryIdx = 0
self . cam = None
if webcam . hasWebcamSupport ( ) :
self . cam = webcam . webcam ( )
if not self . cam . hasCamera ( ) :
self . cam = None
self . SetSizer ( wx . BoxSizer ( ) )
self . panel = wx . Panel ( self )
self . GetSizer ( ) . Add ( self . panel , 1 , flag = wx . EXPAND )
self . sizer = wx . GridBagSizer ( 2 , 2 )
self . panel . SetSizer ( self . sizer )
sb = wx . StaticBox ( self . panel , label = " Statistics " )
boxsizer = wx . StaticBoxSizer ( sb , wx . VERTICAL )
self . powerWarningText = wx . StaticText ( parent = self . panel ,
id = - 1 ,
2012-12-05 17:33:55 +00:00
label = " Your computer is running on battery power. \n Connect your computer to AC power or your print might not finish. " ,
2012-12-05 12:14:06 +00:00
style = wx . ALIGN_CENTER )
self . powerWarningText . SetBackgroundColour ( ' red ' )
self . powerWarningText . SetForegroundColour ( ' white ' )
boxsizer . AddF ( self . powerWarningText , flags = wx . SizerFlags ( ) . Expand ( ) . Border ( wx . BOTTOM , 10 ) )
self . powerManagement = power . PowerManagement ( )
self . powerWarningTimer = wx . Timer ( self )
self . Bind ( wx . EVT_TIMER , self . OnPowerWarningChange , self . powerWarningTimer )
self . OnPowerWarningChange ( None )
self . powerWarningTimer . Start ( 10000 )
self . statsText = wx . StaticText ( self . panel , - 1 ,
" Filament: ####.##m #.##g \n Estimated print time: #####:## \n Machine state: \n Detecting baudrateXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX " )
boxsizer . Add ( self . statsText , flag = wx . LEFT , border = 5 )
self . sizer . Add ( boxsizer , pos = ( 0 , 0 ) , span = ( 7 , 1 ) , flag = wx . EXPAND )
self . connectButton = wx . Button ( self . panel , - 1 , ' Connect ' )
#self.loadButton = wx.Button(self.panel, -1, 'Load')
self . printButton = wx . Button ( self . panel , - 1 , ' Print ' )
self . pauseButton = wx . Button ( self . panel , - 1 , ' Pause ' )
self . cancelButton = wx . Button ( self . panel , - 1 , ' Cancel print ' )
self . machineLogButton = wx . Button ( self . panel , - 1 , ' Error log ' )
self . progress = wx . Gauge ( self . panel , - 1 )
self . sizer . Add ( self . connectButton , pos = ( 1 , 1 ) , flag = wx . EXPAND )
#self.sizer.Add(self.loadButton, pos=(1,1), flag=wx.EXPAND)
self . sizer . Add ( self . printButton , pos = ( 2 , 1 ) , flag = wx . EXPAND )
self . sizer . Add ( self . pauseButton , pos = ( 3 , 1 ) , flag = wx . EXPAND )
self . sizer . Add ( self . cancelButton , pos = ( 4 , 1 ) , flag = wx . EXPAND )
self . sizer . Add ( self . machineLogButton , pos = ( 5 , 1 ) , flag = wx . EXPAND )
self . sizer . Add ( self . progress , pos = ( 7 , 0 ) , span = ( 1 , 7 ) , flag = wx . EXPAND )
nb = wx . Notebook ( self . panel )
self . sizer . Add ( nb , pos = ( 0 , 2 ) , span = ( 7 , 4 ) , flag = wx . EXPAND )
self . temperaturePanel = wx . Panel ( nb )
sizer = wx . GridBagSizer ( 2 , 2 )
self . temperaturePanel . SetSizer ( sizer )
self . temperatureSelect = wx . SpinCtrl ( self . temperaturePanel , - 1 , ' 0 ' , size = ( 21 * 3 , 21 ) , style = wx . SP_ARROW_KEYS )
self . temperatureSelect . SetRange ( 0 , 400 )
self . bedTemperatureLabel = wx . StaticText ( self . temperaturePanel , - 1 , " BedTemp: " )
self . bedTemperatureSelect = wx . SpinCtrl ( self . temperaturePanel , - 1 , ' 0 ' , size = ( 21 * 3 , 21 ) ,
style = wx . SP_ARROW_KEYS )
self . bedTemperatureSelect . SetRange ( 0 , 400 )
self . bedTemperatureLabel . Show ( False )
self . bedTemperatureSelect . Show ( False )
self . temperatureGraph = temperatureGraph ( self . temperaturePanel )
sizer . Add ( wx . StaticText ( self . temperaturePanel , - 1 , " Temp: " ) , pos = ( 0 , 0 ) )
sizer . Add ( self . temperatureSelect , pos = ( 0 , 1 ) )
sizer . Add ( self . bedTemperatureLabel , pos = ( 1 , 0 ) )
sizer . Add ( self . bedTemperatureSelect , pos = ( 1 , 1 ) )
sizer . Add ( self . temperatureGraph , pos = ( 2 , 0 ) , span = ( 1 , 2 ) , flag = wx . EXPAND )
sizer . AddGrowableRow ( 2 )
sizer . AddGrowableCol ( 1 )
nb . AddPage ( self . temperaturePanel , ' Temp ' )
self . directControlPanel = wx . Panel ( nb )
sizer = wx . GridBagSizer ( 2 , 2 )
self . directControlPanel . SetSizer ( sizer )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Y100 F6000 ' , ' G90 ' ] , ' print-move-y100.png ' ) , pos = ( 0 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Y10 F6000 ' , ' G90 ' ] , ' print-move-y10.png ' ) , pos = ( 1 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Y1 F6000 ' , ' G90 ' ] , ' print-move-y1.png ' ) , pos = ( 2 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Y-1 F6000 ' , ' G90 ' ] , ' print-move-y-1.png ' ) , pos = ( 4 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Y-10 F6000 ' , ' G90 ' ] , ' print-move-y-10.png ' ) , pos = ( 5 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Y-100 F6000 ' , ' G90 ' ] , ' print-move-y-100.png ' ) , pos = ( 6 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 X-100 F6000 ' , ' G90 ' ] , ' print-move-x-100.png ' ) , pos = ( 3 , 0 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 X-10 F6000 ' , ' G90 ' ] , ' print-move-x-10.png ' ) , pos = ( 3 , 1 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 X-1 F6000 ' , ' G90 ' ] , ' print-move-x-1.png ' ) , pos = ( 3 , 2 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G28 X0 Y0 ' ] , ' print-move-home.png ' ) , pos = ( 3 , 3 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 X1 F6000 ' , ' G90 ' ] , ' print-move-x1.png ' ) , pos = ( 3 , 4 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 X10 F6000 ' , ' G90 ' ] , ' print-move-x10.png ' ) , pos = ( 3 , 5 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 X100 F6000 ' , ' G90 ' ] , ' print-move-x100.png ' ) , pos = ( 3 , 6 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Z10 F200 ' , ' G90 ' ] , ' print-move-z10.png ' ) , pos = ( 0 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Z1 F200 ' , ' G90 ' ] , ' print-move-z1.png ' ) , pos = ( 1 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Z0.1 F200 ' , ' G90 ' ] , ' print-move-z0.1.png ' ) , pos = ( 2 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G28 Z0 ' ] , ' print-move-home.png ' ) , pos = ( 3 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Z-0.1 F200 ' , ' G90 ' ] , ' print-move-z-0.1.png ' ) , pos = ( 4 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Z-1 F200 ' , ' G90 ' ] , ' print-move-z-1.png ' ) , pos = ( 5 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G91 ' , ' G1 Z-10 F200 ' , ' G90 ' ] , ' print-move-z-10.png ' ) , pos = ( 6 , 8 ) )
sizer . Add ( PrintCommandButton ( self , [ ' G92 E0 ' , ' G1 E2 F120 ' ] , ' extrude.png ' , size = ( 60 , 20 ) ) , pos = ( 1 , 10 ) ,
span = ( 1 , 3 ) , flag = wx . EXPAND )
sizer . Add ( PrintCommandButton ( self , [ ' G92 E0 ' , ' G1 E-2 F120 ' ] , ' retract.png ' , size = ( 60 , 20 ) ) , pos = ( 2 , 10 ) ,
span = ( 1 , 3 ) , flag = wx . EXPAND )
nb . AddPage ( self . directControlPanel , ' Jog ' )
self . speedPanel = wx . Panel ( nb )
sizer = wx . GridBagSizer ( 2 , 2 )
self . speedPanel . SetSizer ( sizer )
self . outerWallSpeedSelect = wx . SpinCtrl ( self . speedPanel , - 1 , ' 100 ' , size = ( 21 * 3 , 21 ) , style = wx . SP_ARROW_KEYS )
self . outerWallSpeedSelect . SetRange ( 5 , 1000 )
self . innerWallSpeedSelect = wx . SpinCtrl ( self . speedPanel , - 1 , ' 100 ' , size = ( 21 * 3 , 21 ) , style = wx . SP_ARROW_KEYS )
self . innerWallSpeedSelect . SetRange ( 5 , 1000 )
self . fillSpeedSelect = wx . SpinCtrl ( self . speedPanel , - 1 , ' 100 ' , size = ( 21 * 3 , 21 ) , style = wx . SP_ARROW_KEYS )
self . fillSpeedSelect . SetRange ( 5 , 1000 )
self . supportSpeedSelect = wx . SpinCtrl ( self . speedPanel , - 1 , ' 100 ' , size = ( 21 * 3 , 21 ) , style = wx . SP_ARROW_KEYS )
self . supportSpeedSelect . SetRange ( 5 , 1000 )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " Outer wall: " ) , pos = ( 0 , 0 ) )
sizer . Add ( self . outerWallSpeedSelect , pos = ( 0 , 1 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " % " ) , pos = ( 0 , 2 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " Inner wall: " ) , pos = ( 1 , 0 ) )
sizer . Add ( self . innerWallSpeedSelect , pos = ( 1 , 1 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " % " ) , pos = ( 1 , 2 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " Fill: " ) , pos = ( 2 , 0 ) )
sizer . Add ( self . fillSpeedSelect , pos = ( 2 , 1 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " % " ) , pos = ( 2 , 2 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " Support: " ) , pos = ( 3 , 0 ) )
sizer . Add ( self . supportSpeedSelect , pos = ( 3 , 1 ) )
sizer . Add ( wx . StaticText ( self . speedPanel , - 1 , " % " ) , pos = ( 3 , 2 ) )
nb . AddPage ( self . speedPanel , ' Speed ' )
self . termPanel = wx . Panel ( nb )
sizer = wx . GridBagSizer ( 2 , 2 )
self . termPanel . SetSizer ( sizer )
f = wx . Font ( 8 , wx . FONTFAMILY_MODERN , wx . FONTSTYLE_NORMAL , wx . FONTWEIGHT_NORMAL , False )
self . termLog = wx . TextCtrl ( self . termPanel , style = wx . TE_MULTILINE | wx . TE_DONTWRAP )
self . termLog . SetFont ( f )
self . termLog . SetEditable ( 0 )
self . termInput = wx . TextCtrl ( self . termPanel , style = wx . TE_PROCESS_ENTER )
self . termInput . SetFont ( f )
sizer . Add ( self . termLog , pos = ( 0 , 0 ) , flag = wx . EXPAND )
sizer . Add ( self . termInput , pos = ( 1 , 0 ) , flag = wx . EXPAND )
sizer . AddGrowableCol ( 0 )
sizer . AddGrowableRow ( 0 )
nb . AddPage ( self . termPanel , ' Term ' )
if self . cam != None :
self . camPage = wx . Panel ( nb )
sizer = wx . GridBagSizer ( 2 , 2 )
self . camPage . SetSizer ( sizer )
2012-12-10 09:07:46 +00:00
self . timelapsEnable = wx . CheckBox ( self . camPage , - 1 , ' Enable timelapse movie recording ' )
2012-12-05 12:14:06 +00:00
sizer . Add ( self . timelapsEnable , pos = ( 0 , 0 ) , span = ( 1 , 2 ) , flag = wx . EXPAND )
pages = self . cam . propertyPages ( )
self . cam . buttons = [ self . timelapsEnable ]
for page in pages :
button = wx . Button ( self . camPage , - 1 , page )
button . index = pages . index ( page )
sizer . Add ( button , pos = ( 1 , pages . index ( page ) ) )
button . Bind ( wx . EVT_BUTTON , self . OnPropertyPageButton )
self . cam . buttons . append ( button )
self . campreviewEnable = wx . CheckBox ( self . camPage , - 1 , ' Show preview ' )
sizer . Add ( self . campreviewEnable , pos = ( 2 , 0 ) , span = ( 1 , 2 ) , flag = wx . EXPAND )
self . camPreview = wx . Panel ( self . camPage )
sizer . Add ( self . camPreview , pos = ( 3 , 0 ) , span = ( 1 , 2 ) , flag = wx . EXPAND )
nb . AddPage ( self . camPage , ' Camera ' )
self . camPreview . timer = wx . Timer ( self )
self . Bind ( wx . EVT_TIMER , self . OnCameraTimer , self . camPreview . timer )
self . camPreview . timer . Start ( 500 )
self . camPreview . Bind ( wx . EVT_ERASE_BACKGROUND , self . OnCameraEraseBackground )
2012-12-05 17:33:55 +00:00
self . sizer . AddGrowableRow ( 6 )
2012-12-05 12:14:06 +00:00
self . sizer . AddGrowableCol ( 3 )
self . Bind ( wx . EVT_CLOSE , self . OnClose )
self . connectButton . Bind ( wx . EVT_BUTTON , self . OnConnect )
#self.loadButton.Bind(wx.EVT_BUTTON, self.OnLoad)
self . printButton . Bind ( wx . EVT_BUTTON , self . OnPrint )
self . pauseButton . Bind ( wx . EVT_BUTTON , self . OnPause )
self . cancelButton . Bind ( wx . EVT_BUTTON , self . OnCancel )
self . machineLogButton . Bind ( wx . EVT_BUTTON , self . OnMachineLog )
self . Bind ( wx . EVT_SPINCTRL , self . OnTempChange , self . temperatureSelect )
self . Bind ( wx . EVT_SPINCTRL , self . OnBedTempChange , self . bedTemperatureSelect )
self . Bind ( wx . EVT_SPINCTRL , self . OnSpeedChange , self . outerWallSpeedSelect )
self . Bind ( wx . EVT_SPINCTRL , self . OnSpeedChange , self . innerWallSpeedSelect )
self . Bind ( wx . EVT_SPINCTRL , self . OnSpeedChange , self . fillSpeedSelect )
self . Bind ( wx . EVT_SPINCTRL , self . OnSpeedChange , self . supportSpeedSelect )
self . Bind ( wx . EVT_TEXT_ENTER , self . OnTermEnterLine , self . termInput )
self . termInput . Bind ( wx . EVT_CHAR , self . OnTermKey )
self . Layout ( )
self . Fit ( )
self . Centre ( )
self . statsText . SetMinSize ( self . statsText . GetSize ( ) )
self . UpdateButtonStates ( )
#self.UpdateProgress()
def OnCameraTimer ( self , e ) :
if not self . campreviewEnable . GetValue ( ) :
return
if self . machineCom != None and self . machineCom . isPrinting ( ) :
return
self . cam . takeNewImage ( )
self . camPreview . Refresh ( )
def OnCameraEraseBackground ( self , e ) :
dc = e . GetDC ( )
if not dc :
dc = wx . ClientDC ( self )
rect = self . GetUpdateRegion ( ) . GetBox ( )
dc . SetClippingRect ( rect )
dc . SetBackground ( wx . Brush ( self . camPreview . GetBackgroundColour ( ) , wx . SOLID ) )
if self . cam . getLastImage ( ) != None :
self . camPreview . SetMinSize ( ( self . cam . getLastImage ( ) . GetWidth ( ) , self . cam . getLastImage ( ) . GetHeight ( ) ) )
self . camPage . Fit ( )
dc . DrawBitmap ( self . cam . getLastImage ( ) , 0 , 0 )
else :
dc . Clear ( )
def OnPropertyPageButton ( self , e ) :
self . cam . openPropertyPage ( e . GetEventObject ( ) . index )
def UpdateButtonStates ( self ) :
self . connectButton . Enable ( self . machineCom == None or self . machineCom . isClosedOrError ( ) )
#self.loadButton.Enable(self.machineCom == None or not (self.machineCom.isPrinting() or self.machineCom.isPaused()))
self . printButton . Enable ( self . machineCom != None and self . machineCom . isOperational ( ) and not (
self . machineCom . isPrinting ( ) or self . machineCom . isPaused ( ) ) )
self . pauseButton . Enable (
self . machineCom != None and ( self . machineCom . isPrinting ( ) or self . machineCom . isPaused ( ) ) )
if self . machineCom != None and self . machineCom . isPaused ( ) :
self . pauseButton . SetLabel ( ' Resume ' )
else :
self . pauseButton . SetLabel ( ' Pause ' )
self . cancelButton . Enable (
self . machineCom != None and ( self . machineCom . isPrinting ( ) or self . machineCom . isPaused ( ) ) )
self . temperatureSelect . Enable ( self . machineCom != None and self . machineCom . isOperational ( ) )
self . bedTemperatureSelect . Enable ( self . machineCom != None and self . machineCom . isOperational ( ) )
self . directControlPanel . Enable (
self . machineCom != None and self . machineCom . isOperational ( ) and not self . machineCom . isPrinting ( ) )
self . machineLogButton . Show ( self . machineCom != None and self . machineCom . isClosedOrError ( ) )
if self . cam != None :
for button in self . cam . buttons :
button . Enable ( self . machineCom == None or not self . machineCom . isPrinting ( ) )
def UpdateProgress ( self ) :
status = " "
if self . gcode == None :
status + = " Loading gcode... \n "
else :
status + = " Filament: %.2f m %.2f g \n " % (
self . gcode . extrusionAmount / 1000 , self . gcode . calculateWeight ( ) * 1000 )
cost = self . gcode . calculateCost ( )
if cost != False :
status + = " Filament cost: %s \n " % ( cost )
status + = " Estimated print time: %02d : %02d \n " % (
int ( self . gcode . totalMoveTimeMinute / 60 ) , int ( self . gcode . totalMoveTimeMinute % 60 ) )
if self . machineCom == None or not self . machineCom . isPrinting ( ) :
self . progress . SetValue ( 0 )
if self . gcodeList != None :
status + = ' Line: -/ %d \n ' % ( len ( self . gcodeList ) )
else :
printTime = self . machineCom . getPrintTime ( ) / 60
printTimeLeft = self . machineCom . getPrintTimeRemainingEstimate ( )
status + = ' Line: %d / %d %d %% \n ' % ( self . machineCom . getPrintPos ( ) , len ( self . gcodeList ) ,
self . machineCom . getPrintPos ( ) * 100 / len ( self . gcodeList ) )
if self . currentZ > 0 :
status + = ' Height: %0.1f \n ' % ( self . currentZ )
status + = ' Print time: %02d : %02d \n ' % ( int ( printTime / 60 ) , int ( printTime % 60 ) )
if printTimeLeft == None :
status + = ' Print time left: Unknown \n '
else :
status + = ' Print time left: %02d : %02d \n ' % ( int ( printTimeLeft / 60 ) , int ( printTimeLeft % 60 ) )
self . progress . SetValue ( self . machineCom . getPrintPos ( ) )
taskbar . setProgress ( self , self . machineCom . getPrintPos ( ) , len ( self . gcodeList ) )
if self . machineCom != None :
if self . machineCom . getTemp ( ) > 0 :
status + = ' Temp: %d \n ' % ( self . machineCom . getTemp ( ) )
if self . machineCom . getBedTemp ( ) > 0 :
status + = ' Bed Temp: %d \n ' % ( self . machineCom . getBedTemp ( ) )
self . bedTemperatureLabel . Show ( True )
self . bedTemperatureSelect . Show ( True )
self . temperaturePanel . Layout ( )
status + = ' Machine state: %s \n ' % ( self . machineCom . getStateString ( ) )
self . statsText . SetLabel ( status . strip ( ) )
def OnConnect ( self , e ) :
if self . machineCom != None :
self . machineCom . close ( )
self . machineCom = machineCom . MachineCom ( callbackObject = self )
self . UpdateButtonStates ( )
taskbar . setBusy ( self , True )
def OnLoad ( self , e ) :
pass
def OnPrint ( self , e ) :
if self . machineCom == None or not self . machineCom . isOperational ( ) :
return
if self . gcodeList == None :
return
if self . machineCom . isPrinting ( ) :
return
self . currentZ = - 1
if self . cam != None and self . timelapsEnable . GetValue ( ) :
2012-12-10 09:07:46 +00:00
self . cam . startTimelapse ( self . filename [ : self . filename . rfind ( ' . ' ) ] + " .mpg " )
2012-12-05 12:14:06 +00:00
self . machineCom . printGCode ( self . gcodeList )
self . UpdateButtonStates ( )
def OnCancel ( self , e ) :
self . pauseButton . SetLabel ( ' Pause ' )
self . machineCom . cancelPrint ( )
self . machineCom . sendCommand ( " M84 " )
self . UpdateButtonStates ( )
def OnPause ( self , e ) :
if self . machineCom . isPaused ( ) :
self . machineCom . setPause ( False )
else :
self . machineCom . setPause ( True )
def OnMachineLog ( self , e ) :
LogWindow ( ' \n ' . join ( self . machineCom . getLog ( ) ) )
def OnClose ( self , e ) :
global printWindowHandle
printWindowHandle = None
if self . machineCom != None :
self . machineCom . close ( )
self . Destroy ( )
def OnTempChange ( self , e ) :
self . machineCom . sendCommand ( " M104 S %d " % ( self . temperatureSelect . GetValue ( ) ) )
def OnBedTempChange ( self , e ) :
self . machineCom . sendCommand ( " M140 S %d " % ( self . bedTemperatureSelect . GetValue ( ) ) )
def OnSpeedChange ( self , e ) :
if self . machineCom == None :
return
self . machineCom . setFeedrateModifier ( ' WALL-OUTER ' , self . outerWallSpeedSelect . GetValue ( ) / 100.0 )
self . machineCom . setFeedrateModifier ( ' WALL-INNER ' , self . innerWallSpeedSelect . GetValue ( ) / 100.0 )
self . machineCom . setFeedrateModifier ( ' FILL ' , self . fillSpeedSelect . GetValue ( ) / 100.0 )
self . machineCom . setFeedrateModifier ( ' SUPPORT ' , self . supportSpeedSelect . GetValue ( ) / 100.0 )
def AddTermLog ( self , line ) :
self . termLog . AppendText ( unicode ( line , ' utf-8 ' , ' replace ' ) )
l = len ( self . termLog . GetValue ( ) )
self . termLog . SetCaret ( wx . Caret ( self . termLog , ( l , l ) ) )
def OnTermEnterLine ( self , e ) :
line = self . termInput . GetValue ( )
if line == ' ' :
return
self . termLog . AppendText ( ' > %s \n ' % ( line ) )
self . machineCom . sendCommand ( line )
self . termHistory . append ( line )
self . termHistoryIdx = len ( self . termHistory )
self . termInput . SetValue ( ' ' )
def OnTermKey ( self , e ) :
if len ( self . termHistory ) > 0 :
if e . GetKeyCode ( ) == wx . WXK_UP :
self . termHistoryIdx = self . termHistoryIdx - 1
if self . termHistoryIdx < 0 :
self . termHistoryIdx = len ( self . termHistory ) - 1
self . termInput . SetValue ( self . termHistory [ self . termHistoryIdx ] )
if e . GetKeyCode ( ) == wx . WXK_DOWN :
self . termHistoryIdx = self . termHistoryIdx - 1
if self . termHistoryIdx > = len ( self . termHistory ) :
self . termHistoryIdx = 0
self . termInput . SetValue ( self . termHistory [ self . termHistoryIdx ] )
e . Skip ( )
def OnPowerWarningChange ( self , e ) :
type = self . powerManagement . get_providing_power_source_type ( )
if type == power . POWER_TYPE_AC and self . powerWarningText . IsShown ( ) :
self . powerWarningText . Hide ( )
2012-12-05 17:33:55 +00:00
self . panel . Layout ( )
2012-12-05 12:14:06 +00:00
self . Layout ( )
elif type != power . POWER_TYPE_AC and not self . powerWarningText . IsShown ( ) :
self . powerWarningText . Show ( )
2012-12-05 17:33:55 +00:00
self . panel . Layout ( )
2012-12-05 12:14:06 +00:00
self . Layout ( )
def LoadGCodeFile ( self , filename ) :
if self . machineCom != None and self . machineCom . isPrinting ( ) :
return
#Send an initial M110 to reset the line counter to zero.
prevLineType = lineType = ' CUSTOM '
gcodeList = [ " M110 " ]
for line in open ( filename , ' r ' ) :
if line . startswith ( ' ;TYPE: ' ) :
lineType = line [ 6 : ] . strip ( )
if ' ; ' in line :
line = line [ 0 : line . find ( ' ; ' ) ]
line = line . strip ( )
if len ( line ) > 0 :
if prevLineType != lineType :
gcodeList . append ( ( line , lineType , ) )
else :
gcodeList . append ( line )
prevLineType = lineType
gcode = gcodeInterpreter . gcode ( )
gcode . loadList ( gcodeList )
#print "Loaded: %s (%d)" % (filename, len(gcodeList))
self . filename = filename
self . gcode = gcode
self . gcodeList = gcodeList
wx . CallAfter ( self . progress . SetRange , len ( gcodeList ) )
wx . CallAfter ( self . UpdateButtonStates )
wx . CallAfter ( self . UpdateProgress )
wx . CallAfter ( self . SetTitle , ' Printing: %s ' % ( filename ) )
def sendLine ( self , lineNr ) :
if lineNr > = len ( self . gcodeList ) :
return False
line = self . gcodeList [ lineNr ]
try :
if ( ' M104 ' in line or ' M109 ' in line ) and ' S ' in line :
n = int ( re . search ( ' S([0-9]*) ' , line ) . group ( 1 ) )
wx . CallAfter ( self . temperatureSelect . SetValue , n )
if ( ' M140 ' in line or ' M190 ' in line ) and ' S ' in line :
n = int ( re . search ( ' S([0-9]*) ' , line ) . group ( 1 ) )
wx . CallAfter ( self . bedTemperatureSelect . SetValue , n )
except :
print " Unexpected error: " , sys . exc_info ( )
checksum = reduce ( lambda x , y : x ^ y , map ( ord , " N %d %s " % ( lineNr , line ) ) )
self . machineCom . sendCommand ( " N %d %s * %d " % ( lineNr , line , checksum ) )
return True
def mcLog ( self , message ) :
#print message
pass
def mcTempUpdate ( self , temp , bedTemp , targetTemp , bedTargetTemp ) :
self . temperatureGraph . addPoint ( temp , targetTemp , bedTemp , bedTargetTemp )
2012-12-05 17:33:55 +00:00
# ToFix, this causes problems with setting the temperature with the keyboard
# if self.temperatureSelect.GetValue() != targetTemp:
# wx.CallAfter(self.temperatureSelect.SetValue, targetTemp)
# if self.bedTemperatureSelect.GetValue() != bedTargetTemp:
# wx.CallAfter(self.bedTemperatureSelect.SetValue, bedTargetTemp)
2012-12-05 12:14:06 +00:00
def mcStateChange ( self , state ) :
if self . machineCom != None :
if state == self . machineCom . STATE_OPERATIONAL and self . cam != None :
2012-12-10 09:07:46 +00:00
self . cam . endTimelapse ( )
2012-12-05 12:14:06 +00:00
if state == self . machineCom . STATE_OPERATIONAL :
taskbar . setBusy ( self , False )
if self . machineCom . isClosedOrError ( ) :
taskbar . setBusy ( self , False )
if self . machineCom . isPaused ( ) :
taskbar . setPause ( self , True )
wx . CallAfter ( self . UpdateButtonStates )
wx . CallAfter ( self . UpdateProgress )
def mcMessage ( self , message ) :
wx . CallAfter ( self . AddTermLog , message )
def mcProgress ( self , lineNr ) :
wx . CallAfter ( self . UpdateProgress )
def mcZChange ( self , newZ ) :
self . currentZ = newZ
if self . cam != None :
wx . CallAfter ( self . cam . takeNewImage )
wx . CallAfter ( self . camPreview . Refresh )
class temperatureGraph ( wx . Panel ) :
def __init__ ( self , parent ) :
super ( temperatureGraph , self ) . __init__ ( parent )
self . Bind ( wx . EVT_ERASE_BACKGROUND , self . OnEraseBackground )
self . Bind ( wx . EVT_SIZE , self . OnSize )
self . Bind ( wx . EVT_PAINT , self . OnDraw )
self . lastDraw = time . time ( ) - 1.0
self . points = [ ]
self . backBuffer = None
self . addPoint ( 0 , 0 , 0 , 0 )
self . SetMinSize ( ( 320 , 200 ) )
def OnEraseBackground ( self , e ) :
pass
def OnSize ( self , e ) :
if self . backBuffer == None or self . GetSize ( ) != self . backBuffer . GetSize ( ) :
self . backBuffer = wx . EmptyBitmap ( * self . GetSizeTuple ( ) )
self . UpdateDrawing ( True )
def OnDraw ( self , e ) :
dc = wx . BufferedPaintDC ( self , self . backBuffer )
def UpdateDrawing ( self , force = False ) :
now = time . time ( )
if not force and now - self . lastDraw < 1.0 :
return
self . lastDraw = now
dc = wx . MemoryDC ( )
dc . SelectObject ( self . backBuffer )
dc . Clear ( )
2012-12-05 17:33:55 +00:00
dc . SetFont ( wx . SystemSettings . GetFont ( wx . SYS_SYSTEM_FONT ) )
2012-12-05 12:14:06 +00:00
w , h = self . GetSizeTuple ( )
bgLinePen = wx . Pen ( ' #A0A0A0 ' )
tempPen = wx . Pen ( ' #FF4040 ' )
tempSPPen = wx . Pen ( ' #FFA0A0 ' )
tempPenBG = wx . Pen ( ' #FFD0D0 ' )
bedTempPen = wx . Pen ( ' #4040FF ' )
bedTempSPPen = wx . Pen ( ' #A0A0FF ' )
bedTempPenBG = wx . Pen ( ' #D0D0FF ' )
#Draw the background up to the current temperatures.
x0 = 0
t0 = 0
bt0 = 0
tSP0 = 0
btSP0 = 0
for temp , tempSP , bedTemp , bedTempSP , t in self . points :
x1 = int ( w - ( now - t ) )
for x in xrange ( x0 , x1 + 1 ) :
t = float ( x - x0 ) / float ( x1 - x0 + 1 ) * ( temp - t0 ) + t0
bt = float ( x - x0 ) / float ( x1 - x0 + 1 ) * ( bedTemp - bt0 ) + bt0
dc . SetPen ( tempPenBG )
dc . DrawLine ( x , h , x , h - ( t * h / 300 ) )
dc . SetPen ( bedTempPenBG )
dc . DrawLine ( x , h , x , h - ( bt * h / 300 ) )
t0 = temp
bt0 = bedTemp
tSP0 = tempSP
btSP0 = bedTempSP
x0 = x1 + 1
#Draw the grid
for x in xrange ( w , 0 , - 30 ) :
dc . SetPen ( bgLinePen )
dc . DrawLine ( x , 0 , x , h )
2012-12-05 17:33:55 +00:00
tmpNr = 0
2012-12-05 12:14:06 +00:00
for y in xrange ( h - 1 , 0 , - h * 50 / 300 ) :
dc . SetPen ( bgLinePen )
dc . DrawLine ( 0 , y , w , y )
2012-12-05 17:33:55 +00:00
dc . DrawText ( str ( tmpNr ) , 0 , y - dc . GetFont ( ) . GetPixelSize ( ) . GetHeight ( ) )
tmpNr + = 50
2012-12-05 12:14:06 +00:00
dc . DrawLine ( 0 , 0 , w , 0 )
dc . DrawLine ( 0 , 0 , 0 , h )
#Draw the main lines
x0 = 0
t0 = 0
bt0 = 0
tSP0 = 0
btSP0 = 0
for temp , tempSP , bedTemp , bedTempSP , t in self . points :
x1 = int ( w - ( now - t ) )
for x in xrange ( x0 , x1 + 1 ) :
t = float ( x - x0 ) / float ( x1 - x0 + 1 ) * ( temp - t0 ) + t0
bt = float ( x - x0 ) / float ( x1 - x0 + 1 ) * ( bedTemp - bt0 ) + bt0
tSP = float ( x - x0 ) / float ( x1 - x0 + 1 ) * ( tempSP - tSP0 ) + tSP0
btSP = float ( x - x0 ) / float ( x1 - x0 + 1 ) * ( bedTempSP - btSP0 ) + btSP0
dc . SetPen ( tempSPPen )
dc . DrawPoint ( x , h - ( tSP * h / 300 ) )
dc . SetPen ( bedTempSPPen )
dc . DrawPoint ( x , h - ( btSP * h / 300 ) )
dc . SetPen ( tempPen )
dc . DrawPoint ( x , h - ( t * h / 300 ) )
dc . SetPen ( bedTempPen )
dc . DrawPoint ( x , h - ( bt * h / 300 ) )
t0 = temp
bt0 = bedTemp
tSP0 = tempSP
btSP0 = bedTempSP
x0 = x1 + 1
del dc
self . Refresh ( eraseBackground = False )
self . Update ( )
if len ( self . points ) > 0 and ( time . time ( ) - self . points [ 0 ] [ 4 ] ) > w + 20 :
self . points . pop ( 0 )
def addPoint ( self , temp , tempSP , bedTemp , bedTempSP ) :
if bedTemp == None :
bedTemp = 0
if bedTempSP == None :
bedTempSP = 0
self . points . append ( ( temp , tempSP , bedTemp , bedTempSP , time . time ( ) ) )
wx . CallAfter ( self . UpdateDrawing )
class LogWindow ( wx . Frame ) :
def __init__ ( self , logText ) :
super ( LogWindow , self ) . __init__ ( None , title = " Machine log " )
self . textBox = wx . TextCtrl ( self , - 1 , logText , style = wx . TE_MULTILINE | wx . TE_DONTWRAP | wx . TE_READONLY )
self . SetSize ( ( 500 , 400 ) )
self . Centre ( )
self . Show ( True )