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)
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()