Ejemplo n.º 1
0
	def restartServer(self):
		if platform == "linux" or platform == "linux2":
			actions = self._settings.get(["system", "actions"])
			for a in actions:
				if a['action'] == 'astrobox-restart':
					#Call to Popen will start the restart command but return inmediately before it completes
					threading.Timer(1.0, subprocess.Popen, [a['command'].split(' ')]).start()
					self._logger.info('Restart command scheduled')

					from astroprint.boxrouter import boxrouterManager
					from astroprint.printer.manager import printerManager
					from astroprint.camera import cameraManager
					from astroprint.network.manager import networkManagerShutdown

					#let's be nice about shutthing things down
					boxrouterManager().boxrouter_disconnect()
					printerManager().disconnect()
					cameraManager().close_camera()
					networkManagerShutdown()

					return True

			return False

		return True
Ejemplo n.º 2
0
	def copy(self, src, dst, progressCb, observerId):
		blksize = 1048576 # 1MiB
		s = None
		d = None

		try:
			s = open(src, 'rb')
			d = open(dst, 'wb')

			sizeWritten = 0.0
			total = float( os.stat(src).st_size )

			while sizeWritten < total:
				buf = s.read(blksize)
				d.write(buf)

				sizeWritten += len(buf)

				progressCb((sizeWritten / total)*100, dst, observerId)

			printerManager().fileManager._metadataAnalyzer.addFileToQueue(dst)
			progressCb(100.0,dst,observerId)

		except (KeyboardInterrupt, Exception) as e:
			raise

		finally:
			if s:
				s.close()

			if d:
				d.close()
Ejemplo n.º 3
0
	def set(self, changes):
		for k in changes:
			if k in self.data:
				if self.data[k] != changes[k]:
					if k == 'driver':
						#change printer object
						from astroprint.printer.manager import printerManager

						try:
							printerManager(changes['driver'])

						except Exception as e:
							self._logger.error("Error selecting driver %s: %s" % (changes['driver'], e))
							#revent to previous driver
							printerManager(self.data['driver'])
							raise e
					elif k == 'printer_model':
						data = {
							"printerModel": changes[k]
						}
						astroprintCloud().updateBoxrouterData(data)
					self.data[k] = self._clean(k, changes[k])

					# Send astrobox event
					from octoprint.events import eventManager, Events
					if k == 'filament':
						eventManager().fire(Events.FILAMENT_CHANGE, { k: self.data[k]})
					eventManager().fire(Events.PRINTERPROFILE_CHANGE, { k: self.data[k]})

			else:
				self._logger.error("trying to set unkonwn printer profile field %s to %s" % (k, str(changes[k])))
Ejemplo n.º 4
0
	def _getLocalFileList(self, data):

		origin = data

		if origin == FileDestinations.SDCARD:
			sdFileList = printerManager().getSdFiles()

			files = []
			if sdFileList is not None:
				for sdFile, sdSize in sdFileList:
					file = {
						"name": sdFile,
						"origin": FileDestinations.SDCARD,
						#"refs": {
						#	"resource": url_for(".readPrintFile", target=FileDestinations.SDCARD, filename=sdFile, _external=True)
						#}
					}
					if sdSize is not None:
						file.update({"size": sdSize})
					files.append(file)
		else:
			files = printerManager().fileManager.getAllFileData()
			'''for file in files:
				file.update({
					"refs": {
						"resource": url_for(".readPrintFile", target=FileDestinations.LOCAL, filename=file["name"], _external=True),
						"download": url_for("index", _external=True) + "downloads/files/" + FileDestinations.LOCAL + "/" + file["name"]
					}
				})'''
		return files
Ejemplo n.º 5
0
		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)
Ejemplo n.º 6
0
def _verifyFileExists(origin, filename):
	if origin == FileDestinations.SDCARD:
		availableFiles = map(lambda x: x[0], printerManager().getSdFiles())
	else:
		availableFiles = printerManager().fileManager.getAllFilenames()

	return filename in availableFiles
Ejemplo n.º 7
0
	def selectAndOrPrint(filename, absFilename, destination):
		"""
		Callback for when the file is ready to be selected and optionally printed. For SD file uploads this is only
		the case after they have finished streaming to the printer, which is why this callback is also used
		for the corresponding call to addSdFile.

		Selects the just uploaded file if either selectAfterUpload or printAfterSelect are True, or if the
		exact file is already selected, such reloading it.
		"""
		if selectAfterUpload or printAfterSelect or (currentFilename == filename and currentOrigin == destination):
			printerManager().selectFile(absFilename, destination == FileDestinations.SDCARD, printAfterSelect)
Ejemplo n.º 8
0
	def cleanup(self):
		global discoveryManager

		printerManager().rampdown()
		discoveryManager.shutdown()
		discoveryManager = None
		boxrouterManager().shutdown()
		cameraManager().shutdown()

		from astroprint.network.manager import networkManagerShutdown
		networkManagerShutdown()
Ejemplo n.º 9
0
	def set(self, changes):
		for k in changes:
			if k in self.data:
				if self.data[k] != changes[k]:
					if k == 'driver':
						#change printer object
						from astroprint.printer.manager import printerManager 

						printerManager(changes['driver']) 

					self.data[k] = self._clean(k, changes[k])
			else:
				self._logger.error("trying to set unkonwn printer profile field %s to %s" % (k, str(changes[k])))
