def SD_setup(self, spi, cs):

        sd = None
        # setup SD card
        try:
            sd = SDCard(spi, Pin(cs))
        except Exception as e:
            print('Error in SDCard()!!')
            print(e)
            return None
        else:
            print('SD OK')

        # mount sd volume
        utime.sleep(0.1)
        uos.mount(sd, '/sd')
        utime.sleep(0.1)
        uos.listdir('/sd')
        #utime.sleep(0.1)
        #ls('/sd')
        return sd
#classmachine.SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None)
#SDCard(slot=1, width=1, cd=None, wp=None, sck=None, miso=None, mosi=None, cs=None)
Acelx = I2C(scl=Pin(22), sda=Pin(21), freq=100000)
Acelx.writeto_mem(MMA8254Q_ADDR, 0x2A, b'\x00')
Acelx.writeto_mem(MMA8254Q_ADDR, 0x2A, b'\x01')
Acelx.writeto_mem(MMA8254Q_ADDR, 0x0E, b'\x00')
Acelx.writeto_mem(MMA8254Q_ADDR, 0x0F, b'\x30')

#SD1 = SPI(1, 1000000, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
SD1 = SPI(1, 10000000, sck=Pin(14), mosi=Pin(13), miso=Pin(32))

sleep_ms(500)
SD1.init()  # Ensure right baudrate
#sd = SDCard(SD1,Pin(05)) # Compatible with PCB
sd = SDCard(SD1, Pin(27))
vfs = os.VfsFat(sd)
os.mount(vfs, '/fc')

in_xAcc1 = 0
in_yAcc1 = 0
in_zAcc1 = 0

xAcc1 = 0
yAcc1 = 0
zAcc1 = 0

in_in_xAcc1 = 0
in_in_yAcc1 = 0
in_in_zAcc1 = 0
Example #3
0
    def __init__(self, master=None):
        self.master = master
        Frame.__init__(self, master, relief=SUNKEN, bd=2)

        self.gcode = []
        self.slicing = False
        self.printing = False
        self.connected = False
        self.monitorTemp = False
        self.paused = False
        self.sdpresent = False
        self.sdlisting = False
        self.sdchecking = False
        self.sdprinting = False
        self.sdpaused = False
        self.sduploading = False
        self.sdbytes = 0
        self.sdmaxbytes = 0
        self.insidelisting = False
        self.readingFirmware = False
        self.sdfiles = []
        self.bedtemp = float(0)
        self.bedtarget = float(0)
        self.exttemp = float(0)
        self.exttarget = float(0)
        self.acceleration = 0
        self.m114count = 0
        self.speedcount = 0
        self.location = [0, 0, 0, 0]
        self.pausePoint = [0, 0, 0, 0]
        self.percent = 0.0
        self.ets = "??"
        self.gcodeInfo = None
        self.GCodeFile = None
        self.StlFile = None
        self.Profile = None
        self.printStartLine = 0
        self.startTime = 0
        self.endTime = 0
        self.elapsedTime = 0
        self.FanSpeed = 0
        self.FeedMultiply = 100
        self.ExtrudeMultiply = 100

        self.timingReport = None
        self.filamentReport = None
        self.measurementsReport = None

        self.macroButtons = None

        self.rpt1re = re.compile(" *T:([0-9\.]+) *E:[0-9\.]+ *B:([0-9\.]+)")
        self.rpt2re = re.compile(" *T:([0-9\.]+) *E:[0-9\.]+ *W:.*")
        self.locrptre = re.compile("^X:([0-9\.\-]+)Y:([0-9\.\-]+)Z:([0-9\.\-]+)E:([0-9\.\-]+) *Count")
        self.speedrptre = re.compile("Fan speed:([0-9]+) Feed Multiply:([0-9]+) Extrude Multiply:([0-9]+)")

        self.sdre = re.compile("SD printing byte *([0-9]+) *\/ *([0-9]+)")

        self.printer = printcore()
        self.settings = Settings()
        self.settings.cmdFolder = cmd_folder
        self.logger = Logger(self)

        if self.settings.speedcommand is not None:
            allow_while_printing.append(self.settings.speedcommand)

        self.acceleration = self.settings.acceleration

        self.dataLoggers = {}
        for d in DLLIST:
            self.dataLoggers[d] = DataLogger(self, d)

        self.skeinforge = Skeinforge(self.settings)
        self.slic3r = Slic3r(self.settings)

        self.httpServer = RepRapServer(self, self.printer, self.settings, self.logger, self.settings.port)

        self.menubar = Menu(self)
        self.filemenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.filemenu.add_command(label="Slice", command=self.openSTLFile)
        self.filemenu.add_command(label="Load GCode", command=self.openGCodeFile)
        self.slicemenuindex = self.filemenu.index("Slice")
        self.loadgcodemenuindex = self.filemenu.index("Load GCode")

        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=self.quitApp)

        self.editmenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Edit", menu=self.editmenu)

        self.editmenu.add_command(label="Settings", command=self.editSettings)
        self.editmenu.add_command(label="Firmware Settings", command=self.FirmwareSettings)
        self.editmenu.add_separator()
        self.editmenu.add_command(label=GCODE_MENU_TEXT, command=self.doGEdit, state=DISABLED)

        self.slicermenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Slicer", menu=self.slicermenu)
        self.rbSlicer = StringVar()

        self.slicermenu.add_radiobutton(
            label="Skeinforge", command=self.selSlicer, value=SKEINFORGE, variable=self.rbSlicer
        )
        self.slicermenu.add_command(label="Settings", command=self.skeinforgeSettings)
        self.slicermenu.add_command(label="Choose Profile", command=self.chooseSFProfile)
        self.SFprofileindex = self.slicermenu.index("Choose Profile")
        self.setSFProfileMenuText()
        self.slicermenu.add_command(label="Alterations", command=self.doEditAlterations)

        self.slicermenu.add_separator()
        self.slicermenu.add_radiobutton(label="Slic3r", command=self.selSlicer, value=SLIC3R, variable=self.rbSlicer)
        self.slicermenu.add_command(label="Settings", command=self.slic3rSettings)
        self.slicermenu.add_command(label="Choose Profile", command=self.chooseS3Profile)
        self.S3profileindex = self.slicermenu.index("Choose Profile")
        self.setS3ProfileMenuText()

        self.rbSlicer.set(self.settings.slicer)

        self.macromenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Macros", menu=self.macromenu)
        self.macromenu.add_command(label="New", command=self.doNewMacro)
        self.macromenu.add_command(label="Edit", command=self.doEditMacro)
        self.macromenu.add_command(label="Delete", command=self.doDelMacro)
        self.macromenu.add_separator()
        self.cbShowMacroButtons = BooleanVar()
        self.cbShowMacroButtons.set(self.settings.showmacrobuttons)
        self.macromenu.add_checkbutton(
            label="Show Macro Buttons",
            command=self.doShowButtons,
            onvalue=True,
            offvalue=False,
            variable=self.cbShowMacroButtons,
        )
        self.macromenu.add_separator()
        self.runmacromenu = Menu(self.macromenu, tearoff=0)
        self.loadMacros()
        self.macromenu.add_cascade(label="Run", menu=self.runmacromenu)

        self.reportmenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="View", menu=self.reportmenu)
        self.cbShowPrevious = BooleanVar()
        self.cbShowPrevious.set(self.settings.showprevious)
        self.reportmenu.add_checkbutton(
            label="Show Previous Layer",
            command=self.toggleShowPrevious,
            onvalue=True,
            offvalue=False,
            variable=self.cbShowPrevious,
        )
        self.cbShowMoves = BooleanVar()
        self.cbShowMoves.set(self.settings.showmoves)
        self.reportmenu.add_checkbutton(
            label="Show Non-extrusion Moves",
            command=self.toggleShowMoves,
            onvalue=True,
            offvalue=False,
            variable=self.cbShowMoves,
        )
        self.reportmenu.add_separator()
        self.reportmenu.add_command(label="Show Hours of Usage", command=self.doDataLogReport)
        self.reportmenu.add_command(label="Reset Hours of Usage", command=self.doDataLogReset)
        self.reportmenu.add_separator()
        self.reportmenu.add_command(label="Layer by Layer Timing", command=self.doTimingReport)
        self.reportmenu.add_command(label="Layer by Layer Filament Usage", command=self.doFilamentReport)
        self.reportmenu.add_command(label="GCode Measurements", command=self.doMeasurementsReport)

        self.toolsmenu = Menu(self.menubar, tearoff=0)
        n = 0
        if self.settings.platercmd is not None:
            n += 1
            self.toolsmenu.add_command(label="Plater", command=self.doPlater)

        if self.settings.gcodeviewcmd is not None:
            n += 1
            self.toolsmenu.add_command(label="GCode Viewer", command=self.doGCodeView)

        if self.settings.stlviewcmd is not None:
            n += 1
            self.toolsmenu.add_command(label="STL Viewer", command=self.doSTLView)

        if self.settings.openscadcmd is not None:
            n += 1
            self.toolsmenu.add_command(label="OpenSCAD", command=self.doOpenSCAD)

        if n > 0:
            self.menubar.add_cascade(label="Tools", menu=self.toolsmenu)

        try:
            self.master.config(menu=self.menubar)
        except AttributeError:
            self.master.tk.call(master, "config", "-menu", self.menubar)

        self.toolbar = ToolBar(self, self.printer, self.settings, self.logger)
        self.toolbar.grid(row=1, column=1, columnspan=4, sticky=W)

        self.ctl = MoveControl(self, self.printer, self.settings, self.logger)
        self.ctl.grid(row=2, column=1, rowspan=3, sticky=N)

        self.extr = Extruder(self, self.printer, self.settings, self.logger)
        self.extr.grid(row=2, column=2, rowspan=1, sticky=N + E + W)

        self.temps = Temperatures(self, self.printer, self.settings, self.logger)
        self.temps.grid(row=3, column=2, rowspan=2, sticky=N + E + W)

        self.gc = GcFrame(self, None, [], self.settings, self.logger)
        self.gc.grid(row=2, column=3, rowspan=3, sticky=N)

        self.statline = Status(self, self.printer, self.settings, self.logger)
        self.statline.grid(row=5, column=1, columnspan=4, sticky=E + W)

        self.logger.grid(row=2, column=4, rowspan=2, sticky=N + E + W)

        self.sendgcode = SendGCode(self, self.printer, self.settings, self.logger)
        self.sendgcode.grid(row=4, column=4, sticky=N + E + W)

        self.printer.errorcb = self.errorcb
        self.printer.sendcb = self.sendcb
        self.printer.recvcb = self.recvcb

        self.sd = SDCard(self, self.printer, self.settings, self.logger)
        self.firmware = FirmwareParms(self, self.printer, self.settings, self.logger)
        self.bind(MWM_FIRMWARECOMPLETE, self.firmwareReportComplete)
        self.bind(MWM_SLICERCOMPLETE, self.sliceComplete)
        self.bind(MWM_GCODELOADCOMPLETE, self.loadgcodeFinished)
        self.bind(MWM_GEDITMEASURECOMPLETE, self.geditMeasureComplete)
        self.bind(MWM_REQUESTPOSITIONREPORT, self.requestPosition)

        self.doShowButtons()
Example #4
0
def mnt():
    cs = Pin("P22", mode=Pin.OUT)
    sd = SDCard(SPI(0), cs)
    os.mount(sd, '/')
Example #5
0
	def __init__(self, parent, app, prtname, reprap, history):
		self.model = None
		self.cfgString = None
		self.app = app
		self.prtsettings = self.app.settings.printersettings[prtname]
		self.buildarea = self.prtsettings.buildarea
		self.prtname = prtname
		self.history = history
		self.reprap = reprap
		self.manctl = None
		self.hassd = self.prtsettings.hassdcard
		self.filamentdiameter = self.prtsettings.filamentdiam
		self.sliceTime = ""

		self.M105pending = False
		self.M27pending = False
		self.suspendM105 = False
		self.cycle = 0
		self.skipCycles = 5
		self.logger = self.app.logger
		self.printPos = 0
		self.printing = False
		self.paused = False
		self.sdpaused = False
		self.sdprintingfrom = False
		self.settings = app.settings.printmon
		wx.Panel.__init__(self, parent, wx.ID_ANY, size=(100, 100))
		self.SetBackgroundColour("white")
		self.knownHeaters = ['HE0', 'HE1', 'HE2', 'Bed']
		self.targets = {}
		self.temps = {}
		self.tempData = {}
		for h in self.knownHeaters:
			self.temps[h] = None
			self.targets[h] = 0
			self.tempData[h] = []
		self.startTime = None
		self.endTime = None
		self.gcFile = None
		self.printMode = None
		self.origEta = None
		self.countGLines = None
		self.syncPrint = True
		self.holdFan = False
		self.setStatus(PMSTATUS_NOT_READY)
				
		self.sdcard = SDCard(self.app, self, self.reprap, self.logger)
		
		self.M27Timer = wx.Timer(self)
		self.Bind(wx.EVT_TIMER, self.onM27Timer, self.M27Timer)
		self.printingfrom = False

		self.sizerMain = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerLeft = wx.BoxSizer(wx.VERTICAL)
		self.sizerRight = wx.BoxSizer(wx.VERTICAL)
		self.sizerLeft.AddSpacer((10,10))
		
		self.sizerBtns = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerBtns.AddSpacer((10,10))

		self.images = Images(os.path.join(self.settings.cmdfolder, "images"))		
		
		self.bPull = wx.BitmapButton(self, wx.ID_ANY, self.images.pngPull, size=BUTTONDIMWIDE)
		self.sizerBtns.Add(self.bPull)
		self.bPull.SetToolTipString("Pull model from file preparation")
		self.Bind(wx.EVT_BUTTON, self.doPull, self.bPull)
		self.bPull.Enable(self.app.currentPullStatus())
		
		self.sizerBtns.AddSpacer((20, 20))
		
		self.bPrint = wx.BitmapButton(self, wx.ID_ANY, self.images.pngPrint, size=BUTTONDIM)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.sizerBtns.Add(self.bPrint)
		self.Bind(wx.EVT_BUTTON, self.doPrint, self.bPrint)
		self.bPrint.Enable(False)
		
		self.bPause = wx.BitmapButton(self, wx.ID_ANY, self.images.pngPause, size=BUTTONDIM)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.sizerBtns.Add(self.bPause)
		self.Bind(wx.EVT_BUTTON, self.doPause, self.bPause)
		self.bPause.Enable(False)

		self.sizerBtns.AddSpacer(BUTTONDIM)
		
		if self.hassd:
			self.bSDPrintFrom = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSdprintfrom, size=BUTTONDIMWIDE)
			self.bSDPrintFrom.SetToolTipString("Print from SD Card")
			self.sizerBtns.Add(self.bSDPrintFrom)
			self.Bind(wx.EVT_BUTTON, self.doSDPrintFrom, self.bSDPrintFrom)
			self.bSDPrintFrom.Enable(True)
			
			self.bSDPrintTo = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSdprintto, size=BUTTONDIMWIDE)
			self.bSDPrintTo.SetToolTipString("Print to SD Card")
			self.sizerBtns.Add(self.bSDPrintTo)
			self.Bind(wx.EVT_BUTTON, self.doSDPrintTo, self.bSDPrintTo)
			self.bSDPrintTo.Enable(False)
			
			self.bSDDelete = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSddelete, size=BUTTONDIM)
			self.bSDDelete.SetToolTipString("Delete a file from SD Card")
			self.sizerBtns.Add(self.bSDDelete)
			self.Bind(wx.EVT_BUTTON, self.doSDDelete, self.bSDDelete)
			self.bSDDelete.Enable(True)
			
			self.sizerBtns.AddSpacer(BUTTONDIM)
	
		self.bZoomIn = wx.BitmapButton(self, wx.ID_ANY, self.images.pngZoomin, size=BUTTONDIM)
		self.bZoomIn.SetToolTipString("Zoom the view in")
		self.sizerBtns.Add(self.bZoomIn)
		self.Bind(wx.EVT_BUTTON, self.viewZoomIn, self.bZoomIn)
		
		self.bZoomOut = wx.BitmapButton(self, wx.ID_ANY, self.images.pngZoomout, size=BUTTONDIM)
		self.bZoomOut.SetToolTipString("Zoom the view out")
		self.sizerBtns.Add(self.bZoomOut)
		self.Bind(wx.EVT_BUTTON, self.viewZoomOut, self.bZoomOut)

		self.sizerLeft.Add(self.sizerBtns)
		self.sizerLeft.AddSpacer((10,10))
		
		self.sizerGCM = wx.BoxSizer(wx.HORIZONTAL)

		self.gcf = GcmFrame(self, self.model, self.settings, self.buildarea)
		self.sizerGCM.Add(self.gcf)
		
		sz = self.buildarea[1] * self.settings.gcodescale
		
		self.slideLayer = wx.Slider(
			self, wx.ID_ANY, 1, 1, 9999, size=(150, sz),
			style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | wx.SL_LABELS)
		self.slideLayer.Bind(wx.EVT_SCROLL, self.onSpinLayer)
		self.slideLayer.SetRange(1, 10)
		self.slideLayer.SetValue(1)
		self.slideLayer.SetPageSize(1);
		self.slideLayer.Disable()
		self.sizerGCM.Add(self.slideLayer)
		
		self.sizerLeft.Add(self.sizerGCM)

		self.sizerLeft.AddSpacer((10,10))

		self.sizerOpts = wx.BoxSizer(wx.HORIZONTAL)
				
		self.cbPrevious = wx.CheckBox(self, wx.ID_ANY, "Show Previous Layer")
		self.cbPrevious.SetToolTipString("Turn on/off drawing of the previous layer in the background")
		self.Bind(wx.EVT_CHECKBOX, self.checkPrevious, self.cbPrevious)
		self.cbPrevious.SetValue(self.settings.showprevious)
		self.sizerOpts.Add(self.cbPrevious)
		
		self.sizerOpts.AddSpacer((10, 10))

		self.cbMoves = wx.CheckBox(self, wx.ID_ANY, "Show Moves")
		self.cbMoves.SetToolTipString("Turn on/off the drawing of non-extrusion moves")
		self.Bind(wx.EVT_CHECKBOX, self.checkMoves, self.cbMoves)
		self.cbMoves.SetValue(self.settings.showmoves)
		self.sizerOpts.Add(self.cbMoves)
		
		self.sizerOpts.AddSpacer((10, 10))
		
		self.cbToolOnly = wx.CheckBox(self, wx.ID_ANY, "Tool Path Only")
		self.cbToolOnly.SetToolTipString("Show narrow lines indicating tool path")
		self.Bind(wx.EVT_CHECKBOX, self.checkToolPathsOnly, self.cbToolOnly)
		self.cbToolOnly.SetValue(self.settings.toolpathsonly)
		self.sizerOpts.Add(self.cbToolOnly)
		
		self.sizerOpts.AddSpacer((10, 10))

		self.cbSync = wx.CheckBox(self, wx.ID_ANY, "Sync with print")
		self.Bind(wx.EVT_CHECKBOX, self.checkSync, self.cbSync)
		self.cbSync.SetValue(True)
		self.sizerOpts.Add(self.cbSync)

		self.sizerLeft.AddSpacer((5, 5))		
		self.sizerLeft.Add(self.sizerOpts)

		self.sizerOpts2 = wx.BoxSizer(wx.HORIZONTAL)

		self.cbBuffDC = wx.CheckBox(self, wx.ID_ANY, "Use Buffered DC")
		self.Bind(wx.EVT_CHECKBOX, self.checkBuffDC, self.cbBuffDC)
		self.cbBuffDC.SetValue(self.settings.usebuffereddc)
		self.sizerOpts2.Add(self.cbBuffDC)
		
		self.sizerOpts2.AddSpacer((10, 10))
		
		self.cbHoldFan = wx.CheckBox(self, wx.ID_ANY, "Hold Fan Speed")
		self.cbHoldFan.SetToolTipString("Maintain fan speed at its manual setting")
		self.Bind(wx.EVT_CHECKBOX, self.checkHoldFan, self.cbHoldFan)
		self.cbHoldFan.SetValue(self.holdFan)
		self.sizerOpts2.Add(self.cbHoldFan)

		self.sizerLeft.AddSpacer((5, 5))		
		self.sizerLeft.Add(self.sizerOpts2)

		self.sizerLeft.AddSpacer((10,10))
		
		self.sizerRight.AddSpacer((40,40))

		self.gTemp = TempGraph(self, self.settings)
		self.sizerRight.Add(self.gTemp)

		self.sizerRight.AddSpacer((20, 20))
		
		self.infoPane = InfoPane(self, self.app)
		self.sizerRight.Add(self.infoPane, flag=wx.EXPAND)
		
		self.sizerMain.AddSpacer((50,50))
		self.sizerMain.Add(self.sizerLeft)
		self.sizerMain.Add(self.sizerRight)

		self.SetSizer(self.sizerMain)

		self.timer = wx.Timer(self)
		self.Bind(wx.EVT_TIMER, self.onTimer, self.timer) 
		self.secCounter = 0    
		self.openFpLog()
		self.timer.Start(1000)
		self.reprap.setHoldFan(self.holdFan)
		
		self.Bind(EVT_HTTP_PRINTMON, self.httpRequest)
		
		self.infoPane.setMode(MODE_NORMAL)
		self.setSDTargetFile(None)
