Exemplo n.º 1
0
	def add_file(self, destination, path, file_object, links=None, allow_overwrite=False, printer_profile=None, analysis=None, display=None):
		if printer_profile is None:
			printer_profile = self._printer_profile_manager.get_current_or_default()

		for hook in self._preprocessor_hooks.values():
			try:
				hook_file_object = hook(path, file_object, links=links, printer_profile=printer_profile, allow_overwrite=allow_overwrite)
			except:
				self._logger.exception("Error when calling preprocessor hook {}, ignoring".format(hook))
				continue

			if hook_file_object is not None:
				file_object = hook_file_object

		queue_entry = self._analysis_queue_entry(destination, path)

		if queue_entry is not None:
			self._analysis_queue.dequeue(queue_entry)

		path_in_storage = self._storage(destination).add_file(path, file_object, links=links, printer_profile=printer_profile, allow_overwrite=allow_overwrite, display=display)

		queue_entry = self._analysis_queue_entry(destination, path_in_storage, printer_profile=printer_profile, analysis=analysis)
		if queue_entry:
			self._analysis_queue.enqueue(queue_entry, high_priority=True)

		_, name = self._storage(destination).split_path(path_in_storage)
		eventManager().fire(Events.FILE_ADDED, dict(storage=destination,
		                                            path=path_in_storage,
		                                            name=name,
		                                            type=get_file_type(name)))
		eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
		return path_in_storage
Exemplo n.º 2
0
	def _handleErrors(self, line):
		# 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.
			
			line_lower = line.lower()

			if 'checksum mismatch' in line_lower \
				or 'wrong checksum' in line_lower \
				or 'line number is not last line number' in line_lower \
				or 'expected line' in line_lower \
				or 'no line number with checksum' in line_lower \
				or 'no checksum with line number' in line_lower \
				or 'format error' in line_lower \
				or 'missing checksum' in line_lower:
				pass
			elif not self.isError():
				self._errorValue = line[6:]
				self._changeState(self.STATE_ERROR)
				eventManager().fire(Events.ERROR, {"error": self.getErrorString()})
		return line
Exemplo n.º 3
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())
Exemplo n.º 4
0
	def unselectFile(self):
		if self.isBusy():
			return

		self._currentFile = None
		eventManager().fire("FileSelected", None)
		self._callback.mcFileSelected(None, None, False)
Exemplo n.º 5
0
	def mcStateChange(self, state):
		"""
		 Callback method for the comm object, called if the connection state changes.
		"""
		oldState = self._state
		self._state = state

		# forward relevant state changes to gcode manager
		if self._comm:
			if oldState == self._comm.STATE_PRINTING:
				if self._selectedFile is not None:
					if state == self._comm.STATE_OPERATIONAL:
						self._fileManager.printSucceeded(self._selectedFile["filename"], self._comm.getPrintTime())

					elif state == self._comm.STATE_CLOSED or state == self._comm.STATE_ERROR or state == self._comm.STATE_CLOSED_WITH_ERROR:
						self._fileManager.printFailed(self._selectedFile["filename"], self._comm.getPrintTime())

				self._fileManager.resumeAnalysis() # printing done, put those cpu cycles to good use

			if state == self._comm.STATE_PRINTING:
				self._fileManager.pauseAnalysis() # do not analyse gcode while printing
			elif state == self._comm.STATE_CONNECTING:
				eventManager().fire(Events.CONNECTING)
			elif state == self._comm.STATE_CLOSED:
				eventManager().fire(Events.DISCONNECTED)
			elif state == self._comm.STATE_ERROR:
				# Event has already been fired by comm since it has the error info.
				# here we close the comm object
				self._comm.close(True)
				self._comm = None
			elif state == self._comm.STATE_CLOSED_WITH_ERROR:
				# It's already closed so we only need to set it null so we can connect again
				self._comm = None

		self.refreshStateData()
Exemplo n.º 6
0
	def _analyze(self, entry, high_priority=False):
		path = entry.absolute_path
		if path is None or not os.path.exists(path):
			return

		self._current = entry
		self._current_highprio = high_priority
		self._current_progress = 0

		try:
			start_time = time.time()
			self._logger.info("Starting analysis of {}".format(entry))
			eventManager().fire(Events.METADATA_ANALYSIS_STARTED, {"name": entry.name,
			                                                       "path": entry.path,
			                                                       "origin": entry.location,
			                                                       "type": entry.type,

			                                                       # TODO deprecated, remove in 1.4.0
			                                                       "file": entry.path})
			try:
				result = self._do_analysis(high_priority=high_priority)
			except TypeError:
				result = self._do_analysis()
			self._logger.info("Analysis of entry {} finished, needed {:.2f}s".format(entry, time.time() - start_time))
			self._finished_callback(self._current, result)
		finally:
			self._current = None
			self._current_progress = None