Ejemplo n.º 10
0
	def successCb(destFile, fileInfo):
		if printerManager().fileManager.saveCloudPrintFile(destFile, fileInfo, FileDestinations.LOCAL):
			em.fire(
				Events.CLOUD_DOWNLOAD, {
					"type": "success",
					"id": print_file_id,
					"filename": printerManager().fileManager._getBasicFilename(destFile),
					"info": fileInfo["info"]
				}
			)

		else:
			errorCb(destFile, "Couldn't save the file")
Ejemplo n.º 11
0
def changeSerialLogs():
	data = request.json

	if data and 'active' in data:
		s = settings()
		s.setBoolean(['serial', 'log'], data['active'])
		s.save()

		printerManager().setSerialDebugLogging(data['active'])

		return jsonify();
	
	else:
		return ("Wrong data sent in.", 400)
Ejemplo n.º 12
0
def save_printer_profile_settings():
	driver = request.values.get('driver', None)

	if driver:
		pp = printerProfileManager()
		pp.data['driver'] = driver
		pp.save()

		#swap the printerManager here
		printerManager(driver)

		return make_response("OK", 200)

	return make_response('Invalid Connection Settings', 400)
Ejemplo n.º 13
0
	def download_print_file(self, print_file_id, progressCb, successCb, errorCb):
		progressCb(1)

		try:
			r = requests.get('%s/print-files/%s' % (self.apiHost, print_file_id), auth=self.hmacAuth)
			data = r.json()
		except:
			data = None

		destFile = None

		if data and "download_url" in data and "name" in data and "info" in data:
			progressCb(2)

			destFile = printerManager().fileManager.getAbsolutePath(data['name'], mustExist=False)

			if destFile:
				downloadManager().startDownload({
					'downloadUrl': data["download_url"],
					'destFile': destFile,
					'printFileId': print_file_id,
					'printFileInfo': data['info'],
					'progressCb': progressCb,
					'successCb': successCb,
					'errorCb': errorCb
				})

				return True

		else:
			errorCb(destFile, 'Unable to download file')
			return False
Ejemplo n.º 14
0
	def initial_state(self, data, clientId, done):
		printer = printerManager()
		cm = cameraManager()
		softwareManager = swManager()

		state = {
			'printing': printer.isPrinting(),
			'heatingUp': printer.isHeatingUp(),
			'operational': printer.isOperational(),
			'paused': printer.isPaused(),
			'camera': printer.isCameraConnected(),
			'filament' : printerProfileManager().data['filament'],
			'printCapture': cm.timelapseInfo,
			'profile': printerProfileManager().data,
			'remotePrint': True,
			'capabilities': softwareManager.capabilities() + cm.capabilities,
			'tool': printer.getSelectedTool() if printer.isOperational() else None,
			'printSpeed': printer.getPrintingSpeed(),
			'printFlow': printer.getPrintingFlow()
		}

		if state['printing'] or state['paused']:
			#Let's add info about the ongoing print job
			state['job'] = printer._stateMonitor._jobData
			state['progress'] = printer._stateMonitor._progress

		done(state)
Ejemplo n.º 15
0
	def getStatus(self):
		printer = printerManager()
		cm = cameraManager()
		ppm = printerProfileManager()

		fileName = None

		if printer.isPrinting():
			currentJob = printer.getCurrentJob()
			fileName = currentJob["file"]["name"]

		return {
				'id': boxrouterManager().boxId,
				'name': networkManager().getHostname(),
				'printing': printer.isPrinting(),
				'fileName': fileName,
				'printerModel': ppm.data['printer_model'] if ppm.data['printer_model']['id'] else None,
				'filament' : ppm.data['filament'],
				'material': None,
				'operational': printer.isOperational(),
				'paused': printer.isPaused(),
				'camera': cm.isCameraConnected(),
				#'printCapture': cm.timelapseInfo,
				'remotePrint': True,
				'capabilities': ['remotePrint'] + cm.capabilities
			}
Ejemplo n.º 16
0
def printerBedCommand():
	pm = printerManager()

	if not pm.isOperational():
		return make_response("Printer is not operational", 409)

	valid_commands = {
		"target": ["target"],
		"offset": ["offset"]
	}
	command, data, response = util.getJsonCommandFromRequest(request, valid_commands)
	if response is not None:
		return response

	##~~ temperature
	if command == "target":
		target = data["target"]

		# make sure the target is a number
		if not isinstance(target, (int, long, float)):
			return make_response("Not a number: %r" % target, 400)

		# perform the actual temperature command
		pm.setTemperature("bed", target)

	return NO_CONTENT
Ejemplo n.º 17
0
	def _sync_print_file_store(self):
		if self.cloud_enabled():
			try:
				r = requests.get( "%s/print-files?format=%s" % (self.apiHost, printerManager().fileManager.fileFormat), auth=self.hmacAuth )
				self._print_file_store = r.json()
			except Exception as e:
				self._logger.error("Error syncing with cloud: %s" % e, exc_info = True)
