def __init__(self, parent):
        super(decideToUpdateSigma, self).__init__(parent,
                                                  _('Firmware Updater'))

        self._port = 'AUTO'
        self._baudrate = 250000

        if self._port == 'AUTO':
            print 'entramos en port auto despues de baudrate'
            programmer = stk500v2.Stk500v2()
            print 'antes', self._port
            if not programmer.isConnected():
                print 'not connected'
                for self._port in machineCom.serialList(False):
                    try:
                        print 'despues', self._port
                        programmer.connect(self._port)
                        print 'lo que devuelve', programmer.isConnected()
                        print self._baudrate
                        profile.putMachineSetting('serial_port_auto',
                                                  self._port)
                        print 'hemos llegado despues del port'
                        print self._port
                        #wx.MessageBox('esto es lo que tenemoss',self._port)
                        programmer.close()
                        self._serial = serial.Serial(str(self._port),
                                                     self._baudrate,
                                                     timeout=1)
                        print self._serial
                        profile.putMachineSetting('self_serial', self._serial)
                        self._state = 'Online'
                        print 'bueno', self._state
                        break
                    except ispBase.IspError as (e):
                        self._state = 'Offline'
                        pass
                    programmer.close()
                if self._port not in machineCom.serialList(False):
                    self._state = 'Offline'
                    print 'malo', self._state

        if self._state == 'Offline':
            self.AddText(
                _('Please connect your printer to the computer.\n\n'
                  'In case you already had it connected and it was not detected,\n'
                  'please disconnect and connect again.\n\n'
                  'Once you have done this, you may press Connect && Upgrade to\n'
                  'continue with the process.\n\n'
                  '(Note: this may take a minute)\n'))
            connectButton = self.AddButton('Connect && Upgrade')
            connectButton.Bind(wx.EVT_BUTTON, self.OnWantToConnect)
            self.AddSeperator()
        if self._state == 'Online':
            self.AddText(
                _('We have detected a printer, please press Upgrade to continue\n'
                  'with the process.\n\n'
                  '(Note: this may take a minute)\n'))
            upgradeButton = self.AddButton('Upgrade')
            upgradeButton.Bind(wx.EVT_BUTTON, self.OnWantToUpgrade)
            self.AddSeperator()
Example #2
0
	def OnRun(self):
		wx.CallAfter(self.updateLabel, _("Reading firmware..."))
		hexFile = intelHex.readHex(self.filename)
		wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
		programmer = stk500v2.Stk500v2()
		programmer.progressCallback = self.OnProgress
		if self.port == 'AUTO':
			wx.CallAfter(self.updateLabel, _("Please connect the printer to\nyour computer with the USB cable."))
			while not programmer.isConnected():
				for self.port in machineCom.serialList(True):
					try:
						programmer.connect(self.port)
						break
					except ispBase.IspError:
						programmer.close()
				time.sleep(1)
				if not self:
					#Window destroyed
					return
		else:
			try:
				programmer.connect(self.port)
			except ispBase.IspError:
				programmer.close()

		if not programmer.isConnected():
			wx.MessageBox(_("Failed to find machine for firmware upgrade\nIs your machine connected to the PC?"),
						  _("Firmware update"), wx.OK | wx.ICON_ERROR)
			wx.CallAfter(self.Close)
			return

		if self._machine_type == 'ultimaker':
			if programmer.hasChecksumFunction():
				wx.CallAfter(self.updateLabel, _("Failed to install firmware:\nThis firmware is not compatible with this machine.\nTrying to install UMO firmware on an UM2 or UMO+?"))
				programmer.close()
				wx.CallAfter(self.okButton.Enable)
				return
		if self._machine_type == 'ultimaker_plus' or self._machine_type == 'ultimaker2':
			if not programmer.hasChecksumFunction():
				wx.CallAfter(self.updateLabel, _("Failed to install firmware:\nThis firmware is not compatible with this machine.\nTrying to install UM2 or UMO+ firmware on an UMO?"))
				programmer.close()
				wx.CallAfter(self.okButton.Enable)
				return

		wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
		try:
			programmer.programChip(hexFile)
			self.success = True
			wx.CallAfter(self.updateLabel, _("Done!\nInstalled firmware: %s") % (os.path.basename(self.filename)))
		except ispBase.IspError as e:
			wx.CallAfter(self.updateLabel, _("Failed to write firmware.\n") + str(e))

		programmer.close()
		wx.CallAfter(self.okButton.Enable)
