chiark / gitweb /
If programmer based auto-detection of serial port fails, try all ports and baudrates...
[cura.git] / Cura / util / machineCom.py
index 9df8d72142880f4f98fbe844509683d0278c54ad..8e14aac35c5ce3e6754bbda01e2d113a7a9dfad4 100644 (file)
@@ -41,12 +41,12 @@ def serialList(forAutoDetect=False):
        if forAutoDetect:
                baselist = baselist + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + glob.glob("/dev/cu.usb*")
                baselist = filter(lambda s: not 'Bluetooth' in s, baselist)
+               prev = profile.getMachineSetting('serial_port_auto')
+               if prev in baselist:
+                       baselist.remove(prev)
+                       baselist.insert(0, prev)
        else:
                baselist = baselist + glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyACM*') + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/rfcomm*")
-       prev = profile.getMachineSetting('serial_port_auto')
-       if prev in baselist:
-               baselist.remove(prev)
-               baselist.insert(0, prev)
        if version.isDevVersion() and not forAutoDetect:
                baselist.append('VIRTUAL')
        return baselist
@@ -116,7 +116,7 @@ class VirtualPrinter():
                                return ''
                        if self.readList is None:
                                return ''
-               time.sleep(0.1)
+               time.sleep(0.001)
                #print "Recv: %s" % (self.readList[0].rstrip())
                return self.readList.pop(0)
        
@@ -171,6 +171,7 @@ class MachineCom(object):
                self._callback = callbackObject
                self._state = self.STATE_NONE
                self._serial = None
+               self._serialDetectList = []
                self._baudrateDetectList = baudrateList()
                self._baudrateDetectRetry = 0
                self._extruderCount = int(profile.getMachineSetting('extruder_amount'))
@@ -284,8 +285,8 @@ class MachineCom(object):
                #Open the serial port.
                if self._port == 'AUTO':
                        self._changeState(self.STATE_DETECT_SERIAL)
-                       programmer = stk500v2.Stk500v2()
                        self._log("Serial port list: %s" % (str(serialList(True))))
+                       programmer = stk500v2.Stk500v2()
                        for p in serialList(True):
                                try:
                                        self._log("Connecting to: %s" % (p))
@@ -299,6 +300,8 @@ class MachineCom(object):
                                except:
                                        self._log("Unexpected error while connecting to serial port: %s %s" % (p, getExceptionString()))
                                programmer.close()
+                       if self._serial is None:
+                               self._serialDetectList = serialList(True)
                elif self._port == 'VIRTUAL':
                        self._changeState(self.STATE_OPEN_SERIAL)
                        self._serial = VirtualPrinter()
@@ -312,17 +315,17 @@ class MachineCom(object):
                                        self._serial = serial.Serial(str(self._port), self._baudrate, timeout=2, writeTimeout=10000)
                        except:
                                self._log("Unexpected error while connecting to serial port: %s %s" % (self._port, getExceptionString()))
-               if self._serial == None:
-                       self._log("Failed to open serial port (%s)" % (self._port))
-                       self._errorValue = 'Failed to autodetect serial port.'
-                       self._changeState(self.STATE_ERROR)
-                       return
-               self._log("Connected to: %s, starting monitor" % (self._serial))
-               if self._baudrate == 0:
-                       self._changeState(self.STATE_DETECT_BAUDRATE)
+               if self._serial is None:
+                       baudrate = self._baudrate
+                       if baudrate == 0:
+                               baudrate = self._baudrateDetectList.pop(0)
+                       self._serial = serial.Serial(self._serialDetectList.pop(0), baudrate, timeout=0.1, writeTimeout=10000)
                else:
-                       self._changeState(self.STATE_CONNECTING)
-
+                       self._log("Connected to: %s, starting monitor" % (self._serial))
+                       if self._baudrate == 0:
+                               self._changeState(self.STATE_DETECT_BAUDRATE)
+                       else:
+                               self._changeState(self.STATE_CONNECTING)
                #Start monitoring the serial port.
                if self._state == self.STATE_CONNECTING:
                        timeout = time.time() + 15
@@ -334,7 +337,8 @@ class MachineCom(object):
                        if line is None:
                                break
                        
-                       #No matter the state, if we see an error, goto the error state and store the error for reference.
+                       #No matter the state, if we see an fatal error, goto the error state and store the error for reference.
+                       # Only goto error on known fatal errors.
                        if line.startswith('Error:'):
                                #Oh YEAH, consistency.
                                # Marlin reports an MIN/MAX temp error as "Error:x\n: Extruder switched off. MAXTEMP triggered !\n"