Ejemplo n.º 18
0
def deletePrintFile(filename, target):
	if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
		return make_response("Unknown target: %s" % target, 404)

	if not _verifyFileExists(target, filename):
		return make_response("File not found on '%s': %s" % (target, filename), 404)

	sd = target == FileDestinations.SDCARD

	printer = printerManager()

	currentJob = printer.getCurrentJob()
	currentFilename = None
	currentSd = None
	if currentJob is not None and "filename" in currentJob.keys() and "sd" in currentJob.keys():
		currentFilename = currentJob["filename"]
		currentSd = currentJob["sd"]

	# prohibit deleting the file that is currently being printed
	if currentFilename == filename and currentSd == sd and (printer.isPrinting() or printer.isPaused()):
		make_response("Trying to delete file that is currently being printed: %s" % filename, 409)

	# deselect the file if it's currently selected
	if currentFilename is not None and filename == currentFilename:
		printer.unselectFile()

	# delete it
	if sd:
		printer.deleteSdFile(filename)
	else:
		printer.fileManager.removeFile(filename)

	return NO_CONTENT
Ejemplo n.º 19
0
	def startPrintCapture(self, filename):
		data = {'name': filename}

		pm = printerManager()

		print_file_id = pm.fileManager.getFileCloudId(filename)
		print_job_id = pm.currentPrintJobId

		if print_file_id:
			data['print_file_id'] = print_file_id

		if print_job_id:
			data['print_job_id'] = print_job_id

		try:
			r = requests.post( 
				"%s/prints" % self.apiHost, 
				data= data,
				auth= self.hmacAuth
			)
			status_code = r.status_code
		except:
			status_code = 500

		if status_code == 201:
			data = r.json()
			return data['print_id']

		else:
			return None
Ejemplo n.º 20
0
def jobState():
	currentData = printerManager().getCurrentData()
	return jsonify({
		"job": currentData["job"],
		"progress": currentData["progress"],
		"state": currentData["state"]["text"]
	})
Ejemplo n.º 21
0
	def on_deleted(self, event):
		fm = printerManager().fileManager
		filename = fm._getBasicFilename(event.src_path)
		if not filename:
			return

		fm.removeFileFromMetadata(filename)
Ejemplo n.º 22
0
	def printerPrintheadCommand(self, data, callback):
		pm = printerManager()

		if not pm.isOperational() or pm.isPrinting():
			# do not jog when a print job is running or we don't have a connection
			callback("Printer is not operational or currently printing",True)

		valid_axes = ["x", "y", "z"]

		validated_values = {}
		for axis in valid_axes:
			try:
				value = data[axis]
			except:
				value = None
			if isinstance(value,(int,long,float)):
				validated_values[axis] = value

		if len(validated_values) <= 0:
			self._logger.error('not a number')
			callback('movement value is not a number',True)
		else:
			# execute the jog commands
			for axis, value in validated_values.iteritems():
				pm.jog(axis, value)

		callback({'success': 'no_error'})
Ejemplo n.º 23
0
	def _sync_print_file_store(self):
		if self.cloud_enabled():
			try:
				r = requests.get( "%s/print-files?format=%s" % (self.apiHost, printerManager().fileManager.fileFormat), auth=self.hmacAuth )
				self._print_file_store = r.json()
			except:
				pass		
Ejemplo n.º 24
0
	def extrude(self,data,callback):

		pm = printerManager()

		if not pm.isOperational():
			callback("Printer is not operational", True)
			return

		if pm.isPrinting():
			# do not extrude when a print job is running
			callback("Printer is currently printing", True)
			return

		amount = data["amount"]
		speed = data["speed"]
		tool = data["tool"]

		if not isinstance(amount, (int, long, float)):
			callback("Not a number for extrusion amount: " + amount, True)
			return

		if speed and not isinstance(speed, (int, long, float)):
			speed = None

		pm.extrude(tool, amount, speed)

		callback({'success': 'no_error'})
		return
Ejemplo n.º 25
0
def printerState():
	pm = printerManager()

	if not pm.isOperational():
		return make_response("Printer is not operational", 409)

	# process excludes
	excludes = []
	if "exclude" in request.values:
		excludeStr = request.values["exclude"]
		if len(excludeStr.strip()) > 0:
			excludes = filter(lambda x: x in ["temperature", "sd", "state"], map(lambda x: x.strip(), excludeStr.split(",")))

	result = {}

	# add temperature information
	if not "temperature" in excludes:
		result.update({"temperature": _getTemperatureData(lambda x: x)})

	# add sd information
	if not "sd" in excludes and settings().getBoolean(["feature", "sdSupport"]):
		result.update({"sd": {"ready": pm.isSdReady()}})

	# add state information
	if not "state" in excludes:
		state = pm.getCurrentData()["state"]
		result.update({"state": state})

	return jsonify(result)
Ejemplo n.º 26
0
def printerCommand():
	pm = printerManager()

	if not pm.isOperational():
		return make_response("Printer is not operational", 409)

	if not "application/json" in request.headers["Content-Type"]:
		return make_response("Expected content type JSON", 400)

	data = request.json

	parameters = {}
	if "parameters" in data.keys():
		parameters = data["parameters"]

	commands = []
	if "command" in data.keys():
		commands = [data["command"]]
	elif "commands" in data.keys():
		commands = data["commands"]

	commandsToSend = []
	for command in commands:
		commandToSend = command
		if len(parameters) > 0:
			commandToSend = command % parameters
		commandsToSend.append(commandToSend)

	pm.commands(commandsToSend)

	return NO_CONTENT