Example #3
0
    def OnInstall(self):
        wx.CallAfter(self.okButton.Disable)
        wx.CallAfter(self.updateLabel, _("Reading firmware..."))
        hexFile = intelHex.readHex(self.filename)
        wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
        programmer = stk500v2.Stk500v2()
        programmer.progressCallback = self.OnProgress
        if self.port == 'AUTO':
            wx.CallAfter(
                self.updateLabel,
                _("Please connect the printer to\nyour computer with the USB cable."
                  ))
            while not programmer.isConnected():
                for self.port in machineCom.serialList(True):
                    try:
                        programmer.connect(self.port)
                        break
                    except ispBase.IspError:
                        pass
                time.sleep(1)
                if not self:
                    #Window destroyed
                    return
        else:
            try:
                programmer.connect(self.port)
            except ispBase.IspError:
                pass

        if not programmer.isConnected():
            wx.CallAfter(self.updateLabel,
                         _("Failed to connect to programmer.\n"))
            return

        wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
        try:
            programmer.programChip(hexFile)
            wx.CallAfter(
                self.updateLabel,
                _("Done!\nInstalled firmware: %s") %
                (os.path.basename(self.filename)))
        except ispBase.IspError as e:
            wx.CallAfter(self.updateLabel,
                         _("Failed to write firmware.\n") + str(e))

        programmer.close()
        wx.CallAfter(self.okButton.Enable)
Example #4
0
 def _monitor(self):
     programmer = stk500v2.Stk500v2()
     if self._port == 'AUTO':
         while not programmer.isConnected():
             for self._port in machineCom.serialList(False):
                 try:
                     programmer.connect(self._port)
                     if programmer.isConnected():
                         return self._serial
                 except ispBase.IspError:
                     programmer.close()
             time.sleep(1)
             if not self:
                 #Window destroyed
                 return
     else:
         try:
             programmer.connect(self._port)
         except ispBase.IspError:
             programmer.close()
    def OnRun(self):
        programmer = stk500v2.Stk500v2()
        programmer.progressCallback = self.OnProgress
        if self.port == 'AUTO':
            wx.CallAfter(
                self.updateLabel,
                _("Please connect the printer to\nyour computer with the USB cable."
                  ))
            while not programmer.isConnected():
                for self.port in machineCom.serialList(False):
                    try:
                        programmer.connect(self.port)
                        break
                    except ispBase.IspError:
                        programmer.close()
                time.sleep(1)
                if not self:
                    #Window destroyed
                    return
        else:
            try:
                programmer.connect(self.port)
            except ispBase.IspError:
                programmer.close()

        if not programmer.isConnected():
            wx.MessageBox(
                _("Failed to find machine for firmware upgrade\nIs your machine connected to the PC?"
                  ), _("Firmware update"), wx.OK | wx.ICON_ERROR)
            wx.CallAfter(self.Close)
            return

        #wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
        #try:
        #    programmer.programChip(hexFile)
        #    wx.CallAfter(self.updateLabel, _("Done!\nInstalled firmware: %s") % (os.path.basename(self.filename)))
        #except ispBase.IspError as e:
        #    wx.CallAfter(self.updateLabel, _("Failed to write firmware.\n") + str(e))

        programmer.close()
        wx.CallAfter(self.okButton.Enable)
    def OnWantToConnect(self, e):
        self._port = 'AUTO'
        self._baudrate = 250000

        if self._port == 'AUTO':
            print 'entramos en port auto despues de baudrate'
            programmer = stk500v2.Stk500v2()
            print 'antes', self._port
            if not programmer.isConnected():
                print 'not connected'
                for self._port in machineCom.serialList(False):
                    try:
                        print 'despues', self._port
                        programmer.connect(self._port)
                        print 'lo que devuelve', programmer.isConnected()
                        print self._baudrate
                        profile.putMachineSetting('serial_port_auto',
                                                  self._port)
                        print 'hemos llegado despues del port'
                        print self._port
                        programmer.close()
                        self._serial = serial.Serial(str(self._port),
                                                     self._baudrate,
                                                     timeout=1)
                        print self._serial
                        profile.putMachineSetting('self_serial', self._serial)
                        self._state = 'Online'
                        print 'bueno', self._state
                        break
                    except ispBase.IspError as (e):
                        self._state = 'Offline'
                        pass
                    programmer.close()
                if self._port not in machineCom.serialList(False):
                    self._state = 'Offline'
                    print 'malo', self._state

        if self._state == 'Online':
            self._serial.close()
            self.readFirstLine()
            self.getFirmwareHardware()