Example #6
0
class App(Frame):
    def __init__(self, master=None):
        self.master = master
        Frame.__init__(self, master, relief=SUNKEN, bd=2)

        self.gcode = []
        self.slicing = False
        self.printing = False
        self.connected = False
        self.monitorTemp = False
        self.paused = False
        self.sdpresent = False
        self.sdlisting = False
        self.sdchecking = False
        self.sdprinting = False
        self.sdpaused = False
        self.sduploading = False
        self.sdbytes = 0
        self.sdmaxbytes = 0
        self.insidelisting = False
        self.readingFirmware = False
        self.sdfiles = []
        self.bedtemp = float(0)
        self.bedtarget = float(0)
        self.exttemp = float(0)
        self.exttarget = float(0)
        self.acceleration = 0
        self.m114count = 0
        self.speedcount = 0
        self.location = [0, 0, 0, 0]
        self.pausePoint = [0, 0, 0, 0]
        self.percent = 0.0
        self.ets = "??"
        self.gcodeInfo = None
        self.GCodeFile = None
        self.StlFile = None
        self.Profile = None
        self.printStartLine = 0
        self.startTime = 0
        self.endTime = 0
        self.elapsedTime = 0
        self.FanSpeed = 0
        self.FeedMultiply = 100
        self.ExtrudeMultiply = 100

        self.timingReport = None
        self.filamentReport = None
        self.measurementsReport = None

        self.macroButtons = None

        self.rpt1re = re.compile(" *T:([0-9\.]+) *E:[0-9\.]+ *B:([0-9\.]+)")
        self.rpt2re = re.compile(" *T:([0-9\.]+) *E:[0-9\.]+ *W:.*")
        self.locrptre = re.compile("^X:([0-9\.\-]+)Y:([0-9\.\-]+)Z:([0-9\.\-]+)E:([0-9\.\-]+) *Count")
        self.speedrptre = re.compile("Fan speed:([0-9]+) Feed Multiply:([0-9]+) Extrude Multiply:([0-9]+)")

        self.sdre = re.compile("SD printing byte *([0-9]+) *\/ *([0-9]+)")

        self.printer = printcore()
        self.settings = Settings()
        self.settings.cmdFolder = cmd_folder
        self.logger = Logger(self)

        if self.settings.speedcommand is not None:
            allow_while_printing.append(self.settings.speedcommand)

        self.acceleration = self.settings.acceleration

        self.dataLoggers = {}
        for d in DLLIST:
            self.dataLoggers[d] = DataLogger(self, d)

        self.skeinforge = Skeinforge(self.settings)
        self.slic3r = Slic3r(self.settings)

        self.httpServer = RepRapServer(self, self.printer, self.settings, self.logger, self.settings.port)

        self.menubar = Menu(self)
        self.filemenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="File", menu=self.filemenu)
        self.filemenu.add_command(label="Slice", command=self.openSTLFile)
        self.filemenu.add_command(label="Load GCode", command=self.openGCodeFile)
        self.slicemenuindex = self.filemenu.index("Slice")
        self.loadgcodemenuindex = self.filemenu.index("Load GCode")

        self.filemenu.add_separator()
        self.filemenu.add_command(label="Exit", command=self.quitApp)

        self.editmenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Edit", menu=self.editmenu)

        self.editmenu.add_command(label="Settings", command=self.editSettings)
        self.editmenu.add_command(label="Firmware Settings", command=self.FirmwareSettings)
        self.editmenu.add_separator()
        self.editmenu.add_command(label=GCODE_MENU_TEXT, command=self.doGEdit, state=DISABLED)

        self.slicermenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Slicer", menu=self.slicermenu)
        self.rbSlicer = StringVar()

        self.slicermenu.add_radiobutton(
            label="Skeinforge", command=self.selSlicer, value=SKEINFORGE, variable=self.rbSlicer
        )
        self.slicermenu.add_command(label="Settings", command=self.skeinforgeSettings)
        self.slicermenu.add_command(label="Choose Profile", command=self.chooseSFProfile)
        self.SFprofileindex = self.slicermenu.index("Choose Profile")
        self.setSFProfileMenuText()
        self.slicermenu.add_command(label="Alterations", command=self.doEditAlterations)

        self.slicermenu.add_separator()
        self.slicermenu.add_radiobutton(label="Slic3r", command=self.selSlicer, value=SLIC3R, variable=self.rbSlicer)
        self.slicermenu.add_command(label="Settings", command=self.slic3rSettings)
        self.slicermenu.add_command(label="Choose Profile", command=self.chooseS3Profile)
        self.S3profileindex = self.slicermenu.index("Choose Profile")
        self.setS3ProfileMenuText()

        self.rbSlicer.set(self.settings.slicer)

        self.macromenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Macros", menu=self.macromenu)
        self.macromenu.add_command(label="New", command=self.doNewMacro)
        self.macromenu.add_command(label="Edit", command=self.doEditMacro)
        self.macromenu.add_command(label="Delete", command=self.doDelMacro)
        self.macromenu.add_separator()
        self.cbShowMacroButtons = BooleanVar()
        self.cbShowMacroButtons.set(self.settings.showmacrobuttons)
        self.macromenu.add_checkbutton(
            label="Show Macro Buttons",
            command=self.doShowButtons,
            onvalue=True,
            offvalue=False,
            variable=self.cbShowMacroButtons,
        )
        self.macromenu.add_separator()
        self.runmacromenu = Menu(self.macromenu, tearoff=0)
        self.loadMacros()
        self.macromenu.add_cascade(label="Run", menu=self.runmacromenu)

        self.reportmenu = Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="View", menu=self.reportmenu)
        self.cbShowPrevious = BooleanVar()
        self.cbShowPrevious.set(self.settings.showprevious)
        self.reportmenu.add_checkbutton(
            label="Show Previous Layer",
            command=self.toggleShowPrevious,
            onvalue=True,
            offvalue=False,
            variable=self.cbShowPrevious,
        )
        self.cbShowMoves = BooleanVar()
        self.cbShowMoves.set(self.settings.showmoves)
        self.reportmenu.add_checkbutton(
            label="Show Non-extrusion Moves",
            command=self.toggleShowMoves,
            onvalue=True,
            offvalue=False,
            variable=self.cbShowMoves,
        )
        self.reportmenu.add_separator()
        self.reportmenu.add_command(label="Show Hours of Usage", command=self.doDataLogReport)
        self.reportmenu.add_command(label="Reset Hours of Usage", command=self.doDataLogReset)
        self.reportmenu.add_separator()
        self.reportmenu.add_command(label="Layer by Layer Timing", command=self.doTimingReport)
        self.reportmenu.add_command(label="Layer by Layer Filament Usage", command=self.doFilamentReport)
        self.reportmenu.add_command(label="GCode Measurements", command=self.doMeasurementsReport)

        self.toolsmenu = Menu(self.menubar, tearoff=0)
        n = 0
        if self.settings.platercmd is not None:
            n += 1
            self.toolsmenu.add_command(label="Plater", command=self.doPlater)

        if self.settings.gcodeviewcmd is not None:
            n += 1
            self.toolsmenu.add_command(label="GCode Viewer", command=self.doGCodeView)

        if self.settings.stlviewcmd is not None:
            n += 1
            self.toolsmenu.add_command(label="STL Viewer", command=self.doSTLView)

        if self.settings.openscadcmd is not None:
            n += 1
            self.toolsmenu.add_command(label="OpenSCAD", command=self.doOpenSCAD)

        if n > 0:
            self.menubar.add_cascade(label="Tools", menu=self.toolsmenu)

        try:
            self.master.config(menu=self.menubar)
        except AttributeError:
            self.master.tk.call(master, "config", "-menu", self.menubar)

        self.toolbar = ToolBar(self, self.printer, self.settings, self.logger)
        self.toolbar.grid(row=1, column=1, columnspan=4, sticky=W)

        self.ctl = MoveControl(self, self.printer, self.settings, self.logger)
        self.ctl.grid(row=2, column=1, rowspan=3, sticky=N)

        self.extr = Extruder(self, self.printer, self.settings, self.logger)
        self.extr.grid(row=2, column=2, rowspan=1, sticky=N + E + W)

        self.temps = Temperatures(self, self.printer, self.settings, self.logger)
        self.temps.grid(row=3, column=2, rowspan=2, sticky=N + E + W)

        self.gc = GcFrame(self, None, [], self.settings, self.logger)
        self.gc.grid(row=2, column=3, rowspan=3, sticky=N)

        self.statline = Status(self, self.printer, self.settings, self.logger)
        self.statline.grid(row=5, column=1, columnspan=4, sticky=E + W)

        self.logger.grid(row=2, column=4, rowspan=2, sticky=N + E + W)

        self.sendgcode = SendGCode(self, self.printer, self.settings, self.logger)
        self.sendgcode.grid(row=4, column=4, sticky=N + E + W)

        self.printer.errorcb = self.errorcb
        self.printer.sendcb = self.sendcb
        self.printer.recvcb = self.recvcb

        self.sd = SDCard(self, self.printer, self.settings, self.logger)
        self.firmware = FirmwareParms(self, self.printer, self.settings, self.logger)
        self.bind(MWM_FIRMWARECOMPLETE, self.firmwareReportComplete)
        self.bind(MWM_SLICERCOMPLETE, self.sliceComplete)
        self.bind(MWM_GCODELOADCOMPLETE, self.loadgcodeFinished)
        self.bind(MWM_GEDITMEASURECOMPLETE, self.geditMeasureComplete)
        self.bind(MWM_REQUESTPOSITIONREPORT, self.requestPosition)

        self.doShowButtons()

    def doStopAll(self):
        self.toolbar.doPause()
        self.temps.doOffBed()
        self.temps.doOffExt()

    def requestPosition(self, *arg):
        self.m114count += 1
        self.printer.send_now("M400")  # finish all moves
        self.printer.send_now("M114")

    def doShowButtons(self):
        self.settings.showmacrobuttons = self.cbShowMacroButtons.get() == 1
        self.settings.setModified()
        if self.settings.showmacrobuttons:
            self.macroButtons = MacroButtons(self, self.printer, self.settings, self.logger)
        else:
            if self.macroButtons:
                self.macroButtons.close()
                self.macroButtons = None

    def toggleShowPrevious(self):
        self.settings.showprevious = self.cbShowPrevious.get() == 1
        self.settings.setModified()
        self.gc.drawCanvas()

    def toggleShowMoves(self):
        self.settings.showmoves = self.cbShowMoves.get() == 1
        self.settings.setModified()
        self.gc.drawCanvas()

    def selSlicer(self):
        self.settings.slicer = self.rbSlicer.get()
        self.settings.setModified()
        self.toolbar.setSliceText()

    def macroButtonClose(self):
        self.settings.showmacrobuttons = False
        self.settings.setModified()
        self.cbShowMacroButtons.set(False)

    def firmwareReportComplete(self, *arg):
        p = self.firmware.reportComplete()
        if p is not None:
            self.acceleration = p["m204_s"].getFlash()
            print "Retrieved acc value of ", self.acceleration

    def openSTLFile(self):
        if self.printing:
            self.logger.logMsg("Cannot open a new file while printing")
            return

        if self.StlFile is None:
            fn = askopenfilename(
                filetypes=[("STL files", "*.stl"), ("G Code files", "*.gcode")], initialdir=self.settings.lastdirectory
            )
        else:
            fn = askopenfilename(
                filetypes=[("STL files", "*.stl"), ("G Code files", "*.gcode")],
                initialdir=self.settings.lastdirectory,
                initialfile=os.path.basename(self.StlFile),
            )
        if fn:
            self.settings.lastdirectory = os.path.dirname(os.path.abspath(fn))
            self.settings.setModified()
            if fn.lower().endswith(".gcode"):
                self.StlFile = None
                self.loadgcode(fn)
            elif fn.lower().endswith(".stl"):
                self.StlFile = fn
                self.doSlice(fn)
            else:
                self.logger.logMsg("Invalid file type")

    def openGCodeFile(self):
        if self.printing:
            self.logger.logMsg("Cannot open a new file while printing")
            return

        fn = askopenfilename(filetypes=[("G Code files", "*.gcode")], initialdir=self.settings.lastdirectory)
        if fn:
            self.settings.lastdirectory = os.path.dirname(os.path.abspath(fn))
            self.settings.setModified()
            if fn.lower().endswith(".gcode"):
                self.StlFile = None
                self.loadgcode(fn)
            else:
                self.logger.logMsg("Invalid file type")
        else:
            self.toolbar.clearCancelMode()

    def loadgcode(self, fn):
        self.GCodeFile = fn
        self.gcodeloadSuccess = True
        self.toolbar.setLoading(True)
        self.loader = threading.Thread(target=self.loadgcodeThread)
        self.loader.daemon = True
        self.loader.start()

    def loadgcodeFinished(self, *arg):
        self.toolbar.setLoading(False)
        if self.gcodeloadSuccess:
            self.showMetrics()

    def loadgcodeThread(self):
        try:
            self.gcode = []
            l = list(open(self.GCodeFile))
            for s in l:
                self.gcode.append(s.rstrip())
            self.logger.logMsg("read %d lines from %s" % (len(self.gcode), os.path.basename(self.GCodeFile)))
        except:
            self.logger.logMsg("Problem reading gcode from %s" % self.GCodeFile)
            self.gcode = []
            self.GCodeFile = None

        if len(self.gcode) != 0:
            self.logger.logMsg("Processing...")
            self.gc.loadFile(self.GCodeFile, self.gcode)
            self.printStartLine = self.gc.getPrintStartLine()
            self.gcodeInfo = GCode(self.gcode)
            self.logger.logMsg("Measuring...")
            self.gcodeInfo.measure(self.acceleration)
            self.estEta = self.gcodeInfo.totalduration
            self.timeLayers = self.gcodeInfo.layerdurations
        else:
            self.gcodeloadSuccess = False

        self.event_generate(MWM_GCODELOADCOMPLETE)

    def replace(self, s, slicer):
        if slicer == SLIC3R:
            d = os.path.expandvars(os.path.expanduser(self.settings.s3profiledir))
            profile = os.path.join(d, self.slic3r.getProfile() + ".ini")
        else:
            profile = self.skeinforge.getProfile()

        d = {}

        d["%starttime%"] = time.strftime("%H:%M:%S", time.localtime(self.startTime))
        d["%endtime%"] = time.strftime("%H:%M:%S", time.localtime(self.endTime))
        d["%elapsed%"] = formatElapsed(self.elapsedTime)

        d["%profile%"] = profile
        d["%slicer%"] = self.settings.slicer

        if self.StlFile is not None:
            d["%stlbase%"] = os.path.basename(self.StlFile)
            d["%stl%"] = self.StlFile
        else:
            d["%stlbase%"] = ""
            d["%stl%"] = ""

        if self.GCodeFile is not None:
            d["%gcodebase%"] = os.path.basename(self.GCodeFile)
            d["%gcode%"] = self.GCodeFile
        else:
            d["%gcodebase%"] = ""
            d["%gcode%"] = ""

        for t in d.keys():
            if d[t] is not None:
                s = s.replace(t, d[t])

        s = s.replace('""', "")
        return s

    def showMetrics(self):
        if len(self.gcode) != 0:
            self.paused = False
            self.toolbar.initializeToolbar()
            self.toolbar.checkAllowPrint()
            self.allowGEdit()

            self.logger.logMsg(
                "Width: %f mm (%f -> %f)" % (self.gcodeInfo.width, self.gcodeInfo.xmin, self.gcodeInfo.xmax)
            )
            self.logger.logMsg(
                "Depth: %f mm (%f -> %f)" % (self.gcodeInfo.depth, self.gcodeInfo.ymin, self.gcodeInfo.ymax)
            )
            self.logger.logMsg(
                "Height: is %f mm (%f -> %f)" % (self.gcodeInfo.height, self.gcodeInfo.zmin, self.gcodeInfo.zmax)
            )
            self.logger.logMsg("Total extrusion length: %f mm" % self.gcodeInfo.filament_length())

            self.logger.logMsg("Estimated print time: %s" % formatElapsed(self.estEta))

    def calcEta(self, line, timeThusFar):
        foundLayer = False
        for i in range(len(self.timeLayers)):
            if self.timeLayers[i][0] > line:
                foundLayer = True
                break

        if not foundLayer:
            return 0

        currentLayer = i - 1
        if currentLayer < 0:
            return 0

        totalInLayer = self.timeLayers[i][0] - self.timeLayers[currentLayer][0]
        printedInLayer = line - self.timeLayers[currentLayer][0]
        pct = printedInLayer / float(totalInLayer)
        thisLayerTime = (self.timeLayers[currentLayer][1]) * pct
        ratio = (self.timeLayers[currentLayer][2] - self.timeLayers[currentLayer][1] + thisLayerTime) / float(
            timeThusFar
        )
        ne = self.estEta / float(ratio)
        return ne - timeThusFar

    def doTimingReport(self):
        if not self.printing:
            self.logger.logMsg("Only available while printing")
            return

        self.timingReport = TimingReport(self, self.printer, self.settings, self.logger)

    def closeTimingReport(self):
        if self.timingReport is not None:
            self.timingReport.cleanup()
            self.timingReport.destroy()

        self.timingReport = None

    def doMeasurementsReport(self):
        if not self.gcodeInfo:
            self.logger.logMsg("Only available when GCode loaded")
            return

        self.measurementsReport = MeasurementsReport(self, self.printer, self.settings, self.logger)

    def closeMeasurementsReport(self):
        if self.measurementsReport is not None:
            self.measurementsReport.destroy()

        self.measurementsReport = None

    def doFilamentReport(self):
        if not self.gcodeInfo:
            self.logger.logMsg("Only available when GCode loaded")
            return
        if len(self.gcodeInfo.filLayers) == 0:
            self.logger.logMsg("No filament usage in this gcode")
            return

        self.filamentReport = FilamentReport(self, self.printer, self.settings, self.logger)

    def closeFilamentReport(self):
        if self.filamentReport is not None:
            self.filamentReport.destroy()

        self.filamentReport = None

    def closeAllReports(self):
        self.closeTimingReport()
        self.closeFilamentReport()
        self.closeMeasurementsReport()

    def doPlater(self):
        s = self.replace(self.settings.platercmd, self.settings.slicer)
        args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
        subprocess.Popen(args, close_fds=True)

    def doGCodeView(self):
        s = self.replace(self.settings.gcodeviewcmd, self.settings.slicer)
        args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
        subprocess.Popen(args, close_fds=True)

    def doSTLView(self):
        s = self.replace(self.settings.stlviewcmd, self.settings.slicer)
        self.logger.logMsg(s)
        args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
        subprocess.Popen(args, close_fds=True)

    def doOpenSCAD(self):
        s = self.replace(self.settings.openscadcmd, self.settings.slicer)
        args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
        subprocess.Popen(args, close_fds=True)

    def doSlice(self, fn):
        self.paused = False
        self.toolbar.initializeToolbar()
        self.slicerfn = fn
        self.slicing = True
        self.slicerCancel = False
        self.toolbar.setCancelMode()
        if self.settings.slicer == SLIC3R:
            self.GCodeFile = fn.replace(".stl", ".gcode")
            cmd = self.replace(os.path.expandvars(os.path.expanduser(self.settings.s3cmd)), SLIC3R)
        else:
            self.GCodeFile = fn.replace(".stl", "_export.gcode")
            cmd = self.replace(os.path.expandvars(os.path.expanduser(self.settings.sfcmd)), SKEINFORGE)
        self.slicer = threading.Thread(target=self.slicerThread, args=(cmd,))
        self.slicer.daemon = True
        self.slicer.start()

    def slicerThread(self, cmd):
        args = shlex.split(cmd)
        p = subprocess.Popen(args, stderr=subprocess.STDOUT, stdout=subprocess.PIPE)
        obuf = ""
        while not self.slicerCancel:
            o = p.stdout.read(1)
            if o == "":
                break
            if o == "\r" or o == "\n":
                self.logger.logMsg(obuf)
                obuf = ""
            elif ord(o) < 32:
                pass
            else:
                obuf += o

        if self.slicerCancel:
            p.kill()

        p.wait()
        self.event_generate(MWM_SLICERCOMPLETE)

    def sliceComplete(self, *arg):
        self.slicing = False
        self.toolbar.clearCancelMode()
        if self.slicerCancel:
            self.slicerCancel = False
            self.logger.logMsg("Slicing was cancelled")
            return

        self.logger.logMsg("Slicing has completed successfully")
        if os.path.exists(self.GCodeFile):
            self.loadgcode(self.GCodeFile)
        else:
            self.logger.logMsg("Unable to find slicer output file: %s" % self.GCodeFile)

    def allowGEdit(self):
        self.editmenu.entryconfig(self.editmenu.index(GCODE_MENU_TEXT), state=NORMAL)

    def allowSliceMenu(self, flag=True):
        s = NORMAL
        if not flag:
            s = DISABLED
        self.filemenu.entryconfig(self.slicemenuindex, state=s)

    def allowLoadGCodeMenu(self, flag=True):
        s = NORMAL
        if not flag:
            s = DISABLED
        self.filemenu.entryconfig(self.loadgcodemenuindex, state=s)

    def doGEdit(self):
        GEditor(self, self.gcode, None)

    def geditMeasureComplete(self, *arg):
        self.showMetrics()

    def gEditSave(self, newgcode, fn, editwindow):
        if fn == None:
            self.gcode = newgcode
            self.meas = threading.Thread(target=self.geditMeasureThread)
            self.meas.daemon = True
            self.meas.start()
            return False
        else:
            try:
                f = open(fn, "w")
                for l in newgcode:
                    f.write(l + "\n")
                f.close()
                self.logger.logMsg("Alterations %s successfully saved" % fn)
                return True
            except:
                self.logger.logMsg("Unable to open %s for output" % fn)
                return False

    def geditMeasureThread(self):
        self.logger.logMsg("Processing...")
        self.gcodeInfo = GCode(self.gcode)
        self.logger.logMsg("Measuring...")
        self.gcodeInfo.measure(self.acceleration)
        self.estEta = self.gcodeInfo.totalduration
        self.timeLayers = self.gcodeInfo.layerdurations
        self.event_generate(MWM_GEDITMEASURECOMPLETE)

    def doSD(self):
        if not self.sd.isActive():
            self.sd.start()

    def setToolbarSDPrint(self):
        self.toolbar.setSDPrint()

    def startUpload(self):
        self.sduploading = True
        self.toolbar.doPrint()

    def printerAvailable(self, silent=False, cmd="xx"):
        if not self.connected:
            if not silent:
                self.logger.logMsg("Unable to comply - printer not on-line")
            return False
        if (self.printing or self.sdprinting) and cmd.upper() not in allow_while_printing:
            if not silent:
                self.logger.logMsg("Unable to comply - currently printing")
            return False

        return True

    def printerConnected(self, flag):
        self.sendgcode.activate(flag)
        self.connected = flag
        if flag:
            self.firmware.start(True)

    def updateScreen(self):
        if self.printing:
            self.gc.updatePrintProgress(self.printer.queueindex)

    def errorcb(self, s):
        self.logger.logMsg(s.rstrip())

    def sendcb(self, s):
        # self.logger.logMsg("Sent: %s" % s)
        pass

    def recvcb(self, s):
        if self.readingFirmware:
            if "M92" in s:
                X = self.parseG(s, "X")
                Y = self.parseG(s, "Y")
                Z = self.parseG(s, "Z")
                E = self.parseG(s, "E")
                self.firmware.m92(X, Y, Z, E)
                return
            elif "M201" in s:
                X = self.parseG(s, "X")
                Y = self.parseG(s, "Y")
                Z = self.parseG(s, "Z")
                E = self.parseG(s, "E")
                self.firmware.m201(X, Y, Z, E)
                return
            elif "M203" in s:
                X = self.parseG(s, "X")
                Y = self.parseG(s, "Y")
                Z = self.parseG(s, "Z")
                E = self.parseG(s, "E")
                self.firmware.m203(X, Y, Z, E)
                return
            elif "M204" in s:
                S = self.parseG(s, "S")
                T = self.parseG(s, "T")
                self.firmware.m204(S, T)
                return
            elif "M205" in s:
                S = self.parseG(s, "S")
                T = self.parseG(s, "T")
                B = self.parseG(s, "B")
                X = self.parseG(s, "X")
                Z = self.parseG(s, "Z")
                E = self.parseG(s, "E")
                self.firmware.m205(S, T, B, X, Z, E)
                return
            elif "M206" in s:
                X = self.parseG(s, "X")
                Y = self.parseG(s, "Y")
                Z = self.parseG(s, "Z")
                self.firmware.m206(X, Y, Z)
                return
            elif "M301" in s:
                P = self.parseG(s, "P")
                I = self.parseG(s, "I")
                D = self.parseG(s, "D")
                self.firmware.m301(P, I, D)
                return
            elif (
                ("Steps per unit" in s)
                or ("Acceleration:" in s)
                or ("Maximum Acceleration" in s)
                or ("Maximum feedrates" in s)
                or ("Advanced variables" in s)
                or ("Home offset" in s)
                or ("PID settings" in s)
                or ("Stored settings retreived" in s)
            ):
                return

        if self.sdchecking:
            if "SD card ok" in s:
                self.sdchecking = False
                self.sdpresent = True
                self.sd.sdCheckComplete(True)
                return
            elif "SD init fail" in s:
                self.sdchecking = False
                self.sdpresent = False
                self.sd.sdCheckComplete(False)
                return

        if self.sdlisting:
            if "Begin file list" in s:
                self.insidelisting = True
                self.sdfiles = []
                return
            elif "End file list" in s:
                self.sdlisting = False
                self.insidelisting = False
                self.sd.sdListComplete(self.sdfiles)
                return
            else:
                if self.insidelisting:
                    self.sdfiles.append(s.strip())
                    return

        if "SD printing byte" in s:
            m = self.sdre.search(s)
            t = m.groups()
            if len(t) != 2:
                return

            self.sdbytes = int(t[0])
            self.sdmaxbytes = int(t[1])
            return

        elif "Done printing file" in s:
            if self.sdprinting:
                self.sdprinting = False
                self.toolbar.clearSDPrint()

        m = self.speedrptre.search(s)
        if m:
            t = m.groups()
            if len(t) >= 3:
                if self.settings.forcefanspeed:
                    ns = int(t[0])
                    if ns != self.FanSpeed:
                        self.logger.logMsg("Asserting fan speed of %d" % self.FanSpeed)
                        self.toolbar.forceFanSpeed(self.FanSpeed)
                else:
                    self.FanSpeed = int(t[0])

                self.FeedMultiply = int(t[1])
                self.ExtrudeMultiply = int(t[2])
                self.toolbar.syncSpeeds()
                if self.speedcount > 0:
                    self.speedcount -= 1
                    return

        m = self.locrptre.search(s)
        if m:
            t = m.groups()
            if len(t) >= 4:
                self.location[XAxis] = float(t[0])
                self.location[YAxis] = float(t[1])
                self.location[ZAxis] = float(t[2])
                self.location[EAxis] = float(t[3])
                if self.m114count != 0:
                    self.m114count -= 1
                    if self.m114count < 0:
                        self.m114count = 0
                    return

        if s.startswith("ok"):
            return

        if s.startswith("echo:"):
            s = s[5:]

        m = self.rpt1re.search(s)
        if m:
            t = m.groups()
            if len(t) >= 1:
                self.exttemp = float(t[0])
            if len(t) >= 2:
                self.bedtemp = float(t[1])
            self.temps.updateTempDisplay(self.bedtemp, self.exttemp)

        m = self.rpt2re.search(s)
        if m:
            t = m.groups()
            if len(t) >= 1:
                self.exttemp = float(t[0])
            self.temps.updateTempDisplay(self.bedtemp, self.exttemp)

        self.logger.logMsg(s.rstrip())

    def parseG(self, s, v):
        l = s.split()
        for p in l:
            if p.startswith(v):
                try:
                    return float(p[1:])
                except:
                    return None
        return None

    def editSettings(self):
        # TO DO
        pass

    def slic3rSettings(self):
        s = self.replace(self.settings.s3config, SLIC3R)
        args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
        subprocess.Popen(args, close_fds=True)

    def skeinforgeSettings(self):
        s = self.replace(self.settings.sfconfig, SKEINFORGE)
        args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
        subprocess.Popen(args, close_fds=True)

    def chooseS3Profile(self):
        pl = self.slic3r.getProfileOptions()
        if len(pl) > 0:
            l = ListBoxChoice(
                clist=pl.keys(), master=self, title="Choose Slic3r Profile", message="Choose Slic3r profile"
            )
            pn = l.returnValue()
            if pn:
                self.slic3r.setProfile(pn)
                self.setS3ProfileMenuText()
                self.toolbar.setSliceText()
        else:
            self.logger.logMsg("Unable to retrieve available slic3r profiles")

    def chooseSFProfile(self):
        pl = self.skeinforge.getProfileOptions()
        if len(pl) > 0:
            l = ListBoxChoice(
                clist=pl.keys(), master=self, title="Choose Skeinforge Profile", message="Choose Skeinforge profile"
            )
            pn = l.returnValue()
            if pn:
                self.skeinforge.setProfile(pn)
                self.setSFProfileMenuText()
                self.toolbar.setSliceText()
        else:
            self.logger.logMsg("Unable to retrieve available skeinforge profiles")

    def setS3ProfileMenuText(self):
        self.slicermenu.entryconfig(self.S3profileindex, label="Choose Profile (%s)" % self.slic3r.getProfile())

    def setSFProfileMenuText(self):
        self.slicermenu.entryconfig(self.SFprofileindex, label="Choose Profile (%s)" % self.skeinforge.getProfile())

    def quitApp(self):
        self.cleanUp()
        self.master.quit()

    def cleanUp(self):
        if self.connected:
            self.printer.disconnect()
        if self.slicing:
            self.slicerCancel = True
        self.httpServer.close()
        self.statline.cleanUp()
        self.settings.cleanUp()

    def doEditMacro(self):
        idir = os.path.join(self.settings.cmdFolder, "macros")
        try:
            l = os.listdir(idir)
        except:
            self.logger.logMsg("Unable to get listing from macros directory: " + idir)
            return
        r = []
        for f in sorted(l):
            if f.endswith(".macro"):
                r.append(f)

        l = ListBoxChoice(master=self, title="Macro Files", message="Choose a macro to edit", clist=r)
        fn = l.returnValue()
        if fn:
            try:
                fn = os.path.join(idir, fn)
                with open(fn) as f:
                    text = f.read()
                self.macroEdit = MacroEdit(self, self.printer, self.settings, self.logger, fn, text)
            except:
                self.logger.logMsg("Unable to open %s for input" % fn)

    def doEditAlterations(self):
        idir = os.path.expandvars(os.path.expanduser(self.settings.sfalterationsdir))
        try:
            l = os.listdir(idir)
        except:
            self.logger.logMsg("Unable to get listing from alterations directory: " + idir)
            return
        r = []
        for f in sorted(l):
            if f.endswith(".gcode"):
                r.append(f)

        l = ListBoxChoice(master=self, title="Alteration Files", message="Choose an alteration file to edit", clist=r)
        fn = l.returnValue()
        if fn:
            try:
                fn = os.path.join(idir, fn)
                text = [line.strip() for line in open(fn)]
                GEditor(self, text, fn)
            except:
                self.logger.logMsg("Unable to open %s for input" % fn)

    def doNewMacro(self):
        self.macroEdit = MacroEdit(self, self.printer, self.settings, self.logger, None, "")

    def doDelMacro(self):
        idir = os.path.join(self.settings.cmdFolder, "macros")
        try:
            l = os.listdir(idir)
        except:
            self.logger.logMsg("Unable to get listing from macros directory: " + idir)
            return
        r = []
        for f in sorted(l):
            if f.endswith(".macro"):
                r.append(f)

        l = ListBoxChoice(master=self, title="Macro Files", message="Choose a macro to delete", clist=r)
        fn = l.returnValue()
        if fn:
            if askyesno("Delete?", "Are you sure you want to delete this macro?", parent=self):
                try:
                    os.unlink(os.path.join(idir, fn))
                    self.adjustMacroMenu(fn, True)
                    if self.settings.getMacroList().delMacroByName(fn):
                        self.settings.setModified()
                        if self.settings.showmacrobuttons:
                            self.macroButtons.close()
                            self.macroButtons = MacroButtons(self, self.printer, self.settings, self.logger)
                except:
                    self.logger.logMsg("Unable to delete %s" % fn)

    def macroEditSave(self, fn, text, btn, editwindow):
        if fn == None:
            idir = os.path.join(self.settings.cmdFolder, "macros")

            try:
                l = os.listdir(idir)
            except:
                self.logger.logMsg("Unable to get listing from macros directory: " + idir)
                return

            r = []
            for f in sorted(l):
                if f.endswith(".macro"):
                    r.append(f)

            l = ListBoxChoice(
                master=self,
                title="Macro Files",
                message="Choose a macro to overwrite",
                clist=r,
                newmessage="or enter new file name:",
            )
            fn = l.returnValue()
            if fn:
                fn = os.path.join(idir, fn)
                if not fn.endswith(".macro"):
                    fn += ".macro"

        if fn is None:
            return False

        try:
            f = open(fn, "w")
            f.write(text)
            f.close()
            self.settings.setModified()
            if btn != None:
                if not self.settings.getMacroList().addMacro(btn[0], btn[1], os.path.basename(fn), btn[2]):
                    self.settings.getMacroList().setMacroByName(btn[0], btn[1], os.path.basename(fn), btn[2])
                self.settings.setModified()

                if self.settings.showmacrobuttons:
                    self.macroButtons.close()
                    self.macroButtons = MacroButtons(self, self.printer, self.settings, self.logger)

            self.adjustMacroMenu(fn)
            self.logger.logMsg("Macro %s successfully saved" % fn)
            return True
        except:
            self.logger.logMsg("Unable to open %s for output" % fn)
            return False

    def macroEditExit(self, fn):
        pass

    def loadMacros(self):
        p = os.path.join(".", "macros")
        if not os.path.exists(p):
            os.makedirs(p)

        self.macroList = {}
        for filename in sorted(os.listdir(p)):
            if filename.endswith(".macro"):
                n = os.path.splitext(filename)[0]
                self.macroList[n] = 1
                self.runmacromenu.add_command(label=n, command=lambda m=n: self.doMacro(m))

    def adjustMacroMenu(self, fn, delete=False):
        mn = os.path.splitext(os.path.basename(fn))[0]

        if not delete:
            if mn in self.macroList:
                # nothing to be done here
                pass
            else:
                self.macroList[mn] = 1
                self.runmacromenu.add_command(label=mn, command=lambda m=mn: self.doMacro(name=mn))
        else:
            # delete the menu entry
            if mn in self.macroList:
                self.runmacromenu.delete(self.runmacromenu.index(mn))
                del self.macroList[mn]
            else:
                # huh??
                pass

    def doMacro(self, name=None, fname=None, silent=False):
        if name:
            if not silent:
                self.logger.logMsg("Invoking macro: %s" % name)
            n = os.path.join(self.settings.cmdFolder, "macros", name + ".macro")
        elif fname:
            if not silent:
                self.logger.logMsg("Invoking macro file: %s" % fname)
            n = os.path.join(self.settings.cmdFolder, "macros", fname)
        else:
            self.logger.logMsg("Error - must provide a macro name or filename")
            return

        try:
            l = list(open(n))
            for s in l:
                sl = s.lower()
                if sl.startswith("@log "):
                    self.logger.logMsg(self.replace(s[5:].strip(), self.settings.slicer))
                elif sl.startswith("@sh "):
                    s = self.replace(sl[4:], self.settings.slicer)
                    args = shlex.split(os.path.expandvars(os.path.expanduser(s)))
                    subprocess.Popen(args, close_fds=True)
                else:
                    verb = s.split()[0]
                    if self.printerAvailable(cmd=verb):
                        self.printer.send_now(s)
                    else:
                        self.logger.logMsg("Printer not available for %s command" % verb)

            if not silent:
                self.logger.logMsg("End of macro")
        except:
            self.logger.logMsg("Error attempting to invoke macro file %s" % n)

    def FirmwareSettings(self):
        if self.connected:
            if not self.firmware.isActive():
                self.firmware.start()
        else:
            self.logger.logMsg("Unable to comply - printer not on-line")

    def doDataLogReport(self):
        for d in DLLIST:
            self.logger.logMsg("%s Usage: %s" % (DLNAMES[d], self.dataLoggers[d].getToNowStr()))

    def doDataLogReset(self):
        DataLogReset(self)