Ejemplo n.º 27
0
def printerSdCommand():
	if not settings().getBoolean(["feature", "sdSupport"]):
		return make_response("SD support is disabled", 404)

	pm = printerManager()

	if not pm.isOperational() or pm.isPrinting() or pm.isPaused():
		return make_response("Printer is not operational or currently busy", 409)

	valid_commands = {
		"init": [],
		"refresh": [],
		"release": []
	}
	command, data, response = util.getJsonCommandFromRequest(request, valid_commands)
	if response is not None:
		return response

	if command == "init":
		pm.initSdCard()
	elif command == "refresh":
		pm.refreshSdFiles()
	elif command == "release":
		pm.releaseSdCard()

	return NO_CONTENT
Ejemplo n.º 28
0
def printerPrintheadCommand():
	pm = printerManager()

	valid_commands = {
		"jog": [],
		"home": ["axes"],
		"babystepping": []
	}
	command, data, response = util.getJsonCommandFromRequest(request, valid_commands)
	if not pm.isOperational() or command != "babystepping" and pm.isPrinting():
		# do not jog when a print job is running or we don't have a connection
		return make_response("Printer is not operational or currently printing", 409)

	if response is not None:
		return response

	valid_axes = ["x", "y", "z"]
	##~~ jog command
	if command == "jog":
		# validate all jog instructions, make sure that the values are numbers
		validated_values = {}
		for axis in valid_axes:
			if axis in data:
				value = data[axis]
				if not isinstance(value, (int, long, float)):
					return make_response("Not a number for axis %s: %r" % (axis, value), 400)
				validated_values[axis] = value

		# execute the jog commands
		for axis, value in validated_values.iteritems():
			pm.jog(axis, value)

	##~~ home command
	elif command == "home":
		validated_values = []
		axes = data["axes"]
		for axis in axes:
			if not axis in valid_axes:
				return make_response("Invalid axis: %s" % axis, 400)
			validated_values.append(axis)

		# execute the home command
		pm.home(validated_values)

	##~~ babystepping command
	elif command == "babystepping":
		if "amount" in data:
			value = data['amount']

			if not isinstance(value, (int, long, float)):
				return make_response("Not a number for amount: %r" % (value), 400)

			validated_values = {}
			validated_values['amount'] = value

			# execute the babystepping command
			pm.babystepping(validated_values['amount'])

	return NO_CONTENT
Ejemplo n.º 29
0
	def printerPrintingSpeed(self, data, callback):
		pm = printerManager()

		amount = data["amount"]

		pm.printingSpeed(amount)

		callback({'success': 'no_error'})
Ejemplo n.º 30
0
	def setPrintingFlow(self, data, sendResponse= None):
		pm = printerManager()

		pm.setPrintingFlow(int(data))

		sendResponse({'success': 'no_error'})

		return
Ejemplo n.º 31
0
	def download_print_file(self, print_file_id, progressCb, successCb, errorCb):
		dm = downloadManager()

		if dm.isDownloading(print_file_id):
			#We just return, there's already a download for this file in process
			#which means that the events will be issued for that one.
			return True

		fileManager = printerManager().fileManager

		try:
			r = requests.get('%s/print-files/%s' % (self.apiHost, print_file_id), auth=self.hmacAuth)
			data = r.json()
		except:
			data = None

		printFile = fileManager.getFileByCloudId(print_file_id)

		if printFile:
			self._logger.info('Print file %s is already on the box as %s' % (print_file_id, printFile))

			if data and "printFileName" in data:
				pm = printerManager()
				localPrintFileName = pm.fileManager.getPrintFileName(printFile)

				if data["printFileName"] != localPrintFileName:
					pm.fileManager.setPrintFileName(printFile, data["printFileName"])
					#update printFileName for this printFile in the collection
					if self._print_file_store:
						for x in self._print_file_store:
							if x['id'] == print_file_id:
								x['printFileName'] = data["printFileName"]
								break

			successCb(printFile, True)
			return True

		#The file wasn't there so let's go get it
		progressCb(1)

		destFile = None
		printFileName = None

		if data and "download_url" in data and (("name" in data) or ("filename" in data)) and "info" in data:
			progressCb(2)

			if "filename" in data:
				destFile = fileManager.getAbsolutePath(data['filename'], mustExist=False)
				printFileName = data["printFileName"]

			else:
				destFile = fileManager.getAbsolutePath(data['name'], mustExist=False)
				printFileName = data["name"]

			destFile = fileManager.getAbsolutePath(data['name'], mustExist=False)

			if destFile:
				def onSuccess(pf, error):
					self._print_file_store = None
					successCb(pf, error)

				dm.startDownload({
					'downloadUrl': data["download_url"],
					'destFile': destFile,
					'printFileId': print_file_id,
					'printFileInfo': data['info'],
					'printFileName': printFileName,
					'progressCb': progressCb,
					'successCb': onSuccess,
					'errorCb': errorCb
				})

				return True

		else:
			errorCb(destFile, 'Unable to download file')
			return False