Example #7
0
    def OnRun(self):
        wx.CallAfter(self.updateLabel, "Reading firmware...")
        hexFile = intelHex.readHex(self.filename)
        wx.CallAfter(self.updateLabel, "Connecting to machine...")
        programmer = stk500v2.Stk500v2()
        programmer.progressCallback = self.OnProgress
        if self.port == 'AUTO':
            for self.port in machineCom.serialList(True):
                try:
                    programmer.connect(self.port)
                    break
                except ispBase.IspError:
                    pass
        else:
            try:
                programmer.connect(self.port)
            except ispBase.IspError:
                pass

        if programmer.isConnected():
            wx.CallAfter(self.updateLabel, "Uploading firmware...")
            try:
                programmer.programChip(hexFile)
                wx.CallAfter(
                    self.updateLabel, "Done!\nInstalled firmware: %s" %
                    (os.path.basename(self.filename)))
            except ispBase.IspError as e:
                wx.CallAfter(self.updateLabel,
                             "Failed to write firmware.\n" + str(e))

            programmer.close()
            wx.CallAfter(self.okButton.Enable)
            return
        wx.MessageBox(
            'Failed to find machine for firmware upgrade\nIs your machine connected to the PC?',
            'Firmware update', wx.OK | wx.ICON_ERROR)
        wx.CallAfter(self.Close)
