Ejemplo n.º 1
0
 def _openSerial(self):
     if self._port == 'AUTO':
         self._changeState(self.STATE_DETECT_SERIAL)
         programmer = stk500v2.Stk500v2()
         self._log("Serial port list: %s" % (str(serialList())))
         for p in serialList():
             try:
                 self._log("Connecting to: %s" % (p))
                 programmer.connect(p)
                 self._serial = programmer.leaveISP()
                 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("Failed to autodetect serial port")
             self._errorValue = 'Failed to autodetect serial port.'
             self._changeState(self.STATE_ERROR)
             eventManager().fire("Error", self.getErrorString())
             return False
     elif self._port == 'VIRTUAL':
         self._changeState(self.STATE_OPEN_SERIAL)
         self._serial = VirtualPrinter()
     else:
         self._changeState(self.STATE_OPEN_SERIAL)
         try:
             self._log("Connecting to: %s" % self._port)
             if self._baudrate == 0:
                 self._serial = serial.Serial(str(self._port),
                                              115200,
                                              timeout=0.1,
                                              writeTimeout=10000)
             else:
                 self._serial = serial.Serial(str(self._port),
                                              self._baudrate,
                                              timeout=settings().getFloat([
                                                  "serial", "timeout",
                                                  "connection"
                                              ]),
                                              writeTimeout=10000)
         except:
             self._log(
                 "Unexpected error while connecting to serial port: %s %s" %
                 (self._port, getExceptionString()))
             self._errorValue = "Failed to open serial port, permissions correct?"
             self._changeState(self.STATE_ERROR)
             eventManager().fire("Error", self.getErrorString())
             return False
     return True