Ejemplo n.º 32
0
def index():
    s = settings()
    loggedUsername = s.get(["cloudSlicer", "loggedUser"])

    if (s.getBoolean(["server", "firstRun"])):
        swm = swManager()

        # we need to get the user to sign into their AstroPrint account
        return render_template("setup.jinja2",
                               debug=debug,
                               uiApiKey=UI_API_KEY,
                               version=VERSION,
                               commit=swm.commit,
                               variantData=variantManager().data,
                               astroboxName=networkManager().getHostname(),
                               checkSoftware=swm.shouldCheckForNew,
                               settings=s,
                               wsToken=create_ws_token(
                                   userManager.findUser(loggedUsername).
                                   publicKey if loggedUsername else None))

    elif softwareManager.updatingRelease or softwareManager.forceUpdateInfo:
        return render_template(
            "updating.jinja2",
            uiApiKey=UI_API_KEY,
            showForceUpdate=softwareManager.forceUpdateInfo != None,
            releaseInfo=softwareManager.updatingRelease
            or softwareManager.forceUpdateInfo,
            lastCompletionPercent=softwareManager.lastCompletionPercent,
            lastMessage=softwareManager.lastMessage,
            variantData=variantManager().data,
            astroboxName=networkManager().getHostname(),
            wsToken=create_ws_token(
                userManager.findUser(loggedUsername).
                publicKey if loggedUsername else None))

    elif loggedUsername and (current_user is None
                             or not current_user.is_authenticated
                             or current_user.get_id() != loggedUsername):
        if current_user.is_authenticated:
            logout_user()
        return render_template("locked.jinja2",
                               username=loggedUsername,
                               uiApiKey=UI_API_KEY,
                               astroboxName=networkManager().getHostname(),
                               variantData=variantManager().data)

    else:
        pm = printerManager()
        nm = networkManager()
        swm = swManager()
        cm = cameraManager()

        paused = pm.isPaused()
        printing = pm.isPrinting()
        online = nm.isOnline()

        return render_template(
            "app.jinja2",
            user_email=loggedUsername,
            show_bad_shutdown=swm.wasBadShutdown and not swm.badShutdownShown,
            version=VERSION,
            commit=swm.commit,
            printing=printing,
            paused=paused,
            online=online,
            print_capture=cm.timelapseInfo if printing or paused else None,
            printer_profile=printerProfileManager().data,
            uiApiKey=UI_API_KEY,
            astroboxName=nm.getHostname(),
            variantData=variantManager().data,
            checkSoftware=swm.shouldCheckForNew,
            serialLogActive=s.getBoolean(['serial', 'log']),
            cameraManager=cm.name,
            wsToken=create_ws_token(
                userManager.findUser(loggedUsername).
                publicKey if loggedUsername else None))
Ejemplo n.º 33
0
 def unregisterEvents(self):
     if self._systemListener:
         printerManager().unregisterCallback(self._systemListener)
         self._systemListener.cleanup()
         self._systemListener = None
Ejemplo n.º 34
0
 def registerEvents(self):
     if not self._systemListener:
         self._systemListener = SystemListener(self._weakRefRouter)
         printerManager().registerCallback(self._systemListener)
Ejemplo n.º 35
0
def uploadPrintFile(target):
    printer = printerManager()

    if not target in [FileDestinations.LOCAL, FileDestinations.SDCARD]:
        return make_response("Unknown target: %s" % target, 404)

    if not "file" in request.files.keys():
        return make_response("No file included", 400)

    if target == FileDestinations.SDCARD and not settings().getBoolean(
        ["feature", "sdSupport"]):
        return make_response("SD card support is disabled", 404)

    file = request.files["file"]
    sd = target == FileDestinations.SDCARD
    selectAfterUpload = "select" in request.values.keys(
    ) and request.values["select"] in valid_boolean_trues
    printAfterSelect = "print" in request.values.keys(
    ) and request.values["print"] in valid_boolean_trues

    if sd:
        # validate that all preconditions for SD upload are met before attempting it
        if not (printer.isOperational()
                and not (printer.isPrinting() or printer.isPaused())):
            return make_response(
                "Can not upload to SD card, printer is either not operational or already busy",
                409)
        if not printer.isSdReady():
            return make_response(
                "Can not upload to SD card, not yet initialized", 409)

    # determine current job
    currentFilename = None
    currentOrigin = None
    currentJob = printer.getCurrentJob()
    if currentJob is not None and "file" in currentJob.keys():
        currentJobFile = currentJob["file"]
        if "name" in currentJobFile.keys() and "origin" in currentJobFile.keys(
        ):
            currentFilename = currentJobFile["name"]
            currentOrigin = currentJobFile["origin"]

    # determine future filename of file to be uploaded, abort if it can't be uploaded
    futureFilename = printer.fileManager.getFutureFilename(file)
    if futureFilename is None or (
            not settings().getBoolean(["cura", "enabled"])
            and not printer.fileManager.isValidFilename(futureFilename)):
        return make_response(
            "Can not upload file %s, wrong format?" % file.filename, 415)

    # prohibit overwriting currently selected file while it's being printed
    if futureFilename == currentFilename and target == currentOrigin and printer.isPrinting(
    ) or printer.isPaused():
        return make_response(
            "Trying to overwrite file that is currently being printed: %s" %
            currentFilename, 409)

    def fileProcessingFinished(filename, absFilename, destination):
        """
        Callback for when the file processing (upload, optional slicing, addition to analysis queue) has
        finished.

        Depending on the file's destination triggers either streaming to SD card or directly calls selectAndOrPrint.
        """
        if destination == FileDestinations.SDCARD:
            return filename, printerManager().addSdFile(
                filename, absFilename, selectAndOrPrint)
        else:
            selectAndOrPrint(filename, absFilename, destination)
            return filename

    def selectAndOrPrint(filename, absFilename, destination):
        """
        Callback for when the file is ready to be selected and optionally printed. For SD file uploads this is only
        the case after they have finished streaming to the printer, which is why this callback is also used
        for the corresponding call to addSdFile.

        Selects the just uploaded file if either selectAfterUpload or printAfterSelect are True, or if the
        exact file is already selected, such reloading it.
        """
        if selectAfterUpload or printAfterSelect or (
                currentFilename == filename and currentOrigin == destination):
            printerManager().selectFile(absFilename,
                                        destination == FileDestinations.SDCARD,
                                        printAfterSelect)

    try:
        filename, done = printer.fileManager.addFile(file, target,
                                                     fileProcessingFinished)
    except IOError:
        return make_response("Your filesystem seems to be corrupt", 500)

    if filename is None:
        return make_response("Could not upload the file %s" % file.filename,
                             500)

    sdFilename = None
    if isinstance(filename, tuple):
        filename, sdFilename = filename

    eventManager.fire(Events.UPLOAD, {"file": filename, "target": target})

    files = {}
    location = url_for(".readPrintFile",
                       target=FileDestinations.LOCAL,
                       filename=filename,
                       _external=True)
    files.update({
        FileDestinations.LOCAL: {
            "name": filename,
            "origin": FileDestinations.LOCAL,
            "refs": {
                "resource":
                location,
                "download":
                url_for("index", _external=True) + "downloads/files/" +
                FileDestinations.LOCAL + "/" + filename
            }
        }
    })

    if sd and sdFilename:
        location = url_for(".readPrintFile",
                           target=FileDestinations.SDCARD,
                           filename=sdFilename,
                           _external=True)
        files.update({
            FileDestinations.SDCARD: {
                "name": sdFilename,
                "origin": FileDestinations.SDCARD,
                "refs": {
                    "resource": location
                }
            }
        })

    r = make_response(jsonify(files=files, done=done), 201)
    r.headers["Location"] = location
    return r