@@ -343,25 +347,30 @@ class MachineCom(object):
                                if re.match('Error:[0-9]\n', line):
                                        line = line.rstrip() + self._readline()
                                #Skip the communication errors, as those get corrected.
-                               if 'checksum mismatch' in line or 'Line Number is not Last Line Number' in line or 'No Line Number with checksum' in line or 'No Checksum with line number' in line:
-                                       pass
-                               elif not self.isError():
-                                       self._errorValue = line[6:]
-                                       self._changeState(self.STATE_ERROR)
+                               if 'Extruder switched off' in line or 'Temperature heated bed switched off' in line or 'Something is wrong, please turn off the printer.' in line:
+                                       if not self.isError():
+                                               self._errorValue = line[6:]
+                                               self._changeState(self.STATE_ERROR)
                        if ' T:' in line or line.startswith('T:'):
-                               self._temp[self._temperatureRequestExtruder] = float(re.search("[0-9\.]*", line.split('T:')[1]).group(0))
-                               if ' B:' in line:
-                                       self._bedTemp = float(re.search("[0-9\.]*", line.split(' B:')[1]).group(0))
+                               try:
+                                       self._temp[self._temperatureRequestExtruder] = float(re.search("T: *([0-9\.]*)", line).group(1))
+                               except:
+                                       pass
+                               if 'B:' in line:
+                                       try:
+                                               self._bedTemp = float(re.search("B: *([0-9\.]*)", line).group(1))
+                                       except:
+                                               pass
                                self._callback.mcTempUpdate(self._temp, self._bedTemp, self._targetTemp, self._bedTargetTemp)
                                #If we are waiting for an M109 or M190 then measure the time we lost during heatup, so we can remove that time from our printing time estimate.
                                if not 'ok' in line and self._heatupWaitStartTime != 0:
                                        t = time.time()
                                        self._heatupWaitTimeLost = t - self._heatupWaitStartTime
                                        self._heatupWaitStartTime = t
-                       elif line.strip() != '' and line.strip() != 'ok' and not line.startswith('Resend:') and line != 'echo:Unknown command:""\n' and self.isOperational():
+                       elif line.strip() != '' and line.strip() != 'ok' and not line.startswith('Resend:') and not line.startswith('Error:checksum mismatch') and not line.startswith('Error:Line Number is not Last Line Number+1') and line != 'echo:Unknown command:""\n' and self.isOperational():
                                self._callback.mcMessage(line)
 
-                       if self._state == self.STATE_DETECT_BAUDRATE:
+                       if self._state == self.STATE_DETECT_BAUDRATE or self._state == self.STATE_DETECT_SERIAL:
                                if line == '' or time.time() > timeout:
                                        if len(self._baudrateDetectList) < 1:
                                                self.close()
@@ -374,7 +383,20 @@ class MachineCom(object):
                                                self._sendCommand("M105")
                                                self._testingBaudrate = True
                                        else:
-                                               baudrate = self._baudrateDetectList.pop(0)
+                                               if self._state == self.STATE_DETECT_SERIAL:
+                                                       if len(self._serialDetectList) == 0:
+                                                               if len(self._baudrateDetectList) == 0:
+                                                                       self._log("Tried all serial ports and baudrates, but still not printer found that responds to M105.")
+                                                                       self._errorValue = 'Failed to autodetect serial port.'
+                                                                       self._changeState(self.STATE_ERROR)
+                                                                       return
+                                                               else:
+                                                                       self._serialDetectList = serialList(True)
+                                                                       baudrate = self._baudrateDetectList.pop(0)
+                                                       self._serial.close()
+                                                       self._serial = serial.Serial(self._serialDetectList.pop(0), baudrate, timeout=0.5, writeTimeout=10000)
+                                               else:
+                                                       baudrate = self._baudrateDetectList.pop(0)
                                                try:
                                                        self._setBaudrate(baudrate)
                                                        self._serial.timeout = 0.5
@@ -400,7 +422,7 @@ class MachineCom(object):
                                else:
                                        self._testingBaudrate = False
                        elif self._state == self.STATE_CONNECTING:
-                               if line == '':
+                               if line == '' or 'wait' in line:        # 'wait' needed for Repetier (kind of watchdog)
                                        self._sendCommand("M105")
                                elif 'ok' in line:
                                        self._changeState(self.STATE_OPERATIONAL)