Ejemplo n.º 2
0
	def _readline(self):
		if self._serial == None:
			return None
		try:
			ret = self._serial.readline()
		except:
			self._log("Unexpected error while reading serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
			return None
		if ret == '':
			#self._log("Recv: TIMEOUT")
			return ''
		self._log("Recv: %s" % sanitizeAscii(ret))
		return ret
Ejemplo n.º 3
0
	def _readline(self):
		if self._serial == None:
			return None
		try:
			ret = self._serial.readline()
		except:
			self._log("Unexpected error while reading serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
			return None
		if ret == '':
			#self._log("Recv: TIMEOUT")
			return ''
		self._log("Recv: %s" % (unicode(ret, 'ascii', 'replace').encode('ascii', 'replace').rstrip()))
		return ret
Ejemplo n.º 4
0
	def _readline(self):
		if self._serial == None:
			return None
		try:
			ret = self._serial.readline()
		except:
			self._log("Unexpected error while reading serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
			return None
		if ret == '':
			#self._log("Recv: TIMEOUT")
			return ''
		self._log("Recv: %s" % (unicode(ret, 'ascii', 'replace').encode('ascii', 'replace').rstrip()))
		return ret
Ejemplo n.º 5
0
	def _readline(self):
		if self._serial == None:
			return None
		try:
			ret = self._serial.readline()
		except:
			self._log("Unexpected error while reading serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
			return None
		if ret == '':
			#self._log("Recv: TIMEOUT")
			return ''
		self._log("Recv: %s" % sanitizeAscii(ret))
		return ret
Ejemplo n.º 6
0
	def startPrint(self):
		if not self.isOperational() or self.isPrinting():
			return

		if self._currentFile is None:
			raise ValueError("No file selected for printing")

		try:
			self._currentFile.start()
			self._lastLayerHeight = 0.0;
			self._currentLayer  = 0;
			#self._currentLayer = 1;
			#sefl._lastLayerHeight;
			#self._callback.mcLayerChange(self._tentativeLayer)

			wasPaused = self.isPaused()
			self._changeState(self.STATE_PRINTING)
			eventManager().fire(Events.PRINT_STARTED, {
				"file": self._currentFile.getFilename(),
				"filename": os.path.basename(self._currentFile.getFilename()),
				"origin": self._currentFile.getFileLocation()
			})

			if self.isSdFileSelected():
				if wasPaused:
					self.sendCommand("M26 S0")
					self._currentFile.setFilepos(0)
				self.sendCommand("M24")
			else:
				self._sendNext()
		except:
			self._errorValue = getExceptionString()
			self._changeState(self.STATE_ERROR)
			eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
Ejemplo n.º 7
0
	def startPrint(self):
		if not self.isOperational() or self.isPrinting():
			return

		if self._currentFile is None:
			raise ValueError("No file selected for printing")

		try:
			self._currentFile.start()

			wasPaused = self.isPaused()
			self._changeState(self.STATE_PRINTING)
			eventManager().fire(Events.PRINT_STARTED, {
				"file": self._currentFile.getFilename(),
				"filename": os.path.basename(self._currentFile.getFilename()),
				"origin": self._currentFile.getFileLocation()
			})

			if self.isSdFileSelected():
				if wasPaused:
					self.sendCommand("M26 S0")
					self._currentFile.setFilepos(0)
				self.sendCommand("M24")
			else:
				self._sendNext()
		except:
			self._errorValue = getExceptionString()
			self._changeState(self.STATE_ERROR)
			eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
Ejemplo n.º 8
0
	def startPrint(self):
		if not self.isOperational() or self.isPrinting():
			return

		if self._currentFile is None:
			raise ValueError("No file selected for printing")
		wasPaused = self.isPaused()

		try:
			self._currentFile.start()

			self._changeState(self.STATE_PRINTING)
			eventManager().fire("PrintStarted", self._currentFile.getFilename())

			if self.isSdFileSelected():
				if wasPaused:
					self.sendCommand("M26 S0")
					self._currentFile.setFilepos(0)
				self.sendCommand("M24")
			else:
				self._sendNext()
		except:
			self._errorValue = getExceptionString()
			self._changeState(self.STATE_ERROR)
			eventManager().fire("Error", self.getErrorString())
Ejemplo n.º 9
0
	def startPrint(self):
		if not self.isOperational() or self.isPrinting():
			return

		if self._currentFile is None:
			raise ValueError("No file selected for printing")

		self._heatupWaitStartTime = 0
		self._heatupWaitTimeLost = 0.0
		self._pauseWaitStartTime = 0
		self._pauseWaitTimeLost = 0.0

		try:
			self._currentFile.start()

			wasPaused = self.isPaused()
			self._changeState(self.STATE_PRINTING)
			eventManager().fire(Events.PRINT_STARTED, {
				"file": self._currentFile.getFilename(),
				"filename": os.path.basename(self._currentFile.getFilename()),
				"origin": self._currentFile.getFileLocation()
			})

			if self.isSdFileSelected():
				if wasPaused:
					self.sendCommand("M26 S0")
					self._currentFile.setFilepos(0)
				self.sendCommand("M24")
			else:
				self._sendNext()
		except:
			self._logger.exception("Error while trying to start printing")
			self._errorValue = getExceptionString()
			self._changeState(self.STATE_ERROR)
			eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
Ejemplo n.º 10
0
    def startPrint(self):
        if not self.isOperational() or self.isPrinting():
            return

        if self._currentFile is None:
            raise ValueError("No file selected for printing")
        wasPaused = self.isPaused()

        try:
            self._currentFile.start()

            self._changeState(self.STATE_PRINTING)
            eventManager().fire("PrintStarted",
                                self._currentFile.getFilename())

            if self.isSdFileSelected():
                if wasPaused:
                    self.sendCommand("M26 S0")
                    self._currentFile.setFilepos(0)
                self.sendCommand("M24")
            else:
                self._sendNext()
        except:
            self._errorValue = getExceptionString()
            self._changeState(self.STATE_ERROR)
            eventManager().fire("Error", self.getErrorString())
Ejemplo n.º 11
0
 def _connect(self):
     self.changeState(State.OPENING_CONNECTION)
     if self._port == "VIRTUAL":
         self._serial = VirtualPrinter(read_timeout=self._readTimeout,
                                       write_timeout=self._writeTimeout)
         self.changeState(State.CONNECTED)
         self._transport_logger.debug("Connected to %s" % self._serial)
     else:
         try:
             self._serial = serial.Serial(self._port,
                                          self._baudrate,
                                          timeout=self._readTimeout,
                                          writeTimeout=self._writeTimeout)
             self.changeState(State.CONNECTED)
             self._transport_logger.debug("Connected to %s" % self._serial)
         except:
             self.logError(
                 "Unexpected error while connecting to serial port: %s %s" %
                 (self._port, getExceptionString()))
             self.onError(
                 "Failed to open serial port, permissions correct?")
             return False
     eventManager().fire(Events.CONNECTED, {
         "port": self._port,
         "baudrate": self._baudrate
     })
     return True
Ejemplo n.º 12
0
	def _doSend(self, cmd):
		#make sure sends are done orderly
		with self._sendingLock:
			self._serialLoggerEnabled and self._log("Send: %s" % cmd)
			retriesLeft = 5
			while True:
				try:
					self._serial.write(cmd + '\n')
					break

				except serial.SerialTimeoutException:
					retriesLeft -= 1

					if retriesLeft == 0:
						self._serialLoggerEnabled and self._log("No more retries left. Closing the connection")
						self._errorValue = "Unable to send data"
						self.close(True)
						break
					else:
						self._serialLoggerEnabled and self._log("Serial Timeout while sending data. Retries left: %d" % retriesLeft)
						time.sleep(0.5)

				except:
					self._serialLoggerEnabled and self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
					self._errorValue = getExceptionString()
					self.close(True)
					break
Ejemplo n.º 13
0
	def _doSendWithoutChecksum(self, cmd):
		self._log("Send: %s" % cmd)
		try:
			self._serial.write(cmd + '\n')
		except serial.SerialTimeoutException:
			self._log("Serial timeout while writing to serial port, trying again.")
			try:
				self._serial.write(cmd + '\n')
			except:
				self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
				self._errorValue = getExceptionString()
				self.close(True)
		except:
			self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
Ejemplo n.º 14
0
	def _doSendWithoutChecksum(self, cmd):
		self._log("Send: %s" % cmd)
		try:
			self._serial.write(cmd + '\n')
		except serial.SerialTimeoutException:
			self._log("Serial timeout while writing to serial port, trying again.")
			try:
				self._serial.write(cmd + '\n')
			except:
				self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
				self._errorValue = getExceptionString()
				self.close(True)
		except:
			self._log("Unexpected error while writing serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
Ejemplo n.º 15
0
	def write(self, value):
		if self._socketWrite is not None:
			#self._logger.info("PipeReadWrite write:%s" % value)

			with self._stateMutex :
				try:
					self._socketWrite.send(value)
					#self._socketWrite.flush()
				except:
					exceptionString = getExceptionString()
					self._logger.error("Unexpected error while writing pipe port: %s" % exceptionString)
Ejemplo n.º 16
0
    def write(self, value):
        if self._socketWrite is not None:
            #self._logger.info("PipeReadWrite write:%s" % value)

            with self._stateMutex:
                try:
                    self._socketWrite.send(value)
                    #self._socketWrite.flush()
                except:
                    exceptionString = getExceptionString()
                    self._logger.error(
                        "Unexpected error while writing pipe port: %s" %
                        exceptionString)
Ejemplo n.º 17
0
	def send(self, command):
		commandToSend = command + "\n"
		try:
			self._pipe.write(commandToSend)
			self._transport_logger.info("Send: %s" % command)
			self.logTx(command)
#lkj		except serial.SerialTimeoutException:
#			self._transport_logger.warn("Timeout while sending: %s" % command)
#			self.logError("Pipe timeout while writing to pipe port, try again later.")
#			raise SendTimeout()
		except:
			exceptionString = getExceptionString()
			self.logError("Unexpected error while writing pipe port: %s" % exceptionString)
			self.onError(exceptionString)
			self.disconnect(True)
			raise TransportError()
Ejemplo n.º 18
0
	def send(self, command):
		commandToSend = command + "\n"
		try:
			self._serial.write(commandToSend)
			self._transport_logger.info("Send: %s" % command)
			self.logTx(command)
		except serial.SerialTimeoutException:
			self._transport_logger.warn("Timeout while sending: %s" % command)
			self.logError("Serial timeout while writing to serial port, try again later.")
			raise SendTimeout()
		except:
			exceptionString = getExceptionString()
			self.logError("Unexpected error while writing serial port: %s" % exceptionString)
			self.onError(exceptionString)
			self.disconnect(True)
			raise TransportError()
Ejemplo n.º 19
0
def _validate_profile(profile):
    if not "name" in profile \
      and "volume" in profile \
      and "width" in profile["volume"] \
      and "depth" in profile["volume"] \
      and "height" in profile["volume"] \
      and "formFactor" in profile["volume"] \
      and "heatedBed" in profile \
      and "extruder" in profile \
      and "count" in profile["extruder"] \
      and "offsets" in profile["extruder"] \
      and len(profile["extruder"]["offsets"]) == profile["extruder"]["count"]:
        return False

    for dimension in ("width", "depth", "height"):
        try:
            profile["volume"][dimension] = float(profile["volume"][dimension])
        except:
            return False

    if not profile["volume"]["formFactor"] in ("rectangular", "circular"):
        return False

    try:
        profile["heatedBed"] = bool(profile["heatedBed"])
    except:
        return False

    try:
        profile["extruder"]["count"] = int(profile["extruder"]["count"])
    except:
        return False

    converted_offsets = []
    for offset in profile["extruder"]["offsets"]:
        try:
            #converted_offsets.append((float(offset[0]), float(offset[1]), float(offset[2])))
            converted_offsets.append(offset)

        except:
            from octoprint.util import getExceptionString
            exceptionString = getExceptionString()
            print("lkj except : %s" % exceptionString)
            return False
    profile["extruder"]["offsets"] = converted_offsets

    return True
Ejemplo n.º 20
0
def _validate_profile(profile):
	if not "name" in profile \
			and "volume" in profile \
			and "width" in profile["volume"] \
			and "depth" in profile["volume"] \
			and "height" in profile["volume"] \
			and "formFactor" in profile["volume"] \
			and "heatedBed" in profile \
			and "extruder" in profile \
			and "count" in profile["extruder"] \
			and "offsets" in profile["extruder"] \
			and len(profile["extruder"]["offsets"]) == profile["extruder"]["count"]:
		return False

	for dimension in ("width", "depth", "height"):
		try:
			profile["volume"][dimension] = float(profile["volume"][dimension])
		except:
			return False

	if not profile["volume"]["formFactor"] in ("rectangular", "circular"):
		return False

	try:
		profile["heatedBed"] = bool(profile["heatedBed"])
	except:
		return False

	try:
		profile["extruder"]["count"] = int(profile["extruder"]["count"])
	except:
		return False

	converted_offsets = []
	for offset in profile["extruder"]["offsets"]:
		try:
			#converted_offsets.append((float(offset[0]), float(offset[1]), float(offset[2])))
			converted_offsets.append(offset)
			
		except:
			from octoprint.util import getExceptionString			
			exceptionString = getExceptionString()
			print("lkj except : %s" % exceptionString)			
			return False
	profile["extruder"]["offsets"] = converted_offsets

	return True
Ejemplo n.º 21
0
	def _readline(self):
		if self._serial is None:
			return None

		try:
			line = self._serial.readline()
		except:
			exceptionString = getExceptionString()
			self.logError("Unexpected error while reading serial port: %s" % exceptionString)
			self.onError(exceptionString)
			self.disconnect()
			return None

		if line != "":
			loggable_line = unicode(line, "ascii", "replace").encode("ascii", "replace").rstrip()
			self._transport_logger.debug("Recv: %s" % loggable_line)
			self.logRx(loggable_line)
		return line
Ejemplo n.º 22
0
	def _readline(self):
		if self._pipe is None:
			return None

		try:
			line = self._pipe.readline()
		except:
			exceptionString = getExceptionString()
			print("lkj Unexpected error while reading pipe port: %s" % exceptionString)
			self.logError("Unexpected error while reading pipe port: %s" % exceptionString)
			self.onError(exceptionString)
			self.disconnect()
			return None

		if line != "":
			loggable_line = unicode(line, "ascii", "replace").encode("ascii", "replace").rstrip()
			self._transport_logger.debug("Recv: %s" % loggable_line)
			self.logRx(loggable_line)
		return line
Ejemplo n.º 23
0
	def _openSerial(self):
		if self._port == 'AUTO':
			self._changeState(self.STATE_DETECT_SERIAL)
			programmer = stk500v2.Stk500v2()
			self._log("Serial port list: %s" % (str(self._callback.serialList())))
			for p in self._callback.serialList():
				try:
					self._log("Connecting to: %s" % (p))
					programmer.connect(p)
					self._serial = programmer.leaveISP()
					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("Failed to autodetect serial port")
				self._errorValue = 'Failed to autodetect serial port.'
				self._changeState(self.STATE_ERROR)
				eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
				return False
		elif self._port == 'VIRTUAL':
			self._changeState(self.STATE_OPEN_SERIAL)
			self._serial = VirtualPrinter()
		else:
			self._changeState(self.STATE_OPEN_SERIAL)
			try:
				self._log("Connecting to: %s" % self._port)
				if self._baudrate == 0:
					self._serial = serial.Serial(str(self._port), 115200, timeout=0.1, writeTimeout=10000)
				else:
					self._serial = serial.Serial(str(self._port), self._baudrate, timeout=settings().getFloat(["serial", "timeout", "connection"]), writeTimeout=10000)
			except:
				self._log("Unexpected error while connecting to serial port: %s %s" % (self._port, getExceptionString()))
				self._errorValue = "Failed to open serial port, permissions correct?"
				self._changeState(self.STATE_ERROR)
				eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
				return False
		return True
Ejemplo n.º 24
0
	def _readline(self):
		if self._serial == None:
			return None

		try:
			ret = self._serial.readline()

		except:
			self._serialLoggerEnabled and self._log("Unexpected error while reading serial port: %s" % (getExceptionString()))
			self._errorValue = getExceptionString()
			self.close(True)
			return None

		if ret == '':
		#	self._serialLoggerEnabled and self._log("Recv: TIMEOUT")
			return ''

		self._serialLoggerEnabled and self._log("Recv: %s" % sanitizeAscii(ret))

		if self._callback.broadcastTraffic > 0:
			self._callback.doTrafficBroadcast('r', ret) #sanitizeAscii(ret))

		return ret
Ejemplo n.º 25
0
	def _monitor(self):
		feedbackControls = settings().getFeedbackControls()
		pauseTriggers = settings().getPauseTriggers()
		feedbackErrors = []

		#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())))
			for p in serialList():
				try:
					self._log("Connecting to: %s" % (p))
					programmer.connect(p)
					self._serial = programmer.leaveISP()
					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()
		elif self._port == 'VIRTUAL':
			self._changeState(self.STATE_OPEN_SERIAL)
			self._serial = VirtualPrinter()
		else:
			self._changeState(self.STATE_OPEN_SERIAL)
			try:
				self._log("Connecting to: %s" % (self._port))
				if self._baudrate == 0:
					self._serial = serial.Serial(str(self._port), 115200, timeout=0.1, writeTimeout=10000)
				else:
					self._serial = serial.Serial(str(self._port), self._baudrate, timeout=settings().getFloat(["serial", "timeout", "connection"]), 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)
			eventManager().fire("Error", self.getErrorString())
			return
		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.
		timeout = getNewTimeout("communication")
		tempRequestTimeout = timeout
		sdStatusRequestTimeout = timeout
		startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
		heatingUp = False
		swallowOk = False
		while True:
			try:
				line = self._readline()
				if line == None:
					break

				##~~ Error handling
				# No matter the state, if we see an error, goto the error state and store the error for reference.
				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 'checksum mismatch' in line \
							or 'Wrong checksum' in line \
							or 'Line Number is not Last Line Number' in line \
							or 'expected line' in line \
							or 'No Line Number with checksum' in line \
							or 'No Checksum with line number' in line \
							or 'Missing checksum' in line:
						pass
					elif not self.isError():
						self._errorValue = line[6:]
						self._changeState(self.STATE_ERROR)
						eventManager().fire("Error", self.getErrorString())

				##~~ SD file list
				# if we are currently receiving an sd file list, each line is just a filename, so just read it and abort processing
				if self._sdFileList and not 'End file list' in line:
					self._sdFiles.append(line.strip().lower())
					continue

				##~~ Temperature processing
				if ' T:' in line or line.startswith('T:'):
					try:
						self._temp = 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))

						self._callback.mcTempUpdate(self._temp, self._bedTemp, self._targetTemp, self._bedTargetTemp)
					except ValueError:
						# catch conversion issues, we'll rather just not get the temperature update instead of killing the connection
						pass

					#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:
						heatingUp = True
						if self._heatupWaitStartTime != 0:
							t = time.time()
							self._heatupWaitTimeLost = t - self._heatupWaitStartTime
							self._heatupWaitStartTime = t

				##~~ SD Card handling
				elif 'SD init fail' in line:
					self._sdAvailable = False
					self._sdFiles = []
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Not SD printing' in line:
					if self.isSdFileSelected() and self.isPrinting():
						# something went wrong, printer is reporting that we actually are not printing right now...
						self._sdFilePos = 0
						self._changeState(self.STATE_OPERATIONAL)
				elif 'SD card ok' in line:
					self._sdAvailable = True
					self.refreshSdFiles()
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Begin file list' in line:
					self._sdFiles = []
					self._sdFileList = True
				elif 'End file list' in line:
					self._sdFileList = False
					self._callback.mcSdFiles(self._sdFiles)
				elif 'SD printing byte' in line:
					# answer to M27, at least on Marlin, Repetier and Sprinter: "SD printing byte %d/%d"
					match = re.search("([0-9]*)/([0-9]*)", line)
					self._currentFile.setFilepos(int(match.group(1)))
					self._callback.mcProgress()
				elif 'File opened' in line:
					# answer to M23, at least on Marlin, Repetier and Sprinter: "File opened:%s Size:%d"
					match = re.search("File opened:\s*(.*?)\s+Size:\s*([0-9]*)", line)
					self._currentFile = PrintingSdFileInformation(match.group(1), int(match.group(2)))
				elif 'File selected' in line:
					# final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected"
					self._callback.mcFileSelected(self._currentFile.getFilename(), self._currentFile.getFilesize(), True)
					eventManager().fire("FileSelected", self._currentFile.getFilename())
				elif 'Writing to file' in line:
					# anwer to M28, at least on Marlin, Repetier and Sprinter: "Writing to file: %s"
					self._printSection = "CUSTOM"
					self._changeState(self.STATE_PRINTING)
				elif 'Done printing file' in line:
					# printer is reporting file finished printing
					self._sdFilePos = 0
					self._callback.mcPrintjobDone()
					self._changeState(self.STATE_OPERATIONAL)
					eventManager().fire("PrintDone")

				##~~ Message handling
				elif line.strip() != '' and line.strip() != 'ok' and not line.startswith("wait") and not line.startswith('Resend:') and line != 'echo:Unknown command:""\n' and self.isOperational():
					self._callback.mcMessage(line)

				##~~ Parsing for feedback commands
				if feedbackControls:
					for name, matcher, template in feedbackControls:
						try:
							match = matcher.search(line)
							if match is not None:
								format = None
								if isinstance(template, str):
									format = str.format
								elif isinstance(template, unicode):
									format = unicode.format

								if format is not None:
									self._callback.mcReceivedRegisteredMessage(name, format(template, *(match.groups("n/a"))))
						except:
							if not name in feedbackErrors:
								self._logger.info("Something went wrong with feedbackControl \"%s\": " % name, exc_info=True)
								feedbackErrors.append(name)
							pass

				##~~ Parsing for pause triggers
				if pauseTriggers:
					if "enable" in pauseTriggers.keys() and pauseTriggers["enable"].search(line) is not None:
						self.setPause(True)
					elif "disable" in pauseTriggers.keys() and pauseTriggers["disable"].search(line) is not None:
						self.setPause(False)
					elif "toggle" in pauseTriggers.keys() and pauseTriggers["toggle"].search(line) is not None:
						self.setPause(not self.isPaused())

				if "ok" in line and heatingUp:
					heatingUp = False

				### Baudrate detection
				if self._state == self.STATE_DETECT_BAUDRATE:
					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)
							eventManager().fire("Error", self.getErrorString())
						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:
							baudrate = self._baudrateDetectList.pop(0)
							try:
								self._serial.baudrate = baudrate
								self._serial.timeout = settings().getFloat(["serial", "timeout", "detection"])
								self._log("Trying baudrate: %d" % (baudrate))
								self._baudrateDetectRetry = 5
								self._baudrateDetectTestOk = 0
								timeout = getNewTimeout("communication")
								self._serial.write('\n')
								self._sendCommand("M105")
								self._testingBaudrate = True
							except:
								self._log("Unexpected error while setting baudrate: %d %s" % (baudrate, getExceptionString()))
					elif 'ok' in line and '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 = settings().getFloat(["serial", "timeout", "connection"])
							self._changeState(self.STATE_OPERATIONAL)
							if self._sdAvailable:
								self.refreshSdFiles()
							eventManager().fire("Connected", "%s at %s baud" % (self._port, self._baudrate))
					else:
						self._testingBaudrate = False

				### Connection attempt
				elif self._state == self.STATE_CONNECTING:
					if (line == "" or "wait" in line) and startSeen:
						self._sendCommand("M105")
					elif "start" in line:
						startSeen = True
					elif "ok" in line and startSeen:
						self._changeState(self.STATE_OPERATIONAL)
						if self._sdAvailable:
							self.refreshSdFiles()
						eventManager().fire("Connected", "%s at %s baud" % (self._port, self._baudrate))
					elif time.time() > timeout:
						self.close()

				### Operational
				elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
					#Request the temperature on comm timeout (every 5 seconds) when we are not printing.
					if line == "" or "wait" in line:
						if self._resendDelta is not None:
							self._resendNextCommand()
						elif not self._commandQueue.empty():
							self._sendCommand(self._commandQueue.get())
						else:
							self._sendCommand("M105")
						tempRequestTimeout = getNewTimeout("communication")
					# resend -> start resend procedure from requested line
					elif line.lower().startswith("resend") or line.lower().startswith("rs"):
						if settings().get(["feature", "swallowOkAfterResend"]):
							swallowOk = True
						self._handleResendRequest(line)

				### Printing
				elif self._state == self.STATE_PRINTING:
					if line == "" and time.time() > timeout:
						self._log("Communication timeout during printing, forcing a line")
						line = 'ok'

					if self.isSdPrinting():
						if time.time() > tempRequestTimeout and not heatingUp:
							self._sendCommand("M105")
							tempRequestTimeout = getNewTimeout("communication")

						if time.time() > sdStatusRequestTimeout and not heatingUp:
							self._sendCommand("M27")
							sdStatusRequestTimeout = time.time() + 1

						if 'ok' or 'SD printing byte' in line:
							timeout = getNewTimeout("communication")
					else:
						# Even when printing request the temperature every 5 seconds.
						if time.time() > tempRequestTimeout and not self.isStreaming():
							self._commandQueue.put("M105")
							tempRequestTimeout = getNewTimeout("communication")

						if "ok" in line and swallowOk:
							swallowOk = False
						elif "ok" in line:
							timeout = getNewTimeout("communication")
							if self._resendDelta is not None:
								self._resendNextCommand()
							elif not self._commandQueue.empty() and not self.isStreaming():
								self._sendCommand(self._commandQueue.get())
							else:
								self._sendNext()
						elif line.lower().startswith("resend") or line.lower().startswith("rs"):
							if settings().get(["feature", "swallowOkAfterResend"]):
								swallowOk = True
							self._handleResendRequest(line)
			except:
				self._logger.exception("Something crashed inside the serial connection loop, please report this in OctoPrint's bug tracker:")

				errorMsg = "See octoprint.log for details"
				self._log(errorMsg)
				self._errorValue = errorMsg
				self._changeState(self.STATE_ERROR)
				eventManager().fire("Error", self.getErrorString())
		self._log("Connection closed, closing down monitor")
Ejemplo n.º 26
0
	def _monitor(self):
		feedbackControls = settings().getFeedbackControls()
		pauseTriggers = settings().getPauseTriggers()
		feedbackErrors = []

		#Open the serial port.
		if not self._openSerial():
			return

		self._log("Connected to: %s, starting monitor" % self._serial)
		if self._baudrate == 0:
			self._log("Starting baud rate detection")
			self._changeState(self.STATE_DETECT_BAUDRATE)
		else:
			self._changeState(self.STATE_CONNECTING)

		#Start monitoring the serial port.
		timeout = getNewTimeout("communication")
		tempRequestTimeout = getNewTimeout("temperature")
		sdStatusRequestTimeout = getNewTimeout("sdStatus")
		startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
		self._heatingUp = False
		swallowOk = False
		supportRepetierTargetTemp = settings().getBoolean(["feature", "repetierTargetTemp"])

		while True:
			try:
				line = self._readline()
				if line is None:
					break
				if line.strip() is not "" and line.isalnum():
					timeout = getNewTimeout("communication")

				##~~ Error handling
				line = self._handleErrors(line)

				##~~ SD file list
				# if we are currently receiving an sd file list, each line is just a filename, so just read it and abort processing
				if self._sdFileList and not "End file list" in line:
					fileinfo = line.strip().split(None, 2)
					if len(fileinfo) > 1:
						# we got extended file information here, so let's split filename and size and try to make them a bit nicer
						filename, size = fileinfo
						filename = filename.lower()
						try:
							size = int(size)
						except ValueError:
							# whatever that was, it was not an integer, so we'll just ignore it and set size to None
							size = None
					else:
						# no extended file information, so only the filename is there and we set size to None
						filename = fileinfo[0].lower()
						size = None

					if self._callback.fileManager.isValidFilename(filename):
						if filterNonAscii(filename):
							self._logger.warn("Got a file from printer's SD that has a non-ascii filename (%s), that shouldn't happen according to the protocol" % filename)
						else:
							self._sdFiles.append((filename, size))
						continue

				##~~ Temperature processing
				if ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:'):
					self._processTemperatures(line)
					self._callback.mcTempUpdate(self._temp, self._bedTemp)

					#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 supportRepetierTargetTemp and ('TargetExtr' in line or 'TargetBed' in line):
					matchExtr = self._regex_repetierTempExtr.match(line)
					matchBed = self._regex_repetierTempBed.match(line)

					if matchExtr is not None:
						toolNum = int(matchExtr.group(1))
						try:
							target = float(matchExtr.group(2))
							if toolNum in self._temp.keys() and self._temp[toolNum] is not None and isinstance(self._temp[toolNum], tuple):
								(actual, oldTarget) = self._temp[toolNum]
								self._temp[toolNum] = (actual, target)
							else:
								self._temp[toolNum] = (None, target)
							self._callback.mcTempUpdate(self._temp, self._bedTemp)
						except ValueError:
							pass
					elif matchBed is not None:
						try:
							target = float(matchBed.group(1))
							if self._bedTemp is not None and isinstance(self._bedTemp, tuple):
								(actual, oldTarget) = self._bedTemp
								self._bedTemp = (actual, target)
							else:
								self._bedTemp = (None, target)
							self._callback.mcTempUpdate(self._temp, self._bedTemp)
						except ValueError:
							pass

				##~~ SD Card handling
				elif 'SD init fail' in line or 'volume.init failed' in line or 'openRoot failed' in line:
					self._sdAvailable = False
					self._sdFiles = []
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Not SD printing' in line:
					if self.isSdFileSelected() and self.isPrinting():
						# something went wrong, printer is reporting that we actually are not printing right now...
						self._sdFilePos = 0
						self._changeState(self.STATE_OPERATIONAL)
				elif 'SD card ok' in line and not self._sdAvailable:
					self._sdAvailable = True
					self.refreshSdFiles()
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Begin file list' in line:
					self._sdFiles = []
					self._sdFileList = True
				elif 'End file list' in line:
					self._sdFileList = False
					self._callback.mcSdFiles(self._sdFiles)
				elif 'SD printing byte' in line:
					# answer to M27, at least on Marlin, Repetier and Sprinter: "SD printing byte %d/%d"
					match = self._regex_sdPrintingByte.search(line)
					self._currentFile.setFilepos(int(match.group(1)))
					self._callback.mcProgress()
				elif 'File opened' in line:
					# answer to M23, at least on Marlin, Repetier and Sprinter: "File opened:%s Size:%d"
					match = self._regex_sdFileOpened.search(line)
					self._currentFile = PrintingSdFileInformation(match.group(1), int(match.group(2)))
				elif 'File selected' in line:
					# final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected"
					if self._currentFile is not None:
						self._callback.mcFileSelected(self._currentFile.getFilename(), self._currentFile.getFilesize(), True)
						eventManager().fire(Events.FILE_SELECTED, {
							"file": self._currentFile.getFilename(),
							"origin": self._currentFile.getFileLocation()
						})
				elif 'Writing to file' in line:
					# anwer to M28, at least on Marlin, Repetier and Sprinter: "Writing to file: %s"
					self._printSection = "CUSTOM"
					self._changeState(self.STATE_PRINTING)
					line = "ok"
				elif 'Done printing file' in line:
					# printer is reporting file finished printing
					self._sdFilePos = 0
					self._callback.mcPrintjobDone()
					self._changeState(self.STATE_OPERATIONAL)
					eventManager().fire(Events.PRINT_DONE, {
						"file": self._currentFile.getFilename(),
						"filename": os.path.basename(self._currentFile.getFilename()),
						"origin": self._currentFile.getFileLocation(),
						"time": self.getPrintTime(),
						"layerCount": self._currentLayer
					})
				elif 'Done saving file' in line:
					self.refreshSdFiles()

				##~~ Message handling
				elif line.strip() != '' \
						and line.strip() != 'ok' and not line.startswith("wait") \
						and not line.startswith('Resend:') \
						and line != 'echo:Unknown command:""\n' \
						and self.isOperational():
					self._callback.mcMessage(line)

				##~~ Parsing for feedback commands
				if feedbackControls:
					for name, matcher, template in feedbackControls:
						if name in feedbackErrors:
							# we previously had an error with that one, so we'll skip it now
							continue
						try:
							match = matcher.search(line)
							if match is not None:
								formatFunction = None
								if isinstance(template, str):
									formatFunction = str.format
								elif isinstance(template, unicode):
									formatFunction = unicode.format

								if formatFunction is not None:
									self._callback.mcReceivedRegisteredMessage(name, formatFunction(template, *(match.groups("n/a"))))
						except:
							if not name in feedbackErrors:
								self._logger.info("Something went wrong with feedbackControl \"%s\": " % name, exc_info=True)
								feedbackErrors.append(name)
							pass

				##~~ Parsing for pause triggers
				if pauseTriggers and not self.isStreaming():
					if "enable" in pauseTriggers.keys() and pauseTriggers["enable"].search(line) is not None:
						self.setPause(True)
					elif "disable" in pauseTriggers.keys() and pauseTriggers["disable"].search(line) is not None:
						self.setPause(False)
					elif "toggle" in pauseTriggers.keys() and pauseTriggers["toggle"].search(line) is not None:
						self.setPause(not self.isPaused())

				if "ok" in line and self._heatingUp:
					self._heatingUp = False
					self._callback.mcHeatingUpUpdate(self._heatingUp)

				### Baudrate detection
				if self._state == self.STATE_DETECT_BAUDRATE:
					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)
							eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
						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:
							baudrate = self._baudrateDetectList.pop(0)
							try:
								self._serial.baudrate = baudrate
								self._serial.timeout = settings().getFloat(["serial", "timeout", "detection"])
								self._log("Trying baudrate: %d" % (baudrate))
								self._baudrateDetectRetry = 5
								self._baudrateDetectTestOk = 0
								timeout = getNewTimeout("communication")
								self._serial.write('\n')
								self._sendCommand("M105")
								self._testingBaudrate = True
							except:
								self._log("Unexpected error while setting baudrate: %d %s" % (baudrate, getExceptionString()))
					elif 'ok' in line and '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 = settings().getFloat(["serial", "timeout", "connection"])
							self._changeState(self.STATE_OPERATIONAL)
							if self._sdAvailable:
								self.refreshSdFiles()
							else:
								self.initSdCard()
							eventManager().fire(Events.CONNECTED, {"port": self._port, "baudrate": self._baudrate})
					else:
						self._testingBaudrate = False

				### Connection attempt
				elif self._state == self.STATE_CONNECTING:
					if (line == "" or "wait" in line) and startSeen:
						if time.time() > timeout:
							self.close()
						else:
							self._sendCommand("M105")
					elif "start" in line:
						startSeen = True
					elif "ok" in line and startSeen:
						self._changeState(self.STATE_OPERATIONAL)
						if self._sdAvailable:
							self.refreshSdFiles()
						else:
							self.initSdCard()
						eventManager().fire(Events.CONNECTED, {"port": self._port, "baudrate": self._baudrate})
					elif time.time() > timeout:
						self.close()

				### Operational
				elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
					#Request the temperature on comm timeout (every 5 seconds) when we are not printing.
					if line == "" or "wait" in line:
						if self._resendDelta is not None:
							self._resendNextCommand()
						elif not self._commandQueue.empty():
							self._sendCommand(self._commandQueue.get())
						else:
							self._sendCommand("M105")
						tempRequestTimeout = getNewTimeout("temperature")
					# resend -> start resend procedure from requested line
					elif line.lower().startswith("resend") or line.lower().startswith("rs"):
						if settings().get(["feature", "swallowOkAfterResend"]):
							swallowOk = True
						self._handleResendRequest(line)

					else:
						positionMatch = self._regex_M114Response.search(line)
						if positionMatch:
							self._positionWhenPaused = (
								float(positionMatch.group(1)),
								float(positionMatch.group(2)),
								float(positionMatch.group(3)),
								float(positionMatch.group(4))
							)

							if self.isPaused():
								self.sendCommand("G1 F9000 X0 Y0 Z%.4f E%.4f" % (self._positionWhenPaused[2] + 5, self._positionWhenPaused[3] - 5))

				### Printing
				elif self._state == self.STATE_PRINTING:
					if line == "" and time.time() > timeout:
						self._log("Communication timeout during printing, forcing a line")
						line = 'ok'

					if self.isSdPrinting():
						if time.time() > tempRequestTimeout and not self._heatingUp:
							self._sendCommand("M105")
							tempRequestTimeout = getNewTimeout("temperature")

						if time.time() > sdStatusRequestTimeout and not self._heatingUp:
							self._sendCommand("M27")
							sdStatusRequestTimeout = getNewTimeout("sdStatus")
					else:
						# Even when printing request the temperature every 5 seconds.
						if time.time() > tempRequestTimeout and not self.isStreaming():
							self._commandQueue.put("M105")
							tempRequestTimeout = getNewTimeout("temperature")

						if "ok" in line and swallowOk:
							swallowOk = False
						elif "ok" in line:
							if self._resendDelta is not None:
								self._resendNextCommand()
							elif not self._commandQueue.empty() and not self.isStreaming():
								self._sendCommand(self._commandQueue.get(), True)
							else:
								self._sendNext()
						elif line.lower().startswith("resend") or line.lower().startswith("rs"):
							if settings().get(["feature", "swallowOkAfterResend"]):
								swallowOk = True
							self._handleResendRequest(line)

			except:
				self._logger.exception("Something crashed inside the serial connection loop, please report this to AstroPrint:")

				errorMsg = "See astrobox.log for details"
				self._log(errorMsg)
				self._errorValue = errorMsg
				self._changeState(self.STATE_ERROR)
				eventManager().fire(Events.ERROR, {"error": self.getErrorString()})

		self._log("Connection closed, closing down monitor")
Ejemplo n.º 27
0
	def run(self):
		profile = self._printer._profile

		self._printer._heatingUp = True
		self._printer.mcHeatingUpUpdate(True)
		self._heatupWaitStartTime = time.time()
		self._heatingTool = True
		self._lastLayerHeight = 0.0
		self._currentLayer = 0

		try:
			self._printer._comm.reset()
			self._printer._comm.build_start_notification(os.path.basename(self._file['filename'])[:15])
			self._printer._comm.set_build_percent(0)

			self._file['start_time'] = time.time()
			self._file['progress'] = 0

			lastProgressReport = 0
			lastProgressValueSentToPrinter = 0
			lastHeatingCheck = self._file['start_time']

			with open(self._file['filename'], 'rb') as f:
				while True:
					packet = bytearray()

					try:
						command = f.read(1)

						if self._canceled or len(command) == 0:
							break

						packet.append(ord(command))

						command = struct.unpack("B",command)
						try:
							parse = self.commandTable[command[0]]

						except KeyError:
							raise Exception("Unexpected packet type: 0x%x" % command[0])

						if type(parse) == type(""):
							packetLen = struct.calcsize(parse)
							packetData = f.read(packetLen)
							if len(packetData) != packetLen:
								raise Exception("Packet incomplete")
						else:
							packetData = parse(f)

						for c in packetData:
							packet.append(ord(c))

						if self.send_packet(packet):
							self._serialLoggerEnabled and self._serialLogger.debug('{"event":"packet_sent", "data": "%s"}' % ' '.join('0x{:02x}'.format(x) for x in packet) )

							now = time.time()
							if now - lastProgressReport > self.UPDATE_INTERVAL_SECS:
								position = f.tell()
								self._file['position'] = position
								self._file['progress'] = float(position) / float(self._file['size'])
								self._printer.mcProgress()

								printerProgress = int(self._file['progress'] * 100.0)

								if lastProgressValueSentToPrinter != printerProgress:
									try:
										self._printer._comm.set_build_percent(printerProgress)
										lastProgressValueSentToPrinter = printerProgress
										lastProgressReport = now

									except BufferOverflowError:
										time.sleep(.2)

							if self._printer._heatingUp and now - lastHeatingCheck > self.UPDATE_INTERVAL_SECS:
								lastHeatingCheck = now

								if  	( not self._heatingPlatform or ( self._heatingPlatform and self._printer._comm.is_platform_ready(0) ) )  \
									and ( not self._heatingTool or ( self._heatingTool and self._printer._comm.is_tool_ready(0) ) ):
								 
									self._heatingTool = False
									self._heatingPlatform = False
									self._printer._heatingUp = False
									self._printer.mcHeatingUpUpdate(False)
									self._heatupWaitTimeLost = now - self._heatupWaitStartTime
									self._heatupWaitStartTime = now
									self._file['start_time'] += self._heatupWaitTimeLost

					except ProtocolError as e:
						self._logger.warn('ProtocolError: %s' % e)

			self._printer._comm.build_end_notification()

			if self._canceled:
				self._printer._comm.clear_buffer()

			#Is possible to get a BufferOverflowError when succesfully completing a job
			continueEndSequence = False
			findAxesTries = 0
			while not continueEndSequence:
				try:
					self._printer._comm.find_axes_maximums(['x', 'y'], 200, 10)
					continueEndSequence = True

				except BufferOverflowError:
					if findAxesTries < 3:
						time.sleep(.2)
						findAxesTries += 1
					else:
						continueEndSequence = True

			#find current z:
			moveToPosition, endStopsStates = self._printer._comm.get_extended_position()
			zEndStopReached = endStopsStates & 16 == 16 #endstop is a bitfield. See https://github.com/makerbot/s3g/blob/master/doc/s3gProtocol.md (command 21)

			if zEndStopReached:

				#calculate Z max
				moveToPosition[2] = self._printer._profile.values['axes']['Z']['platform_length'] *  self._printer._profile.values['axes']['Z']['steps_per_mm']

				#move to the bottom:
				self._printer._comm.queue_extended_point_classic(moveToPosition, 100)

			self._printer._comm.toggle_axes(['x','y','z','a','b'], False)

			self._printer._changeState(self._printer.STATE_OPERATIONAL)

			payload = {
				"file": self._file['filename'],
				"filename": os.path.basename(self._file['filename']),
				"origin": self._file['origin'],
				"time": self._printer.getPrintTime(),
				"layerCount": self._currentLayer
			}

			if self._canceled:
				self._printer.printJobCancelled()
				eventManager().fire(Events.PRINT_FAILED, payload)
				self._printer._fileManager.printFailed(payload['filename'], payload['time'])

			else:
				self._printer.mcPrintjobDone()
				self._printer._fileManager.printSucceeded(payload['filename'], payload['time'], payload['layerCount'])
				eventManager().fire(Events.PRINT_DONE, payload)

		except BuildCancelledError:
			self._logger.warn('Build Cancel detected')
			self._printer.printJobCancelled()
			payload = {
				"file": self._file['filename'],
				"filename": os.path.basename(self._file['filename']),
				"origin": self._file['origin'],
				"time": self._printer.getPrintTime()
			}
			eventManager().fire(Events.PRINT_FAILED, payload)
			self._printer._fileManager.printFailed(payload['filename'], payload['time'])
			self._printer._changeState(self._printer.STATE_OPERATIONAL)

		except ExternalStopError:
			self._logger.warn('External Stop detected')
			self._printer._comm.writer.set_external_stop(False)
			self._printer.printJobCancelled()
			payload = {
				"file": self._file['filename'],
				"filename": os.path.basename(self._file['filename']),
				"origin": self._file['origin'],
				"time": self._printer.getPrintTime()
			}
			eventManager().fire(Events.PRINT_FAILED, payload)
			self._printer._fileManager.printFailed(payload['filename'], payload['time'])
			self._printer._changeState(self._printer.STATE_OPERATIONAL)			

		except Exception as e:
			self._errorValue = getExceptionString()
			self._printer._changeState(self._printer.STATE_ERROR)
			eventManager().fire(Events.ERROR, {"error": self._errorValue })
			self._logger.error(self._errorValue)
Ejemplo n.º 28
0
	def _connect(self):
		self.changeState(State.OPENING_CONNECTION)
		if self._port == "VIRTUAL":
			self._serial = VirtualPrinter(read_timeout=self._readTimeout, write_timeout=self._writeTimeout)
			self.changeState(State.CONNECTED)
			self._transport_logger.debug("Connected to %s" % self._serial)
		else:
			try:
				self._serial = serial.Serial(self._port, self._baudrate, timeout=self._readTimeout, writeTimeout=self._writeTimeout)
				self.changeState(State.CONNECTED)
				self._transport_logger.debug("Connected to %s" % self._serial)
			except:
				self.logError("Unexpected error while connecting to serial port: %s %s" % (self._port, getExceptionString()))
				self.onError("Failed to open serial port, permissions correct?")
				return False
		eventManager().fire(Events.CONNECTED, {"port": self._port, "baudrate": self._baudrate})
		return True
Ejemplo n.º 29
0
	def _work(self):
		import makerbot_driver.MachineFactory

		s = settings()

		retries = self.CONNECT_MAX_RETRIES

		try:
			while True:
				if self.isConnected():
					self._comm.close()

				if retries < 0:
					self._changeState(self.STATE_ERROR)
					self._errorValue = "Error Connecting"
					self._logger.error('Error connecting to printer.')
					self._comm = None
					break;

				else:
					try:
						result = makerbot_driver.MachineFactory().build_from_port(self._port, condition= self._state_condition)

						self._comm = result.s3g
						self._profile = result.profile
						self._gcodeParser = result.gcodeparser

						version_info = self._comm.get_advanced_version()

						#We should update some of the profile values with stuff retrieved from the EEPROM
						axisLengths = self._comm.read_named_value_from_EEPROM('AXIS_LENGTHS_MM')
						stepsPerMM = self._comm.read_named_value_from_EEPROM('AXIS_STEPS_PER_MM')

						self._profile.values['axes']['X']['platform_length'] = axisLengths[0]
						self._profile.values['axes']['Y']['platform_length'] = axisLengths[1]
						self._profile.values['axes']['Z']['platform_length'] = axisLengths[2]
						self._profile.values['axes']['A']['platform_length'] = axisLengths[3]

						self._profile.values['axes']['X']['steps_per_mm'] = stepsPerMM[0]/1000000.0
						self._profile.values['axes']['Y']['steps_per_mm'] = stepsPerMM[1]/1000000.0
						self._profile.values['axes']['Z']['steps_per_mm'] = stepsPerMM[2]/1000000.0
						self._profile.values['axes']['A']['steps_per_mm'] = -stepsPerMM[3]/1000000.0

						if "B" in self._profile.values['axes']:
							self._profile.values['axes']['B']['steps_per_mm'] = -stepsPerMM[4]/1000000.0
							self._profile.values['axes']['B']['platform_length'] = axisLengths[4]

						self._firmwareVersion = version_info['Version']
						self._logger.info('Connected to Machine running version: %d, variant: 0x%x' % (self._firmwareVersion, version_info['SoftwareVariant']) )

						self._changeState(self.STATE_OPERATIONAL)
						s.set(['serial', 'port'], self._port)
						s.save()
						break

					except makerbot_driver.errors.TransmissionError as e:
						retries -= 1
						if retries > 0:
							self._logger.info('TransmissionError - Retrying. Retries left %d...' % retries)
							time.sleep(.2)

					except makerbot_driver.errors.UnknownResponseError as e:
						retries -= 1
						if retries > 0:
							self._logger.info('UnknownResponseError - Retrying. Retries left %d...' % retries)
							time.sleep(.2)

					except makerbot_driver.errors.BuildCancelledError:
						self._logger.info("Build cancelled detected. No problem")


			if retries >=0:
				toolHeadCount = len(self._profile.values['tools'])

				while self._comm:
					try:
						for i in range(0, toolHeadCount):
							self._temp[i] = (self._comm.get_toolhead_temperature(i), self._comm.get_toolhead_target_temperature(i))

						self._bedTemp = (self._comm.get_platform_temperature(0), self._comm.get_platform_target_temperature(0))
						self.mcTempUpdate(self._temp, self._bedTemp)

					except makerbot_driver.BufferOverflowError:
						pass

					except makerbot_driver.TransmissionError:
						self._logger.error('Unfortunatelly an unrecoverable error occurred between the printer and the box')
						self.disconnect()
						break

					except makerbot_driver.BuildCancelledError:
						self._logger.warn('Build cancelled detected.')
						if self._printJob:
							self._logger.warn('Cancelling current job.')
							self._printJob.cancel()

					except makerbot_driver.ProtocolError:
						# It has been observed that sometimes the response comes back empty but
						# in a valid package. This was in a Flash Forge running Sailfish 7.7
						self._logger.warn('Badly formatted response. skipping...')

					except SerialException as e:
						raise e

					except Exception as e:
						# we shouldn't kill the thread as this is only an informational
						# thread
						import traceback

						print traceback.format_exc()
						self._logger.warn(getExceptionString())

					time.sleep(self.UPDATE_INTERVAL)

		except SerialException as e:
			self._logger.error(e)
			self._errorValue = "Serial Link failed"
			self._changeState(self.STATE_ERROR)
			eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
			self.disconnect()
Ejemplo n.º 30
0
    def run(self):
        self._printer._heatingUp = True
        self._printer.mcHeatingUpUpdate(True)
        self._heatupWaitStartTime = time.time()
        self._heatingTool = True
        self._lastLayerHeight = 0.0
        self._currentLayer = 0

        try:
            self._printer._comm.reset()
            self._printer._comm.build_start_notification(
                os.path.basename(self._file['filename'])[:15])
            self._printer._comm.set_build_percent(0)

            self._file['start_time'] = time.time()
            self._file['progress'] = 0

            lastProgressReport = 0
            lastProgressValueSentToPrinter = 0
            lastHeatingCheck = self._file['start_time']

            #Now we assume that the bed won't be clear from this point on
            self._printer.set_bed_clear(False)

            with open(self._file['filename'], 'rb') as f:
                while True:
                    packet = bytearray()

                    try:
                        command = f.read(1)

                        if self._canceled or len(command) == 0:
                            break

                        packet.append(ord(command))

                        command = struct.unpack("B", command)

                        try:
                            parse = self.commandTable[command[0]]

                        except KeyError:
                            raise Exception("Unexpected packet type: 0x%x" %
                                            command[0])

                        if type(parse) == type(""):
                            packetLen = struct.calcsize(parse)
                            packetData = f.read(packetLen)
                            if len(packetData) != packetLen:
                                raise Exception(
                                    "Packet incomplete when reading command 0x%x from file"
                                    % command[0])
                        else:
                            packetData = parse(f)

                        for c in packetData:
                            packet.append(ord(c))

                        if self.send_packet(packet):
                            self._serialLoggerEnabled and self._serialLogger.debug(
                                '{"event":"packet_sent", "data": "%s"}' %
                                ' '.join('0x{:02x}'.format(x) for x in packet))

                            now = time.time()
                            if now - lastProgressReport > self.UPDATE_INTERVAL_SECS:
                                position = f.tell()
                                self._file['position'] = position
                                self._file['progress'] = float(
                                    position) / float(self._file['size'])
                                self._printer.mcProgress()

                                printerProgress = int(self._file['progress'] *
                                                      100.0)

                                if lastProgressValueSentToPrinter != printerProgress:
                                    try:
                                        self._printer._comm.set_build_percent(
                                            printerProgress)
                                        lastProgressValueSentToPrinter = printerProgress
                                        lastProgressReport = now

                                    except BufferOverflowError:
                                        time.sleep(.2)

                            if self._printer._heatingUp and now - lastHeatingCheck > self.UPDATE_INTERVAL_SECS:
                                lastHeatingCheck = now

                                if   ( not self._heatingPlatform or ( self._heatingPlatform and self._printer._comm.is_platform_ready(0) ) )  \
                                 and ( not self._heatingTool or ( self._heatingTool and self._printer._comm.is_tool_ready(self._printer.getSelectedTool()) ) ):

                                    self._heatingTool = False
                                    self._heatingPlatform = False
                                    self._printer._heatingUp = False
                                    self._printer.mcHeatingUpUpdate(False)
                                    self._heatupWaitTimeLost = now - self._heatupWaitStartTime
                                    self._heatupWaitStartTime = now
                                    self._file[
                                        'start_time'] += self._heatupWaitTimeLost

                    except ProtocolError as e:
                        self._logger.warn('ProtocolError: %s' % e)

            self._printer._comm.build_end_notification()

            if self._canceled:
                self._printer._comm.clear_buffer()

            #Is possible to get a BufferOverflowError when succesfully completing a job
            continueEndSequence = False
            findAxesTries = 0
            while not continueEndSequence:
                try:
                    self._printer._comm.find_axes_maximums(['x', 'y'], 200, 10)
                    continueEndSequence = True

                except BufferOverflowError:
                    if findAxesTries < 3:
                        time.sleep(.2)
                        findAxesTries += 1
                    else:
                        continueEndSequence = True

            # The ability to find out the platform length of an axis dissapeared in Sailfish 7.3 so we remove for now
            #find current z:
            #moveToPosition, endStopsStates = self._printer._comm.get_extended_position()
            #zEndStopReached = endStopsStates & 16 == 16 #endstop is a bitfield. See https://github.com/makerbot/s3g/blob/master/doc/s3gProtocol.md (command 21)

            #if zEndStopReached:

            #calculate Z max
            #	moveToPosition[2] = self._printer._profile.values['axes']['Z']['platform_length'] *  self._printer._profile.values['axes']['Z']['steps_per_mm']

            #move to the bottom:
            #	self._printer._comm.queue_extended_point_classic(moveToPosition, 100)

            self._printer._comm.toggle_axes(['x', 'y', 'z', 'a', 'b'], False)
            self._printer._changeState(
                self._printer.STATE_OPERATIONAL if self._printer.
                isBedClear else self._printer.STATE_NOT_READY_TO_PRINT)

            payload = {
                "file": self._file['filename'],
                "filename": os.path.basename(self._file['filename']),
                "origin": self._file['origin'],
                "time": self._printer.getPrintTime(),
                "layerCount": self._currentLayer
            }

            if self._canceled:
                self._printer.printJobCancelled()
                eventManager().fire(Events.PRINT_FAILED, payload)
                self._printer._fileManager.printFailed(payload['filename'],
                                                       payload['time'])

            else:
                self._printer.mcPrintjobDone()
                self._printer._fileManager.printSucceeded(
                    payload['filename'], payload['time'],
                    payload['layerCount'])
                eventManager().fire(Events.PRINT_DONE, payload)

        except BuildCancelledError:
            self._logger.warn('Build Cancel detected')
            self._printer.printJobCancelled()
            payload = {
                "file": self._file['filename'],
                "filename": os.path.basename(self._file['filename']),
                "origin": self._file['origin'],
                "time": self._printer.getPrintTime()
            }
            eventManager().fire(Events.PRINT_FAILED, payload)
            self._printer._fileManager.printFailed(payload['filename'],
                                                   payload['time'])
            self._printer._changeState(
                self._printer.STATE_OPERATIONAL if self._printer.
                isBedClear else self._printer.STATE_NOT_READY_TO_PRINT)

        except ExternalStopError:
            self._logger.warn('External Stop detected')
            self._printer._comm.writer.set_external_stop(False)
            self._printer.printJobCancelled()
            payload = {
                "file": self._file['filename'],
                "filename": os.path.basename(self._file['filename']),
                "origin": self._file['origin'],
                "time": self._printer.getPrintTime()
            }
            eventManager().fire(Events.PRINT_FAILED, payload)
            self._printer._fileManager.printFailed(payload['filename'],
                                                   payload['time'])
            self._printer._changeState(
                self._printer.STATE_OPERATIONAL if self._printer.
                isBedClear else self._printer.STATE_NOT_READY_TO_PRINT)

        except Exception as e:
            self._errorValue = getExceptionString()
            self._printer._changeState(self._printer.STATE_ERROR)
            eventManager().fire(Events.ERROR, {"error": self._errorValue})
            self._logger.error(self._errorValue)
Ejemplo n.º 31
0
    def _work(self):
        import makerbot_driver.MachineFactory

        s = settings()

        retries = self.CONNECT_MAX_RETRIES

        try:
            while True:
                if self.isConnected():
                    self._comm.close()

                if retries < 0:
                    self._changeState(self.STATE_ERROR)
                    self._errorValue = "Error Connecting"
                    self._logger.error('Error connecting to printer.')
                    self._comm = None
                    break

                else:
                    try:
                        result = makerbot_driver.MachineFactory(
                        ).build_from_port(self._port,
                                          condition=self._state_condition)

                        self._comm = result.s3g
                        self._profile = result.profile
                        self._gcodeParser = result.gcodeparser

                        version_info = self._comm.get_advanced_version()

                        # We should update some of the profile values
                        # with stuff retrieved from the EEPROM
                        axisLengths = self._comm.read_named_value_from_EEPROM(
                            'AXIS_LENGTHS_MM')
                        stepsPerMM = self._comm.read_named_value_from_EEPROM(
                            'AXIS_STEPS_PER_MM')

                        self._profile.values['axes']['X'][
                            'platform_length'] = axisLengths[0]
                        self._profile.values['axes']['Y'][
                            'platform_length'] = axisLengths[1]
                        self._profile.values['axes']['Z'][
                            'platform_length'] = axisLengths[2]
                        self._profile.values['axes']['A'][
                            'platform_length'] = axisLengths[3]

                        self._profile.values['axes']['X'][
                            'steps_per_mm'] = stepsPerMM[0] / 1000000.0
                        self._profile.values['axes']['Y'][
                            'steps_per_mm'] = stepsPerMM[1] / 1000000.0
                        self._profile.values['axes']['Z'][
                            'steps_per_mm'] = stepsPerMM[2] / 1000000.0
                        self._profile.values['axes']['A'][
                            'steps_per_mm'] = -stepsPerMM[3] / 1000000.0

                        if "B" in self._profile.values['axes']:
                            self._profile.values['axes']['B'][
                                'steps_per_mm'] = -stepsPerMM[4] / 1000000.0
                            self._profile.values['axes']['B'][
                                'platform_length'] = axisLengths[4]

                        self._firmwareVersion = version_info['Version']
                        self._logger.info(
                            'Connected to Machine running version: %d, variant: 0x%x' % \
                            (self._firmwareVersion, version_info['SoftwareVariant']) )

                        self._changeState(self.STATE_OPERATIONAL)
                        s.set(['serial', 'port'], self._port)
                        s.save()
                        break

                    except makerbot_driver.errors.TransmissionError as e:
                        retries -= 1
                        if retries > 0:
                            self._logger.info(
                                'TransmissionError - Retrying. Retries left %d...'
                                % retries)
                            time.sleep(.2)

                    except makerbot_driver.errors.UnknownResponseError as e:
                        retries -= 1
                        if retries > 0:
                            self._logger.info(
                                'UnknownResponseError - Retrying. Retries left %d...' % \
                                retries)
                            time.sleep(.2)

                    except makerbot_driver.errors.BuildCancelledError:
                        self._logger.info(
                            "Build cancelled detected. No problem")

            if retries >= 0:
                toolHeadCount = len(self._profile.values['tools'])

                while self._comm:
                    try:
                        for i in range(0, toolHeadCount):
                            self._temp[i] = (
                                self._comm.get_toolhead_temperature(i),
                                self._comm.get_toolhead_target_temperature(i))

                        self._bedTemp = (
                            self._comm.get_platform_temperature(0),
                            self._comm.get_platform_target_temperature(0))
                        self.mcTempUpdate(self._temp, self._bedTemp)

                    except makerbot_driver.BufferOverflowError:
                        pass

                    except makerbot_driver.TransmissionError:
                        self._logger.error(
                            'Unfortunatelly an unrecoverable error occurred between the printer and the box'
                        )
                        self.disconnect()
                        break

                    except makerbot_driver.BuildCancelledError:
                        self._logger.warn('Build cancelled detected.')
                        if self._printJob:
                            self._logger.warn('Cancelling current job.')
                            self._printJob.cancel()

                    except makerbot_driver.ProtocolError:
                        # It has been observed that sometimes the
                        # response comes back empty but in a valid package.
                        # This was in a Flash Forge running Sailfish 7.7
                        self._logger.warn(
                            'Badly formatted response. skipping...')

                    except SerialException as e:
                        raise e

                    except Exception as e:
                        # we shouldn't kill the thread as this is only an
                        # informational thread
                        import traceback

                        print traceback.format_exc()
                        self._logger.warn(getExceptionString())

                    time.sleep(self.UPDATE_INTERVAL)

        except SerialException as e:
            self._logger.error(e)
            self._errorValue = "Serial Link failed"
            self._changeState(self.STATE_ERROR)
            eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
            self.disconnect()
Ejemplo n.º 32
0
    def _monitor(self):
        feedbackControls = settings().getFeedbackControls()
        pauseTriggers = settings().getPauseTriggers()
        feedbackErrors = []

        #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())))
            for p in serialList():
                try:
                    self._log("Connecting to: %s" % (p))
                    programmer.connect(p)
                    self._serial = programmer.leaveISP()
                    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()
        elif self._port == 'VIRTUAL':
            self._changeState(self.STATE_OPEN_SERIAL)
            self._serial = VirtualPrinter()
        else:
            self._changeState(self.STATE_OPEN_SERIAL)
            try:
                self._log("Connecting to: %s" % (self._port))
                if self._baudrate == 0:
                    self._serial = serial.Serial(str(self._port),
                                                 115200,
                                                 timeout=0.1,
                                                 writeTimeout=10000)
                else:
                    self._serial = serial.Serial(str(self._port),
                                                 self._baudrate,
                                                 timeout=settings().getFloat([
                                                     "serial", "timeout",
                                                     "connection"
                                                 ]),
                                                 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)
            eventManager().fire("Error", self.getErrorString())
            return
        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.
        timeout = getNewTimeout("communication")
        tempRequestTimeout = timeout
        sdStatusRequestTimeout = timeout
        startSeen = not settings().getBoolean(
            ["feature", "waitForStartOnConnect"])
        heatingUp = False
        swallowOk = False
        while True:
            try:
                line = self._readline()
                if line == None:
                    break

                ##~~ Error handling
                # No matter the state, if we see an error, goto the error state and store the error for reference.
                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 self._regex_minMaxError.match(line):
                        line = line.rstrip() + self._readline()
                    #Skip the communication errors, as those get corrected.
                    if 'checksum mismatch' in line \
                      or 'Wrong checksum' in line \
                      or 'Line Number is not Last Line Number' in line \
                      or 'expected line' in line \
                      or 'No Line Number with checksum' in line \
                      or 'No Checksum with line number' in line \
                      or 'Missing checksum' in line:
                        pass
                    elif not self.isError():
                        self._errorValue = line[6:]
                        self._changeState(self.STATE_ERROR)
                        eventManager().fire("Error", self.getErrorString())

                ##~~ SD file list
                # if we are currently receiving an sd file list, each line is just a filename, so just read it and abort processing
                if self._sdFileList and not 'End file list' in line:
                    self._sdFiles.append(line.strip().lower())
                    continue

                ##~~ Temperature processing
                if ' T:' in line or line.startswith('T:'):
                    try:
                        self._temp = float(
                            self._regex_float.search(
                                line.split('T:')[1]).group(0))
                        if ' B:' in line:
                            self._bedTemp = float(
                                self._regex_float.search(
                                    line.split(' B:')[1]).group(0))

                        self._callback.mcTempUpdate(self._temp, self._bedTemp,
                                                    self._targetTemp,
                                                    self._bedTargetTemp)
                    except ValueError:
                        # catch conversion issues, we'll rather just not get the temperature update instead of killing the connection
                        pass

                    #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:
                        heatingUp = True
                        if self._heatupWaitStartTime != 0:
                            t = time.time()
                            self._heatupWaitTimeLost = t - self._heatupWaitStartTime
                            self._heatupWaitStartTime = t

                ##~~ SD Card handling
                elif 'SD init fail' in line:
                    self._sdAvailable = False
                    self._sdFiles = []
                    self._callback.mcSdStateChange(self._sdAvailable)
                elif 'Not SD printing' in line:
                    if self.isSdFileSelected() and self.isPrinting():
                        # something went wrong, printer is reporting that we actually are not printing right now...
                        self._sdFilePos = 0
                        self._changeState(self.STATE_OPERATIONAL)
                elif 'SD card ok' in line:
                    self._sdAvailable = True
                    self.refreshSdFiles()
                    self._callback.mcSdStateChange(self._sdAvailable)
                elif 'Begin file list' in line:
                    self._sdFiles = []
                    self._sdFileList = True
                elif 'End file list' in line:
                    self._sdFileList = False
                    self._callback.mcSdFiles(self._sdFiles)
                elif 'SD printing byte' in line:
                    # answer to M27, at least on Marlin, Repetier and Sprinter: "SD printing byte %d/%d"
                    match = self._regex_sdPrintingByte.search(
                        "([0-9]*)/([0-9]*)", line)
                    self._currentFile.setFilepos(int(match.group(1)))
                    self._callback.mcProgress()
                elif 'File opened' in line:
                    # answer to M23, at least on Marlin, Repetier and Sprinter: "File opened:%s Size:%d"
                    match = self._regex_sdFileOpened.search(line)
                    self._currentFile = PrintingSdFileInformation(
                        match.group(1), int(match.group(2)))
                elif 'File selected' in line:
                    # final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected"
                    self._callback.mcFileSelected(
                        self._currentFile.getFilename(),
                        self._currentFile.getFilesize(), True)
                    eventManager().fire("FileSelected",
                                        self._currentFile.getFilename())
                elif 'Writing to file' in line:
                    # anwer to M28, at least on Marlin, Repetier and Sprinter: "Writing to file: %s"
                    self._changeState(self.STATE_PRINTING)
                    line = "ok"
                elif 'Done printing file' in line:
                    # printer is reporting file finished printing
                    self._sdFilePos = 0
                    self._callback.mcPrintjobDone()
                    self._changeState(self.STATE_OPERATIONAL)
                    eventManager().fire("PrintDone")

                ##~~ Message handling
                elif line.strip() != '' and line.strip(
                ) != 'ok' and not line.startswith(
                        "wait"
                ) and not line.startswith(
                        'Resend:'
                ) and line != 'echo:Unknown command:""\n' and self.isOperational(
                ):
                    self._callback.mcMessage(line)

                ##~~ Parsing for feedback commands
                if feedbackControls:
                    for name, matcher, template in feedbackControls:
                        try:
                            match = matcher.search(line)
                            if match is not None:
                                format = None
                                if isinstance(template, str):
                                    format = str.format
                                elif isinstance(template, unicode):
                                    format = unicode.format

                                if format is not None:
                                    self._callback.mcReceivedRegisteredMessage(
                                        name,
                                        format(template,
                                               *(match.groups("n/a"))))
                        except:
                            if not name in feedbackErrors:
                                self._logger.info(
                                    "Something went wrong with feedbackControl \"%s\": "
                                    % name,
                                    exc_info=True)
                                feedbackErrors.append(name)
                            pass

                ##~~ Parsing for pause triggers
                if pauseTriggers and not self.isStreaming():
                    if "enable" in pauseTriggers.keys(
                    ) and pauseTriggers["enable"].search(line) is not None:
                        self.setPause(True)
                    elif "disable" in pauseTriggers.keys(
                    ) and pauseTriggers["disable"].search(line) is not None:
                        self.setPause(False)
                    elif "toggle" in pauseTriggers.keys(
                    ) and pauseTriggers["toggle"].search(line) is not None:
                        self.setPause(not self.isPaused())

                if "ok" in line and heatingUp:
                    heatingUp = False

                ### Baudrate detection
                if self._state == self.STATE_DETECT_BAUDRATE:
                    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)
                            eventManager().fire("Error", self.getErrorString())
                        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:
                            baudrate = self._baudrateDetectList.pop(0)
                            try:
                                self._serial.baudrate = baudrate
                                self._serial.timeout = settings().getFloat(
                                    ["serial", "timeout", "detection"])
                                self._log("Trying baudrate: %d" % (baudrate))
                                self._baudrateDetectRetry = 5
                                self._baudrateDetectTestOk = 0
                                timeout = getNewTimeout("communication")
                                self._serial.write('\n')
                                self._sendCommand("M105")
                                self._testingBaudrate = True
                            except:
                                self._log(
                                    "Unexpected error while setting baudrate: %d %s"
                                    % (baudrate, getExceptionString()))
                    elif 'ok' in line and '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 = settings().getFloat(
                                ["serial", "timeout", "connection"])
                            self._changeState(self.STATE_OPERATIONAL)
                            if self._sdAvailable:
                                self.refreshSdFiles()
                            eventManager().fire(
                                "Connected",
                                "%s at %s baud" % (self._port, self._baudrate))
                    else:
                        self._testingBaudrate = False

                ### Connection attempt
                elif self._state == self.STATE_CONNECTING:
                    if (line == "" or "wait" in line) and startSeen:
                        self._sendCommand("M105")
                    elif "start" in line:
                        startSeen = True
                    elif "ok" in line and startSeen:
                        self._changeState(self.STATE_OPERATIONAL)
                        if self._sdAvailable:
                            self.refreshSdFiles()
                        eventManager().fire(
                            "Connected",
                            "%s at %s baud" % (self._port, self._baudrate))
                    elif time.time() > timeout:
                        self.close()

                ### Operational
                elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
                    #Request the temperature on comm timeout (every 5 seconds) when we are not printing.
                    if line == "" or "wait" in line:
                        if self._resendDelta is not None:
                            self._resendNextCommand()
                        elif not self._commandQueue.empty():
                            self._sendCommand(self._commandQueue.get())
                        else:
                            self._sendCommand("M105")
                        tempRequestTimeout = getNewTimeout("communication")
                    # resend -> start resend procedure from requested line
                    elif line.lower().startswith(
                            "resend") or line.lower().startswith("rs"):
                        if settings().get(["feature", "swallowOkAfterResend"]):
                            swallowOk = True
                        self._handleResendRequest(line)

                ### Printing
                elif self._state == self.STATE_PRINTING:
                    if line == "" and time.time() > timeout:
                        self._log(
                            "Communication timeout during printing, forcing a line"
                        )
                        line = 'ok'

                    if self.isSdPrinting():
                        if time.time() > tempRequestTimeout and not heatingUp:
                            self._sendCommand("M105")
                            tempRequestTimeout = getNewTimeout("communication")

                        if time.time(
                        ) > sdStatusRequestTimeout and not heatingUp:
                            self._sendCommand("M27")
                            sdStatusRequestTimeout = time.time() + 1

                        if 'ok' or 'SD printing byte' in line:
                            timeout = getNewTimeout("communication")
                    else:
                        # Even when printing request the temperature every 5 seconds.
                        if time.time(
                        ) > tempRequestTimeout and not self.isStreaming():
                            self._commandQueue.put("M105")
                            tempRequestTimeout = getNewTimeout("communication")

                        if "ok" in line and swallowOk:
                            swallowOk = False
                        elif "ok" in line:
                            timeout = getNewTimeout("communication")
                            if self._resendDelta is not None:
                                self._resendNextCommand()
                            elif not self._commandQueue.empty(
                            ) and not self.isStreaming():
                                self._sendCommand(self._commandQueue.get())
                            else:
                                self._sendNext()
                        elif line.lower().startswith(
                                "resend") or line.lower().startswith("rs"):
                            if settings().get(
                                ["feature", "swallowOkAfterResend"]):
                                swallowOk = True
                            self._handleResendRequest(line)
            except:
                self._logger.exception(
                    "Something crashed inside the serial connection loop, please report this in OctoPrint's bug tracker:"
                )

                errorMsg = "See octoprint.log for details"
                self._log(errorMsg)
                self._errorValue = errorMsg
                self._changeState(self.STATE_ERROR)
                eventManager().fire("Error", self.getErrorString())
        self._log("Connection closed, closing down monitor")
