def set_private_key(): email = request.values.get('email', None) password = request.values.get('password', None) private_key = request.values.get('private_key', None) if email and password: try: if astroprintCloud().signin(email, password): return jsonify(SUCCESS) except (AstroPrintCloudNoConnectionException, ConnectionError): abort(503, "AstroPrint.com can't be reached") except (AstroPrintCloudInsufficientPermissionsException) as e: r = jsonify(e.data) r.status_code = 403 return r elif email and private_key: try: if astroprintCloud().signinWithKey(email, private_key): return jsonify(SUCCESS) except (AstroPrintCloudNoConnectionException, ConnectionError): abort(503, "AstroPrint.com can't be reached") except (AstroPrintCloudInsufficientPermissionsException) as e: r = jsonify(e.data) r.status_code = 403 return r else: abort(400) abort(401)
def processAuthenticate(self, data): if data: self._silentReconnect = False if 'error' in data: self._logger.warn(data['message'] if 'message' in data else 'Unkonwn authentication error') self.status = self.STATUS_ERROR self._eventManager.fire(Events.ASTROPRINT_STATUS, self.status) self.close() if data.get('should_retry'): self._doRetry() elif data.get('type') == 'unable_to_authenticate': self._logger.info("Unuable to authenticate user in fleet box. Logout") astroprintCloud().remove_logged_user() elif 'success' in data: self._logger.info("Connected to astroprint service") self.authenticated = True if 'groupId' in data: astroprintCloud().updateFleetInfo(data['orgId'], data['groupId']) self._eventManager.fire(Events.FLEET_STATUS, data) self._retries = 0 self._retryTimer = None self.status = self.STATUS_CONNECTED self._eventManager.fire(Events.ASTROPRINT_STATUS, self.status) return None else: from octoprint.server import VERSION from octoprint_WBCustom.astroprint.printerprofile import printerProfileManager nm = networkManager() sm = softwareManager() ppm = printerProfileManager() authData = { 'silentReconnect': self._silentReconnect, 'boxId': self.boxId, 'variantId': sm.variant['id'], 'boxName': nm.getHostname(), 'swVersion': VERSION, 'platform': sm.platform, 'localIpAddress': nm.activeIpAddress, 'publicKey': self._publicKey, 'privateKey': self._privateKey, 'printerModel': ppm.data['printer_model'] if ppm.data['printer_model']['id'] else None } pkgId = sm.mfPackageId if pkgId: authData['mfPackageId'] = pkgId return { 'type': 'auth', 'data': authData }
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 cancelPrint(self, disableMotorsAndHeater=True): """ Cancel the current printjob. """ if self.isConnected() and (self.isPrinting() or self.isPaused()): activePrintJob = None cameraManager().stop_timelapse() consumedMaterial = self.getTotalConsumedFilament() timeElapsed = self.getPrintTime() if self._currentPrintJobId: astroprintCloud().print_job(self._currentPrintJobId, status='failed', materialUsed=consumedMaterial) activePrintJob = self._currentPrintJobId self._currentPrintJobId = None self._logger.info( "Print job [%s] CANCELED. Filament used: %f, Time elapsed: %f" % (os.path.split(self._selectedFile['filename'])[1] if self._selectedFile else 'unknown', consumedMaterial, timeElapsed)) self.executeCancelCommands(disableMotorsAndHeater) return {'print_job_id': activePrintJob} else: return { 'error': 'no_print_job', 'message': 'No active print job to cancel' }
def resetFactorySettings(): from octoprint_WBCustom.astroprint.cloud import astroprintCloud from shutil import copy logger = logging.getLogger(__name__) logger.warning("Executing a Restore Factory Settings operation") #We log out first astroprintCloud().signout() s = settings() emptyFolder(s.get(['folder', 'uploads']) or s.getBaseFolder('uploads')) emptyFolder(s.get(['folder', 'timelapse']) or s.getBaseFolder('timelapse')) emptyFolder( s.get(['folder', 'timelapse_tmp']) or s.getBaseFolder('timelapse_tmp')) emptyFolder(s.get(['folder', 'virtualSd']) or s.getBaseFolder('virtualSd')) networkManager().forgetWifiNetworks() configFolder = s.getConfigFolder() #replace config.yaml with config.factory config_file = s._configfile config_factory = os.path.join(configFolder, "config.factory") if config_file and os.path.exists(config_file): if os.path.exists(config_factory): copy(config_factory, config_file) else: os.unlink(config_file) #replace printer-profile.yaml with printer-profile.factory p_profile_file = os.path.join(configFolder, "printer-profile.yaml") p_profile_factory = os.path.join(configFolder, "printer-profile.factory") if os.path.exists(p_profile_file): if os.path.exists(p_profile_factory): copy(p_profile_factory, p_profile_file) else: os.unlink(p_profile_file) #remove info about users user_file = s.get(["accessControl", "userfile"]) or os.path.join( configFolder, "users.yaml") if user_file and os.path.exists(user_file): os.unlink(user_file) logger.info("Restore completed, rebooting...") #We should reboot the whole device if softwareManager.restartServer(): return jsonify() else: return ("There was an error rebooting.", 500)
def printerModel(model_id): printerModel = astroprintCloud().printerModel(model_id) if 'error' in printerModel: return abort(500, printerModel['error']) else: return json.dumps(printerModel)
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 manufacturers(): manufacturers = astroprintCloud().manufacturers() if 'error' in manufacturers: return abort(500, manufacturers['error']) else: return json.dumps(manufacturers)
def printerModels(manufacturer_id): printerModels = astroprintCloud().printerModels(manufacturer_id) if 'error' in printerModels: return abort(500, printerModels['error']) else: return json.dumps(printerModels)
def _checkAuth(self): if current_user and current_user.is_authenticated and not current_user.is_anonymous: privateKey = current_user.privateKey publicKey = current_user.publicKey if privateKey and publicKey: from octoprint_WBCustom.astroprint.cloud import astroprintCloud return astroprintCloud().hmacAuth return None
def get_login_key(): try: key = astroprintCloud().get_login_key() if key: return jsonify(key) except (AstroPrintCloudNoConnectionException, ConnectionError): abort(503, "AstroPrint.com can't be reached") abort(401)
def start_timelapse(self, freq): if not self.isCameraConnected(): return 'no_camera' if freq == '0': return 'invalid_frequency' if self.timelapseWorker: self.stop_timelapse() #check that there's a print ongoing otherwise don't start selectedFile = printerManager()._selectedFile if not selectedFile: return 'no_print_file_selected' printCapture = astroprintCloud().startPrintCapture( os.path.split(selectedFile["filename"])[1]) if printCapture['error']: return printCapture['error'] else: timelapseId = printCapture['print_id'] self.timelapseInfo = { 'id': timelapseId, 'freq': freq, 'paused': False, 'last_photo': None } if freq != 'gcode': if freq == 'layer': # send first pic and subscribe to layer change events self.addPhotoToTimelapse(timelapseId) self._eventManager.subscribe(Events.LAYER_CHANGE, self._onLayerChange) else: try: freq = float(freq) except ValueError: return 'invalid_frequency' self.timelapseInfo['freq'] = freq self.timelapseWorker = TimelapseWorker( self, timelapseId, freq) self.timelapseWorker.start() self._eventManager.fire(Events.CAPTURE_INFO_CHANGED, self.timelapseInfo) return 'success' return 'unkonwn_error'
def getAccessKeys(self, data, sendResponse): publicKey = email = accessKey = None if 'email' in data: email = data['email'] if 'accessKey' in data: accessKey = data['accessKey'] userLogged = settings().get(["cloudSlicer", "loggedUser"]) #### # - nobody logged: None # - any log: email if email and accessKey: #somebody is logged in the remote client if userLogged: #Somebody logged in Astrobox if userLogged == email: #I am the user logged online = networkManager().isOnline() if online: publicKey = astroprintCloud().get_public_key( email, accessKey) if not publicKey: self._logger.error('error getting public key', exc_info=True) sendResponse('error_getting_public_key', True) return else: user = userManager.findUser(email) if user.get_private_key() != accessKey: self._logger.error('incorrect logged user', exc_info=True) sendResponse('incorrect_logged_user', True) return else: #I am NOT the logged user self._logger.error('incorrect logged user', exc_info=True) sendResponse('incorrect_logged_user', True) return else: #nodody is logged in the remote client if userLogged: self._logger.error('any user logged', exc_info=True) sendResponse('no_user_logged', True) return sendResponse({ 'api_key': UI_API_KEY, 'ws_token': create_ws_token(publicKey) })
def manufacturers(self, data, sendMessage): try: manufacturers = astroprintCloud().manufacturers() if 'error' in manufacturers: sendMessage("error_getting_manufacturers", True) else: sendMessage(manufacturers) except Exception: self._logger.error('There was an error getting manufacturers', exc_info=True) sendMessage("error_getting_manufacturers", True)
def design_download(print_file_id): if current_user is None or not current_user.is_authenticated or not current_user.publicKey: abort(401) em = eventManager() def progressCb(progress): em.fire( Events.CLOUD_DOWNLOAD, { "type": "progress", "id": print_file_id, "progress": progress } ) def successCb(destFile, fileInfo): if fileInfo is True: #This means the files was already on the device em.fire( Events.CLOUD_DOWNLOAD, { "type": "success", "id": print_file_id } ) def errorCb(destFile, error): if error == 'cancelled': em.fire( Events.CLOUD_DOWNLOAD, { "type": "cancelled", "id": print_file_id } ) else: em.fire( Events.CLOUD_DOWNLOAD, { "type": "error", "id": print_file_id, "reason": error } ) if destFile and os.path.exists(destFile): os.remove(destFile) if astroprintCloud().download_print_file(print_file_id, progressCb, successCb, errorCb) is True: return jsonify(SUCCESS) return abort(400)
def getFileInfo(self, filename): estimatedPrintTime = None date = None filament = None layerCount = None cloudId = None renderedImage = None printFileName = None if filename: # Use a string for mtime because it could be float and the # javascript needs to exact match date = int(os.stat(filename).st_ctime) fileData = self._fileManager.getFileData(filename) if fileData is not None: gcodeAnalysis = fileData.get('gcodeAnalysis') if gcodeAnalysis: estimatedPrintTime = gcodeAnalysis.get('print_time') filament = gcodeAnalysis.get('filament_length') layerCount = gcodeAnalysis.get('layer_count') renderedImage = fileData.get('image') cloudId = self._fileManager.getFileCloudId(filename) if cloudId: if self._selectedFile: self._selectedFile['cloudId'] = cloudId printFile = astroprintCloud().getPrintFile(cloudId) if printFile: renderedImage = printFile['images']['square'] if fileData is not None and "printFileName" in fileData.keys(): printFileName = fileData["printFileName"] return { "file": { "name": os.path.basename(filename) if filename is not None else None, "printFileName": printFileName, "origin": FileDestinations.LOCAL, "date": date, "cloudId": cloudId, "rendered_image": renderedImage }, "estimatedPrintTime": estimatedPrintTime, "layerCount": layerCount, "filament": filament, }
def mcPrintjobDone(self): #stop timelapse if there was one cameraManager().stop_timelapse( True) #True makes it take one last photo timeElapsed = self.getPrintTime() #Not sure if this is the best way to get the layer count self._setProgressData(1.0, self._selectedFile["filesize"], timeElapsed, 0, self._layerCount) self.refreshStateData() consumedMaterial = self.getTotalConsumedFilament() if self._currentPrintJobId: astroprintCloud().print_job(self._currentPrintJobId, status='success', materialUsed=consumedMaterial) self._currentPrintJobId = None self._logger.info( "Print job [%s] COMPLETED. Filament used: %f, Time elapsed: %f" % (os.path.split(self._selectedFile['filename'])[1] if self._selectedFile else 'unknown', consumedMaterial, timeElapsed))
def login_astroprint(): email = request.values.get('email', None) password = request.values.get('password', None) if email and password: ap = astroprintCloud() try: if ap.signin(email, password): return make_response("OK", 200) except (AstroPrintCloudNoConnectionException, ConnectionError): return make_response("AstroPrint.com can't be reached", 503) except (AstroPrintCloudInsufficientPermissionsException): return make_response("Insuficient permissions", 403) return make_response('Invalid Credentials', 400)
def startPrint(self, printJobId=None): """ Starts the currently loaded print job. Only starts if the printer is connected and operational, not currently printing and a printjob is loaded """ if not self.isConnected() or not self.isOperational( ) or self.isPrinting(): return False if self._selectedFile is None: return False self._setCurrentZ(None) kwargs = { 'print_file_name': os.path.basename(self._selectedFile['filename']), 'id': printJobId } if self._selectedFile['cloudId']: kwargs['print_file_id'] = self._selectedFile['cloudId'] #tell astroprint that we started a print result = astroprintCloud().print_job(**kwargs) #start time lapse if is set s = settings() c = cameraManager() freq = s.get(['camera', 'freq']) if freq and c.isCameraConnected(): c.start_timelapse(freq) if result and "id" in result: self._currentPrintJobId = result['id'] self._timeStarted = time.time() self._secsPaused = 0 self._pausedSince = None self._currentLayer = 0 self.printedLayersCounter = 0 return True
def onDone(picBuf): result = False if picBuf: picData = astroprintCloud().uploadImageFile( timelapseId, picBuf) #we need to check again as it's possible that this was the last #pic and the timelapse is closed. if picData and self.timelapseInfo: self.timelapseInfo['last_photo'] = picData['url'] self._eventManager.fire(Events.CAPTURE_INFO_CHANGED, self.timelapseInfo) result = True if waitForPhoto and not waitForPhoto.isSet(): responseCont[0] = result waitForPhoto.set()
def printerModelInfo(self, data, sendMessage): if "printer_model_id" in data: try: printerModel = astroprintCloud().printerModel( data['printer_model_id']) if 'error' in printerModel: sendMessage("error_getting_printer_info", True) else: sendMessage(printerModel) except Exception: self._logger.error( 'There was an error getting Printer model info', exc_info=True) sendMessage("error_getting_printer_info", True) else: sendMessage("invalid_params", True)
def printerModels(self, data, sendMessage): if "manufacturer_id" in data: try: printerModels = astroprintCloud().printerModels( data['manufacturer_id']) if 'error' in printerModels: sendMessage("error_getting_printer_models", True) else: sendMessage(printerModels) except Exception: self._logger.error( 'There was and error getting printer models', exc_info=True) sendMessage("error_getting_printer_models", True) else: sendMessage("invalid_params", True)
def upload_data(): filePath = request.args.get('file', None) if filePath: uploadInfo = astroprintCloud().get_upload_info(filePath) if uploadInfo: if 'error' in uploadInfo: if uploadInfo['error'] == 'no_user': abort(401) else: abort(500) else: return json.dumps(uploadInfo) else: abort(500) abort(400)
def enable(self): if not self.isSslActive(): disabledPath = self.sslCertPath.replace('ssl', 'ssl_disabled') if os.path.isfile(disabledPath): os.rename(os.path.dirname(disabledPath), os.path.dirname(self.sslCertPath)) else: from octoprint_WBCustom.astroprint.cloud import astroprintCloud astroprint = astroprintCloud() cert = astroprint.get_local_certificate() if cert is not None: mkpath(os.path.dirname(self.sslCertPath)) with open(self.sslCertPath, 'w') as f: f.write(cert) else: raise NoCertException() softwareManager().restartServer()
def update_cancel_reason(print_job_id): if not "application/json" in request.headers["Content-Type"]: return abort(400) data = request.json #get reason reason = {} if 'reason' in data: reason['reason_id'] = data['reason'] if 'other_text' in data: reason['other_text'] = data['other_text'] if reason: if not astroprintCloud().updateCancelReason(print_job_id, reason): return abort(500) else: return jsonify(SUCCESS) else: return abort(400)
def signoff(self, data, clientId, done): self._logger.info('Remote signoff requested.') threading.Timer(1, astroprintCloud().remove_logged_user).start() done(None)
def resetFactorySettings(self, data, sendMessage): from octoprint_WBCustom.astroprint.cloud import astroprintCloud from shutil import copy try: #astroprintCloud().signout() astroprintCloud().remove_logged_user() logger = logging.getLogger(__name__) logger.warning("Executing a Restore Factory Settings operation") s = settings() #empty all folders def emptyFolder(folder): if folder and os.path.exists(folder): for f in os.listdir(folder): p = os.path.join(folder, f) try: if os.path.isfile(p): os.unlink(p) except Exception: pass emptyFolder( s.get(['folder', 'uploads']) or s.getBaseFolder('uploads')) emptyFolder( s.get(['folder', 'timelapse']) or s.getBaseFolder('timelapse')) emptyFolder( s.get(['folder', 'timelapse_tmp']) or s.getBaseFolder('timelapse_tmp')) emptyFolder( s.get(['folder', 'virtualSd']) or s.getBaseFolder('virtualSd')) networkManager().forgetWifiNetworks() configFolder = s.getConfigFolder() #replace config.yaml with config.factory config_file = s._configfile config_factory = os.path.join(configFolder, "config.factory") if config_file and os.path.exists(config_file): if os.path.exists(config_factory): copy(config_factory, config_file) else: os.unlink(config_file) #replace printer-profile.yaml with printer-profile.factory p_profile_file = os.path.join(configFolder, "printer-profile.yaml") p_profile_factory = os.path.join(configFolder, "printer-profile.factory") if os.path.exists(p_profile_file): if os.path.exists(p_profile_factory): copy(p_profile_factory, p_profile_file) else: os.unlink(p_profile_file) #remove info about users user_file = s.get(["accessControl", "userfile"]) or os.path.join( configFolder, "users.yaml") if user_file and os.path.exists(user_file): os.unlink(user_file) logger.info("Restore completed, rebooting...") #We should reboot the whole device if softwareManager.restartServer(): sendMessage({'success': 'no_error'}) else: sendMessage("error_rebooting", True) except Exception: self._logger.error('unsuccessfully factory settings restored', exc_info=True) sendMessage("error_restoring_factory_settings", True)
def print_file(self, data, clientId, done): print_file_id = data['printFileId'] if 'printJobId' in data : print_job_id = data['printJobId'] else : print_job_id = None em = eventManager() def progressCb(progress): em.fire( Events.CLOUD_DOWNLOAD, { "type": "progress", "id": print_file_id, "progress": progress } ) 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 errorCb(destFile, error): if error == 'cancelled': em.fire( Events.CLOUD_DOWNLOAD, { "type": "cancelled", "id": print_file_id } ) else: em.fire( Events.CLOUD_DOWNLOAD, { "type": "error", "id": print_file_id, "reason": error } ) if destFile and os.path.exists(destFile): os.remove(destFile) res = astroprintCloud().download_print_file(print_file_id, progressCb, successCb, errorCb, True) if res is not True : done({ 'error': True, 'message': res['message'], 'id': res['id'] }) return s = settings() if s.getBoolean(['clearFiles']): printer = printerManager() try: printer.fileManager.clearLeftOverFiles() except Exception: self._logger.error('Error clearing left over print files', exc_info=True) done(None)
def logout_astroprint(): astroprintCloud().signout() return make_response("OK", 200)
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) is True: sendResponse({'success': 'no error'}) return sendResponse('error', True) return