Exemplo n.º 7
0
	def f(movie):
		delete_unrendered_timelapse(name)
		payload = dict(gcode=gcode if gcode is not None else "unknown",
		               movie=movie,
		               movie_basename=os.path.basename(movie),
		               movie_prefix=name)
		eventManager().fire(Events.MOVIE_DONE, payload)
Exemplo n.º 8
0
		def continue_rendering():
			if self._capture_success == 0:
				# no images - either nothing was attempted to be captured or all attempts ran into an error
				if self._capture_errors > 0:
					# this is the latter case
					_create_render_fail_handler(self._file_prefix,
					                            gcode=self._gcode_file)("n/a",
					                                                    returncode=0,
					                                                    stdout="",
					                                                    stderr="",
					                                                    reason="no_frames")

				# in any case, don't continue
				return

			# check if we have post roll configured
			if self._post_roll > 0:
				# capture post roll, wait for THAT to finish, THEN render
				eventManager().fire(Events.POSTROLL_START,
				                    dict(postroll_duration=self.calculate_post_roll(),
				                         postroll_length=self.post_roll,
				                         postroll_fps=self.fps))
				self._post_roll_start = time.time()
				if do_create_movie:
					self._on_post_roll_done = create_wait_for_captures(reset_and_create)
				else:
					self._on_post_roll_done = reset_image_number
				self.process_post_roll()
			else:
				# no post roll? perfect, render
				self._post_roll_start = None
				if do_create_movie:
					wait_for_captures(reset_and_create)
				else:
					reset_image_number()
Exemplo 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()})
Exemplo n.º 10
0
	def add_file(self, destination, path, file_object, links=None, allow_overwrite=False, printer_profile=None, analysis=None):
		if printer_profile is None:
			printer_profile = self._printer_profile_manager.get_current_or_default()

		for hook in self._preprocessor_hooks.values():
			try:
				hook_file_object = hook(path, file_object, links=links, printer_profile=printer_profile, allow_overwrite=allow_overwrite)
			except:
				self._logger.exception("Error when calling preprocessor hook {}, ignoring".format(hook))
				continue

			if hook_file_object is not None:
				file_object = hook_file_object
		file_path = self._storage(destination).add_file(path, file_object, links=links, printer_profile=printer_profile, allow_overwrite=allow_overwrite)
		absolute_path = self._storage(destination).path_on_disk(file_path)

		if analysis is None:
			file_type = get_file_type(absolute_path)
			if file_type:
				queue_entry = QueueEntry(file_path, file_type[-1], destination, absolute_path, printer_profile)
				self._analysis_queue.enqueue(queue_entry, high_priority=True)
		else:
			self._add_analysis_result(destination, path, analysis)

		eventManager().fire(Events.UPDATED_FILES, dict(type="printables"))
		return file_path
Exemplo n.º 11
0
    def processStl(self, absolutePath, destination, uploadCallback=None):
        from octoprint.slicers.cura import CuraFactory

        cura = CuraFactory.create_slicer()
        gcodePath = genGcodeFileName(absolutePath)
        config = settings.get("cura", "config")

        slicingStart = time.time()

        def stlProcessed(stlPath, gcodePath, error=None):
            if error:
                eventManager().fire("SlicingFailed", {"stl": self._getBasicFilename(
                    stlPath), "gcode": self._getBasicFilename(gcodePath), "reason": error})
                if os.path.exists(stlPath):
                    os.remove(stlPath)
            else:
                slicingStop = time.time()
                eventManager().fire("SlicingDone", {"stl": self._getBasicFilename(
                    stlPath), "gcode": self._getBasicFilename(gcodePath), "time": "%.2f" % (slicingStop - slicingStart)})
                self.processGcode(gcodePath, destination, uploadCallback)

        eventManager().fire("SlicingStarted", {"stl": self._getBasicFilename(
            absolutePath), "gcode": self._getBasicFilename(gcodePath)})
        cura.process_file(
            config, gcodePath, absolutePath, stlProcessed, [absolutePath, gcodePath])
