def __init__(self,filePath=None): Task.__init__(self,"print") self.logger=logging.getLogger("dobozweb.core.Automation.PrintTask") self.logger.setLevel(logging.ERROR) self.filePath=filePath self.totalLines=1 self.lastLine=None self.currentLine=0#for post error recup self.reconnectionCommand=None self.currentLayer=0#for layer counting self.totalLayers=0 self.currentLayerValue=0#the actual z component self.pointCloud=PointCloud() self.source=None self.recoveryMode=False self.doLayerAnalysis=False """For all things related to the print positioning tracking """ self.gcodeParser=GCodeParser() """For the history of all previous commands this will need to be replaced with something more robust in the future""" self.gcodeHistoryMaxSize=100 self.gcodeHistoryIndex=0 self.gcodeHistory=[]
def __init__(self,scanWidth=1,scanLength=1,resolution=1,passes=1,filePath=None,saveScan=False): Task.__init__(self,"scan") self.logger=logging.getLogger("dobozweb.core.Automation.ScanTask") self.logger.setLevel(logging.ERROR) self.width=scanWidth self.length=scanLength self.resolution=resolution self.filePath=filePath self.saveScan=saveScan self.pointCloud=PointCloud() self.pointCloudBuilder=PointCloudBuilder(resolution=resolution,width=scanWidth,length=scanLength,passes=passes) totalPoints=(int(scanWidth/resolution)+1)*(int(scanLength/resolution)+1)*passes self.logger.info("Total scan points %d",totalPoints) self.progressFraction=float(100.00/float(totalPoints)) self.logger.info("Progress Fraction set by scan to %s",str(self.progressFraction)) self.logger.critical("Task Init Done")
class ScanTask(Task): """For all things related to the scanning """ def __init__(self,scanWidth=1,scanLength=1,resolution=1,passes=1,filePath=None,saveScan=False): Task.__init__(self,"scan") self.logger=logging.getLogger("dobozweb.core.Automation.ScanTask") self.logger.setLevel(logging.ERROR) self.width=scanWidth self.length=scanLength self.resolution=resolution self.filePath=filePath self.saveScan=saveScan self.pointCloud=PointCloud() self.pointCloudBuilder=PointCloudBuilder(resolution=resolution,width=scanWidth,length=scanLength,passes=passes) totalPoints=(int(scanWidth/resolution)+1)*(int(scanLength/resolution)+1)*passes self.logger.info("Total scan points %d",totalPoints) self.progressFraction=float(100.00/float(totalPoints)) self.logger.info("Progress Fraction set by scan to %s",str(self.progressFraction)) self.logger.critical("Task Init Done") def __str__(self): string='{"id": "%s", "type": "%s", "width": %s, "height":%f, "resolution": %s}' %(str(self.id), self.type,self.width,self.length,self.resolution) return string def connect(self,connector): self.connector=connector if hasattr(self.connector, 'events'): self.connector.events.OnDataRecieved+=self._data_recieved # self.connector.events.OnDisconnected+=self.on_connector_disconnect # self.connector.events.OnReconnected+=self.on_connector_reconnect def disconnect(self): """Dsiconnected the task from the connector: to remove event handling """ self.connector.events.OnDataRecieved-=self._data_recieved self.connector=None def start(self): self.status="SR"#actual first start self.events.OnEntered(self,"Entered") ####################### #Initialize base position self.connector.send_command("G21") self.connector.send_command("G90") self.connector.send_command("G92") ptBld=self.pointCloudBuilder.currentPoint self.connector.send_command("G1 X"+str(ptBld.x)+" Y"+str(ptBld.y)) def stop(self): self.status="NP" self.events.OnExited(self,"OnExited") def _do_action_step(self): #move the printhead , ask for scan, wait for answer if not self.pointCloudBuilder.finished: self.progress+=self.progressFraction ptBld=self.pointCloudBuilder.currentPoint ptStr="G1 X"+str(ptBld.x)+" Y"+str(ptBld.y) self.connector.send_command(ptStr) else: self.progress=100 self.pointCloud=self.pointCloudBuilder.pointCloud self.status="F"#finished if self.saveScan: if self.filePath: self.pointCloud.save(self.filePath) else: pass self.connector.send_command("G1 X0 Y0") self.totalTime+=time.time()-self.startTime self.startTime=time.time() def _data_recieved(self,args,kargs): """ Function that gets called each time a new serial event is recieved. If the last command was confirmed, move to next position and get height info """ self.logger.info("event recieved from reprap %s",str(kargs)) if self.status!="F": if "ok" in kargs: if "height" in kargs: try: height=float(kargs.split(' ')[2]) height=height/50 self.logger.info("Scan thing %s",str(height)) #self.events.OnScanHeightRecieved(height) self.pointCloudBuilder.add_point(height) self.logger.critical("current point %s",str(self.pointCloudBuilder.currentPoint)) self.pointCloudBuilder.next_point_continuous() self.pointCloud=self.pointCloudBuilder.pointCloud except: pass if self.status!="NP" and self.status!="SP": self._do_action_step() else: if not "G92" in kargs and not "G90" in kargs and not "G21" in kargs and "G1" in kargs and self.status!="NP" and self.status!="SP" : self.connector.send_command("M180") else: if "ok" in kargs and "G1" in kargs: self.events.OnExited(self,"OnExited")
class PrintTask(Task): """ A task for printing gcode files""" def __init__(self,filePath=None): Task.__init__(self,"print") self.logger=logging.getLogger("dobozweb.core.Automation.PrintTask") self.logger.setLevel(logging.ERROR) self.filePath=filePath self.totalLines=1 self.lastLine=None self.currentLine=0#for post error recup self.reconnectionCommand=None self.currentLayer=0#for layer counting self.totalLayers=0 self.currentLayerValue=0#the actual z component self.pointCloud=PointCloud() self.source=None self.recoveryMode=False self.doLayerAnalysis=False """For all things related to the print positioning tracking """ self.gcodeParser=GCodeParser() """For the history of all previous commands this will need to be replaced with something more robust in the future""" self.gcodeHistoryMaxSize=100 self.gcodeHistoryIndex=0 self.gcodeHistory=[] # self.logFile=open("log.txt","r") # logContent=self.logFile.read() # self.logFile.close() # if logContent.find("ok")==-1: # #read line # self.logger.critical("last instance of program failed, loading up file") # self.set_filePath_fromLog() def __str__(self): string='{"id": "%s", "type": "%s", "file": "%s"}' %(str(self.id), self.type, os.path.basename(self.filePath)) return string def connect(self,connector): self.connector=connector print(self.connector) if hasattr(self.connector, 'events'): self.connector.events.OnDataRecieved+=self._data_recieved # self.connector.events.OnDisconnected+=self.on_connector_disconnect # self.connector.events.OnReconnected+=self.on_connector_reconnect def disconnect(self): self.connector.events.OnDataRecieved-=self._data_recieved self.connector=None def start(self): """ Starts the current print task""" self._set_filePath() try: self.source=open(self.filePath,"r") self._forward_toLine(self.currentLine)#go to requested start line self.status="SR"#actual first start self.events.OnEntered(self,"Entered") self._do_action_step() except Exception as inst: self.logger.critical("invalid gcode file %s",str(inst)) def _forward_toLine(self,lineNumber): """ Function to go to a specific line of the gcode file Params: lineNumber: the line we want to go to """ if lineNumber>0: line = self.source.readline() lineIndex=0 while line: if lineIndex>=self.currentLine: self.currentLine=lineIndex print("going to line ",self.currentLine) break line = self.source.readline() lineIndex+=1 def _set_filePath(self): """ This function sets the current sourceFile, parses it for line numbers and layer count, sets everything up, and sends adapted events """ self.logger.critical("setting filePath: %s",self.filePath) try: self.source=open(self.filePath,"r") if not self.recoveryMode: self.currentLine=0 else: self.forward_toLine(self.currentLine) self.totalLayers=0 lastZ=0 lineIndex=self.currentLine for line in self.source.readlines(): #TODO: some more inteligent "guestimate" of layers : read from the start, get two diferent z components, read from the end, get last Z component # layerInfo=self.gcodeParser.parse(line) # try: # zInfo=float(layerInfo.zcmd.value.to_eng_string()) # if zInfo!=lastZ: # self.totalLayers+=1 # lastZ=zInfo # except: # pass lineIndex+=1 self.source.close() self.totalLines=lineIndex #- self.currentLine+1 print("TOTALLINES",self.totalLines) if self.totalLayers>2: self.totalLayers-=2 #self.logger.critical("Total layers %g",self.totalLayers) #self.events.OnTotalLinesSet(self,str(self.totalLines)) #self.events.OnTotalLayersSet(self,str(self.totalLayers)) self.progressFraction=float(100/float(self.totalLines)) self.logger.info("totalLines %s",str(self.totalLines)) self.logger.info("ProgressFraction set %s",str(self.progressFraction)) self.progress=0 self.logFile=open("log.txt",'w') self.logFile.write("path="+str(self.filePath)) self.logFile.close() except Exception as inst: self.logger.critical("can't load file %s",str(inst)) def _set_filePath_fromLog(self): """ This function is for recovery mode exclusively: it gets the params of the last loaded gcode file and the last send gcode line from the log file """ try: self.logFile=open("log.txt",'r') number = Word(nums) #parse last filePath and lineNumber path=Dict(OneOrMore(Group("path"+"="+SkipTo( "," | stringEnd )))) lastline=Dict(OneOrMore(Group("line"+'='+ number))) tmp=path+Optional(",")+Optional(lastline) ln=self.logFile.readline() params=tmp.parseString(ln).asDict() self.logFile.close() self.recoveryMode=True try: self.currentLine=eval(params["line="]) #skip one line : it is better to lose one command than loose the print self.currentLine+=1 except: self.currentLine=0 self.set_filePath(params["path="]) self.events.OnPathSet(self,params["path="]) self.recoveryMode=False except: pass def _do_action_step(self): """ gets the next line in the gCode file, sends it via serial, updates the logFile and then increments the currentLine counter """ line=None print("LINe",line,"linenb",self.currentLine,"progress",self.progress) try: line = self.source.readline() self.line=line self.lastLine=line except : pass if line is not None: if line!= "":# and line !="\n" and line != "\r\n" and line != "\n\r": self.connector.add_command(line,answerRequired=True) try: self.gcodeHistory.insert(self.gcodeHistoryIndex, line) if len(self.gcodeHistory)>self.gcodeHistoryMaxSize: self.gcodeHistoryIndex=0 except: pass """ Update the logfile with the current Line number """ self.logger.debug("Sent command "+ line) self.currentLine+=1 pos=self.gcodeParser.parse(line) if pos: try: #self.position=[pos.xcmd.value.to_eng_string(),pos.zcmd.value.to_eng_string(),pos.ycmd.value.to_eng_string()] x=float(pos.xcmd.value.to_eng_string()) y=float(pos.ycmd.value.to_eng_string()) z=float(pos.zcmd.value.to_eng_string()) if z!=self.currentLayerValue: self.currentLayer+=1 self.currentLayerValue=z self.pointCloud.add_point(Point(x/20,y/20,z/20)) except Exception as inst: self.logger.debug("failed to add point to movement map %s",str(inst)) self.totalTime+=time.time()-self.startTime self.startTime=time.time() if self.currentLine==self.totalLines: self.progress=100 self.status="F" self.events.OnExited(self,"OnExited") else: self.progress+=self.progressFraction else: print("empty line") self.currentLine+=1 if (self.currentLine)<self.totalLines: self.progress+=self.progressFraction self._do_action_step() else: self.progress=100 self.status="F" self.events.OnExited(self,"OnExited") def _data_recieved(self,args,kargs): """ Function that gets called each time a new serial event is recieved. If the last command was confirmed, read next line frome gcode file, and send it over serial. """ command=kargs self.logger.debug("event recieved from reprap %s",str(command)) if self.reconnectionCommand and self.status=="SP": if self.reconnectionCommand in command.answer: self.reconnectionCommand=None if self.status!="NP" and self.status!="SP":#not paused if "ok" in command.answer or "start" in command.answer and not command.special: self._do_action_step() # tmpLastLine=(self.lastLine.rstrip()).replace("\n","") # tmpAnsw=" ".join(kargs.lstrip().split(' ')[:-1]) # tmpAnswLine=tmpAnsw.rstrip() # # if tmpLastLine == tmpAnswLine:#did we recieve the right answer def stop(self): """ clean shutdown mode """ self.status="NP" try: self.source.close() except: pass self.logFile=open("log.txt","a") self.logFile.write(", shutdown=ok") self.events.OnExited(self,"OnExited")