Ejemplo n.º 36
0
class Server():
    def __init__(self,
                 configfile=None,
                 basedir=None,
                 host="0.0.0.0",
                 port=5000,
                 debug=False,
                 allowRoot=False,
                 logConf=None):
        self._configfile = configfile
        self._basedir = basedir
        self._host = host
        self._port = port
        self._debug = debug
        self._allowRoot = allowRoot
        self._logConf = logConf
        self._ioLoop = None

    def stop(self):
        if self._ioLoop:
            self._ioLoop.stop()
            self._ioLoop = None

    def run(self):
        if not self._allowRoot:
            self._checkForRoot()

        global userManager
        global eventManager
        global loginManager
        global debug
        global softwareManager
        global discoveryManager
        global VERSION
        global UI_API_KEY

        from tornado.wsgi import WSGIContainer
        from tornado.httpserver import HTTPServer
        from tornado.ioloop import IOLoop
        from tornado.web import Application, FallbackHandler

        from astroprint.printfiles.watchdogs import UploadCleanupWatchdogHandler

        debug = self._debug

        # first initialize the settings singleton and make sure it uses given configfile and basedir if available
        self._initSettings(self._configfile, self._basedir)
        s = settings()

        if not s.getBoolean(['api', 'regenerate']) and s.getString(
            ['api', 'key']):
            UI_API_KEY = s.getString(['api', 'key'])
        else:
            UI_API_KEY = ''.join('%02X' % ord(z) for z in uuid.uuid4().bytes)

        # then initialize logging
        self._initLogging(self._debug, self._logConf)
        logger = logging.getLogger(__name__)

        if s.getBoolean(["accessControl", "enabled"]):
            userManagerName = s.get(["accessControl", "userManager"])
            try:
                clazz = util.getClass(userManagerName)
                userManager = clazz()
            except AttributeError, e:
                logger.exception(
                    "Could not instantiate user manager %s, will run with accessControl disabled!"
                    % userManagerName)

        softwareManager = swManager()
        VERSION = softwareManager.versionString

        logger.info("Starting AstroBox (%s) - Commit (%s)" %
                    (VERSION, softwareManager.commit))

        from astroprint.migration import migrateSettings
        migrateSettings()

        eventManager = events.eventManager()
        printer = printerManager(printerProfileManager().data['driver'])

        #Start some of the managers here to make sure there are no thread collisions
        from astroprint.network.manager import networkManager
        from astroprint.boxrouter import boxrouterManager

        networkManager()
        boxrouterManager()

        # configure timelapse
        #octoprint.timelapse.configureTimelapse()

        app.wsgi_app = ReverseProxied(app.wsgi_app)

        app.secret_key = boxrouterManager().boxId
        loginManager = LoginManager()
        loginManager.session_protection = "strong"
        loginManager.user_callback = load_user
        if userManager is None:
            loginManager.anonymous_user = users.DummyUser
            principals.identity_loaders.appendleft(users.dummy_identity_loader)
        loginManager.init_app(app)

        # setup command triggers
        events.CommandTrigger(printer)
        if self._debug:
            events.DebugEventListener()

        if networkManager().isOnline():
            softwareManager.checkForcedUpdate()

        if self._host is None:
            self._host = s.get(["server", "host"])
        if self._port is None:
            self._port = s.getInt(["server", "port"])

        app.debug = self._debug

        from octoprint.server.api import api

        app.register_blueprint(api, url_prefix="/api")

        boxrouterManager(
        )  # Makes sure the singleton is created here. It doesn't need to be stored
        self._router = SockJSRouter(self._createSocketConnection, "/sockjs")

        discoveryManager = DiscoveryManager()

        def access_validation_factory(validator):
            """
			Creates an access validation wrapper using the supplied validator.

			:param validator: the access validator to use inside the validation wrapper
			:return: an access validation wrapper taking a request as parameter and performing the request validation
			"""
            def f(request):
                """
				Creates a custom wsgi and Flask request context in order to be able to process user information
				stored in the current session.

				:param request: The Tornado request for which to create the environment and context
				"""
                wsgi_environ = tornado.wsgi.WSGIContainer.environ(request)
                with app.request_context(wsgi_environ):
                    app.session_interface.open_session(app, request)
                    loginManager.reload_user()
                    validator(request)

            return f

        self._tornado_app = Application(self._router.urls + [
            #(r"/downloads/timelapse/([^/]*\.mpg)", LargeResponseHandler, {"path": s.getBaseFolder("timelapse"), "as_attachment": True}),
            (r"/downloads/files/local/([^/]*\.(gco|gcode))",
             LargeResponseHandler, {
                 "path": s.getBaseFolder("uploads"),
                 "as_attachment": True
             }),
            (r"/downloads/logs/([^/]*)", LargeResponseHandler, {
                "path": s.getBaseFolder("logs"),
                "as_attachment": True,
                "access_validation": access_validation_factory(admin_validator)
            }),
            #(r"/downloads/camera/current", UrlForwardHandler, {"url": s.get(["webcam", "snapshot"]), "as_attachment": True, "access_validation": access_validation_factory(user_validator)}),
            (r".*", FallbackHandler, {
                "fallback": WSGIContainer(app.wsgi_app)
            })
        ])
        self._server = HTTPServer(self._tornado_app,
                                  max_buffer_size=1048576 *
                                  s.getInt(['server', 'maxUploadSize']))
        self._server.listen(self._port, address=self._host)

        logger.info("Listening on http://%s:%d" % (self._host, self._port))

        eventManager.fire(events.Events.STARTUP)
        if s.getBoolean(["serial", "autoconnect"]):
            (port, baudrate) = s.get(["serial", "port"
                                      ]), s.getInt(["serial", "baudrate"])
            connectionOptions = printer.getConnectionOptions()
            if port in connectionOptions["ports"]:
                printer.connect(port, baudrate)

        # start up watchdogs
        observer = Observer()
        observer.schedule(UploadCleanupWatchdogHandler(),
                          s.getBaseFolder("uploads"))
        observer.start()

        try:
            self._ioLoop = IOLoop.instance()
            self._ioLoop.start()

        except SystemExit:
            pass

        except:
            logger.fatal(
                "Please report this including the stacktrace below in AstroPrint's bugtracker. Thanks!"
            )
            logger.exception("Stacktrace follows:")

        finally:
            observer.stop()
            self.cleanup()

        observer.join()
        logger.info('Good Bye!')
