Example #1
0
 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=[]
Example #2
0
 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")    
Example #3
0
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")
                    
Example #4
0
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")