Exemplo n.º 12
0
	def startPrint(self):
		if not super(PrinterVirtual, self).startPrint():
			return

		if not self.isOperational() or self.isPrinting():
			return

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

		if self._printJob and self._printJob.isAlive():
			raise Exception("A Print Job is still running")

		self._changeState(self.STATE_PRINTING)
		eventManager().fire(Events.PRINT_STARTED, {
			"file": self._currentFile['filename'],
			"filename": os.path.basename(self._currentFile['filename']),
			"origin": self._currentFile['origin']
		})

		#First we simulate heatup
		self.setTemperature("tool0", 210)
		self.setTemperature("bed", 60)
		self.mcHeatingUpUpdate(True)

		def heatupDone():
			if not self._shutdown:
				self.mcHeatingUpUpdate(False)
				self._printJob = JobSimulator(self, self._currentFile)
				self._printJob.start()

		t = threading.Timer(self._settings['heatingUp'], heatupDone)
		t.start()		 
Exemplo n.º 13
0
	def selectFile(self, filename, sd, printAfterSelect=False):
		if not super(PrinterVirtual, self).selectFile(filename, sd, printAfterSelect):
			return False

		if sd:
			raise('Printing from SD card is not supported for the Virtual Driver')

		if not os.path.exists(filename) or not os.path.isfile(filename):
			raise IOError("File %s does not exist" % filename)
		filesize = os.stat(filename).st_size

		eventManager().fire(Events.FILE_SELECTED, {
			"file": filename,
			"origin": FileDestinations.LOCAL
		})

		self._setJobData(filename, filesize, sd)
		self._stateMonitor.setState({"text": self.getStateString(), "flags": self._getStateFlags()})

		self._currentFile = {
			'filename': filename,
			'size': filesize,
			'origin': FileDestinations.LOCAL,
			'start_time': None,
			'progress': None,
			'position': None
		}

		if self._printAfterSelect:
			self.startPrint()

		return True
Exemplo n.º 14
0
	def on_comm_print_job_paused(self):
		payload = self._payload_for_print_job_event(position=self._comm.pause_position.as_dict() if self._comm and self._comm.pause_position else None)
		if payload:
			eventManager().fire(Events.PRINT_PAUSED, payload)
			self.script("afterPrintPaused",
			            context=dict(event=payload),
			            must_be_set=False)
Exemplo n.º 15
0
	def on_comm_print_job_resumed(self):
		payload = self._payload_for_print_job_event()
		if payload:
			eventManager().fire(Events.PRINT_RESUMED, payload)
			self.script("beforePrintResumed",
			            context=dict(event=payload),
			            must_be_set=False)
Exemplo n.º 16
0
	def unselectFile(self):
		if self.isBusy():
			return

		self._currentFile = None
		eventManager().fire(Events.FILE_DESELECTED)
		self._callback.mcFileSelected(None, None, False)
Exemplo n.º 17
0
	def close(self, isError = False):
		printing = self.isPrinting() or self.isPaused()
		if self._serial is not None:
			try:
				self._serial.close()
			except OSError as e:
				#log it but continue
				self._logger.error('Error closing serial port: %s' % e)

			if isError:
				self._changeState(self.STATE_CLOSED_WITH_ERROR)
			else:
				self._changeState(self.STATE_CLOSED)

		self._serial = None

		if settings().get(["feature", "sdSupport"]):
			self._sdFileList = []

		if printing:
			payload = None
			if self._currentFile is not None:
				payload = {
					"file": self._currentFile.getFilename(),
					"filename": os.path.basename(self._currentFile.getFilename()),
					"origin": self._currentFile.getFileLocation()
				}
			eventManager().fire(Events.PRINT_FAILED, payload)

		eventManager().fire(Events.DISCONNECTED)
Exemplo n.º 18
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()})
Exemplo n.º 19
0
	def __init__(self, post_roll=0, fps=25):
		self._logger = logging.getLogger(__name__)
		self._image_number = None
		self._in_timelapse = False
		self._gcode_file = None

		self._post_roll = post_roll
		self._on_post_roll_done = None

		self._capture_dir = settings().getBaseFolder("timelapse_tmp")
		self._movie_dir = settings().getBaseFolder("timelapse")
		self._snapshot_url = settings().get(["webcam", "snapshot"])
		self._ffmpeg_threads = settings().get(["webcam", "ffmpegThreads"])

		self._fps = fps

		self._render_thread = None

		self._capture_mutex = threading.Lock()
		self._capture_queue = Queue.Queue()
		self._capture_queue_active = True

		self._capture_queue_thread = threading.Thread(target=self._capture_queue_worker)
		self._capture_queue_thread.daemon = True
		self._capture_queue_thread.start()

		# subscribe events
		eventManager().subscribe(Events.PRINT_STARTED, self.on_print_started)
		eventManager().subscribe(Events.PRINT_FAILED, self.on_print_done)
		eventManager().subscribe(Events.PRINT_DONE, self.on_print_done)
		eventManager().subscribe(Events.PRINT_RESUMED, self.on_print_resumed)
		for (event, callback) in self.event_subscriptions():
			eventManager().subscribe(event, callback)