Ejemplo n.º 33
0
	def _monitor(self):
		feedbackControls = settings().getFeedbackControls()
		pauseTriggers = settings().getPauseTriggers()
		feedbackErrors = []

		#Open the serial port.
		if not self._openSerial():
			return

		self._log("Connected to: %s, starting monitor" % self._serial)
		if self._baudrate == 0:
			self._log("Starting baud rate detection")
			self._changeState(self.STATE_DETECT_BAUDRATE)
		else:
			self._changeState(self.STATE_CONNECTING)

		#Start monitoring the serial port.
		timeout = getNewTimeout("communication")
		tempRequestTimeout = getNewTimeout("temperature")
		sdStatusRequestTimeout = getNewTimeout("sdStatus")
		startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
		heatingUp = False
		swallowOk = False
		supportRepetierTargetTemp = settings().getBoolean(["feature", "repetierTargetTemp"])

		while True:
			try:
				line = self._readline()
				if line is None:
					break
				if line.strip() is not "":
					timeout = getNewTimeout("communication")

				##~~ Error handling
				line = self._handleErrors(line)

				##~~ SD file list
				# if we are currently receiving an sd file list, each line is just a filename, so just read it and abort processing
				if self._sdFileList and isGcodeFileName(line.strip().lower()) and not 'End file list' in line:
					filename = line.strip().lower()
					if filterNonAscii(filename):
						self._logger.warn("Got a file from printer's SD that has a non-ascii filename (%s), that shouldn't happen according to the protocol" % filename)
					else:
						self._sdFiles.append(filename)
					continue

				##~~ Temperature processing
				if ' T:' in line or line.startswith('T:') or ' T0:' in line or line.startswith('T0:'):
					self._processTemperatures(line)
					self._callback.mcTempUpdate(self._temp, self._bedTemp)

					#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:
						heatingUp = True
						if self._heatupWaitStartTime != 0:
							t = time.time()
							self._heatupWaitTimeLost = t - self._heatupWaitStartTime
							self._heatupWaitStartTime = t
				elif supportRepetierTargetTemp:
					matchExtr = self._regex_repetierTempExtr.match(line)
					matchBed = self._regex_repetierTempBed.match(line)

					if matchExtr is not None:
						toolNum = int(matchExtr.group(1))
						try:
							target = float(matchExtr.group(2))
							if toolNum in self._temp.keys() and self._temp[toolNum] is not None and isinstance(self._temp[toolNum], tuple):
								(actual, oldTarget) = self._temp[toolNum]
								self._temp[toolNum] = (actual, target)
							else:
								self._temp[toolNum] = (None, target)
							self._callback.mcTempUpdate(self._temp, self._bedTemp)
						except ValueError:
							pass
					elif matchBed is not None:
						try:
							target = float(matchBed.group(1))
							if self._bedTemp is not None and isinstance(self._bedTemp, tuple):
								(actual, oldTarget) = self._bedTemp
								self._bedTemp = (actual, target)
							else:
								self._bedTemp = (None, target)
							self._callback.mcTempUpdate(self._temp, self._bedTemp)
						except ValueError:
							pass

				##~~ SD Card handling
				elif 'SD init fail' in line or 'volume.init failed' in line or 'openRoot failed' in line:
					self._sdAvailable = False
					self._sdFiles = []
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Not SD printing' in line:
					if self.isSdFileSelected() and self.isPrinting():
						# something went wrong, printer is reporting that we actually are not printing right now...
						self._sdFilePos = 0
						self._changeState(self.STATE_OPERATIONAL)
				elif 'SD card ok' in line and not self._sdAvailable:
					self._sdAvailable = True
					self.refreshSdFiles()
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Begin file list' in line:
					self._sdFiles = []
					self._sdFileList = True
				elif 'End file list' in line:
					self._sdFileList = False
					self._callback.mcSdFiles(self._sdFiles)
				elif 'SD printing byte' in line:
					# answer to M27, at least on Marlin, Repetier and Sprinter: "SD printing byte %d/%d"
					match = self._regex_sdPrintingByte.search(line)
					self._currentFile.setFilepos(int(match.group(1)))
					self._callback.mcProgress()
				elif 'File opened' in line:
					# answer to M23, at least on Marlin, Repetier and Sprinter: "File opened:%s Size:%d"
					match = self._regex_sdFileOpened.search(line)
					self._currentFile = PrintingSdFileInformation(match.group(1), int(match.group(2)))
				elif 'File selected' in line:
					# final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected"
					if self._currentFile is not None:
						self._callback.mcFileSelected(self._currentFile.getFilename(), self._currentFile.getFilesize(), True)
						eventManager().fire(Events.FILE_SELECTED, {
							"file": self._currentFile.getFilename(),
							"origin": self._currentFile.getFileLocation()
						})
				elif 'Writing to file' in line:
					# anwer to M28, at least on Marlin, Repetier and Sprinter: "Writing to file: %s"
					self._printSection = "CUSTOM"
					self._changeState(self.STATE_PRINTING)
					line = "ok"
				elif 'Done printing file' in line:
					# printer is reporting file finished printing
					self._sdFilePos = 0
					self._callback.mcPrintjobDone()
					self._changeState(self.STATE_OPERATIONAL)
					eventManager().fire(Events.PRINT_DONE, {
						"file": self._currentFile.getFilename(),
						"filename": os.path.basename(self._currentFile.getFilename()),
						"origin": self._currentFile.getFileLocation(),
						"time": self.getPrintTime()
					})
				elif 'Done saving file' in line:
					self.refreshSdFiles()

				##~~ Message handling
				elif line.strip() != '' \
						and line.strip() != 'ok' and not line.startswith("wait") \
						and not line.startswith('Resend:') \
						and line != 'echo:Unknown command:""\n' \
						and self.isOperational():
					self._callback.mcMessage(line)

				##~~ Parsing for feedback commands
				if feedbackControls:
					for name, matcher, template in feedbackControls:
						if name in feedbackErrors:
							# we previously had an error with that one, so we'll skip it now
							continue
						try:
							match = matcher.search(line)
							if match is not None:
								formatFunction = None
								if isinstance(template, str):
									formatFunction = str.format
								elif isinstance(template, unicode):
									formatFunction = unicode.format

								if formatFunction is not None:
									self._callback.mcReceivedRegisteredMessage(name, formatFunction(template, *(match.groups("n/a"))))
						except:
							if not name in feedbackErrors:
								self._logger.info("Something went wrong with feedbackControl \"%s\": " % name, exc_info=True)
								feedbackErrors.append(name)
							pass

				##~~ Parsing for pause triggers
				if pauseTriggers and not self.isStreaming():
					if "enable" in pauseTriggers.keys() and pauseTriggers["enable"].search(line) is not None:
						self.setPause(True)
					elif "disable" in pauseTriggers.keys() and pauseTriggers["disable"].search(line) is not None:
						self.setPause(False)
					elif "toggle" in pauseTriggers.keys() and pauseTriggers["toggle"].search(line) is not None:
						self.setPause(not self.isPaused())

				if "ok" in line and heatingUp:
					heatingUp = False

				### Baudrate detection
				if self._state == self.STATE_DETECT_BAUDRATE:
					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)
							eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
						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:
							baudrate = self._baudrateDetectList.pop(0)
							try:
								self._serial.baudrate = baudrate
								self._serial.timeout = settings().getFloat(["serial", "timeout", "detection"])
								self._log("Trying baudrate: %d" % (baudrate))
								self._baudrateDetectRetry = 5
								self._baudrateDetectTestOk = 0
								timeout = getNewTimeout("communication")
								self._serial.write('\n')
								self._sendCommand("M105")
								self._testingBaudrate = True
							except:
								self._log("Unexpected error while setting baudrate: %d %s" % (baudrate, getExceptionString()))
					elif 'ok' in line and '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 = settings().getFloat(["serial", "timeout", "connection"])
							self._changeState(self.STATE_OPERATIONAL)
							if self._sdAvailable:
								self.refreshSdFiles()
							else:
								self.initSdCard()
							eventManager().fire(Events.CONNECTED, {"port": self._port, "baudrate": self._baudrate})
					else:
						self._testingBaudrate = False

				### Connection attempt
				elif self._state == self.STATE_CONNECTING:
					if (line == "" or "wait" in line) and startSeen:
						self._sendCommand("M105")
					elif "start" in line:
						startSeen = True
					elif "ok" in line and startSeen:
						self._changeState(self.STATE_OPERATIONAL)
						if self._sdAvailable:
							self.refreshSdFiles()
						else:
							self.initSdCard()
						eventManager().fire(Events.CONNECTED, {"port": self._port, "baudrate": self._baudrate})
					elif time.time() > timeout:
						self.close()

				### Operational
				elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
					#Request the temperature on comm timeout (every 5 seconds) when we are not printing.
					if line == "" or "wait" in line:
						if self._resendDelta is not None:
							self._resendNextCommand()
						elif not self._commandQueue.empty():
							self._sendCommand(self._commandQueue.get())
						else:
							self._sendCommand("M105")
						tempRequestTimeout = getNewTimeout("temperature")
					# resend -> start resend procedure from requested line
					elif line.lower().startswith("resend") or line.lower().startswith("rs"):
						if settings().get(["feature", "swallowOkAfterResend"]):
							swallowOk = True
						self._handleResendRequest(line)

				### Printing
				elif self._state == self.STATE_PRINTING:
					if line == "" and time.time() > timeout:
						self._log("Communication timeout during printing, forcing a line")
						line = 'ok'

					if self.isSdPrinting():
						if time.time() > tempRequestTimeout and not heatingUp:
							self._sendCommand("M105")
							tempRequestTimeout = getNewTimeout("temperature")

						if time.time() > sdStatusRequestTimeout and not heatingUp:
							self._sendCommand("M27")
							sdStatusRequestTimeout = getNewTimeout("sdStatus")
					else:
						# Even when printing request the temperature every 5 seconds.
						if time.time() > tempRequestTimeout and not self.isStreaming():
							self._commandQueue.put("M105")
							tempRequestTimeout = getNewTimeout("temperature")

						if "ok" in line and swallowOk:
							swallowOk = False
						elif "ok" in line:
							if self._resendDelta is not None:
								self._resendNextCommand()
							elif not self._commandQueue.empty() and not self.isStreaming():
								self._sendCommand(self._commandQueue.get())
							else:
								self._sendNext()
						elif line.lower().startswith("resend") or line.lower().startswith("rs"):
							if settings().get(["feature", "swallowOkAfterResend"]):
								swallowOk = True
							self._handleResendRequest(line)
			except:
				self._logger.exception("Something crashed inside the serial connection loop, please report this in OctoPrint's bug tracker:")

				errorMsg = "See octoprint.log for details"
				self._log(errorMsg)
				self._errorValue = errorMsg
				self._changeState(self.STATE_ERROR)
				eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
		self._log("Connection closed, closing down monitor")