Example #7
0
class PrintMonitor(wx.Panel):
	def __init__(self, parent, app, prtname, reprap, history):
		self.model = None
		self.cfgString = None
		self.app = app
		self.prtsettings = self.app.settings.printersettings[prtname]
		self.buildarea = self.prtsettings.buildarea
		self.prtname = prtname
		self.history = history
		self.reprap = reprap
		self.manctl = None
		self.hassd = self.prtsettings.hassdcard
		self.filamentdiameter = self.prtsettings.filamentdiam
		self.sliceTime = ""

		self.M105pending = False
		self.M27pending = False
		self.suspendM105 = False
		self.cycle = 0
		self.skipCycles = 5
		self.logger = self.app.logger
		self.printPos = 0
		self.printing = False
		self.paused = False
		self.sdpaused = False
		self.sdprintingfrom = False
		self.settings = app.settings.printmon
		wx.Panel.__init__(self, parent, wx.ID_ANY, size=(100, 100))
		self.SetBackgroundColour("white")
		self.knownHeaters = ['HE0', 'HE1', 'HE2', 'Bed']
		self.targets = {}
		self.temps = {}
		self.tempData = {}
		for h in self.knownHeaters:
			self.temps[h] = None
			self.targets[h] = 0
			self.tempData[h] = []
		self.startTime = None
		self.endTime = None
		self.gcFile = None
		self.printMode = None
		self.origEta = None
		self.countGLines = None
		self.syncPrint = True
		self.holdFan = False
		self.setStatus(PMSTATUS_NOT_READY)
				
		self.sdcard = SDCard(self.app, self, self.reprap, self.logger)
		
		self.M27Timer = wx.Timer(self)
		self.Bind(wx.EVT_TIMER, self.onM27Timer, self.M27Timer)
		self.printingfrom = False

		self.sizerMain = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerLeft = wx.BoxSizer(wx.VERTICAL)
		self.sizerRight = wx.BoxSizer(wx.VERTICAL)
		self.sizerLeft.AddSpacer((10,10))
		
		self.sizerBtns = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerBtns.AddSpacer((10,10))

		self.images = Images(os.path.join(self.settings.cmdfolder, "images"))		
		
		self.bPull = wx.BitmapButton(self, wx.ID_ANY, self.images.pngPull, size=BUTTONDIMWIDE)
		self.sizerBtns.Add(self.bPull)
		self.bPull.SetToolTipString("Pull model from file preparation")
		self.Bind(wx.EVT_BUTTON, self.doPull, self.bPull)
		self.bPull.Enable(self.app.currentPullStatus())
		
		self.sizerBtns.AddSpacer((20, 20))
		
		self.bPrint = wx.BitmapButton(self, wx.ID_ANY, self.images.pngPrint, size=BUTTONDIM)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.sizerBtns.Add(self.bPrint)
		self.Bind(wx.EVT_BUTTON, self.doPrint, self.bPrint)
		self.bPrint.Enable(False)
		
		self.bPause = wx.BitmapButton(self, wx.ID_ANY, self.images.pngPause, size=BUTTONDIM)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.sizerBtns.Add(self.bPause)
		self.Bind(wx.EVT_BUTTON, self.doPause, self.bPause)
		self.bPause.Enable(False)

		self.sizerBtns.AddSpacer(BUTTONDIM)
		
		if self.hassd:
			self.bSDPrintFrom = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSdprintfrom, size=BUTTONDIMWIDE)
			self.bSDPrintFrom.SetToolTipString("Print from SD Card")
			self.sizerBtns.Add(self.bSDPrintFrom)
			self.Bind(wx.EVT_BUTTON, self.doSDPrintFrom, self.bSDPrintFrom)
			self.bSDPrintFrom.Enable(True)
			
			self.bSDPrintTo = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSdprintto, size=BUTTONDIMWIDE)
			self.bSDPrintTo.SetToolTipString("Print to SD Card")
			self.sizerBtns.Add(self.bSDPrintTo)
			self.Bind(wx.EVT_BUTTON, self.doSDPrintTo, self.bSDPrintTo)
			self.bSDPrintTo.Enable(False)
			
			self.bSDDelete = wx.BitmapButton(self, wx.ID_ANY, self.images.pngSddelete, size=BUTTONDIM)
			self.bSDDelete.SetToolTipString("Delete a file from SD Card")
			self.sizerBtns.Add(self.bSDDelete)
			self.Bind(wx.EVT_BUTTON, self.doSDDelete, self.bSDDelete)
			self.bSDDelete.Enable(True)
			
			self.sizerBtns.AddSpacer(BUTTONDIM)
	
		self.bZoomIn = wx.BitmapButton(self, wx.ID_ANY, self.images.pngZoomin, size=BUTTONDIM)
		self.bZoomIn.SetToolTipString("Zoom the view in")
		self.sizerBtns.Add(self.bZoomIn)
		self.Bind(wx.EVT_BUTTON, self.viewZoomIn, self.bZoomIn)
		
		self.bZoomOut = wx.BitmapButton(self, wx.ID_ANY, self.images.pngZoomout, size=BUTTONDIM)
		self.bZoomOut.SetToolTipString("Zoom the view out")
		self.sizerBtns.Add(self.bZoomOut)
		self.Bind(wx.EVT_BUTTON, self.viewZoomOut, self.bZoomOut)

		self.sizerLeft.Add(self.sizerBtns)
		self.sizerLeft.AddSpacer((10,10))
		
		self.sizerGCM = wx.BoxSizer(wx.HORIZONTAL)

		self.gcf = GcmFrame(self, self.model, self.settings, self.buildarea)
		self.sizerGCM.Add(self.gcf)
		
		sz = self.buildarea[1] * self.settings.gcodescale
		
		self.slideLayer = wx.Slider(
			self, wx.ID_ANY, 1, 1, 9999, size=(150, sz),
			style = wx.SL_VERTICAL | wx.SL_AUTOTICKS | wx.SL_LABELS)
		self.slideLayer.Bind(wx.EVT_SCROLL, self.onSpinLayer)
		self.slideLayer.SetRange(1, 10)
		self.slideLayer.SetValue(1)
		self.slideLayer.SetPageSize(1);
		self.slideLayer.Disable()
		self.sizerGCM.Add(self.slideLayer)
		
		self.sizerLeft.Add(self.sizerGCM)

		self.sizerLeft.AddSpacer((10,10))

		self.sizerOpts = wx.BoxSizer(wx.HORIZONTAL)
				
		self.cbPrevious = wx.CheckBox(self, wx.ID_ANY, "Show Previous Layer")
		self.cbPrevious.SetToolTipString("Turn on/off drawing of the previous layer in the background")
		self.Bind(wx.EVT_CHECKBOX, self.checkPrevious, self.cbPrevious)
		self.cbPrevious.SetValue(self.settings.showprevious)
		self.sizerOpts.Add(self.cbPrevious)
		
		self.sizerOpts.AddSpacer((10, 10))

		self.cbMoves = wx.CheckBox(self, wx.ID_ANY, "Show Moves")
		self.cbMoves.SetToolTipString("Turn on/off the drawing of non-extrusion moves")
		self.Bind(wx.EVT_CHECKBOX, self.checkMoves, self.cbMoves)
		self.cbMoves.SetValue(self.settings.showmoves)
		self.sizerOpts.Add(self.cbMoves)
		
		self.sizerOpts.AddSpacer((10, 10))
		
		self.cbToolOnly = wx.CheckBox(self, wx.ID_ANY, "Tool Path Only")
		self.cbToolOnly.SetToolTipString("Show narrow lines indicating tool path")
		self.Bind(wx.EVT_CHECKBOX, self.checkToolPathsOnly, self.cbToolOnly)
		self.cbToolOnly.SetValue(self.settings.toolpathsonly)
		self.sizerOpts.Add(self.cbToolOnly)
		
		self.sizerOpts.AddSpacer((10, 10))

		self.cbSync = wx.CheckBox(self, wx.ID_ANY, "Sync with print")
		self.Bind(wx.EVT_CHECKBOX, self.checkSync, self.cbSync)
		self.cbSync.SetValue(True)
		self.sizerOpts.Add(self.cbSync)

		self.sizerLeft.AddSpacer((5, 5))		
		self.sizerLeft.Add(self.sizerOpts)

		self.sizerOpts2 = wx.BoxSizer(wx.HORIZONTAL)

		self.cbBuffDC = wx.CheckBox(self, wx.ID_ANY, "Use Buffered DC")
		self.Bind(wx.EVT_CHECKBOX, self.checkBuffDC, self.cbBuffDC)
		self.cbBuffDC.SetValue(self.settings.usebuffereddc)
		self.sizerOpts2.Add(self.cbBuffDC)
		
		self.sizerOpts2.AddSpacer((10, 10))
		
		self.cbHoldFan = wx.CheckBox(self, wx.ID_ANY, "Hold Fan Speed")
		self.cbHoldFan.SetToolTipString("Maintain fan speed at its manual setting")
		self.Bind(wx.EVT_CHECKBOX, self.checkHoldFan, self.cbHoldFan)
		self.cbHoldFan.SetValue(self.holdFan)
		self.sizerOpts2.Add(self.cbHoldFan)

		self.sizerLeft.AddSpacer((5, 5))		
		self.sizerLeft.Add(self.sizerOpts2)

		self.sizerLeft.AddSpacer((10,10))
		
		self.sizerRight.AddSpacer((40,40))

		self.gTemp = TempGraph(self, self.settings)
		self.sizerRight.Add(self.gTemp)

		self.sizerRight.AddSpacer((20, 20))
		
		self.infoPane = InfoPane(self, self.app)
		self.sizerRight.Add(self.infoPane, flag=wx.EXPAND)
		
		self.sizerMain.AddSpacer((50,50))
		self.sizerMain.Add(self.sizerLeft)
		self.sizerMain.Add(self.sizerRight)

		self.SetSizer(self.sizerMain)

		self.timer = wx.Timer(self)
		self.Bind(wx.EVT_TIMER, self.onTimer, self.timer) 
		self.secCounter = 0    
		self.openFpLog()
		self.timer.Start(1000)
		self.reprap.setHoldFan(self.holdFan)
		
		self.Bind(EVT_HTTP_PRINTMON, self.httpRequest)
		
		self.infoPane.setMode(MODE_NORMAL)
		self.setSDTargetFile(None)
		
	def openFpLog(self):
		self.fnLog = os.path.join(self.app.settings.lastlogdirectory, "temps" + self.prtname + ".log")
		self.logger.LogMessage("Log file %s opened for recording %s temperatures" % (self.fnLog, self.prtname))
		self.fpLog = open(self.fnLog, "a")
		self.lastLogDate = ""
		
	def newFpLogVersion(self):
		try:
			os.unlink(self.fnLog + ".old")
			self.logger.LogMessage("Old temperature log file (%s.old) deleted" % self.fnLog)
		except:
			pass
		
		self.fpLog.close()
		os.rename(self.fnLog, self.fnLog+".old")
		self.logger.LogMessage("Archiving temperature log %s as %s.old" % (self.fnLog, self.fnLog))
		self.openFpLog()
		
	def setManCtl(self, mc):
		self.manctl = mc;
		
	def pendantCommand(self, cmd):
		c = cmd.lower()
		if c in pendantCmds.keys():
			mcmd = pendantCmds[c]
			if mcmd == "@print":
				self.emulatePrintButton()
			elif mcmd == "@pause":
				self.emulatePauseButton()
			else:
				return False # command not handled
		else:
			return False  # command not handled
		
		return True # command handled

	def assertAllowPulls(self, flag):
		if not self.isPrinting():
			self.bPull.Enable(flag)

	def tick(self):
		if self.skipCycles >= 0:
			self.skipCycles -= 1
			return
		
		self.cycle += 1

		if self.cycle % TEMPINTERVAL == 0:
			if self.suspendM105:
				self.M105pending = False
			elif not self.M105pending:
				self.M105pending = True
				self.reprap.send_now("M105", True)
				
		if self.cycle % POSITIONINTERVAL == 0:
			n = self.reprap.getPrintPosition()
			if n is not None:
				self.printPosition = n
				self.updatePrintPosition(n)
				
	def suspendTempProbe(self, flag):
		self.suspendM105 = flag
		
	def prtMonEvent(self, evt):
		if evt.event == SD_PRINT_POSITION:
			if self.sdprintingfrom:
				if evt.pos < evt.max:
					self.infoPane.setSDPrintInfo(evt.pos, evt.max)
					self.M27Timer.Start(M27Interval, True)
			return

		if evt.event == SD_PRINT_COMPLETE:
			self.history.SDPrintFromComplete(self.prtname)
			self.endTime = time.time()
			self.infoPane.setSDPrintComplete()
			self.sdprintingfrom = False
			self.printing = False
			self.paused = False
			if self.hasFileLoaded():
				self.setStatus(PMSTATUS_READY)
				self.bPrint.Enable(True)
			else:
				self.setStatus(PMSTATUS_NOT_READY)
				self.bPrint.Enable(False)
			self.reprap.printComplete()
			self.setPrintMode(PRINT_MODE_PRINT)
			self.setPauseMode(PAUSE_MODE_PAUSE)
			self.bPull.Enable(self.app.currentPullStatus())
			self.bPause.Enable(False)
			self.bSDPrintFrom.Enable(True)
			self.bSDPrintTo.Enable(self.hasFileLoaded())
			self.bSDDelete.Enable(True)
			self.logger.LogMessage("SD Print completed at %s" % time.strftime('%H:%M:%S', time.localtime(self.endTime)))
			self.logger.LogMessage("Total elapsed time: %s" % formatElapsed(self.endTime - self.sdStartTime))
			self.updatePrintPosition(0)
			return
	
	def setStatus(self, s):
		self.status = s
		self.app.updatePrintMonStatus(self.prtname, s)
		
	def isPrinting(self):
		return self.printing or self.sdprintingfrom
		
	def getStatus(self):
		if self.printing or self.sdprintingfrom:
			status = self.infoPane.getStatus()
			status['printing'] = "True"
		else:
			status = {}
			status['printing'] = "False"
			
		return status
		
	def hasFileLoaded(self):
		return self.model is not None
	
	def getBedGCode(self):
		if not self.hasFileLoaded():
			return None;
		
		i = 0
		for l in self.model:
			if l.raw.startswith("M140 ") or l.raw.startswith("M190 "):
				if "S" in l.raw:
					temp = _get_float(l.raw, "S")
					return temp

			i += 1
			if i >= SCANTHRESHOLD:
				return None
	
	def getHEGCode(self, tool):
		if not self.hasFileLoaded():
			return None;
		
		i = 0
		for l in self.model:
			if l.raw.startswith("M104 ") or l.raw.startswith("M109 "):
				t = 1
				if "T" in l.raw:
					t = _get_float(l.raw, "T")
					
				if (t-1) == tool:
					if "S" in l.raw:
						temp = _get_float(l.raw, "S")
						return temp

			i += 1
			if i >= SCANTHRESHOLD:
				return None
	
	def printerReset(self):
		self.printPos = 0
		self.skipCycles = 5
		self.M105pending = False
		self.printing = False
		self.paused = False
		self.sdpaused = False
		self.sdprintingfrom = False
		self.setStatus(PMSTATUS_READY)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.bPrint.Enable(self.hasFileLoaded())
		self.bPull.Enable(self.app.currentPullStatus())
		self.bPause.Enable(False)
		
	def clearModel(self):
		self.gcf.eraseGraph()
		self.slideLayer.SetValue(1)
		self.slideLayer.Enable(False)
		self.infoPane.clearFileInfo()
		self.infoPane.clearLayerInfo()
		self.model = None
		self.cfgString = None
		
	def doSDPrintFrom(self, evt):
		self.printing = False
		self.paused = False
		self.sdpaused = False
		self.sdprintingfrom = True
		self.sdStartTime = time.time()
		self.infoPane.setSDStartTime(self.sdStartTime)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.setStatus(PMSTATUS_PRINTING)
		self.sdcard.startPrintFromSD()
		
	def cancelSDPrintFrom(self):
		self.sdprintingfrom = False
		self.printing = False
		self.paused = False
		self.setStatus(PMSTATUS_READY)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.bPrint.Enable(True)
		self.bPull.Enable(self.app.currentPullStatus())
		self.bPause.Enable(False)
		
	def resumeSDPrintFrom(self, fn):
		self.history.SDPrintFromStart("SD:" + fn[1].lower(), self.prtname)
		self.clearModel()
		self.reprap.send_now("M23 " + fn[1].lower())
		self.reprap.send_now("M24")
		self.sdprintingfrom = True
		self.M27Timer.Start(M27Interval, True)
		self.bPrint.Enable(False)
		self.bPull.Enable(False)
		self.bSDPrintFrom.Enable(False)
		self.bSDPrintTo.Enable(False)
		self.bSDDelete.Enable(False)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.bPause.Enable(True)
		self.sdpaused = False
		self.infoPane.setMode(MODE_FROM_SD)
		
	def doSDPrintTo(self, evt):
		self.sdcard.startPrintToSD()
		
	def resumeSDPrintTo(self, tfn):
		self.history.SDPrintToStart("SD:" + tfn[1].lower(), self.prtname)
		self.setSDTargetFile(tfn[1].lower())
		self.suspendTempProbe(True)
		self.reprap.send_now("M28 %s" % self.sdTargetFile)
		self.printPos = 0
		self.startTime = time.time()
		self.endTime = None
		self.reprap.startPrint(self.model)
		self.logger.LogMessage("Print to SD: %s started at %s" % (self.sdTargetFile, time.strftime('%H:%M:%S', time.localtime(self.startTime))))
		self.origEta = self.startTime + self.model.duration
		self.countGLines = len(self.model)
		self.infoPane.setMode(MODE_TO_SD)
		self.infoPane.showFileInfo()
		self.infoPane.setStartTime(self.startTime)
		self.bPrint.Enable(False)
		self.bPull.Enable(False)
		self.bPause.Enable(False)
		
	def setSDTargetFile(self, tfn):
		self.sdTargetFile = tfn
		self.infoPane.setSDTargetFile(tfn)
		
	def doSDDelete(self, evt):
		self.sdcard.startDeleteFromSD()
		
	def reprapEvent(self, evt):
		if evt.event in [ PRINT_STARTED, PRINT_RESUMED ]:
			self.printing = True
			self.setStatus(PMSTATUS_PRINTING)
			self.paused = False
			self.setPrintMode(PRINT_MODE_PRINT)
			self.setPauseMode(PAUSE_MODE_PAUSE)
			self.bPrint.Enable(False)
			self.bPull.Enable(False)
			self.bPause.Enable(True)
			if self.hassd:
				self.bSDPrintFrom.Enable(False)
				self.bSDPrintTo.Enable(False)
				self.bSDDelete.Enable(False)
			
		elif evt.event in [PRINT_STOPPED, PRINT_AUTOSTOPPED]:
			self.paused = True
			self.setStatus(PMSTATUS_PAUSED)
			self.printing = False
			self.reprap.printStopped()
			self.setPrintMode(PRINT_MODE_RESTART)
			self.setPauseMode(PAUSE_MODE_RESUME)
			self.bPrint.Enable(True)
			self.bPull.Enable(self.app.currentPullStatus())
			self.bPause.Enable(True)
			if self.hassd:
				self.bSDPrintFrom.Enable(True)
				self.bSDPrintTo.Enable(True)
				self.bSDDelete.Enable(True)
			if evt.event == PRINT_AUTOSTOPPED:
				self.logger.LogMessage(evt.msg)
				
			
		elif evt.event == PRINT_COMPLETE:
			
			self.endTime = time.time()
			self.infoPane.setPrintComplete()
			if self.sdTargetFile is not None:
				self.history.SDPrintToComplete(self.prtname)
				self.reprap.send_now("M29 %s" % self.sdTargetFile)
				self.suspendTempProbe(False)
				self.setSDTargetFile(None)
			else:
				self.history.PrintComplete(self.prtname)

			self.printing = False
			self.paused = False
			self.setStatus(PMSTATUS_READY)
			self.reprap.printComplete()
			self.setPrintMode(PRINT_MODE_PRINT)
			self.setPauseMode(PAUSE_MODE_PAUSE)
			self.bPrint.Enable(True)
			self.bPull.Enable(self.app.currentPullStatus())
			self.bPause.Enable(False)
			if self.hassd:
				self.bSDPrintFrom.Enable(True)
				self.bSDPrintTo.Enable(True)
				self.bSDDelete.Enable(True)
			self.logger.LogMessage("Print completed at %s" % time.strftime('%H:%M:%S', time.localtime(self.endTime)))
			self.logger.LogMessage("Total elapsed time: %s" % formatElapsed(self.endTime - self.startTime))
			rs, rq = self.reprap.getCounters()
			if rs + rq != 0:
				self.logger.LogMessage("Resend Requests: %d, messages retransmitted: %d" % (rq, rs))
			self.updatePrintPosition(0)
			
		elif evt.event == PRINT_ERROR:
			self.logger.LogError(evt.msg)
			self.app.doPrinterError(self.prtname)
			
		elif evt.event == PRINT_MESSAGE:
			if evt.immediate:
				self.logger.LogMessage(evt.msg)
			elif evt.primary:
				self.logger.LogCMessage(evt.msg)
			else:
				self.logger.LogGMessage(evt.msg)

		elif evt.event == QUEUE_DRAINED:
			self.logger.LogMessage("Print Queue drained")
			self.reprap.reprapEvent(evt)
		else:
			self.reprap.reprapEvent(evt)
			
	def getPrintTimes(self):
		return self.startTime, self.endTime
	
	def onM27Timer(self, evt):
		if not self.M27pending and not self.sdpaused:
			self.M27pending = True
			self.reprap.send_now("M27")

	def setPrintMode(self, mode):
		self.printMode = mode
		if mode == PRINT_MODE_PRINT:
			self.bPrint.SetToolTipString("Start the print")
			self.bPrint.SetBitmapLabel(self.images.pngPrint)
		elif mode == PRINT_MODE_RESTART:
			self.bPrint.SetToolTipString("Restart the print")
			self.bPrint.SetBitmapLabel(self.images.pngRestart)

	def setPauseMode(self, mode):
		if mode == PAUSE_MODE_PAUSE:
			self.bPause.SetToolTipString("Pause the print")
		elif mode == PAUSE_MODE_RESUME:
			self.bPause.SetToolTipString("Resume the print from the paused point")
			
	def emulatePrintButton(self):
		if self.bPrint.IsEnabled():
			if not self.manctl is None:
				self.manctl.disengageZ()
			self.doPrint(None)
		else:
			self.logger.LogMessage("Print button currently disabled")
		
	def doPrint(self, evt):
		if self.sdpaused:
			self.reprap.send_now("M26 S0")
			self.setPauseMode(PAUSE_MODE_PAUSE)
			self.setPrintMode(PRINT_MODE_PRINT)
			self.bPrint.Enable(False)
			self.bPull.Enable(False)
			self.sdprintingfrom = True
			self.reprap.send_now("M24")
			self.infoPane.setSDStartTime(time.time())
			self.M27Timer.Start(M27Interval, True)
		else:
			self.printPos = 0
			self.startTime = time.time()
			self.endTime = None
			if self.printMode == PRINT_MODE_RESTART:
				action = "restarted"
				self.reprap.restartPrint(self.model)
			else:
				self.history.PrintStart(self.gcFile, self.prtname)
				action = "started"
				self.reprap.startPrint(self.model)
			self.logger.LogMessage("Print %s at %s" % (action, time.strftime('%H:%M:%S', time.localtime(self.startTime))))
			self.origEta = self.startTime + self.model.duration
			self.logger.LogMessage("ETA at %s (%s)" % (time.strftime('%H:%M:%S', time.localtime(self.startTime+self.model.duration)), formatElapsed(self.model.duration)))
			self.countGLines = len(self.model)
			self.infoPane.setMode(MODE_NORMAL)
			self.infoPane.setStartTime(self.startTime)
			self.infoPane.showFileInfo()
			self.bPrint.Enable(False)
			self.bPull.Enable(False)
			self.bPause.Enable(False)
			self.setSDTargetFile(None)
		
	def emulatePauseButton(self):
		if self.sdTargetFile is not None:
			self.logger.LogMessage("Unable to pause print to SD - use GUI")
		elif self.bPause.IsEnabled():
			if not self.manctl is None:
				self.manctl.disengageZ()
			self.doPause(None)
		else:
			self.logger.LogMessage("Pause button currently disabled")
		
	def doPause(self, evt):
		if self.sdTargetFile is not None:
			msgdlg = wx.MessageDialog(self.app, "Are you sure you want to terminate this job",
					'Confirm', wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)
			rc = msgdlg.ShowModal()
			msgdlg.Destroy()
			
			if rc == wx.ID_YES:
				self.stopPrintToSD()
		
		elif self.sdprintingfrom or self.sdpaused:
			if self.sdpaused:
				self.reprap.send_now("M24")
				self.setPauseMode(PAUSE_MODE_PAUSE)
				self.setPrintMode(PRINT_MODE_PRINT)
				self.bPrint.Enable(False)
				self.bPull.Enable(False)
				self.sdprintingfrom = True
				self.M27Timer.Start(M27Interval, True)
				self.setStatus(PMSTATUS_PRINTING)
				self.sdpaused = False
			else:
				self.stopPrintFromSD()
				self.setStatus(PMSTATUS_PAUSED)

		else:
			if self.paused:
				self.bPause.Enable(False)
				self.bPrint.Enable(False)
				self.bPull.Enable(False)
				self.reprap.resumePrint()
			else:
				self.stopPrintNormal()
				
	def stopPrintToSD(self):
		self.reprap.pausePrint()
		self.reprap.send_now("M29 %s" % self.sdTargetFile)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.bPause.Enable(False)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.bPrint.Enable(self.hasFileLoaded())
		self.bPull.Enable(self.app.currentPullStatus())
		self.bSDPrintFrom.Enable(True)
		self.bSDPrintTo.Enable(True)
		self.bSDDelete.Enable(True)
		self.setSDTargetFile(None)
		self.suspendTempProbe(False)
		
	def stopPrintFromSD(self):
		self.reprap.send_now("M25")
		self.setPauseMode(PAUSE_MODE_RESUME)
		self.setPrintMode(PRINT_MODE_PRINT)
		self.bPrint.Enable(False)
		self.bSDPrintFrom.Enable(True)
		self.bPull.Enable(self.app.currentPullStatus())
		self.sdprintingfrom = False
		self.sdpaused = True
		
	def stopPrintNormal(self):
		self.bPause.Enable(False)
		self.bPrint.Enable(False)
		self.bPull.Enable(False)
		self.reprap.pausePrint()
		
	def stopMotorsAndHeaters(self):
		self.reprap.send_now("M84")
		self.reprap.send_now("M106 S0")
		self.reprap.send_now("M140 S0")
		for h in self.knownHeaters:
			if h.startswith("HE"):
				self.reprap.send_now("M104 S0 T" + h[2])
		
	def updatePrintPosition(self, pos):
		if self.printing:
			if pos != self.printPos:
				self.printPos = pos
				newLayer = self.gcf.setPrintPosition(self.printPos, self.syncPrint)
				if newLayer and not self.syncPrint:
					self.infoPane.updateUntilTime()
				
			l = self.model.findLayerByLine(pos)
			gcl = None
			lt = None
			if l is not None:
				gcl = self.model.layerlines[l]
				lt = self.model.layer_time[l]
			self.infoPane.setPrintInfo(pos, l, gcl, lt)
		
	def onSpinLayer(self, evt):
		l = evt.EventObject.GetValue()-1
		self.gcf.setLayer(l)
		self.setLayer(l)
		
	def setLayer(self, l):
		if l >=0 and l < self.layerCount:
			self.slideLayer.SetValue(l+1)
			(zh, xymin, xymax, filament, glines, time, filstart) = self.model.getLayerInfo(l)
			self.infoPane.setLayerInfo(l, zh, xymin, xymax, filament, filstart, time, glines)
			if self.model.checkPendingPause(l+1):
				# TODO Pending Pause at start of this layer
				pass
			plines = self.model.checkImmediatePause(l+1)
			if len(plines) > 0:
				# TODO ct Immediate Pauses on this layer
				pass

	def onClose(self, evt):
		if self.fpLog is not None:
			self.logger.LogMessage("Log file for %s temperatures closed" % self.prtname)
			self.fpLog.close()
			self.fpLog = None
		self.timer.Stop()
		self.lastLogDate = ""
		return True
		
	def viewZoomIn(self, evt):
		self.gcf.zoomIn()
		
	def viewZoomOut(self, evt):
		self.gcf.zoomOut()
		
	def checkSync(self, evt):
		self.syncPrint = evt.IsChecked()
		
	def checkBuffDC(self, evt):
		self.settings.usebuffereddc = evt.IsChecked()
		self.settings.setModified()
		self.gcf.redrawCurrentLayer()
			
	def checkToolPathsOnly(self, evt):
		self.settings.toolpathsonly = evt.IsChecked()
		self.settings.setModified()
		self.gcf.setToolPathsOnly(self.settings.toolpathsonly)
		self.gcf.redrawCurrentLayer()
		
	def checkHoldFan(self, evt):
		self.holdFan = evt.IsChecked()
		self.reprap.setHoldFan(self.holdFan)
		
	def checkPrevious(self, evt):
		self.settings.showprevious = evt.IsChecked()
		self.settings.setModified()
		self.gcf.redrawCurrentLayer()
		
	def checkMoves(self, evt):
		self.settings.showmoves = evt.IsChecked()
		self.settings.setModified()
		self.gcf.redrawCurrentLayer()
		
	def doPull(self, evt):
		self.setStatus(PMSTATUS_NOT_READY)
		self.app.pullGCode(self, self.prtsettings.acceleration, self.prtsettings.retractiontime)
	
	def forwardModel(self, model, name="", cfg=None, fd=None, tp=None, st=""):
		self.setSDTargetFile(None)
		
		self.setStatus(PMSTATUS_NOT_READY)
		self.reprap.clearPrint()
		self.model = model
		self.name = name
		self.cfgString = cfg
		self.modelFilamentDiam = fd
		self.tempProfile = tp
		self.sliceTime = st
		if self.name == TEMPFILELABEL:
			self.gcFile = None
		elif len(self.name) > 40:
			self.gcFile = self.name
			self.name = os.path.basename(self.gcFile)
		else:
			self.gcFile = self.name
			
		layer = 0

		self.layerCount = self.model.countLayers()
		
		self.layerInfo = self.model.getLayerInfo(layer)
		if self.layerInfo is None:
			return
		
		self.slideLayer.SetRange(1, self.layerCount)
		n = int(self.layerCount/20)
		if n<1: n=1
		self.slideLayer.SetTickFreq(n, 1)
		self.slideLayer.SetPageSize(1);
		self.slideLayer.Enable()
		self.slideLayer.Refresh()
		
		self.gcf.loadModel(self.model, layer=layer)
		self.enableButtons()
		
		self.printPos = 0
		self.printing = False
		self.paused = False

		self.setPrintMode(PRINT_MODE_PRINT)
		self.setPauseMode(PAUSE_MODE_PAUSE)
		self.bPrint.Enable(self.hasFileLoaded())
		self.bPull.Enable(self.app.currentPullStatus())
		self.bPause.Enable(False)
		if self.hassd:
			self.bSDPrintFrom.Enable(True)
			self.bSDPrintTo.Enable(self.hasFileLoaded())
			self.bSDDelete.Enable(True)
		self.sdprintingfrom = False
		self.sdpaused = False
		
		self.setStatus(PMSTATUS_READY)
		self.infoPane.setFileInfo(self.name,
					self.cfgString, self.modelFilamentDiam, self.tempProfile, self.sliceTime, self.model.duration, 
					len(self.model), self.layerCount, self.model.zmax, self.model.total_e, self.model.layer_time)
		self.setLayer(layer)

		if self.modelFilamentDiam is None:		
			dlg = wx.MessageDialog(self, 
				"Model sliced with unknown filament\nPrinter filament diameter = %s" % 
				", ".join(["%.2f" % x for x in self.filamentdiameter]),
				'Unknown filament diameter',
				wx.OK | wx.ICON_INFORMATION)
			dlg.ShowModal()
			dlg.Destroy()
		else:
			unequal = False
			if len(self.modelFilamentDiam) != len(self.filamentdiameter):
				unequal = True
			else:
				for i in range(len(self.modelFilamentDiam)):
					if self.modelFilamentDiam[i] != self.filamentdiameter[i]:
						unequal = True
						
			if unequal:
				dlg = wx.MessageDialog(self, 
					"Model sliced with diameter = %s\nPrinter filament diameter = %s" % 
					(", ".join(["%.2f" % x for x in self.modelFilamentDiam]), ", ".join(["%.2f" % x for x in self.filamentdiameter])),
					'Unequal filament diameters',
					wx.OK | wx.ICON_INFORMATION)
				dlg.ShowModal()
				dlg.Destroy()

		
	def setHETarget(self, tool, temp):
		key = 'HE' + str(tool)
		self.targets[key] = temp
		self.gTemp.setTargets(self.targets)
		
	def setHETemp(self, tool, temp):
		key = 'HE' + str(tool)
		self.temps[key] = temp
			
	def setBedTarget(self, temp):
		self.targets['Bed'] = temp
		self.gTemp.setTargets(self.targets)
		
	def setBedTemp(self, temp):
		self.temps['Bed'] = temp
		
	def getTemps(self):
		temps = {}
		temps['temps'] = self.temps
		temps['targets'] = self.targets
		return temps
	
	def onTimer(self, evt):
		for h in self.knownHeaters:
			if h in self.temps.keys():
				self.tempData[h].append(self.temps[h])
			else:
				self.tempData[h].append(None)
			l = len(self.tempData[h])
			if l > MAXX: # 4 minutes data
				self.tempData[h] = self.tempData[h][l-MAXX:]
		self.gTemp.setTemps(self.tempData)

		if self.suspendM105:
			self.logTempMessage("temperature retrieval suspended\n")
			return
		
		self.secCounter += 1		
		if self.secCounter >= 60:
			self.secCounter = 0
			self.logTempMessage(repr(self.temps) + '\n')
			
	def logTempMessage(self, msg):
		if self.fpLog is None:
			return
		
		t = time.localtime(time.time())
		ymd = time.strftime('%y:%m:%d', t)
		if ymd != self.lastLogDate:
			self.fpLog.write("================================: " + ymd + '\n')
			self.lastLogDate = ymd

		tm = time.strftime('%H:%M:%S', t)
		self.fpLog.write(tm + ": " + msg)
		self.fpLog.flush()
		sz = self.fpLog.tell()
		if sz > FILELIMIT:
			self.newFpLogVersion()

		
	def enableButtons(self, flag=True):
		if flag:
			if self.model is not None:
				self.slideLayer.Enable(True)
			else:
				self.slideLayer.Enable(False)
		else:
			self.slideLayer.Enable(False)
			
	def stopPrint(self):
		evt = HttpEvent(cmd=HTTPPM_STOPPRINT)
		wx.PostEvent(self, evt)
	
	def httpRequest(self, evt):
		if evt.cmd == HTTPPM_STOPPRINT:
			if self.sdTargetFile is not None:
				self.stopPrintToSD()
				
			elif self.sdprintingfrom:
				self.stopPrintFromSD()
				self.stopMotorsAndHeaters()
				
			else:
				self.stopPrintNormal()
				self.stopMotorsAndHeaters()