Exemplo n.º 20
0
	def _sendNext(self):
		with self._sendNextLock:
			line = self._currentFile.getNext()
			if line is None:
				if self.isStreaming():
					self._sendCommand("M29")

					remote = self._currentFile.getRemoteFilename()
					payload = {
						"local": self._currentFile.getLocalFilename(),
						"remote": remote,
						"time": self.getPrintTime()
					}

					self._currentFile = None
					self._changeState(self.STATE_OPERATIONAL)
					self._callback.mcFileTransferDone(remote)
					eventManager().fire(Events.TRANSFER_DONE, payload)
					self.refreshSdFiles()
				else:
					payload = {
						"file": self._currentFile.getFilename(),
						"filename": os.path.basename(self._currentFile.getFilename()),
						"origin": self._currentFile.getFileLocation(),
						"time": self.getPrintTime(),
						"layerCount": self._currentLayer
					}
					self._callback.mcPrintjobDone()
					self._changeState(self.STATE_OPERATIONAL)
					eventManager().fire(Events.PRINT_DONE, payload)
				return

			self._sendCommand(line, True)
			self._callback.mcProgress()
Exemplo n.º 21
0
	def setPause(self, pause):
		if self.isStreaming():
			return

		if not pause and self.isPaused():
			self._changeState(self.STATE_PRINTING)
			if self.isSdFileSelected():
				self.sendCommand("M24")
			else:
				self._sendNext()

			eventManager().fire(Events.PRINT_RESUMED, {
				"file": self._currentFile.getFilename(),
				"filename": os.path.basename(self._currentFile.getFilename()),
				"origin": self._currentFile.getFileLocation()
			})
		elif pause and self.isPrinting():
			self._changeState(self.STATE_PAUSED)
			if self.isSdFileSelected():
				self.sendCommand("M25") # pause print

			eventManager().fire(Events.PRINT_PAUSED, {
				"file": self._currentFile.getFilename(),
				"filename": os.path.basename(self._currentFile.getFilename()),
				"origin": self._currentFile.getFileLocation()
			})
Exemplo n.º 22
0
	def rampdown(self):
		self.disconnect()
		eventManager().unsubscribe(Events.METADATA_ANALYSIS_FINISHED, self.onMetadataAnalysisFinished);
		self._callbacks = []
		self._stateMonitor.stop()
		self._stateMonitor._worker.join()
		self._fileManager.rampdown()
Exemplo n.º 23
0
	def _addTemperatureData(self, temp, bedTemp):
		data = {
			"time": int(time.time())
		}

		if temp is not None:
			for tool in temp.keys():
				data["tool%d" % tool] = {
					"actual": temp[tool][0],
					"target": temp[tool][1]
				}

		if bedTemp is not None and isinstance(bedTemp, tuple):
			data["bed"] = {
				"actual": bedTemp[0],
				"target": bedTemp[1]
			}

		self._temps.append(data)

		self._temp = temp
		self._bedTemp = bedTemp

		eventManager().fire(Events.TEMPERATURE_CHANGE, data)
		self._stateMonitor.addTemperature(data)
Exemplo n.º 24
0
	def selectFile(self, filename, sd, printAfterSelect=False):
		if not self.isConnected() or self.isBusy() or self.isStreaming():
			self._logger.info("Cannot load file: printer not connected or currently busy")
			return False

		self._setProgressData(0, None, None, None, 1)
		self._setCurrentZ(None)

		if not os.path.exists(filename) or not os.path.isfile(filename):
			raise IOError("File %s does not exist" % filename)

		filesize = os.stat(filename).st_size

		eventManager().fire(Events.FILE_SELECTED, {
			"file": filename,
			"origin": FileDestinations.SDCARD if sd else FileDestinations.LOCAL
		})

		self._setJobData(filename, filesize, sd)
		self.refreshStateData()

		self._currentFile = {
			'filename': filename,
			'size': filesize,
			'origin': FileDestinations.SDCARD if sd else FileDestinations.LOCAL,
			'start_time': None,
			'progress': None,
			'position': None
		}

		if printAfterSelect:
			self.startPrint()

		return True