Example #8
0
    def _monitor(self):
        #Open the serial port.
        if self._port == 'AUTO':
            self._changeState(self.STATE_DETECT_SERIAL)
            programmer = stk500v2.Stk500v2()
            for p in serialList(True):
                try:
                    self._log("Connecting to: %s (programmer)" % (p))
                    programmer.connect(p)
                    self._serial = programmer.leaveISP()
                    profile.putMachineSetting('serial_port_auto', p)
                    break
                except ispBase.IspError as (e):
                    self._log("Error while connecting to %s: %s" % (p, str(e)))
                    pass
                except:
                    self._log(
                        "Unexpected error while connecting to serial port: %s %s"
                        % (p, getExceptionString()))
                programmer.close()
            if self._serial is None:
                self._log("Serial port list: %s" % (str(serialList(True))))
                self._serialDetectList = serialList(True)
        elif self._port == 'VIRTUAL':
            self._changeState(self.STATE_OPEN_SERIAL)
            self._serial = VirtualPrinter()
        else:
            self._changeState(self.STATE_OPEN_SERIAL)
            try:
                if self._baudrate == 0:
                    self._log(
                        "Connecting to: %s with baudrate: 115200 (fallback)" %
                        (self._port))
                    self._serial = serial.Serial(str(self._port),
                                                 115200,
                                                 timeout=3,
                                                 writeTimeout=10000)
                else:
                    self._log(
                        "Connecting to: %s with baudrate: %s (configured)" %
                        (self._port, self._baudrate))
                    self._serial = serial.Serial(str(self._port),
                                                 self._baudrate,
                                                 timeout=5,
                                                 writeTimeout=10000)
            except:
                self._log(
                    "Unexpected error while connecting to serial port: %s %s" %
                    (self._port, getExceptionString()))
        if self._serial is None:
            baudrate = self._baudrate
            if baudrate == 0:
                baudrate = self._baudrateDetectList.pop(0)
            if len(self._serialDetectList) < 1:
                self._log("Found no ports to try for auto detection")
                self._errorValue = 'Failed to autodetect serial port.'
                self._changeState(self.STATE_ERROR)
                return
            port = self._serialDetectList.pop(0)
            self._log("Connecting to: %s with baudrate: %s (auto)" %
                      (port, baudrate))
            try:
                self._serial = serial.Serial(port,
                                             baudrate,
                                             timeout=3,
                                             writeTimeout=10000)
            except:
                pass
        else:
            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
        else:
            timeout = time.time() + 5
        tempRequestTimeout = timeout
        while True:
            line = self._readline()
            if line is None:
                break

            #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"
                #	But a bed temp error is reported as "Error: Temperature heated bed switched off. MAXTEMP triggered !!"
                #	So we can have an extra newline in the most common case. Awesome work people.
                if re.match('Error:[0-9]\n', line):
                    line = line.rstrip() + self._readline()
                #Skip the communication errors, as those get corrected.
                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:'):
                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 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 or self._state == self.STATE_DETECT_SERIAL:
                if line == '' or time.time() > timeout:
                    if len(self._baudrateDetectList) < 1:
                        self.close()
                        self._errorValue = "No more baudrates to test, and no suitable baudrate found."
                        self._changeState(self.STATE_ERROR)
                    elif self._baudrateDetectRetry > 0:
                        self._baudrateDetectRetry -= 1
                        self._serial.write('\n')
                        self._log("Baudrate test retry: %d" %
                                  (self._baudrateDetectRetry))
                        self._sendCommand("M105")
                        self._testingBaudrate = True
                    else:
                        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=2.5,
                                writeTimeout=10000)
                        else:
                            baudrate = self._baudrateDetectList.pop(0)
                        try:
                            self._setBaudrate(baudrate)
                            self._serial.timeout = 0.5
                            self._log("Trying baudrate: %d" % (baudrate))
                            self._baudrateDetectRetry = 5
                            self._baudrateDetectTestOk = 0
                            timeout = time.time() + 5
                            self._serial.write('\n')
                            self._sendCommand("M105")
                            self._testingBaudrate = True
                        except:
                            self._log(
                                "Unexpected error while setting baudrate: %d %s"
                                % (baudrate, getExceptionString()))
                elif 'T:' in line:
                    self._baudrateDetectTestOk += 1
                    if self._baudrateDetectTestOk < 10:
                        self._log("Baudrate test ok: %d" %
                                  (self._baudrateDetectTestOk))
                        self._sendCommand("M105")
                    else:
                        self._sendCommand("M999")
                        self._serial.timeout = 2
                        profile.putMachineSetting('serial_baud_auto',
                                                  self._serial.baudrate)
                        self._changeState(self.STATE_OPERATIONAL)
                else:
                    self._testingBaudrate = False
            elif self._state == self.STATE_CONNECTING:
                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)
                if time.time() > timeout:
                    self.close()
            elif self._state == self.STATE_OPERATIONAL:
                #Request the temperature on comm timeout (every 2 seconds) when we are not printing.
                if line == '':
                    if self._extruderCount > 0:
                        self._temperatureRequestExtruder = (
                            self._temperatureRequestExtruder +
                            1) % self._extruderCount
                        self.sendCommand("M105 T%d" %
                                         (self._temperatureRequestExtruder))
                    else:
                        self.sendCommand("M105")
                    tempRequestTimeout = time.time() + 5
            elif self._state == self.STATE_PRINTING:
                #Even when printing request the temperature every 5 seconds.
                if time.time() > tempRequestTimeout:
                    if self._extruderCount > 0:
                        self._temperatureRequestExtruder = (
                            self._temperatureRequestExtruder +
                            1) % self._extruderCount
                        self.sendCommand("M105 T%d" %
                                         (self._temperatureRequestExtruder))
                    else:
                        self.sendCommand("M105")
                    tempRequestTimeout = time.time() + 5
                if line == '' and time.time() > timeout:
                    self._log(
                        "Communication timeout during printing, forcing a line"
                    )
                    line = 'ok'
                if 'ok' in line:
                    timeout = time.time() + 5
                    if not self._commandQueue.empty():
                        self._sendCommand(self._commandQueue.get())
                    else:
                        self._sendNext()
                elif "resend" in line.lower() or "rs" in line:
                    try:
                        self._gcodePosition = int(
                            line.replace("N:", " ").replace("N", " ").replace(
                                ":", " ").split()[-1])
                    except:
                        if "rs" in line:
                            self._gcodePosition = int(line.split()[1])
        self._log("Connection closed, closing down monitor")
