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 octoprint_WBCustom.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])))
def saveConnectionSettings(self, data, sendResponse): port = data['port'] baudrate = data['baudrate'] driver = data['driver'] if port: s = settings() s.set(["serial", "port"], port) if baudrate: s.setInt(["serial", "baudrate"], baudrate) s.save() pp = printerProfileManager() pp.set({'driver': driver}) pp.save() printerManager().connect(port, baudrate) sendResponse({'success': 'no_error'}) return sendResponse('invalid_printer_connection_settings', True)
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
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()
def _verifyFileExists(self, origin, filename): filename = secure_filename(filename) if origin == FileDestinations.SDCARD: availableFiles = map(lambda x: x[0], printerManager().getSdFiles()) else: availableFiles = printerManager().fileManager.getAllFilenames() return filename in availableFiles
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)
def changeSerialLogs(self, data, sendResponse): if data and 'active' in data: s = settings() s.setBoolean(['serial', 'log'], data['active']) s.save() printerManager().setSerialDebugLogging(data['active']) sendResponse({'success': 'no_error'}) else: sendResponse("no_data_sent", True)
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)
def handlePrinterSettings(): s = settings() pm = printerManager() ppm = printerProfileManager() connectionOptions = pm.getConnectionOptions() if request.method == "POST": if "application/json" in request.headers["Content-Type"]: data = request.json if "serial" in data.keys(): if "port" in data["serial"].keys(): s.set(["serial", "port"], data["serial"]["port"]) if "baudrate" in data["serial"].keys(): s.setInt(["serial", "baudrate"], data["serial"]["baudrate"]) s.save() driverName = ppm.data['driver'] driverInfo = ppm.driverChoices().get(driverName) if driverInfo: driverName = driverInfo['name'] return jsonify({ "driver": ppm.data['driver'], "driverName": driverName, "serial": { "port": connectionOptions["portPreference"], "baudrate": connectionOptions["baudratePreference"], "portOptions": connectionOptions["ports"].items(), "baudrateOptions": connectionOptions["baudrates"] } })
def on_deleted(self, event): fm = printerManager().fileManager filename = fm._getBasicFilename(event.src_path) if not filename: return fm.removeFileFromMetadata(filename)
def connection_settings(): connectionOptions = printerManager().getConnectionOptions() if connectionOptions: plugins = pluginManager().getPluginsByProvider('printerComms') driverChoices = {("plugin:%s" % k): plugins[k].definition['name'] for k in plugins} driverChoices.update({ 'marlin': 'GCODE - Marlin / Repetier Firmware', 's3g': 'X3G - Sailfish / Makerbot Firmware' }) response = { "driver": printerProfileManager().data['driver'], "driverChoices": driverChoices, "port": connectionOptions["portPreference"], "baudrate": connectionOptions["baudratePreference"], "portOptions": connectionOptions["ports"].items(), "baudrateOptions": connectionOptions["baudrates"] } return jsonify(response) return make_response("Connection options not available", 400)
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 {"error": False, "print_id": data['print_id']} if status_code == 402: return {"error": "no_storage"} else: return {"error": "unable_to_create"}
def initial_state(self, data, clientId, done): printer = printerManager() cm = cameraManager() softwareManager = swManager() state = { 'printing': printer.isPrinting() or printer.isPaused(), '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)
def successCb(destFile, fileInfo): printer = printerManager() abosluteFilename = printer.fileManager.getAbsolutePath(destFile) if printer.selectFile(abosluteFilename, False, True, print_job_id): eventData = { 'id': print_file_id, 'progress': 100, 'selected': True } if printer.currentPrintJobId: eventData['printjob_id'] = printer.currentPrintJobId else: eventData = { 'id': print_file_id, 'progress': 100, 'error': True, 'message': 'Unable to start printing', 'selected': False } self._wsClient.send(json.dumps({ 'type': 'send_event', 'data': { 'eventType': 'print_file_download', 'eventData': eventData } }))
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
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)
def getStatus(self): printer = printerManager() cm = cameraManager() ppm = printerProfileManager() cloudInstance = astroprintCloud() fileName = None if printer.isPrinting(): currentJob = printer.getCurrentJob() fileName = currentJob["file"]["name"] return { 'id': boxrouterManager().boxId, 'name': networkManager().getHostname(), 'orgId' : cloudInstance.orgId, 'groupId' : cloudInstance.groupId, '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 }
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
def printerConnectionDriver(self, data, sendMessage): s = settings() pm = printerManager() ppm = printerProfileManager() connectionOptions = pm.getConnectionOptions() if data and data['settings']: if "serial" in data.keys(): if "port" in data["serial"].keys(): s.set(["serial", "port"], data["serial"]["port"]) if "baudrate" in data["serial"].keys(): s.setInt(["serial", "baudrate"], data["serial"]["baudrate"]) s.save() driverName = ppm.data['driver'] driverInfo = ppm.driverChoices().get(driverName) if driverInfo: driverName = driverInfo['name'] sendMessage({ "driver": ppm.data['driver'], "driverName": driverName, "fileFormat": pm.fileManager.fileFormat, "serial": { "port": connectionOptions["portPreference"], "baudrate": connectionOptions["baudratePreference"], "portOptions": connectionOptions["ports"], "baudrateOptions": connectionOptions["baudrates"] } })
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'})
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
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
def setPrintingFlow(self, data, sendResponse= None): pm = printerManager() pm.setPrintingFlow(int(data)) sendResponse({'success': 'no_error'}) return
def printerPrintingSpeed(self, data, callback): pm = printerManager() amount = data["amount"] pm.printingSpeed(amount) callback({'success': 'no_error'})
def reScan(self, broadcastChange=True): if self._cameraInactivity: self._cameraInactivity.stop() inactivitySecs = settings().getFloat(["camera", "inactivitySecs"]) if inactivitySecs > 0.0: self._cameraInactivity = CameraInactivity(inactivitySecs, self._onInactive) else: self._cameraInactivity = None r = self._doReScan() if broadcastChange: printerManager().mcCameraConnectionChanged(r) return r
def connectionCommand(self, data, sendResponse): # valid_commands = { # "connect": ["autoconnect"], # "disconnect": [], # "reconnect": [] # } command = data['command'] pm = printerManager() if command in ["connect", "reconnect"]: s = settings() #driver = None port = None baudrate = None options = pm.getConnectionOptions() if "port" in data: port = data["port"] if port not in options["ports"]: if port is None: port = "None" sendResponse("invalid_port_" + port, True) return if "baudrate" in data and data['baudrate']: baudrate = int(data["baudrate"]) if baudrate: baudrates = options["baudrates"] if baudrates and baudrate not in baudrates: sendResponse("invalid_baudrate_" + baudrate, True) return else: sendResponse("baudrate_null", True) return if "save" in data and data["save"]: s.set(["serial", "port"], port) s.setInt(["serial", "baudrate"], baudrate) if "autoconnect" in data: s.setBoolean(["serial", "autoconnect"], data["autoconnect"]) s.save() if command == "connect": pm.connect(port, baudrate) elif command == "reconnect": pm.reConnect(port, baudrate) elif command == "disconnect": pm.disconnect() sendResponse({'success': 'no error'})
def printFile(self, data, sendResponse): fileDestination = fileName = None if 'location' in data: fileDestination = data['location'] if 'fileName' in data: fileName = data['fileName'] if not fileDestination in [ FileDestinations.LOCAL, FileDestinations.SDCARD ]: self._logger.error('Unknown file location') sendResponse('unknown_file_location', True) if not fileName or not self._verifyFileExists(fileDestination, fileName): self._logger.error('File not found') sendResponse('file_not_found', True) printer = printerManager() # selects/loads a file if not printer.isOperational(): #We try at least once printer.connect() start = time.time() connect_timeout = 5 #5 secs while not printer.isOperational() and not printer.isClosedOrError( ) and time.time() - start < connect_timeout: time.sleep(1) if not printer.isOperational(): self._logger.error( "The printer is not responding, can't start printing") sendResponse('printer_not_responding', True) return sd = False if fileDestination == FileDestinations.SDCARD: filenameToSelect = fileName sd = True else: filenameToSelect = printer.fileManager.getAbsolutePath(fileName) if filenameToSelect: startPrintingStatus = printer.selectFile(filenameToSelect, sd, True) if startPrintingStatus: sendResponse({'success': 'no error'}) else: sendResponse('printer_not_responding', True) else: sendResponse('invalid_filename', True)
def deletePrintFile(self, data, sendResponse): fileDestination = fileName = None if 'location' in data: fileDestination = data['location'] if 'fileName' in data: fileName = data['fileName'] if not fileDestination in [ FileDestinations.LOCAL, FileDestinations.SDCARD ]: self._logger.error("Unknown file location") sendResponse('unknown_file_location', True) return if not fileName or not self._verifyFileExists(fileDestination, fileName): self._logger.error("File not found") sendResponse('file_not_found', True) return sd = fileDestination == 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()): sendResponse( "Trying to delete file that is currently being printed: %s" % fileName, true) # 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) eventManager().fire(Events.FILE_DELETED, {"filename": fileName}) self.publishEvent('file_deleted', 'deleted') sendResponse({'success': 'no error'})
def selectTool(self,data,sendResponse): pm = printerManager() pm.changeTool(int(data)) sendResponse({'success': 'no_error'}) return
def printerFanSpeed(self, data, callback): pm = printerManager() speed = data["speed"] tool = data["tool"] pm.fan(tool, speed) callback({'success': 'no_error'})