Exemplo n.º 25
0
	def f(movie, returncode=255, stdout="Unknown error", stderr="Unknown error"):
		event_payload = {"gcode": gcode if gcode is not None else "unknown",
		                 "movie": movie,
		                 "movie_basename": os.path.basename(movie)}
		payload = dict(event_payload)
		payload.update(dict(returncode=returncode, error=stderr))
		eventManager().fire(Events.MOVIE_FAILED, payload)
Exemplo n.º 26
0
	def mcProgress(self):
		"""
		 Callback method for the comm object, called upon any change in progress of the printjob.
		 Triggers storage of new values for printTime, printTimeLeft and the current progress.
		"""

		#Calculate estimated print time left
		printTime = self.getPrintTime()
		progress = self.getPrintProgress()
		estimatedTimeLeft = None

		if self._estimatedPrintTime:
			if printTime and progress:
				if progress < 1.0:
					estimatedTimeLeft = self._estimatedPrintTime * ( 1.0 - progress )
					elaspedTimeVariance = printTime - ( self._estimatedPrintTime - estimatedTimeLeft )
					adjustedEstimatedTime = self._estimatedPrintTime + elaspedTimeVariance
					estimatedTimeLeft = ( adjustedEstimatedTime * ( 1.0 -  progress) ) / 60
				else:
					estimatedTimeLeft = 0

			else:
				estimatedTimeLeft = self._estimatedPrintTime / 60

		value = self._formatPrintingProgressData(progress, self.getPrintFilepos(), printTime, estimatedTimeLeft, self.getCurrentLayer())
		eventManager().fire(Events.PRINTING_PROGRESS, value)

		self._setProgressData(progress, self.getPrintFilepos(), printTime, estimatedTimeLeft, self.getCurrentLayer())
Exemplo n.º 27
0
	def f(movie):
		global current_render_job
		event_payload = {"gcode": gcode if gcode is not None else "unknown",
		                 "movie": movie,
		                 "movie_basename": os.path.basename(movie)}
		current_render_job = event_payload
		eventManager().fire(Events.MOVIE_RENDERING, event_payload)
Exemplo n.º 28
0
	def __init__(self, postRoll=0):
		self._logger = logging.getLogger(__name__)
		self._imageNumber = None
		self._inTimelapse = False
		self._gcodeFile = None

		self._postRoll = postRoll
		self._postRollStart = None
		self._onPostRollDone = None

		self._captureDir = settings().getBaseFolder("timelapse_tmp")
		self._movieDir = settings().getBaseFolder("timelapse")
		self._snapshotUrl = settings().get(["webcam", "snapshot"])

		self._fps = 25

		self._renderThread = None
		self._captureMutex = threading.Lock()

		# subscribe events
		eventManager().subscribe(Events.PRINT_STARTED, self.onPrintStarted)
		eventManager().subscribe(Events.PRINT_FAILED, self.onPrintDone)
		eventManager().subscribe(Events.PRINT_DONE, self.onPrintDone)
		eventManager().subscribe(Events.PRINT_RESUMED, self.onPrintResumed)
		for (event, callback) in self.eventSubscriptions():
			eventManager().subscribe(event, callback)
Exemplo n.º 29
0
	def __init__(self):
		self.broadcastTraffic = 0 #Number of clients that wish to receive serial link traffic
		self.doIdleTempReports = True #Let's the client know if periodic temperature reports should be queries to the printer

		self._comm = None
		self._selectedFile = None
		self._printAfterSelect = False
		self._currentZ = None
		self._progress = None
		self._printTime = None
		self._printTimeLeft = None
		self._currentLayer = None
		self._currentPrintJobId = None

		self._profileManager = printerProfileManager()

		self._fileManager= printFileManagerMap[self._fileManagerClass.name]()
		self._fileManager.registerCallback(self)
		self._state = self.STATE_NONE
		self._logger = logging.getLogger(__name__)

		self._temp = {}
		self._bedTemp = None
		self._temps = deque([], 300)
		self._shutdown = False

		self._messages = deque([], 300)

		# callbacks
		self._callbacks = []
		#self._lastProgressReport = None

		self._stateMonitor = StateMonitor(
			ratelimit= 1.0,
			updateCallback= self._sendCurrentDataCallbacks,
			addTemperatureCallback= self._sendAddTemperatureCallbacks,
			addLogCallback= self._sendAddLogCallbacks,
			addMessageCallback= self._sendAddMessageCallbacks
		)

		self._stateMonitor.reset(
			state={"text": self.getStateString(), "flags": self._getStateFlags()},
			jobData={
				"file": {
					"name": None,
					"size": None,
					"origin": None,
					"date": None
				},
				"estimatedPrintTime": None,
				"filament": {
					"length": None,
					"volume": None
				}
			},
			progress={"completion": None, "filepos": None, "printTime": None, "printTimeLeft": None},
			currentZ=None
		)

		eventManager().subscribe(Events.METADATA_ANALYSIS_FINISHED, self.onMetadataAnalysisFinished);