Ejemplo n.º 37
0
def index():
	s = settings()
	loggedUsername = s.get(["cloudSlicer", "loggedUser"])
	publicKey = None

	if loggedUsername:
		user = userManager.findUser(loggedUsername)
		if user:
			publicKey = user.publicKey

	if (s.getBoolean(["server", "firstRun"])):
		swm = swManager()

		# we need to get the user to sign into their AstroPrint account
		return render_template(
			"setup.jinja2",
			debug= debug,
			uiApiKey= UI_API_KEY,
			version= VERSION,
			commit= swm.commit,
			astroboxName= networkManager().getHostname(),
			checkSoftware= swm.shouldCheckForNew,
			settings= s,
			wsToken= create_ws_token(publicKey),
			mfDefinition= manufacturerPkgManager(),
			apApiHost= roConfig('cloud.apiHost')
		)

	elif softwareManager.status != 'idle' or softwareManager.forceUpdateInfo:
		return render_template(
			"updating.jinja2",
			uiApiKey= UI_API_KEY,
			forceUpdateInfo=  softwareManager.forceUpdateInfo,
			releases= softwareManager.updatingReleases or [softwareManager.forceUpdateInfo['id']],
			lastCompletionPercent= softwareManager.lastCompletionPercent,
			lastMessage= softwareManager.lastMessage,
			astroboxName= networkManager().getHostname(),
			wsToken= create_ws_token(publicKey),
			status= softwareManager.status,
			mfDefinition= manufacturerPkgManager()
		)

	elif loggedUsername and (current_user is None or not current_user.is_authenticated or current_user.get_id() != loggedUsername):
		if current_user.is_authenticated:
			logout_user()
		return render_template(
			"locked.jinja2",
			username= loggedUsername,
			uiApiKey= UI_API_KEY,
			astroboxName= networkManager().getHostname(),
			mfDefinition= manufacturerPkgManager()
		)

	else:
		pm = printerManager()
		nm = networkManager()
		swm = swManager()
		cm = cameraManager()
		mmm = maintenanceMenuManager()

		paused = pm.isPaused()
		printing = pm.isPrinting()
		online = nm.isOnline()

		return render_template(
			"app.jinja2",
			user_email= loggedUsername,
			userPublicKey= publicKey,
			show_bad_shutdown= swm.wasBadShutdown and not swm.badShutdownShown,
			version= VERSION,
			commit= swm.commit,
			printing= printing,
			paused= paused,
			online= online,
			print_capture= cm.timelapseInfo if printing or paused else None,
			printer_profile= printerProfileManager().data,
			uiApiKey= UI_API_KEY,
			astroboxName= nm.getHostname(),
			checkSoftware= swm.shouldCheckForNew,
			serialLogActive= s.getBoolean(['serial', 'log']),
			additionalTasks= True,
			maintenanceMenu= True,
			cameraManager= cm.name,
			wsToken= create_ws_token(publicKey),
			mfDefinition= manufacturerPkgManager(),
			apApiHost= roConfig('cloud.apiHost'),
			apApiClientId= roConfig('cloud.apiClientId'),
			boxId= boxrouterManager().boxId
		)