mch = os.uname().machine
if 'PCA10028' in mch:
    sck = Pin.board.P29
    miso = Pin.board.P28
    mosi = Pin.board.P25
    cs = Pin.board.P16
elif 'PCA10040' in mch:
    sck = Pin.board.P25
    miso = Pin.board.P24
    mosi = Pin.board.P23
    cs = Pin.board.P15
elif 'PCA10056' in mch:
    sck = Pin.board.P47
    mosi = Pin.board.P45
    miso = Pin.board.P46
    cs = Pin.board.P37  # P1.05
elif 'PCA10090' in mch:
    sck = Pin.board.P13
    miso = Pin.board.P12
    mosi = Pin.board.P11
    cs = Pin.board.P4
else:
    raise Exception('Board not supported!')

spi = SPI(1, sck=sck, mosi=mosi, miso=miso)
sd = SDCard(spi, cs)

os.mount(sd, '/')
print('testfile.txt' in os.listdir())
print([open("testfile.txt", "r").read()])
Example #9
0
    def __init__(self, parent, wparent, reprap, prtName):
        self.parent = parent
        self.wparent = wparent
        self.log = self.parent.log
        self.history = wparent.history
        self.reprap = reprap
        self.settings = self.parent.settings
        self.images = self.parent.images
        self.state = PrintState.idle
        self.oldState = None
        self.gcodeLoaded = False
        self.gcodeFile = None
        self.printerName = prtName
        self.layerMap = []
        self.okToImport = False
        self.importFile = None

        self.currentLayer = 0
        self.maxTool = 0
        self.eUsed = [0.0, 0.0, 0.0, 0.0]
        self.totalTime = 0
        self.totalTimeStr = ""
        self.layerTimes = []
        self.layerTimeStr = []
        self.layerRange = (0, 0)

        self.gObj = None
        self.printLayer = 0
        self.printPosition = None

        title = self.buildTitle()
        wx.Frame.__init__(self, wparent, wx.ID_ANY, title=title)
        self.Show()
        ico = wx.Icon(os.path.join(cmdFolder, "images", "printmon.png"),
                      wx.BITMAP_TYPE_PNG)
        self.SetIcon(ico)

        if self.settings.hassdcard:
            self.sdcard = SDCard(self.parent, self, self.reprap, self.log)
        else:
            self.sdcard = None

        self.gcf = GcFrame(self, self.gObj, self.settings)
        self.stLayerText = wx.StaticText(self, wx.ID_ANY,
                                         "Layer Height:   0.00")

        ht = self.gcf.GetSize().Get()[1] - BUTTONDIM[1] * 2 - 20

        self.slLayers = wx.Slider(self,
                                  wx.ID_ANY,
                                  0,
                                  0,
                                  1000,
                                  size=(-1, ht),
                                  style=wx.SL_VERTICAL | wx.SL_AUTOTICKS
                                  | wx.SL_LABELS | wx.SL_INVERSE)
        self.Bind(wx.EVT_SCROLL, self.onLayerScroll, self.slLayers)
        self.slLayers.Enable(False)

        self.cbShowMoves = wx.CheckBox(self, wx.ID_ANY, "Show moves")
        self.cbShowMoves.SetValue(self.settings.showmoves)
        self.Bind(wx.EVT_CHECKBOX, self.onShowMoves, self.cbShowMoves)

        self.cbShowPrevious = wx.CheckBox(self, wx.ID_ANY,
                                          "Show previous layer")
        self.cbShowPrevious.SetValue(self.settings.showprevious)
        self.Bind(wx.EVT_CHECKBOX, self.onShowPrevious, self.cbShowPrevious)

        self.cbToolPathOnly = wx.CheckBox(self, wx.ID_ANY,
                                          "Show tool paths only")
        self.cbToolPathOnly.SetValue(self.settings.toolpathonly)
        self.Bind(wx.EVT_CHECKBOX, self.onToolPathOnly, self.cbToolPathOnly)

        self.cbSyncPrint = wx.CheckBox(self, wx.ID_ANY, "Sync with print")
        self.cbSyncPrint.SetValue(True)
        self.Bind(wx.EVT_CHECKBOX, self.onSyncPrint, self.cbSyncPrint)

        self.bImport = wx.BitmapButton(self,
                                       wx.ID_ANY,
                                       self.images.pngImport,
                                       size=BUTTONDIM)
        self.bImport.SetToolTip("Import G Code file from toolbox")
        self.Bind(wx.EVT_BUTTON, self.onImport, self.bImport)

        self.bImportQ = wx.BitmapButton(self,
                                        wx.ID_ANY,
                                        self.images.pngNext,
                                        size=BUTTONDIM)
        self.Bind(wx.EVT_BUTTON, self.onImportFromQueue, self.bImportQ)

        self.bOpen = wx.BitmapButton(self,
                                     wx.ID_ANY,
                                     self.images.pngFileopen,
                                     size=BUTTONDIM)
        self.bOpen.SetToolTip("Open a G Code file")
        self.Bind(wx.EVT_BUTTON, self.onOpenFile, self.bOpen)

        self.Bind(wx.EVT_CLOSE, self.onClose)

        self.bPrint = PrintButton(self, self.images)
        self.bPrint.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onPrint, self.bPrint)

        self.bPause = PauseButton(self, self.images)
        self.bPause.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onPause, self.bPause)

        self.bSdPrintTo = wx.BitmapButton(self,
                                          wx.ID_ANY,
                                          self.images.pngSdprintto,
                                          size=(BUTTONDIMWIDE))
        self.bSdPrintTo.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onSdPrintTo, self.bSdPrintTo)

        self.bSdPrintFrom = wx.BitmapButton(self,
                                            wx.ID_ANY,
                                            self.images.pngSdprintfrom,
                                            size=(BUTTONDIMWIDE))
        self.bSdPrintFrom.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onSdPrintFrom, self.bSdPrintFrom)

        self.bSdDelete = wx.BitmapButton(self,
                                         wx.ID_ANY,
                                         self.images.pngSddelete,
                                         size=(BUTTONDIM))
        self.bSdDelete.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onSdDelete, self.bSdDelete)

        self.bUp = wx.BitmapButton(self,
                                   wx.ID_ANY,
                                   self.images.pngUp,
                                   size=BUTTONDIM)
        self.bUp.SetToolTip("Move up one layer")
        self.Bind(wx.EVT_BUTTON, self.onUp, self.bUp)
        self.bUp.Enable(False)

        self.bDown = wx.BitmapButton(self,
                                     wx.ID_ANY,
                                     self.images.pngDown,
                                     size=BUTTONDIM)
        self.bDown.SetToolTip("Move down one layer")
        self.Bind(wx.EVT_BUTTON, self.onDown, self.bDown)
        self.bDown.Enable(False)

        szGcf = wx.BoxSizer(wx.HORIZONTAL)
        szGcf.AddSpacer(10)
        szGcf.Add(self.gcf)
        szGcf.Add(self.stLayerText, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)
        szGcf.AddSpacer(10)

        szNav = wx.BoxSizer(wx.VERTICAL)
        szNav.Add(self.bUp, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)
        szNav.AddSpacer(10)
        szNav.Add(self.slLayers)
        szNav.AddSpacer(10)
        szNav.Add(self.bDown, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)

        szGcf.Add(szNav)
        szGcf.AddSpacer(10)

        szOpts = wx.BoxSizer(wx.HORIZONTAL)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbShowMoves)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbShowPrevious)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbToolPathOnly)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbSyncPrint)
        szOpts.AddSpacer(10)

        szBtn = wx.BoxSizer(wx.HORIZONTAL)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bImport)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bImportQ)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bOpen)
        szBtn.AddSpacer(20)
        szBtn.Add(self.bPrint)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bPause)
        if self.sdcard:
            szBtn.AddSpacer(20)
            szBtn.Add(self.bSdPrintTo)
            szBtn.AddSpacer(10)
            szBtn.Add(self.bSdPrintFrom)
            szBtn.AddSpacer(10)
            szBtn.Add(self.bSdDelete)

        szBtn.AddSpacer(10)

        szDlg = wx.BoxSizer(wx.VERTICAL)
        szDlg.AddSpacer(10)
        szDlg.Add(szGcf)
        szDlg.AddSpacer(10)
        szDlg.Add(szOpts)
        szDlg.AddSpacer(10)
        szDlg.Add(szBtn)
        szDlg.AddSpacer(10)

        self.SetSizer(szDlg)
        self.Fit()
        self.Layout()

        self.propDlg = PropertiesDlg(self, wparent, self.printerName)
        self.propDlg.Show()
        if not self.settings.propposition is None:
            self.propDlg.SetPosition(self.settings.propposition)

        self.enableButtonsByState()
        self.reprap.registerPositionHandler(self.updatePrintPosition)
        self.reprap.registerEventHandler(self.reprapEvent)
        self.reprap.registerSdEventHandler(self.sdcard)