Ejemplo n.º 34
0
	def _monitor(self):
		feedbackControls = settings().getFeedbackControls()
		pauseTriggers = settings().getPauseTriggers()
		feedbackErrors = []

		#Open the serial port.
		if not self._openSerial():
			return

		self._log("Connected to: %s, starting monitor" % self._serial)
		if self._baudrate == 0:
			self._log("Starting baud rate detection")
			self._changeState(self.STATE_DETECT_BAUDRATE)
		else:
			self._changeState(self.STATE_CONNECTING)

		#Start monitoring the serial port.
		timeout = getNewTimeout("communication")
		tempRequestTimeout = timeout
		sdStatusRequestTimeout = timeout
		startSeen = not settings().getBoolean(["feature", "waitForStartOnConnect"])
		heatingUp = False
		swallowOk = False
		while True:
			try:
				line = self._readline()
				if line is None:
					break

				##~~ Error handling
				line = self._handleErrors(line)

				##~~ SD file list
				# if we are currently receiving an sd file list, each line is just a filename, so just read it and abort processing
				if self._sdFileList and isGcodeFileName(line.strip().lower()) and not 'End file list' in line:
					filename = line.strip().lower()
					if filterNonAscii(filename):
						self._logger.warn("Got a file from printer's SD that has a non-ascii filename (%s), that shouldn't happen according to the protocol" % filename)
					else:
						self._sdFiles.append(filename)
					continue

				##~~ Temperature processing
				if ' T:' in line or line.startswith('T:'):
					try:
						self._temp = float(self._regex_float.search(line.split('T:')[1]).group(0))
						if ' B:' in line:
							self._bedTemp = float(self._regex_float.search(line.split(' B:')[1]).group(0))

						self._callback.mcTempUpdate(self._temp, self._bedTemp, self._targetTemp, self._bedTargetTemp)
					except ValueError:
						# catch conversion issues, we'll rather just not get the temperature update instead of killing the connection
						pass

					#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:
						heatingUp = True
						if self._heatupWaitStartTime != 0:
							t = time.time()
							self._heatupWaitTimeLost = t - self._heatupWaitStartTime
							self._heatupWaitStartTime = t

				##~~ SD Card handling
				elif 'SD init fail' in line or 'volume.init failed' in line or 'openRoot failed' in line:
					self._sdAvailable = False
					self._sdFiles = []
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Not SD printing' in line:
					if self.isSdFileSelected() and self.isPrinting():
						# something went wrong, printer is reporting that we actually are not printing right now...
						self._sdFilePos = 0
						self._changeState(self.STATE_OPERATIONAL)
				elif 'SD card ok' in line:
					self._sdAvailable = True
					self.refreshSdFiles()
					self._callback.mcSdStateChange(self._sdAvailable)
				elif 'Begin file list' in line:
					self._sdFiles = []
					self._sdFileList = True
				elif 'End file list' in line:
					self._sdFileList = False
					self._callback.mcSdFiles(self._sdFiles)
				elif 'SD printing byte' in line:
					# answer to M27, at least on Marlin, Repetier and Sprinter: "SD printing byte %d/%d"
					match = self._regex_sdPrintingByte.search(line)
					self._currentFile.setFilepos(int(match.group(1)))
					self._callback.mcProgress()
				elif 'File opened' in line:
					# answer to M23, at least on Marlin, Repetier and Sprinter: "File opened:%s Size:%d"
					match = self._regex_sdFileOpened.search(line)
					self._currentFile = PrintingSdFileInformation(match.group(1), int(match.group(2)))
				elif 'File selected' in line:
					# final answer to M23, at least on Marlin, Repetier and Sprinter: "File selected"
					if self._currentFile is not None:
						self._callback.mcFileSelected(self._currentFile.getFilename(), self._currentFile.getFilesize(), True)
						eventManager().fire("FileSelected", self._currentFile.getFilename())
				elif 'Writing to file' in line:
					# anwer to M28, at least on Marlin, Repetier and Sprinter: "Writing to file: %s"
					self._changeState(self.STATE_PRINTING)
					line = "ok"
				elif 'Done printing file' in line:
					# printer is reporting file finished printing
					self._sdFilePos = 0
					self._callback.mcPrintjobDone()
					self._changeState(self.STATE_OPERATIONAL)
					eventManager().fire("PrintDone")
				elif 'Done saving file' in line:
					self.refreshSdFiles()

				##~~ Message handling
				elif line.strip() != '' \
						and line.strip() != 'ok' and not line.startswith("wait") \
						and not line.startswith('Resend:') \
						and line != 'echo:Unknown command:""\n' \
						and self.isOperational():
					self._callback.mcMessage(line)

				##~~ Parsing for feedback commands
				if feedbackControls:
					for name, matcher, template in feedbackControls:
						if name in feedbackErrors:
							# we previously had an error with that one, so we'll skip it now
							continue
						try:
							match = matcher.search(line)
							if match is not None:
								formatFunction = None
								if isinstance(template, str):
									formatFunction = str.format
								elif isinstance(template, unicode):
									formatFunction = unicode.format

								if formatFunction is not None:
									self._callback.mcReceivedRegisteredMessage(name, formatFunction(template, *(match.groups("n/a"))))
						except:
							if not name in feedbackErrors:
								self._logger.info("Something went wrong with feedbackControl \"%s\": " % name, exc_info=True)
								feedbackErrors.append(name)
							pass

				##~~ Parsing for pause triggers
				if pauseTriggers and not self.isStreaming():
					if "enable" in pauseTriggers.keys() and pauseTriggers["enable"].search(line) is not None:
						self.setPause(True)
					elif "disable" in pauseTriggers.keys() and pauseTriggers["disable"].search(line) is not None:
						self.setPause(False)
					elif "toggle" in pauseTriggers.keys() and pauseTriggers["toggle"].search(line) is not None:
						self.setPause(not self.isPaused())

				if "ok" in line and heatingUp:
					heatingUp = False

				### Baudrate detection
				if self._state == self.STATE_DETECT_BAUDRATE:
					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)
							eventManager().fire("Error", self.getErrorString())
						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:
							baudrate = self._baudrateDetectList.pop(0)
							try:
								self._serial.baudrate = baudrate
								self._serial.timeout = settings().getFloat(["serial", "timeout", "detection"])
								self._log("Trying baudrate: %d" % (baudrate))
								self._baudrateDetectRetry = 5
								self._baudrateDetectTestOk = 0
								timeout = getNewTimeout("communication")
								self._serial.write('\n')
								self._sendCommand("M105")
								self._testingBaudrate = True
							except:
								self._log("Unexpected error while setting baudrate: %d %s" % (baudrate, getExceptionString()))
					elif 'ok' in line and '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 = settings().getFloat(["serial", "timeout", "connection"])
							self._changeState(self.STATE_OPERATIONAL)
							if self._sdAvailable:
								self.refreshSdFiles()
							eventManager().fire("Connected", "%s at %s baud" % (self._port, self._baudrate))
					else:
						self._testingBaudrate = False

				### Connection attempt
				elif self._state == self.STATE_CONNECTING:
					if (line == "" or "wait" in line) and startSeen:
						self._sendCommand("M105")
					elif "start" in line:
						startSeen = True
					elif "ok" in line and startSeen:
						self._changeState(self.STATE_OPERATIONAL)
						if not self._sdAvailable:
							self.initSdCard()
						eventManager().fire("Connected", "%s at %s baud" % (self._port, self._baudrate))
					elif time.time() > timeout:
						self.close()

				### Operational
				elif self._state == self.STATE_OPERATIONAL or self._state == self.STATE_PAUSED:
					#Request the temperature on comm timeout (every 5 seconds) when we are not printing.
					if line == "" or "wait" in line:
						if self._resendDelta is not None:
							self._resendNextCommand()
						elif not self._commandQueue.empty():
							self._sendCommand(self._commandQueue.get())
						else:
							self._sendCommand("M105")
						tempRequestTimeout = getNewTimeout("communication")
					# resend -> start resend procedure from requested line
					elif line.lower().startswith("resend") or line.lower().startswith("rs"):
						if settings().get(["feature", "swallowOkAfterResend"]):
							swallowOk = True
						self._handleResendRequest(line)

				### Printing
				elif self._state == self.STATE_PRINTING:
					if line == "" and time.time() > timeout:
						self._log("Communication timeout during printing, forcing a line")
						line = 'ok'

					if self.isSdPrinting():
						if time.time() > tempRequestTimeout and not heatingUp:
							self._sendCommand("M105")
							tempRequestTimeout = getNewTimeout("communication")

						if time.time() > sdStatusRequestTimeout and not heatingUp:
							self._sendCommand("M27")
							sdStatusRequestTimeout = time.time() + 1

						if 'ok' or 'SD printing byte' in line:
							timeout = getNewTimeout("communication")
					else:
						# Even when printing request the temperature every 5 seconds.
						if time.time() > tempRequestTimeout and not self.isStreaming():
							self._commandQueue.put("M105")
							tempRequestTimeout = getNewTimeout("communication")

						if "ok" in line and swallowOk:
							swallowOk = False
						elif "ok" in line:
							timeout = getNewTimeout("communication")
							if self._resendDelta is not None:
								self._resendNextCommand()
							elif not self._commandQueue.empty() and not self.isStreaming():
								self._sendCommand(self._commandQueue.get())
							else:
								self._sendNext()
						elif line.lower().startswith("resend") or line.lower().startswith("rs"):
							if settings().get(["feature", "swallowOkAfterResend"]):
								swallowOk = True
							self._handleResendRequest(line)
			except:
				self._logger.exception("Something crashed inside the serial connection loop, please report this in OctoPrint's bug tracker:")

				errorMsg = "See octoprint.log for details"
				self._log(errorMsg)
				self._errorValue = errorMsg
				self._changeState(self.STATE_ERROR)
				eventManager().fire("Error", self.getErrorString())
		self._log("Connection closed, closing down monitor")