Exemplo n.º 30
0
	def on_comm_state_change(self, state):
		"""
		 Callback method for the comm object, called if the connection state changes.
		"""
		oldState = self._state

		state_string = None
		if self._comm is not None:
			state_string = self._comm.getStateString()

		# forward relevant state changes to gcode manager
		if oldState == comm.MachineCom.STATE_PRINTING:
			if self._selectedFile is not None:
				if state == comm.MachineCom.STATE_CLOSED or state == comm.MachineCom.STATE_ERROR or state == comm.MachineCom.STATE_CLOSED_WITH_ERROR:
					self._fileManager.log_print(FileDestinations.SDCARD if self._selectedFile["sd"] else FileDestinations.LOCAL, self._selectedFile["filename"], time.time(), self._comm.getPrintTime(), False, self._printerProfileManager.get_current_or_default()["id"])
			self._analysisQueue.resume() # printing done, put those cpu cycles to good use
		elif state == comm.MachineCom.STATE_PRINTING:
			self._analysisQueue.pause() # do not analyse files while printing

		if state == comm.MachineCom.STATE_CLOSED or state == comm.MachineCom.STATE_CLOSED_WITH_ERROR:
			if self._comm is not None:
				self._comm = None

			self._setProgressData(completion=0)
			self._setCurrentZ(None)
			self._setJobData(None, None, None)
			self._printerProfileManager.deselect()
			eventManager().fire(Events.DISCONNECTED)

		self._setState(state, state_string=state_string)
Exemplo 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()
						#Update maps from https://www.thingiverse.com/thing:32084/#files, place them on ext/makerbot_driver/EEPROM

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

 						# This dissapeared in Sailfish 7.3
						#axisLengths = self._comm.read_named_value_from_EEPROM('AXIS_LENGTHS_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)
						eventManager().fire(Events.CONNECTED, {"port": self._port, "baudrate": self._baudrate})

						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()
Exemplo n.º 32
0
    def downloadPrintFile(self, printFileId, sendResponse):
        em = eventManager()

        def progressCb(progress):
            self.publishEvent('progress_download_printfile', {
                "type": "progress",
                "id": printFileId,
                "progress": progress
            })

        def successCb(destFile, fileInfo):
            if fileInfo is True:
                #This means the files was already on the device

                data = {
                    "type":
                    "success",
                    "id":
                    printFileId,
                    "filename":
                    printerManager().fileManager._getBasicFilename(destFile)
                }

                self.publishEvent('f¡nished_download_printfile', data)
                em.fire(Events.CLOUD_DOWNLOAD, data)

            else:
                data = {
                    "type":
                    "success",
                    "id":
                    printFileId,
                    "filename":
                    printerManager().fileManager._getBasicFilename(destFile),
                    "info":
                    fileInfo["info"],
                    "printer":
                    fileInfo["printer"],
                    "material":
                    fileInfo["material"],
                    "quality":
                    fileInfo["quality"],
                    "image":
                    fileInfo["image"],
                    "created":
                    fileInfo["created"]
                }

                self.publishEvent('f¡nished_download_printfile', data)

        def errorCb(destFile, error):
            if error == 'cancelled':
                data = {"type": "cancelled", "id": printFileId}

                self.publishEvent('f¡nished_download_printfile', data)
                em.fire(Events.CLOUD_DOWNLOAD, data)

            else:
                data = {"type": "error", "id": printFileId, "reason": error}

                em.fire(Events.CLOUD_DOWNLOAD, data)
                self.publishEvent('f¡nished_download_printfile', data)

            if destFile and os.path.exists(destFile):
                os.remove(destFile)

        if astroprintCloud().download_print_file(printFileId, progressCb,
                                                 successCb, errorCb):
            sendResponse({'success': 'no error'})
            return

        sendResponse('error', True)
        return