Example #10
0
class PrintMonitorDlg(wx.Frame):
    def __init__(self, parent, wparent, reprap, prtName):
        self.parent = parent
        self.wparent = wparent
        self.log = self.parent.log
        self.history = wparent.history
        self.reprap = reprap
        self.settings = self.parent.settings
        self.images = self.parent.images
        self.state = PrintState.idle
        self.oldState = None
        self.gcodeLoaded = False
        self.gcodeFile = None
        self.printerName = prtName
        self.layerMap = []
        self.okToImport = False
        self.importFile = None

        self.currentLayer = 0
        self.maxTool = 0
        self.eUsed = [0.0, 0.0, 0.0, 0.0]
        self.totalTime = 0
        self.totalTimeStr = ""
        self.layerTimes = []
        self.layerTimeStr = []
        self.layerRange = (0, 0)

        self.gObj = None
        self.printLayer = 0
        self.printPosition = None

        title = self.buildTitle()
        wx.Frame.__init__(self, wparent, wx.ID_ANY, title=title)
        self.Show()
        ico = wx.Icon(os.path.join(cmdFolder, "images", "printmon.png"),
                      wx.BITMAP_TYPE_PNG)
        self.SetIcon(ico)

        if self.settings.hassdcard:
            self.sdcard = SDCard(self.parent, self, self.reprap, self.log)
        else:
            self.sdcard = None

        self.gcf = GcFrame(self, self.gObj, self.settings)
        self.stLayerText = wx.StaticText(self, wx.ID_ANY,
                                         "Layer Height:   0.00")

        ht = self.gcf.GetSize().Get()[1] - BUTTONDIM[1] * 2 - 20

        self.slLayers = wx.Slider(self,
                                  wx.ID_ANY,
                                  0,
                                  0,
                                  1000,
                                  size=(-1, ht),
                                  style=wx.SL_VERTICAL | wx.SL_AUTOTICKS
                                  | wx.SL_LABELS | wx.SL_INVERSE)
        self.Bind(wx.EVT_SCROLL, self.onLayerScroll, self.slLayers)
        self.slLayers.Enable(False)

        self.cbShowMoves = wx.CheckBox(self, wx.ID_ANY, "Show moves")
        self.cbShowMoves.SetValue(self.settings.showmoves)
        self.Bind(wx.EVT_CHECKBOX, self.onShowMoves, self.cbShowMoves)

        self.cbShowPrevious = wx.CheckBox(self, wx.ID_ANY,
                                          "Show previous layer")
        self.cbShowPrevious.SetValue(self.settings.showprevious)
        self.Bind(wx.EVT_CHECKBOX, self.onShowPrevious, self.cbShowPrevious)

        self.cbToolPathOnly = wx.CheckBox(self, wx.ID_ANY,
                                          "Show tool paths only")
        self.cbToolPathOnly.SetValue(self.settings.toolpathonly)
        self.Bind(wx.EVT_CHECKBOX, self.onToolPathOnly, self.cbToolPathOnly)

        self.cbSyncPrint = wx.CheckBox(self, wx.ID_ANY, "Sync with print")
        self.cbSyncPrint.SetValue(True)
        self.Bind(wx.EVT_CHECKBOX, self.onSyncPrint, self.cbSyncPrint)

        self.bImport = wx.BitmapButton(self,
                                       wx.ID_ANY,
                                       self.images.pngImport,
                                       size=BUTTONDIM)
        self.bImport.SetToolTip("Import G Code file from toolbox")
        self.Bind(wx.EVT_BUTTON, self.onImport, self.bImport)

        self.bImportQ = wx.BitmapButton(self,
                                        wx.ID_ANY,
                                        self.images.pngNext,
                                        size=BUTTONDIM)
        self.Bind(wx.EVT_BUTTON, self.onImportFromQueue, self.bImportQ)

        self.bOpen = wx.BitmapButton(self,
                                     wx.ID_ANY,
                                     self.images.pngFileopen,
                                     size=BUTTONDIM)
        self.bOpen.SetToolTip("Open a G Code file")
        self.Bind(wx.EVT_BUTTON, self.onOpenFile, self.bOpen)

        self.Bind(wx.EVT_CLOSE, self.onClose)

        self.bPrint = PrintButton(self, self.images)
        self.bPrint.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onPrint, self.bPrint)

        self.bPause = PauseButton(self, self.images)
        self.bPause.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onPause, self.bPause)

        self.bSdPrintTo = wx.BitmapButton(self,
                                          wx.ID_ANY,
                                          self.images.pngSdprintto,
                                          size=(BUTTONDIMWIDE))
        self.bSdPrintTo.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onSdPrintTo, self.bSdPrintTo)

        self.bSdPrintFrom = wx.BitmapButton(self,
                                            wx.ID_ANY,
                                            self.images.pngSdprintfrom,
                                            size=(BUTTONDIMWIDE))
        self.bSdPrintFrom.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onSdPrintFrom, self.bSdPrintFrom)

        self.bSdDelete = wx.BitmapButton(self,
                                         wx.ID_ANY,
                                         self.images.pngSddelete,
                                         size=(BUTTONDIM))
        self.bSdDelete.Enable(False)
        self.Bind(wx.EVT_BUTTON, self.onSdDelete, self.bSdDelete)

        self.bUp = wx.BitmapButton(self,
                                   wx.ID_ANY,
                                   self.images.pngUp,
                                   size=BUTTONDIM)
        self.bUp.SetToolTip("Move up one layer")
        self.Bind(wx.EVT_BUTTON, self.onUp, self.bUp)
        self.bUp.Enable(False)

        self.bDown = wx.BitmapButton(self,
                                     wx.ID_ANY,
                                     self.images.pngDown,
                                     size=BUTTONDIM)
        self.bDown.SetToolTip("Move down one layer")
        self.Bind(wx.EVT_BUTTON, self.onDown, self.bDown)
        self.bDown.Enable(False)

        szGcf = wx.BoxSizer(wx.HORIZONTAL)
        szGcf.AddSpacer(10)
        szGcf.Add(self.gcf)
        szGcf.Add(self.stLayerText, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)
        szGcf.AddSpacer(10)

        szNav = wx.BoxSizer(wx.VERTICAL)
        szNav.Add(self.bUp, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)
        szNav.AddSpacer(10)
        szNav.Add(self.slLayers)
        szNav.AddSpacer(10)
        szNav.Add(self.bDown, 1, wx.ALIGN_CENTER_HORIZONTAL, 1)

        szGcf.Add(szNav)
        szGcf.AddSpacer(10)

        szOpts = wx.BoxSizer(wx.HORIZONTAL)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbShowMoves)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbShowPrevious)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbToolPathOnly)
        szOpts.AddSpacer(10)
        szOpts.Add(self.cbSyncPrint)
        szOpts.AddSpacer(10)

        szBtn = wx.BoxSizer(wx.HORIZONTAL)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bImport)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bImportQ)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bOpen)
        szBtn.AddSpacer(20)
        szBtn.Add(self.bPrint)
        szBtn.AddSpacer(10)
        szBtn.Add(self.bPause)
        if self.sdcard:
            szBtn.AddSpacer(20)
            szBtn.Add(self.bSdPrintTo)
            szBtn.AddSpacer(10)
            szBtn.Add(self.bSdPrintFrom)
            szBtn.AddSpacer(10)
            szBtn.Add(self.bSdDelete)

        szBtn.AddSpacer(10)

        szDlg = wx.BoxSizer(wx.VERTICAL)
        szDlg.AddSpacer(10)
        szDlg.Add(szGcf)
        szDlg.AddSpacer(10)
        szDlg.Add(szOpts)
        szDlg.AddSpacer(10)
        szDlg.Add(szBtn)
        szDlg.AddSpacer(10)

        self.SetSizer(szDlg)
        self.Fit()
        self.Layout()

        self.propDlg = PropertiesDlg(self, wparent, self.printerName)
        self.propDlg.Show()
        if not self.settings.propposition is None:
            self.propDlg.SetPosition(self.settings.propposition)

        self.enableButtonsByState()
        self.reprap.registerPositionHandler(self.updatePrintPosition)
        self.reprap.registerEventHandler(self.reprapEvent)
        self.reprap.registerSdEventHandler(self.sdcard)

    def show(self):
        self.Show()
        self.Raise()
        self.propDlg.Show()
        self.propDlg.Raise()

    def setLayerText(self, ht):
        if ht is None:
            htv = 0.0
        else:
            htv = ht
        self.stLayerText.SetLabel("Layer Height: %0.3f" % htv)

    def getStatusReport(self):
        r = self.propDlg.getStatusReport()
        r["PrintStatus"] = PrintState.label[self.state]
        return r

    def buildTitle(self):
        t = "%s print monitor" % self.printerName

        if self.gcodeLoaded:
            if len(self.gcodeFile) > 45:
                t += " - %s" % os.path.basename(self.gcodeFile)
            else:
                t += " - %s" % self.gcodeFile

        return t

    def rememberPositions(self):
        self.settings.propposition = self.propDlg.GetPosition()

    def isPrinting(self):
        return self.state in [
            PrintState.printing, PrintState.sdprintingto,
            PrintState.sdprintingfrom
        ]

    def onClose(self, evt):
        if self.isPrinting():
            dlg = wx.MessageDialog(self, 'Cannot exit with printing active',
                                   "Printer is active",
                                   wx.OK | wx.ICON_INFORMATION)
            dlg.ShowModal()
            dlg.Destroy()
            return
        self.terminate()

    def terminate(self):
        self.reprap.registerPositionHandler(None)
        self.reprap.registerEventHandler(None)
        self.parent.closePrintMon()
        self.propDlg.Destroy()
        self.Destroy()

    def onShowMoves(self, evt):
        v = self.cbShowMoves.GetValue()
        self.settings.showmoves = v
        self.gcf.setShowMoves(v)

    def onShowPrevious(self, evt):
        v = self.cbShowPrevious.GetValue()
        self.settings.showprevious = v
        self.gcf.setShowPrevious(v)

    def onToolPathOnly(self, evt):
        v = self.cbToolPathOnly.GetValue()
        self.settings.toolpathonly = v
        self.gcf.setToolPathsOnly(v)

    def onSyncPrint(self, evt):
        v = self.cbSyncPrint.GetValue()
        self.gcf.setSyncWithPrint(v)

    def onLayerScroll(self, evt):
        v = self.slLayers.GetValue()
        if v == self.currentLayer:
            return

        self.gcf.setLayer(v)
        self.changeLayer(v)

    def onUp(self, evt):
        lmax = self.slLayers.GetRange()[1]
        if self.currentLayer >= lmax:
            return

        v = self.currentLayer + 1
        self.gcf.setLayer(v)
        self.changeLayer(v)

    def onDown(self, evt):
        if self.currentLayer <= 0:
            return

        v = self.currentLayer - 1
        self.gcf.setLayer(v)
        self.changeLayer(v)

    def onImport(self, evt):
        fn = self.wparent.importGcFile()
        if fn is None:
            return

        self.loadGFile(fn)

    def onImportFromQueue(self, evt):
        fn = self.wparent.importGcFromQueue()
        if fn is None:
            return

        self.loadGFile(fn)

    def setImportButton(self, msg):
        if msg is None:
            self.okToImport = False
            self.bImportQ.SetToolTip("")
            self.bImportQ.Enable(False)
        else:
            self.okToImport = True
            self.bImportQ.SetToolTip(msg)
            self.bImportQ.Enable(self.bOpen.IsEnabled())

    def setImportFile(self, fn):
        self.importFile = fn
        if fn is None:
            self.bImport.Enable(False)
            self.bImport.SetToolTip("")
        else:
            self.bImport.Enable(self.bOpen.IsEnabled())
            self.bImport.SetToolTip("Import G Code file (%s)" % fn)

    def onOpenFile(self, evt):
        wildcard = "GCode (*.gcode)|*.gcode;*.GCODE|"	 \
         "All files (*.*)|*.*"

        dlg = wx.FileDialog(self,
                            message="Choose a GCode file",
                            defaultDir=self.settings.lastdirectory,
                            defaultFile="",
                            wildcard=wildcard,
                            style=wx.FD_OPEN)

        rc = dlg.ShowModal()
        if rc == wx.ID_OK:
            path = dlg.GetPath().encode('ascii', 'ignore')
        dlg.Destroy()
        if rc != wx.ID_OK:
            return

        self.loadGFile(path)

    def loadGFile(self, path):
        self.settings.lastdirectory = os.path.dirname(path)

        self.loadGCode(path)

        if self.gObj is None:
            lmax = 1
            self.slLayers.Enable(False)
            self.bUp.Enable(False)
            self.bDown.Enable(False)
        else:
            lmax = self.gObj.layerCount() - 1
            self.slLayers.Enable(True)
            self.bUp.Enable(True)
            self.bDown.Enable(True)

        self.slLayers.SetRange(0, lmax)
        self.slLayers.SetPageSize(int(lmax / 10))

        self.gcf.loadModel(self.gObj)
        self.changeLayer(0)

        self.state = PrintState.idle
        self.oldState = None
        self.enableButtonsByState()
        t = self.buildTitle()
        self.SetTitle(t)
        self.propDlg.setPrintStatus(PrintState.idle)

    def loadGCode(self, fn):
        def gnormal(s):
            if ";" in s:
                return s.split(";")[0].rstrip()
            else:
                return s.rstrip()

        self.gcodeFile = None
        self.gcodeLoaded = False
        self.gcode = []
        self.gObj = None
        self.maxLine = 0
        self.totalTime = 0
        self.totalTimeStr = ""
        self.layerTimes = []
        self.layerTimeStr = []
        self.propDlg.clearAllProperties()
        self.reprap.clearPrint()
        if fn is None:
            return

        try:
            gc = list(open(fn))
        except:
            self.log("Error opening file %s" % fn)
            self.gcode = []
            self.gObj = None
            self.gcodeLoaded = False
            return

        self.gcode = [s for s in map(gnormal, gc) if s.strip() != ""]
        self.gObj = self.buildModel()
        self.maxLine = self.gObj.getMaxLine()
        self.eUsed = self.gObj.getFilament()

        self.gcodeLoaded = True
        self.gcodeFile = pfn = fn
        if len(pfn) > 45:
            pfn = os.path.basename(fn)
        self.propDlg.setProperty(PropertyEnum.fileName, pfn)
        ftime = time.strftime('%y/%m/%d-%H:%M:%S',
                              time.localtime(os.path.getmtime(fn)))
        self.propDlg.setProperty(PropertyEnum.sliceTime, ftime)
        self.propDlg.setProperty(PropertyEnum.printEstimate, self.totalTimeStr)

        if self.settings.nextruders < self.maxTool + 1:
            self.log(
                "G Code file uses more tools (%d) than printer is equipped with (%d)"
                % (self.maxTool + 1, self.settings.nextruders))

        slCfg, filSiz, tempsHE, tempsBed = parseGCSuffix(gc)

        if tempsBed == "??":
            tBed = 0
        else:
            try:
                tBed = int(float(tempsBed))
            except:
                tBed = 0

        if tempsHE == "??":
            tHe = [0] * self.settings.nextruders
        else:
            try:
                x = [int(float(x)) for x in re.split(", *", tempsHE)
                     ] + [0] * self.settings.nextruders
                tHe = x[:self.settings.nextruders]
            except:
                tHe = [0] * self.settings.nextruders

        self.parent.registerGCodeTemps(tHe, tBed)

        self.propDlg.setProperty(PropertyEnum.slicerCfg, slCfg)
        self.propDlg.setProperty(PropertyEnum.filamentSize, filSiz)
        self.propDlg.setProperty(PropertyEnum.temperatures,
                                 "HE:%s  BED:%s" % (tempsHE, tempsBed))

    def updatePrintPosition(self, position):
        self.printLayer = self.getLayerByPosition(position)
        self.printPosition = position
        if self.state in [PrintState.printing, PrintState.sdprintingto]:
            posString = "%d/%d" % (position, self.maxLine)
            if self.maxLine != 0:
                pct = float(position) / float(self.maxLine) * 100.0
                posString += " (%.1f%%)" % pct
            self.propDlg.setProperty(PropertyEnum.position, posString)
            self.gcf.setPrintPosition(position)
            lx = self.gcf.getCurrentLayer()
            if lx != self.currentLayer:
                self.changeLayer(lx)

            layersSplit = self.sumLayerTimes(self.printLayer)
            layerSplit = self.partialPrintingLayer()

            self.elapsed = time.time() - self.startTime
            expected = layersSplit[0] + layerSplit[0]
            elapsedStr = "%s (expected: %s)" % (formatElapsed(
                self.elapsed), formatElapsed(expected))
            self.propDlg.setProperty(PropertyEnum.elapsed, elapsedStr)

            self.remaining = layersSplit[1] + layerSplit[1]
            self.propDlg.setProperty(PropertyEnum.remaining,
                                     formatElapsed(self.remaining))
            #TODO - probably don't need all the various time estimates when printing TO CD
            # BUT IT MAY BREAK LOGIC BELOW (update time until) that rely on these values

            newEta = time.time() + self.remaining
            revisedStr = time.strftime('%H:%M:%S', time.localtime(newEta))
            tdiff = newEta - self.origEta
            if tdiff < 0:
                revisedStr += "  (%s ahead of estimate)" % formatElapsed(
                    -tdiff)
            elif tdiff > 0:
                revisedStr += "  (%s behind estimate)" % formatElapsed(tdiff)
            self.propDlg.setProperty(PropertyEnum.revisedEta, revisedStr)
            self.updateTimeUntil()

        elif self.state == PrintState.sdprintingfrom:
            #TODO Need to convey print position when printing from SD card
            pass

    def getLayerByPosition(self, pos):
        for lx in range(len(self.layerMap)):
            if self.layerMap[lx][0] <= pos and pos <= self.layerMap[lx][1]:
                return lx

        return 0

    def partialPrintingLayer(self):
        f, l = self.gObj.getGCodeLines(self.printLayer)
        if f <= self.printPosition and self.printPosition <= l:
            done = self.printPosition - f
            todo = l - self.printPosition + 1
            total = l - f + 1

            lt = self.layerTimes[self.printLayer]
            pctDone = float(done) / float(total)
            pctToDo = float(todo) / float(total)
            return (pctDone * lt, pctToDo * lt)
        else:
            return (0.0, 0.0)

    def sumLayerTimes(self, lx):
        tBefore = sum(self.layerTimes[:lx])
        tAfter = sum(self.layerTimes[lx + 1:])
        return (tBefore, tAfter)

    def sumLayerRangeTime(self, slx, elx):
        return sum(self.layerTimes[slx:elx])

    def changeLayer(self, lx):
        self.currentLayer = lx
        self.slLayers.SetValue(lx)
        ht = self.gObj.getLayerHeight(lx)
        self.setLayerText(ht)
        if ht is None:
            self.propDlg.setProperty(PropertyEnum.layerNum,
                                     "%d / %d" % (lx, self.gObj.layerCount()))
        else:
            self.propDlg.setProperty(
                PropertyEnum.layerNum,
                "%d / %d (%.2f mm) " % (lx, self.gObj.layerCount(), ht))

        f, l = self.gObj.getGCodeLines(lx)
        if f is None:
            self.propDlg.setProperty(PropertyEnum.gCodeRange, "")
            self.layerRange = (0, 0)
        else:
            self.propDlg.setProperty(PropertyEnum.gCodeRange,
                                     "%d - %d" % (f, l))
            self.layerRange = (f, l)

        x0, y0, xn, yn = self.gObj.getLayerMinMaxXY(lx)
        if x0 is None:
            self.propDlg.setProperty(PropertyEnum.minMaxXY, "")
        else:
            self.propDlg.setProperty(
                PropertyEnum.minMaxXY,
                "(%.2f, %.2f) - (%.2f, %.2f)" % (x0, y0, xn, yn))

        le, prior, after = self.gObj.getLayerFilament(lx)

        s = []
        for i in range(self.settings.nextruders):
            s.append("%.2f/%.2f    <: %.2f    >: %.2f" %
                     (le[i], self.eUsed[i], prior[i], after[i]))

        self.propDlg.setProperty(PropertyEnum.filamentUsed, s)

        self.propDlg.setProperty(
            PropertyEnum.layerPrintTime,
            "%s / %s" % (self.layerTimeStr[lx], self.totalTimeStr))

        self.updateTimeUntil()

    def updateTimeUntil(self):
        if self.currentLayer <= self.printLayer:
            self.propDlg.setProperty(PropertyEnum.timeUntil, "")
        elif self.printPosition is None:
            t = sum(self.layerTimes[:self.currentLayer])
            self.propDlg.setProperty(PropertyEnum.timeUntil, formatElapsed(t))
        else:
            t = sum(self.layerTimes[self.printLayer + 1:self.currentLayer]
                    ) + self.partialPrintingLayer()[1]
            self.propDlg.setProperty(PropertyEnum.timeUntil, formatElapsed(t))

    def reprapEvent(self, evt):
        if evt.event == RepRapEventEnum.PRINT_COMPLETE:
            # TODO - do I need special consideration here for print FROM SD
            if self.state == PrintState.sdprintingto:
                self.reprap.sendNow("M29 %s" % self.sdTargetFile)
                self.reprap.suspendTempProbe(False)
                self.setSDTargetFile(None)

            if self.state == PrintState.printing:
                self.history.addEvent(
                    PrintCompleted(self.history.addFile(self.gcodeFile), ""))

            self.state = PrintState.idle
            self.oldState = None
            self.propDlg.setPrintStatus(PrintState.idle)
            self.gcf.setPrintPosition(-1)
            self.printPosition = None
            self.printLayer = 0
            self.enableButtonsByState()
            self.elapsed = time.time() - self.startTime
            cmpTime = time.time()
            expCmpTime = self.origEta - self.startTime
            cmpTimeStr = time.strftime('%H:%M:%S', time.localtime(cmpTime))
            self.log("Print completed at %s" % (cmpTimeStr))
            self.log("Total print time of %s - expected print time %s" %
                     (formatElapsed(self.elapsed), formatElapsed(expCmpTime)))
            self.reprap.printComplete()
        elif evt.event == RepRapEventEnum.PRINT_STOPPED:
            if self.state != PrintState.paused:
                self.oldState = self.state
                self.state = PrintState.paused
                self.propDlg.setPrintStatus(PrintState.paused)
                self.enableButtonsByState()
            self.reprap.printStopped()
        elif evt.event == RepRapEventEnum.PRINT_STARTED:
            pass
        elif evt.event == RepRapEventEnum.PRINT_RESUMED:
            pass
        elif evt.event == RepRapEventEnum.PRINT_ERROR:
            self.log("Error communicating with printer")
        elif evt.event == RepRapEventEnum.PRINT_SENDGCODE:
            self.log(evt.msg)
        else:
            self.log("unknown reprap event: %s" % str(evt.event))

    def buildModel(self):
        cnc = CNC(self.settings.acceleration, self.settings.layerheight)
        if RECORD_TIMES:
            self.log("recording g code times in /tmp/gcodeTimes")
            fp = open("/tmp/gcodeTimes", "w")

        ln = -1
        for gl in self.gcode:
            ln += 1

            p = re.split("\\s+", gl, 1)

            params = {}
            if not (p[0].strip() in ["M117", "m117"]):
                if len(p) >= 2:
                    self.paramStr = p[1]

                    if "X" in self.paramStr:
                        params["X"] = self._get_float("X")

                    if "Y" in self.paramStr:
                        params["Y"] = self._get_float("Y")

                    if "Z" in self.paramStr:
                        params["Z"] = self._get_float("Z")

                    if "E" in self.paramStr:
                        params["E"] = self._get_float("E")

                    if "F" in self.paramStr:
                        params["F"] = self._get_float("F")

                    if "S" in self.paramStr:
                        params["S"] = self._get_float("S")

                    if "P" in self.paramStr:
                        params["P"] = self._get_float("P")

            t = cnc.execute(p[0], params, ln)
            if RECORD_TIMES:
                fp.write("(%s) (%.3f)\n" % (gl, t))

        if RECORD_TIMES:
            fp.close()

        gobj = cnc.getGObject()
        gobj.setMaxLine(ln)
        self.maxTool = cnc.getMaxTool()
        self.totalTime, self.layerTimes = cnc.getTimes()
        self.layerMap = []
        for lx in range(len(gobj)):
            self.layerMap.append(gobj.getGCodeLines(lx))

        self.totalTimeStr = formatElapsed(self.totalTime)
        self.layerTimeStr = [formatElapsed(s) for s in self.layerTimes]
        return gobj

    def _get_float(self, which):
        try:
            return float(gcRegex.findall(self.paramStr.split(which)[1])[0])
        except:
            self.log("unable to parse float from (%s)" % self.paramStr)

    def enableButtonsByState(self):
        if self.state == PrintState.idle:
            self.bOpen.Enable(True)
            self.setImportFile(self.importFile)
            self.bImportQ.Enable(self.okToImport)
            if self.sdcard:
                self.bSdPrintTo.Enable(self.gcodeLoaded)
                self.bSdPrintFrom.Enable()
                self.bSdDelete.Enable()

            if self.gcodeLoaded:
                self.bPrint.Enable(True)
                self.bPrint.setPrint()
                self.bPause.Enable(False)
                self.bPause.setPause()
            else:
                self.bPrint.Enable(False)
                self.bPause.Enable(False)
        elif self.state in [PrintState.printing, PrintState.sdprintingto]:
            self.bImport.Enable(False)
            self.bImportQ.Enable(False)
            self.bOpen.Enable(False)
            self.bPrint.Enable(False)
            self.bPrint.setPrint()
            self.bPause.Enable(True)
            self.bPause.setPause()
            if self.sdcard:
                self.bSdPrintTo.Enable(False)
                self.bSdPrintFrom.Enable(False)
                self.bSdDelete.Enable(False)
        elif self.state == PrintState.sdprintingfrom:
            #TODO - what makes sense here
            pass
        elif self.state == PrintState.paused:
            self.bOpen.Enable(True)
            self.setImportFile(self.importFile)
            self.bImportQ.Enable(self.okToImport)
            self.bPrint.Enable(True)
            self.bPrint.setRestart()
            self.bPause.Enable(True)
            self.bPause.setResume()
            if self.sdcard:
                self.bSdPrintTo.Enable(self.gcodeLoaded)
                self.bSdPrintFrom.Enable()
                self.bSdDelete.Enable()

    def emulatePrintButton(self):
        if self.state in [
                PrintState.printing, PrintState.sdprintingto,
                PrintState.sdprintingfrom
        ]:
            self.log("Already printing")
        elif not self.bPrint.IsEnabled():
            self.log("Unable to print right now")
        else:
            self.onPrint(None)

    def reset(self):
        #TODO - cleanup if was sdprintingfrom
        self.state = PrintState.idle
        self.oldState = None
        self.reprap.suspendTempProbe(False)
        self.setSDTargetFile(None)
        self.propDlg.setPrintStatus(PrintState.idle)
        self.enableButtonsByState()

    def onPrint(self, evt):
        oldState = self.state
        self.state = PrintState.printing
        self.propDlg.setPrintStatus(PrintState.printing)
        self.enableButtonsByState()

        self.printPos = 0
        self.startTime = time.time()
        self.endTime = None
        self.origEta = self.startTime + self.totalTime
        self.elapsed = 0
        self.remaining = self.totalTime
        if oldState == PrintState.paused:
            action = "restarted"
            self.reprap.restartPrint(self.gcode)
        else:
            action = "started"
            self.reprap.startPrint(self.gcode)

        self.history.addEvent(
            PrintStarted(self.history.addFile(self.gcodeFile), ""))

        stime = time.strftime('%H:%M:%S', time.localtime(self.startTime))
        self.propDlg.setProperty(PropertyEnum.startTime, stime)
        self.propDlg.setProperty(
            PropertyEnum.origEta,
            time.strftime('%H:%M:%S', time.localtime(self.origEta)))
        self.propDlg.setProperty(PropertyEnum.elapsed,
                                 formatElapsed(self.elapsed))
        self.propDlg.setProperty(PropertyEnum.remaining,
                                 formatElapsed(self.remaining))
        self.propDlg.setProperty(PropertyEnum.revisedEta, "")
        self.log("Print %s at %s" % (action, stime))

    def onSdPrintFrom(self, evt):
        print "sd print from"

    def doSDPrintFrom(self, evt):
        self.printing = False
        self.paused = False
        self.sdpaused = False
        self.sdprintingfrom = True
        self.sdStartTime = time.time()
        #self.infoPane.setSDStartTime(self.sdStartTime)
        self.state = PrintState.printing
        #self.propDlg.setPrintStatus(PrintState.printing)
        self.enableButtonsByState()
        self.sdcard.startPrintFromSD()

    def cancelSDPrintFrom(self):
        self.sdprintingfrom = False
        self.printing = False
        self.paused = False
        self.state = PrintState.idle
        #self.propDlg.setPrintStatus(PrintState.printing)
        self.enableButtonsByState()

    def resumeSDPrintFrom(self, fn):
        #self.clearModel()
        self.reprap.sendNow("M23 " + fn[1].lower())
        self.reprap.sendNow("M24")
        self.sdprintingfrom = True
        #self.M27Timer.Start(M27Interval, True)
        self.sdpaused = False
        #self.infoPane.setMode(MODE_FROM_SD)
        self.enableButtonsByState()

    def onSdPrintTo(self, evt):
        self.sdcard.startPrintToSD()

    def resumeSDPrintTo(self, tfn):
        self.setSDTargetFile(tfn[1].lower())
        self.reprap.suspendTempProbe(True)
        self.reprap.sendNow("M28 %s" % self.sdTargetFile)
        self.printPos = 0
        self.startTime = time.time()
        self.endTime = None
        self.reprap.startPrint(self.gcode)

        self.origEta = self.startTime + self.totalTime
        self.elapsed = 0
        self.remaining = self.totalTime

        self.state = PrintState.sdprintingto

        stime = time.strftime('%H:%M:%S', time.localtime(self.startTime))
        self.propDlg.setProperty(PropertyEnum.startTime, stime)
        self.propDlg.setProperty(
            PropertyEnum.origEta,
            time.strftime('%H:%M:%S', time.localtime(self.origEta)))
        self.propDlg.setProperty(PropertyEnum.elapsed,
                                 formatElapsed(self.elapsed))
        self.propDlg.setProperty(PropertyEnum.remaining,
                                 formatElapsed(self.remaining))
        self.propDlg.setProperty(PropertyEnum.revisedEta, "")
        self.log("Print to SD: %s started at %s" % (self.sdTargetFile, stime))

        self.enableButtonsByState()

    def setSDTargetFile(self, tfn):
        self.sdTargetFile = tfn
        self.propDlg.setSDTargetFile(tfn)

    def onSdDelete(self, evt):
        self.sdcard.startDeleteFromSD()

    def emulatePauseButton(self):
        if not self.bPause.IsEnabled():
            self.log("Unable to pause right now")
        else:
            self.onPause(None)

    def onPause(self, evt):
        if self.state == PrintState.paused:
            self.state = self.oldState
            if self.state is None:
                self.state = PrintState.printing
            self.propDlg.setPrintStatus(self.state)
            self.enableButtonsByState()
            self.reprap.resumePrint()
        else:
            self.oldState = self.state
            self.state = PrintState.paused
            self.propDlg.setPrintStatus(PrintState.paused)
            self.enableButtonsByState()
            self.reprap.pausePrint()
Example #11
0
def mount_tf(self, mount_point="/"):
    sd = SDCard(SPI(0), Pin("A15", mode=Pin.OUT))
    os.mount(sd, mount_point)