Example #9
0
    def OnRun(self):
        wx.CallAfter(self.updateLabel, _("Reading firmware..."))
        hexFile = intelHex.readHex(self.filename)
        wx.CallAfter(self.updateLabel, _("Connecting to machine..."))
        programmer = stk500v2.Stk500v2()
        programmer.progressCallback = self.OnProgress
        if self.port == 'AUTO':
            wx.CallAfter(
                self.updateLabel,
                _("Please connect the printer to your\ncomputer with a USB cable and power it on."
                  ))
            while not programmer.isConnected():
                for self.port in machineCom.serialList(True):
                    try:
                        programmer.connect(self.port)
                        break
                    except ispBase.IspError:
                        programmer.close()
                time.sleep(1)
                if not self:
                    #Window destroyed
                    return
        else:
            try:
                programmer.connect(self.port)
            except ispBase.IspError:
                programmer.close()
            if not self:
                #Window destroyed
                return

        self.cancelButton.Disable()
        self.okButton.SetLabel(_('Ok'))

        if not programmer.isConnected():
            self.show_connect_dialog = True
            wx.CallAfter(self.Close)
            return

        if self._machine_type == 'ultimaker':
            if programmer.hasChecksumFunction():
                wx.CallAfter(
                    self.updateLabel,
                    _("Failed to install firmware:\nThis firmware is not compatible with this machine.\nTrying to install UMO firmware on an UM2 or UMO+?"
                      ))
                programmer.close()
                wx.CallAfter(self.okButton.Enable)
                return
        if self._machine_type == 'ultimaker_plus' or self._machine_type == 'ultimaker2':
            if not programmer.hasChecksumFunction():
                wx.CallAfter(
                    self.updateLabel,
                    _("Failed to install firmware:\nThis firmware is not compatible with this machine.\nTrying to install UM2 or UMO+ firmware on an UMO?"
                      ))
                programmer.close()
                wx.CallAfter(self.okButton.Enable)
                return

        wx.CallAfter(self.updateLabel, _("Uploading firmware..."))
        try:
            programmer.programChip(hexFile)
            self.success = True
            wx.CallAfter(self.updateLabel, _("Done!"))
        except ispBase.IspError as e:
            wx.CallAfter(self.updateLabel,
                         _("Failed to write firmware.\n") + str(e))

        programmer.close()
        wx.CallAfter(self.okButton.Enable)
    def _monitor(self):
        #Open the serial port.
        if self._port == 'AUTO':
            self._changeState(self.STATE_DETECT_SERIAL)
            programmer = stk500v2.Stk500v2()
            for p in serialList(True):
                try:
                    self._log("Connecting to: %s (programmer)" % (p))
                    programmer.connect(p)
                    self._serial = programmer.leaveISP()
                    profile.putMachineSetting('serial_port_auto', p)
                    break
                except ispBase.IspError as (e):
                    self._log("Error while connecting to %s: %s" % (p, str(e)))
                    pass
                except:
                    self._log(
                        "Unexpected error while connecting to serial port: %s %s"
                        % (p, getExceptionString()))
                programmer.close()
            if self._serial is None:
                self._log("Serial port list: %s" % (str(serialList(True))))
                self._serialDetectList = serialList(True)
        elif self._port == 'VIRTUAL':
            self._changeState(self.STATE_OPEN_SERIAL)
            self._serial = VirtualPrinter()
        else:
            self._changeState(self.STATE_OPEN_SERIAL)
            try:
                if self._baudrate == 0:
                    self._log(
                        "Connecting to: %s with baudrate: 115200 (fallback)" %
                        (self._port))
                    self._serial = serial.Serial(str(self._port),
                                                 115200,
                                                 timeout=3)
                    # Need to set writeTimeout separately in order to be compatible with pyserial 3.0
                    self._serial.writeTimeout = 10000
                else:
                    self._log(
                        "Connecting to: %s with baudrate: %s (configured)" %
                        (self._port, self._baudrate))
                    self._serial = serial.Serial(str(self._port),
                                                 self._baudrate,
                                                 timeout=5)
                    # Need to set writeTimeout separately in order to be compatible with pyserial 3.0
                    self._serial.writeTimeout = 10000
            except:
                self._log(
                    "Unexpected error while connecting to serial port: %s %s" %
                    (self._port, getExceptionString()))
        if self._serial is None:
            baudrate = self._baudrate
            if baudrate == 0:
                baudrate = self._baudrateDetectList.pop(0)
            if len(self._serialDetectList) < 1:
                self._log("Found no ports to try for auto detection")
                self._errorValue = 'Failed to autodetect serial port.'
                self._changeState(self.STATE_ERROR)
                return
            port = self._serialDetectList.pop(0)
            self._log("Connecting to: %s with baudrate: %s (auto)" %
                      (port, baudrate))
            try:
                self._serial = serial.Serial(port, baudrate, timeout=3)
                # Need to set writeTimeout separately in order to be compatible with pyserial 3.0
                self._serial.writeTimeout = 10000
            except:
                pass
        else:
            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
        else:
            timeout = time.time() + 5
        tempRequestTimeout = timeout
        while True:
            line = self._readline()
            if line is None:
                break

            #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"
                #	But a bed temp error is reported as "Error: Temperature heated bed switched off. MAXTEMP triggered !!"
                #	So we can have an extra newline in the most common case. Awesome work people.
                if re.match('Error:[0-9]\n', line):
                    line = line.rstrip() + self._readline()
                #Skip the communication errors, as those get corrected.
                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 or 'PROBE FAIL' in line:
                    if not self.isError():
                        self._errorValue = line[6:]
                        self._changeState(self.STATE_ERROR)
            if ' T:' in line or line.startswith('T:'):
                tempRequestTimeout = time.time() + 5
                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 \
              not line.startswith('Error:checksum mismatch') and not line.startswith('Error:Line Number is not Last Line Number+1') and \
              not line.startswith('Error:No Checksum with line number') and not line.startswith('Error:No Line Number with checksum') and \
              line != 'echo:Unknown command:""\n' and self.isOperational():
                self._callback.mcMessage(line)

            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()
                        self._errorValue = "No more baudrates to test, and no suitable baudrate found."
                        self._changeState(self.STATE_ERROR)
                    elif self._baudrateDetectRetry > 0:
                        self._baudrateDetectRetry -= 1
                        self._serial.write('\n')
                        self._log("Baudrate test retry: %d" %
                                  (self._baudrateDetectRetry))
                        self._sendCommand("M105")
                        self._testingBaudrate = True
                    else:
                        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=2.5)
                            # Need to set writeTimeout separately in order to be compatible with pyserial 3.0
                            self._serial.writeTimeout = 10000
                        else:
                            baudrate = self._baudrateDetectList.pop(0)
                        try:
                            self._setBaudrate(baudrate)
                            self._serial.timeout = 0.5
                            self._log("Trying baudrate: %d" % (baudrate))
                            self._baudrateDetectRetry = 5
                            self._baudrateDetectTestOk = 0
                            timeout = time.time() + 5
                            self._serial.write('\n')
                            self._sendCommand("M105")
                            self._testingBaudrate = True
                        except:
                            self._log(
                                "Unexpected error while setting baudrate: %d %s"
                                % (baudrate, getExceptionString()))
                elif 'T:' in line:
                    self._baudrateDetectTestOk += 1
                    if self._baudrateDetectTestOk < 10:
                        self._log("Baudrate test ok: %d" %
                                  (self._baudrateDetectTestOk))
                        self._sendCommand("M105")
                    else:
                        self._sendCommand("M999")
                        self._serial.timeout = 2
                        profile.putMachineSetting('serial_baud_auto',
                                                  self._serial.baudrate)
                        self._changeState(self.STATE_OPERATIONAL)
                else:
                    self._testingBaudrate = False
            elif self._state == self.STATE_CONNECTING:
                if line == '' or 'wait' in line or 'start' in line:  # 'wait' needed for Repetier (kind of watchdog)
                    self._sendCommand("M105")
                elif 'ok' in line:
                    self._changeState(self.STATE_OPERATIONAL)
                if time.time() > timeout:
                    self.close()
            elif self._state == self.STATE_OPERATIONAL:
                # Request the temperature on comm timeout (every 2 seconds) when we are not printing.
                # unless we had a temperature feedback (from M109 or M190 for example)
                if line == '' and time.time() > tempRequestTimeout:
                    if self._heatupWaiting and len(self._currentCommands) == 1:
                        self._log(
                            "Canceling heatup due to missing T: line in the past 5 seconds. cmdbuffer desync?"
                        )
                        self._heatupWaiting = False
                        # Force a timeout now if necessary
                        timeout = time.time() - 1
                    if self._extruderCount > 0:
                        self._temperatureRequestExtruder = (
                            self._temperatureRequestExtruder +
                            1) % self._extruderCount
                        self.sendCommand("M105 T%d" %
                                         (self._temperatureRequestExtruder))
                    else:
                        self.sendCommand("M105")
                    # set timeout to less than 2 seconds to make sure it always triggers when comm times out
                    tempRequestTimeout = time.time() + 1.5
                if line == '' and time.time() > timeout:
                    line = 'ok'
                if 'ok' in line:
                    self.receivedOK()
                    timeout = time.time() + 30
                    if not self._heatupWaiting and not self._commandQueue.empty(
                    ):
                        self._sendCommand(self._commandQueue.get())
                    if len(self._currentCommands) > 0 and \
                       ("G28" in self._currentCommands[0] or "G29" in self._currentCommands[0] or \
                     "M109" in self._currentCommands[0] or "M190" in self._currentCommands[0]):
                        # Long command detected. Timeout is now set to 10 minutes to avoid forcing 'ok'
                        # every 30 seconds while it's not needed
                        timeout = time.time() + 600
                elif 'start' in line:
                    self._currentCommands = []
                    timeout = time.time() + 30
            elif self._state == self.STATE_PRINTING:
                #Even when printing request the temperature every 5 seconds.
                if time.time() > tempRequestTimeout:
                    if self._heatupWaiting and len(self._currentCommands) == 1:
                        self._log(
                            "Canceling heatup due to missing T: line in the past 5 seconds. cmdbuffer desync?"
                        )
                        self._heatupWaiting = False
                        # Force a timeout now if necessary
                        timeout = time.time() - 1
                    if self._extruderCount > 0:
                        self._temperatureRequestExtruder = (
                            self._temperatureRequestExtruder +
                            1) % self._extruderCount
                        self.sendCommand("M105 T%d" %
                                         (self._temperatureRequestExtruder))
                    else:
                        self.sendCommand("M105")
                    tempRequestTimeout = time.time() + 5
                if line == '' and time.time() > timeout:
                    self._log(
                        "Communication timeout during printing, forcing a line"
                    )
                    line = 'ok'
                if 'ok' in line:
                    self.receivedOK()
                    timeout = time.time() + 30
                    # If we are heating up with M109 or M190, then we can't send any new
                    # commands until the command buffer queue in firmware is empty (M109/M190 done)
                    # otherwise, we will fill up the buffer queue (2 more commands will be accepted after M109/M190)
                    # and anything else we send will just end up in the serial ringbuffer and will not be read until
                    # the M109/M190 is done.
                    # So if we want to cancel the heatup, we need to send M108 which needs to be able to be read from
                    # the ringbuffer, which means the command queue needs to be empty.
                    # So we stop sending any commands after M109/M190 unless it's M108 (or until heating done) if we want
                    # M108 to get handled.
                    # the small delay that is caused by the firmware buffer getting empty is not important because
                    # this happens during a heat&wait, not during a move command.
                    # If M108 is received, it gets sent directly from the receiving thread, not from here
                    # because the _commandQueue is not iterable
                    if not self._heatupWaiting:
                        # We iterate in case we just came out of a heat&wait
                        for i in xrange(len(self._currentCommands),
                                        CMDBUFFER_SIZE):
                            # One of the next 4 could enable the heatupWaiting mode
                            if not self._heatupWaiting:
                                if not self._commandQueue.empty():
                                    self._sendCommand(self._commandQueue.get())
                                else:
                                    self._sendNext()
                    if len(self._currentCommands) > 0 and \
                       ("G28" in self._currentCommands[0] or "G29" in self._currentCommands[0] or \
                     "M109" in self._currentCommands[0] or "M190" in self._currentCommands[0]):
                        # Long command detected. Timeout is now set to 10 minutes to avoid forcing 'ok'
                        # every 30 seconds while it's not needed
                        timeout = time.time() + 600

                elif 'start' in line:
                    self._currentCommands = []
                    timeout = time.time() + 30
                elif "resend" in line.lower() or "rs" in line:
                    newPos = self._gcodePos
                    try:
                        newPos = int(
                            line.replace("N:", " ").replace("N", " ").replace(
                                ":", " ").split()[-1])
                    except:
                        if "rs" in line:
                            newPos = int(line.split()[1])
                    # If we need to resend more than 10 lines, we can assume that the machine
                    # was shut down and turned back on or something else that's weird just happened.
                    # In that case, it can be dangerous to restart the print, so we'd better kill it
                    if newPos == 1 or self._gcodePos > newPos + 100:
                        self._callback.mcMessage(
                            "Print canceled due to loss of communication to printer (USB unplugged or power lost)"
                        )
                        self.cancelPrint()
                    else:
                        self._gcodePos = newPos
            elif self._state == self.STATE_PAUSED:
                #Even when printing request the temperature every 5 seconds.
                if time.time() > tempRequestTimeout:
                    if self._heatupWaiting and len(self._currentCommands) == 1:
                        self._log(
                            "Canceling heatup due to missing T: line in the past 5 seconds. cmdbuffer desync?"
                        )
                        self._heatupWaiting = False
                        # Force a timeout now if necessary
                        timeout = time.time() - 1
                    if self._extruderCount > 0:
                        self._temperatureRequestExtruder = (
                            self._temperatureRequestExtruder +
                            1) % self._extruderCount
                        self.sendCommand("M105 T%d" %
                                         (self._temperatureRequestExtruder))
                    else:
                        self.sendCommand("M105")
                    tempRequestTimeout = time.time() + 5
                if line == '' and time.time() > timeout:
                    line = 'ok'
                if 'ok' in line:
                    self.receivedOK()
                    timeout = time.time() + 30
                    if not self._heatupWaiting and not self._commandQueue.empty(
                    ):
                        self._sendCommand(self._commandQueue.get())
                    if len(self._currentCommands) > 0 and \
                       ("G28" in self._currentCommands[0] or "G29" in self._currentCommands[0] or \
                     "M109" in self._currentCommands[0] or "M190" in self._currentCommands[0]):
                        # Long command detected. Timeout is now set to 10 minutes to avoid forcing 'ok'
                        # every 30 seconds while it's not needed
                        timeout = time.time() + 600
                elif 'start' in line:
                    self._currentCommands = []
                    timeout = time.time() + 30

        self._log("Connection closed, closing down monitor")