Ejemplo n.º 38
0
	def getFileBrowsingExtensions(self):
		return printerManager().fileManager.SUPPORTED_EXTENSIONS
Ejemplo n.º 39
0
def printerToolCommand():
    pm = printerManager()

    if not pm.isOperational():
        return make_response("Printer is not operational", 409)

    valid_commands = {
        "select": ["tool"],
        "target": ["targets"],
        "offset": ["offsets"],
        "extrude": ["amount"]
    }
    command, data, response = util.getJsonCommandFromRequest(
        request, valid_commands)
    if response is not None:
        return response

    validation_regex = re.compile("tool\d+")

    ##~~ tool selection
    if command == "select":
        tool = data["tool"]
        if re.match(validation_regex, tool) is None:
            return make_response("Invalid tool: %s" % tool, 400)
        if not tool.startswith("tool"):
            return make_response("Invalid tool for selection: %s" % tool, 400)

        pm.changeTool(int(tool[len("tool"):]))

    ##~~ temperature
    elif command == "target":
        targets = data["targets"]

        # make sure the targets are valid and the values are numbers
        validated_values = {}
        for tool, value in targets.iteritems():
            if re.match(validation_regex, tool) is None:
                return make_response(
                    "Invalid target for setting temperature: %s" % tool, 400)
            if not isinstance(value, (int, long, float)):
                return make_response("Not a number for %s: %r" % (tool, value),
                                     400)
            validated_values[tool] = value

        # perform the actual temperature commands
        for tool in validated_values.keys():
            pm.setTemperature(tool, validated_values[tool])

    ##~~ extrusion
    elif command == "extrude":
        if pm.isPrinting():
            # do not extrude when a print job is running
            return make_response("Printer is currently printing", 409)

        amount = data["amount"]
        speed = data.get("speed")
        tool = data.get("tool")
        if not isinstance(amount, (int, long, float)):
            return make_response(
                "Not a number for extrusion amount: %r" % amount, 400)

        if tool is not None and re.match(validation_regex, tool) is None:
            return make_response("Invalid extruder value: %r" % tool, 400)

        if speed and not isinstance(speed, (int, long, float)):
            speed = None

        pm.extrude(
            int(tool[len("tool"):]) if tool is not None else None, amount,
            speed)

    return NO_CONTENT
Ejemplo n.º 40
0
def printerSdState():
    if not settings().getBoolean(["feature", "sdSupport"]):
        return make_response("SD support is disabled", 404)

    return jsonify(ready=printerManager().isSdReady())
Ejemplo n.º 41
0
def designs():
    forceSyncCloud = request.args.get('forceSyncCloud')
    cloud_files = json.loads(astroprintCloud().print_files(forceSyncCloud))
    local_files = list(printerManager().fileManager.getAllFileData())

    if cloud_files:
        for p in cloud_files:
            p['local_filename'] = None
            p['last_print'] = None
            p['uploaded_on'] = None
            for i in range(len(local_files)):
                if "cloud_id" in local_files[i] and p['id'] == local_files[i][
                        'cloud_id']:
                    local_file = local_files[i]
                    p['local_filename'] = local_file['name']
                    p['local_only'] = False
                    p['uploaded_on'] = local_file['date']

                    if 'prints' in local_file \
                        and 'last' in local_file['prints'] \
                        and local_file['prints']['last'] \
                        and 'date' in local_file['prints']['last']:
                        p['last_print'] = local_file['prints']['last']['date']

                    del local_files[i]
                    break

        cloud_files = sorted(cloud_files,
                             key=lambda e: e['local_filename'] is None)

    else:
        cloud_files = []

    if local_files:
        for p in local_files:
            p['id'] = uuid.uuid4().hex
            p['local_filename'] = p['name']
            p['local_only'] = True
            p['last_print'] = None
            p['uploaded_on'] = p['date']
            if 'gcodeAnalysis' in p:
                p['info'] = p['gcodeAnalysis']
                del p['gcodeAnalysis']
            else:
                p['info'] = None

            if 'prints' in p \
                and 'last' in p['prints'] \
                and p['prints']['last'] \
                and 'date' in p['prints']['last']:
                p['last_print'] = p['prints']['last']['date']
                del p['prints']

    else:
        local_files = []

    files = sorted(local_files + cloud_files,
                   key=lambda e: e['last_print'],
                   reverse=True)

    return json.dumps(files)