def deletePrintJob(self, databaseId): databaseIdAsInt = StringUtils.transformToIntOrNone(databaseId) if (databaseIdAsInt == None): self._logger.error( "Could not delete PrintJob, because not a valid databaseId '" + str(databaseId) + "' maybe not a number") return None with self._database.atomic() as transaction: # Opens new transaction. try: # first delete relations n = FilamentModel.delete().where( FilamentModel.printJob == databaseIdAsInt).execute() n = TemperatureModel.delete().where( TemperatureModel.printJob == databaseIdAsInt).execute() n = CostModel.delete().where( CostModel.printJob == databaseIdAsInt).execute() PrintJobModel.delete_by_id(databaseIdAsInt) except Exception as e: # Because this block of code is wrapped with "atomic", a # new transaction will begin automatically after the call # to rollback(). transaction.rollback() self._logger.exception( "Could not delete printJob from database:" + str(e)) self.sendErrorMessageToClient( "PJH-DatabaseManager", "Could not delete the printjob ('" + str(databaseId) + "') from the database. See OctoPrint.log for details!") pass
def _createPrintJobModel(self, payload): self._currentPrintJobModel = PrintJobModel() self._currentPrintJobModel.printStartDateTime = datetime.datetime.now() self._currentPrintJobModel.fileOrigin = payload["origin"] self._currentPrintJobModel.fileName = payload["name"] self._currentPrintJobModel.filePathName = payload["path"] # self._file_manager.path_on_disk() if "owner" in payload: self._currentPrintJobModel.userName = payload["owner"] else: self._currentPrintJobModel.userName = "******" self._currentPrintJobModel.fileSize = payload["size"] tempFound = False tempTool = 0 tempBed = 0 if self._preHeatPluginImplementation != None: path_on_disk = octoprint.server.fileManager.path_on_disk( self._currentPrintJobModel.fileOrigin, self._currentPrintJobModel.filePathName) preHeatTemperature = self._preHeatPluginImplementation.read_temperatures_from_file( path_on_disk) if preHeatTemperature != None: if "bed" in preHeatTemperature: tempBed = preHeatTemperature["bed"] tempFound = True if "tool0" in preHeatTemperature: tempTool = preHeatTemperature["tool0"] tempFound = True pass else: currentTemps = self._printer.get_current_temperatures() if (len(currentTemps) > 0): tempBed = currentTemps[0]["bed"]["target"] tempTool = currentTemps[0]["tool0"]["target"] tempFound = True if (tempFound == True): tempModel = TemperatureModel() tempModel.sensorName = "bed" tempModel.sensorValue = tempBed self._currentPrintJobModel.addTemperatureModel(tempModel) tempModel = TemperatureModel() tempModel.sensorName = "tool0" tempModel.sensorValue = tempTool self._currentPrintJobModel.addTemperatureModel(tempModel)
def loadPrintJobsByQuery(self, tableQuery): offset = int(tableQuery["from"]) limit = int(tableQuery["to"]) sortColumn = tableQuery["sortColumn"] sortOrder = tableQuery["sortOrder"] filterName = tableQuery["filterName"] myQuery = PrintJobModel.select().offset(offset).limit(limit) if (filterName == "onlySuccess"): myQuery = myQuery.where( PrintJobModel.printStatusResult == "success") elif (filterName == "onlyFailed"): myQuery = myQuery.where( PrintJobModel.printStatusResult != "success") if ("printStartDateTime" == sortColumn): if ("desc" == sortOrder): myQuery = myQuery.order_by( PrintJobModel.printStartDateTime.desc()) else: myQuery = myQuery.order_by(PrintJobModel.printStartDateTime) if ("fileName" == sortColumn): if ("desc" == sortOrder): myQuery = myQuery.order_by(PrintJobModel.fileName.desc()) else: myQuery = myQuery.order_by(PrintJobModel.fileName) return myQuery
def _createPrintJobModel(self, payload): self._currentPrintJobModel = PrintJobModel() self._currentPrintJobModel.printStartDateTime = datetime.datetime.now() self._currentPrintJobModel.fileOrigin = payload["origin"] self._currentPrintJobModel.fileName = payload["name"] self._currentPrintJobModel.filePathName = payload["path"] # self._file_manager.path_on_disk() if "owner" in payload: self._currentPrintJobModel.userName = payload["owner"] else: self._currentPrintJobModel.userName = "******" self._currentPrintJobModel.fileSize = payload["size"] tempFound = False toolId = self._settings.get( [SettingsKeys.SETTINGS_KEY_DEFAULT_TOOL_ID]) tempTool = -1 tempBed = 0 shouldReadTemperatureFromPreHeat = self._settings.get_boolean( [SettingsKeys.SETTINGS_KEY_TAKE_TEMPERATURE_FROM_PREHEAT]) if (shouldReadTemperatureFromPreHeat == True): self._logger.info("Try reading Temperature from PreHeat-Plugin...") if (self._preHeatPluginImplementation != None): path_on_disk = octoprint.server.fileManager.path_on_disk( self._currentPrintJobModel.fileOrigin, self._currentPrintJobModel.filePathName) preHeatTemperature = self._preHeatPluginImplementation.read_temperatures_from_file( path_on_disk) if preHeatTemperature != None: if "bed" in preHeatTemperature: tempBed = preHeatTemperature["bed"] tempFound = True if toolId in preHeatTemperature: tempTool = preHeatTemperature[toolId] #"tool0" tempFound = True else: self._logger.warn( "... PreHeat-Temperatures does not include default Extruder-Tool '" + toolId + "'") pass else: self._logger.warn("... PreHeat Plugin not installed/enabled") if (tempFound == True): self._logger.info("... Temperature found '" + str(tempBed) + "' ' Tool '" + toolId + "' '" + str(tempTool) + "'") self._addTemperatureToPrintModel(self._currentPrintJobModel, tempBed, toolId, tempTool) else: # readTemperatureFromPrinter # because temperature is 0 at the beginning, we need to wait a couple of seconds (maybe 3) self._readAndAssignCurrentTemperatureDelayed( self._currentPrintJobModel)
def loadSelectedPrintJobs(self, selectedDatabaseIds): selectedDatabaseIdsSplitted = selectedDatabaseIds.split(',') databaseArray = [] for dbId in selectedDatabaseIdsSplitted: databaseArray.append(dbId) return PrintJobModel.select().where(PrintJobModel.databaseId << databaseArray).order_by(PrintJobModel.printStartDateTime.desc())
def deletePrintJob(self, databaseId): with self._database.atomic() as transaction: # Opens new transaction. try: # first delete relations n = FilamentModel.delete().where(FilamentModel.printJob == databaseId).execute() n = TemperatureModel.delete().where(TemperatureModel.printJob == databaseId).execute() PrintJobModel.delete_by_id(databaseId) except Exception as e: # Because this block of code is wrapped with "atomic", a # new transaction will begin automatically after the call # to rollback(). transaction.rollback() self._logger.exception("Could not delete printJob from database:" + str(e)) self.sendErrorMessageToClient("PJH-DatabaseManager", "Could not delete the printjob ('"+ str(databaseId) +"') from the database. See OctoPrint.log for details!") pass
def loadPrintJob(self, databaseId): databaseIdAsInt = StringUtils.transformToIntOrNone(databaseId) if (databaseIdAsInt == None): self._logger.error( "Could not load PrintJob, because not a valid databaseId '" + str(databaseId) + "' maybe not a number") return None return PrintJobModel.get_or_none(databaseIdAsInt)
def countPrintJobsByQuery(self, tableQuery): filterName = tableQuery["filterName"] myQuery = PrintJobModel.select() if (filterName == "onlySuccess"): myQuery = myQuery.where(PrintJobModel.printStatusResult == "success") elif (filterName == "onlyFailed"): myQuery = myQuery.where(PrintJobModel.printStatusResult != "success") return myQuery.count()
def countPrintJobsByQuery(self, tableQuery): # filterName = tableQuery["filterName"] myQuery = PrintJobModel.select() myQuery = self._addTableQueryToSelect(myQuery, tableQuery) # self._addTableQueryToSelect(myQuery, tableQuery) # if (filterName == "onlySuccess"): # myQuery = myQuery.where(PrintJobModel.printStatusResult == "success") # elif (filterName == "onlyFailed"): # myQuery = myQuery.where(PrintJobModel.printStatusResult != "success") return myQuery.count()
def _test_something(self): db = peewee.SqliteDatabase(self.databaselocation+'/printJobHistory.db') singlePrintJob = PrintJobModel.select().join(FilamentModel).where(PrintJobModel.databaseId == 109).get() print(singlePrintJob) print(singlePrintJob.fileName) singlePrintJob.printFila() # for fila in singlePrintJob.filaments: # print(fila) newFilaModel = FilamentModel() newFilaModel.material = "MeinMaterial" newFilaModel = FilamentModel.create(printJob = singlePrintJob) # singlePrintJob.filaments.append(newFilaModel) # singlePrintJob.save() pass
def _createPrintJobModel(self, payload): self._currentPrintJobModel = PrintJobModel() self._currentPrintJobModel.printStartDateTime = datetime.datetime.now() self._currentPrintJobModel.fileOrigin = payload["origin"] self._currentPrintJobModel.fileName = payload["name"] self._currentPrintJobModel.filePathName = payload["path"] # self._file_manager.path_on_disk() if "owner" in payload: self._currentPrintJobModel.userName = payload["owner"] else: self._currentPrintJobModel.userName = "******" self._currentPrintJobModel.fileSize = payload["size"] tempFound = False tempTool = 0 tempBed = 0 if self._preHeatPluginImplementation != None: path_on_disk = octoprint.server.fileManager.path_on_disk( self._currentPrintJobModel.fileOrigin, self._currentPrintJobModel.filePathName) preHeatTemperature = self._preHeatPluginImplementation.read_temperatures_from_file( path_on_disk) if preHeatTemperature != None: if "bed" in preHeatTemperature: tempBed = preHeatTemperature["bed"] tempFound = True if "tool0" in preHeatTemperature: tempTool = preHeatTemperature["tool0"] tempFound = True pass else: # because temperature is 0 at the beginning, we need to wait a couple of seconds (maybe 3) self._readAndAssignCurrentTemperatureDelayed( self._currentPrintJobModel) if (tempFound == True): self._addTemperatureToPrintModel(self._currentPrintJobModel, tempBed, tempTool)
def loadPrintJobsByQuery(self, tableQuery): offset = int(tableQuery["from"]) limit = int(tableQuery["to"]) # sortColumn = tableQuery["sortColumn"] # sortOrder = tableQuery["sortOrder"] # filterName = tableQuery["filterName"] # dont use join "Kartesischs-Produkt" myQuery = PrintJobModel.select().join(FilamentModel).offset(offset).limit(limit) myQuery = PrintJobModel.select().offset(offset).limit(limit) myQuery = self._addTableQueryToSelect(myQuery, tableQuery) # if (filterName == "onlySuccess"): # myQuery = myQuery.where(PrintJobModel.printStatusResult == "success") # elif (filterName == "onlyFailed"): # myQuery = myQuery.where(PrintJobModel.printStatusResult != "success") # # if ("printStartDateTime" == sortColumn): # if ("desc" == sortOrder): # myQuery = myQuery.order_by(PrintJobModel.printStartDateTime.desc()) # else: # myQuery = myQuery.order_by(PrintJobModel.printStartDateTime) # if ("fileName" == sortColumn): # if ("desc" == sortOrder): # myQuery = myQuery.order_by(PrintJobModel.fileName.desc()) # else: # myQuery = myQuery.order_by(PrintJobModel.fileName) # if ("startDate" in tableQuery): # startDate = tableQuery["startDate"] # endDate = tableQuery["endDate"] # if (len(startDate) > 0 and len(endDate) > 0): # # EndDay + 1 # startDateTime = datetime.datetime.strptime(startDate, "%d.%m.%Y") # endDateTime = datetime.datetime.strptime(endDate, "%d.%m.%Y") + datetime.timedelta(days=1) # # # myQuery = myQuery.where( (( PrintJobModel.printStartDateTime == startDate) | ( PrintJobModel.printStartDateTime > startDate)) # # & # # ((PrintJobModel.printStartDateTime == endDate) | ( PrintJobModel.printStartDateTime < startDate)) ) # myQuery = myQuery.where( ( ( PrintJobModel.printStartDateTime > startDateTime) & ( PrintJobModel.printStartDateTime < endDateTime)) # ) return myQuery
def loadPrintJob(self, databaseId): return PrintJobModel.get_by_id(databaseId)
def loadAllPrintJobs(self): return PrintJobModel.select().order_by( PrintJobModel.printStartDateTime.desc())
def createWithDefaults(self): newPrintJobModel = PrintJobModel() totalFilament = FilamentModel() totalFilament.toolId = "total" newPrintJobModel.addFilamentModel(totalFilament) return newPrintJobModel
def parseCSV(csvFile4Import, errorCollection, logger): result = list() # List with printJobModels lineNumber = 0 try: with open(csvFile4Import) as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') lineNumber = 0 for row in csv_reader: lineNumber += 1 if lineNumber == 1: # createColumnOrderFromHeader(row) # mandatoryFieldCount = 0 mandatoryFieldAvaiable = list() columnIndex = 0 for column in row: column = column.strip() if column in ALL_COLUMNS: columnOrderInFile[columnIndex] = ALL_COLUMNS[ column] if column in mandatoryFieldNames: mandatoryFieldAvaiable.append(column) # mandatoryFieldCount += 1 columnIndex += 1 if len(mandatoryFieldAvaiable) != len(mandatoryFieldNames): # if mandatoryFieldCount != len(mandatoryFieldNames): # identify missing files # mandatoryFieldMissing = mandatoryFieldNames - mandatoryFieldAvaiable mandatoryFieldMissing = list( set(mandatoryFieldNames) - set(mandatoryFieldAvaiable)) errorCollection.append( "Mandatory column is missing! <br/><b>'" + "".join(mandatoryFieldMissing) + "'</b><br/>") break else: printJobModel = PrintJobModel() # parse line with header defined order columnIndex = 0 for columnValue in row: if columnIndex in columnOrderInFile: csvColumn = columnOrderInFile[columnIndex] if not csvColumn == None: columnValue = columnValue.strip() csvColumn.parseAndAssignFieldValue( columnValue, printJobModel, errorCollection, lineNumber) pass columnIndex += 1 if (len(errorCollection) != 0): logger.warn("ERROR(s) occurred!!!!!") else: result.append(printJobModel) pass except Exception as e: errorMessage = "Error during processing file '" + csvFile4Import + "' error '" + str( e) + "' line '" + str(lineNumber) + "'" errorCollection.append(errorMessage) logger.error(errorMessage) finally: logger.info("Removing uploded csv temp-file") try: os.remove(csvFile4Import) except Exception: pass print("Processed " + str(lineNumber)) return result
class PrintJobHistoryPlugin( PrintJobHistoryAPI, octoprint.plugin.SettingsPlugin, octoprint.plugin.AssetPlugin, octoprint.plugin.TemplatePlugin, octoprint.plugin.StartupPlugin, octoprint.plugin.EventHandlerPlugin, #octoprint.plugin.SimpleApiPlugin ): def initialize(self): self._preHeatPluginImplementation = None self._preHeatPluginImplementationState = None self._filamentManagerPluginImplementation = None self._filamentManagerPluginImplementationState = None self._displayLayerProgressPluginImplementation = None self._displayLayerProgressPluginImplementationState = None self._ultimakerFormatPluginImplementation = None self._ultimakerFormatPluginImplementationState = None pluginDataBaseFolder = self.get_plugin_data_folder() self._logger.info("Start initializing") # DATABASE self._databaseManager = DatabaseManager(self._logger) self._databaseManager.initDatabase(pluginDataBaseFolder, self._sendErrorMessageToClient) # databasePath = os.path.join(pluginDataBaseFolder, "printJobHistory.db") # self._databaseManager.initDatabase(databasePath) # CAMERA self._cameraManager = CameraManager(self._logger) pluginBaseFolder = self._basefolder self._cameraManager.initCamera(pluginDataBaseFolder, pluginBaseFolder, self._settings) self._settings.set([SettingsKeys.SETTINGS_KEY_DATABASE_PATH], self._databaseManager.getDatabaseFileLocation()) self._settings.set([SettingsKeys.SETTINGS_KEY_SNAPSHOT_PATH], self._cameraManager.getSnapshotFileLocation()) self._settings.save() # OTHER STUFF self._currentPrintJobModel = None self.alreadyCanceled = False self._logger.info("Done initializing") ################################################################################################## private functions def _sendDataToClient(self, payloadDict): self._plugin_manager.send_plugin_message(self._identifier, payloadDict) def _sendErrorMessageToClient(self, title, message): self._sendDataToClient( dict(action="errorPopUp", title=title, message=message)) def _checkForMissingPluginInfos(self, sendToClient=False): self._displayLayerProgressPluginImplementationState = "enabled" self._preHeatPluginImplementationState = "enabled" self._filamentManagerPluginImplementationState = "enabled" self._ultimakerFormatPluginImplementationState = "enabled" if "preheat" in self._plugin_manager.plugins: plugin = self._plugin_manager.plugins["preheat"] if plugin != None and plugin.enabled == True: self._preHeatPluginImplementation = plugin.implementation else: self._preHeatPluginImplementationState = "disabled" else: self._preHeatPluginImplementationState = "missing" if "filamentmanager" in self._plugin_manager.plugins: plugin = self._plugin_manager.plugins["filamentmanager"] if plugin != None and plugin.enabled == True: self._filamentManagerPluginImplementation = plugin.implementation else: self._filamentManagerPluginImplementationState = "disabled" else: self._filamentManagerPluginImplementationState = "missing" if "DisplayLayerProgress" in self._plugin_manager.plugins: plugin = self._plugin_manager.plugins["DisplayLayerProgress"] if plugin != None and plugin.enabled == True: self._displayLayerProgressPluginImplementation = plugin.implementation else: self._displayLayerProgressPluginImplementationState = "disabled" else: self._displayLayerProgressPluginImplementationState = "missing" if "UltimakerFormatPackage" in self._plugin_manager.plugins: plugin = self._plugin_manager.plugins["UltimakerFormatPackage"] if plugin != None and plugin.enabled == True: self._ultimakerFormatPluginImplementation = plugin.implementation else: self._ultimakerFormatPluginImplementationState = "disabled" else: self._ultimakerFormatPluginImplementationState = "missing" self._logger.info("Plugin-State: " "PreHeat=" + self._preHeatPluginImplementationState + " " "DisplayLayerProgress=" + self._displayLayerProgressPluginImplementationState + " " "filamentmanager=" + self._filamentManagerPluginImplementationState + " " "ultimakerformat=" + self._ultimakerFormatPluginImplementationState) if sendToClient == True: missingMessage = "" if self._preHeatPluginImplementation == None: missingMessage = missingMessage + "<li>PreHeat (<b>" + self._preHeatPluginImplementationState + "</b>)</li>" if self._filamentManagerPluginImplementation == None: missingMessage = missingMessage + "<li>FilamentManager (<b>" + self._filamentManagerPluginImplementationState + "</b>)</li>" if self._displayLayerProgressPluginImplementation == None: missingMessage = missingMessage + "<li>DisplayLayerProgress (<b>" + self._displayLayerProgressPluginImplementationState + "</b>)</li>" if self._ultimakerFormatPluginImplementation == None: missingMessage = missingMessage + "<li>UltimakerFormatPackage (<b>" + self._ultimakerFormatPluginImplementationState + "</b>)</li>" if missingMessage != "": missingMessage = "<ul>" + missingMessage + "</ul>" self._sendDataToClient( dict(action="missingPlugin", message=missingMessage)) # Grabs all informations for the filament attributes def _createAndAssignFilamentModel(self, printJob, payload): filemanentModel = FilamentModel() fileData = self._file_manager.get_metadata(payload["origin"], payload["file"]) filamentLength = None if "analysis" in fileData: if "filament" in fileData["analysis"]: if "tool0" in fileData["analysis"]["filament"]: filamentLength = fileData["analysis"]["filament"]["tool0"][ 'length'] filemanentModel.calculatedLength = filamentLength if self._filamentManagerPluginImplementation != None: filemanentModel.usedLength = self._filamentManagerPluginImplementation.filamentOdometer.totalExtrusion[ 0] selectedSpool = self._filamentManagerPluginImplementation.filamentManager.get_all_selections( self._filamentManagerPluginImplementation.client_id) if selectedSpool != None and len(selectedSpool) > 0: spoolData = selectedSpool[0]["spool"] spoolName = spoolData["name"] spoolCost = spoolData["cost"] spoolCostUnit = self._filamentManagerPluginImplementation._settings.get( ["currencySymbol"]) spoolWeight = spoolData["weight"] profileData = selectedSpool[0]["spool"]["profile"] diameter = profileData["diameter"] material = profileData["material"] vendor = profileData["vendor"] density = profileData["density"] filemanentModel.spoolName = spoolName filemanentModel.spoolCost = spoolCost filemanentModel.spoolCostUnit = spoolCostUnit filemanentModel.spoolWeight = spoolWeight filemanentModel.profileVendor = vendor filemanentModel.diameter = diameter filemanentModel.density = density filemanentModel.material = material radius = diameter / 2 volume = filemanentModel.usedLength * math.pi * radius * radius / 1000 usedWeight = volume * density filemanentModel.usedWeight = usedWeight filemanentModel.usedCost = spoolCost / spoolWeight * usedWeight printJob.addFilamentModel(filemanentModel) pass def _updatePrintJobModelWithLayerHeightInfos(self, payload): totalLayers = payload["totalLayer"] currentLayer = payload["currentLayer"] self._currentPrintJobModel.printedLayers = currentLayer + " / " + totalLayers totalHeightWithExtrusion = payload["totalHeightWithExtrusion"] currentHeight = payload["currentHeight"] self._currentPrintJobModel.printedHeight = currentHeight + " / " + totalHeightWithExtrusion def _createPrintJobModel(self, payload): self._currentPrintJobModel = PrintJobModel() self._currentPrintJobModel.printStartDateTime = datetime.datetime.now() self._currentPrintJobModel.fileOrigin = payload["origin"] self._currentPrintJobModel.fileName = payload["name"] self._currentPrintJobModel.filePathName = payload["path"] # self._file_manager.path_on_disk() if "owner" in payload: self._currentPrintJobModel.userName = payload["owner"] else: self._currentPrintJobModel.userName = "******" self._currentPrintJobModel.fileSize = payload["size"] tempFound = False tempTool = 0 tempBed = 0 if self._preHeatPluginImplementation != None: path_on_disk = octoprint.server.fileManager.path_on_disk( self._currentPrintJobModel.fileOrigin, self._currentPrintJobModel.filePathName) preHeatTemperature = self._preHeatPluginImplementation.read_temperatures_from_file( path_on_disk) if preHeatTemperature != None: if "bed" in preHeatTemperature: tempBed = preHeatTemperature["bed"] tempFound = True if "tool0" in preHeatTemperature: tempTool = preHeatTemperature["tool0"] tempFound = True pass else: currentTemps = self._printer.get_current_temperatures() if (len(currentTemps) > 0): tempBed = currentTemps[0]["bed"]["target"] tempTool = currentTemps[0]["tool0"]["target"] tempFound = True if (tempFound == True): tempModel = TemperatureModel() tempModel.sensorName = "bed" tempModel.sensorValue = tempBed self._currentPrintJobModel.addTemperatureModel(tempModel) tempModel = TemperatureModel() tempModel.sensorName = "tool0" tempModel.sensorValue = tempTool self._currentPrintJobModel.addTemperatureModel(tempModel) def _printJobFinished(self, printStatus, payload): self._currentPrintJobModel.printEndDateTime = datetime.datetime.now() self._currentPrintJobModel.duration = ( self._currentPrintJobModel.printEndDateTime - self._currentPrintJobModel.printStartDateTime).total_seconds() self._currentPrintJobModel.printStatusResult = printStatus if self._settings.get_boolean( [SettingsKeys.SETTINGS_KEY_TAKE_SNAPSHOT_AFTER_PRINT]): self._cameraManager.takeSnapshotAsync( CameraManager.buildSnapshotFilename( self._currentPrintJobModel.printStartDateTime)) if self._settings.get_boolean( [SettingsKeys.SETTINGS_KEY_TAKE_ULTIMAKER_THUMBNAIL_AFTER_PRINT]): # check if available if (not self._ultimakerFormatPluginImplementation == None): self._cameraManager.takeUltimakerPackageThumbnailAsync( CameraManager.buildSnapshotFilename( self._currentPrintJobModel.printStartDateTime), self._currentPrintJobModel.fileName) else: self._logger.error( "UltimakerPackageFormat Thumbnail enabled, but Plugin not available! Activate Plugin-Depenedency check" ) # FilamentInformations e.g. length self._createAndAssignFilamentModel(self._currentPrintJobModel, payload) # store everything in the database databaseId = self._databaseManager.insertPrintJob( self._currentPrintJobModel) printJobItem = None if self._settings.get_boolean( [SettingsKeys.SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT]): self._settings.set_int([ SettingsKeys. SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT_JOB_ID ], databaseId) self._settings.save() # inform client to show job edit dialog printJobModel = self._databaseManager.loadPrintJob(databaseId) printJobItem = TransformPrintJob2JSON.transformPrintJobModel( printJobModel) # inform client for a reload payload = {"action": "printFinished", "printJobItem": printJobItem} self._sendDataToClient(payload) ######################################################################################### Hooks and public functions def on_after_startup(self): # check if needed plugins were available self._checkForMissingPluginInfos() def on_event(self, event, payload): # WebBroswer opened if Events.CLIENT_OPENED == event: # Check if all needed Plugins are available, if not modale dialog to User if self._settings.get_boolean( [SettingsKeys.SETTINGS_KEY_PLUGIN_DEPENDENCY_CHECK]): self._checkForMissingPluginInfos(True) if self._settings.get_boolean( [SettingsKeys.SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT]): printJobId = self._settings.get_int([ SettingsKeys. SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT_JOB_ID ]) if (not printJobId == None): try: printJobModel = self._databaseManager.loadPrintJob( printJobId) printJobItem = TransformPrintJob2JSON.transformPrintJobModel( printJobModel) payload = { "action": "showPrintJobDialogAfterClientConnection", "printJobItem": printJobItem } self._sendDataToClient(payload) except DoesNotExist as e: self._settings.remove([ SettingsKeys. SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT_JOB_ID ]) elif Events.PRINT_STARTED == event: self.alreadyCanceled = False self._createPrintJobModel(payload) elif "DisplayLayerProgress_layerChanged" == event or event == "DisplayLayerProgress_heightChanged": self._updatePrintJobModelWithLayerHeightInfos(payload) elif Events.PRINT_DONE == event: self._printJobFinished("success", payload) elif Events.PRINT_FAILED == event: if self.alreadyCanceled == False: self._printJobFinished("failed", payload) elif Events.PRINT_CANCELLED == event: self.alreadyCanceled = True self._printJobFinished("canceled", payload) pass def on_settings_save(self, data): # default save function octoprint.plugin.SettingsPlugin.on_settings_save(self, data) # to allow the frontend to trigger an GET call def on_api_get(self, request): if len(request.values) != 0: action = request.values["action"] pass ##~~ SettingsPlugin mixin def get_settings_defaults(self): settings = dict() settings[SettingsKeys.SETTINGS_KEY_PLUGIN_DEPENDENCY_CHECK] = True settings[ SettingsKeys.SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT] = True settings[SettingsKeys. SETTINGS_KEY_SHOW_PRINTJOB_DIALOG_AFTER_PRINT_JOB_ID] = None settings[SettingsKeys.SETTINGS_KEY_TAKE_SNAPSHOT_AFTER_PRINT] = True settings[SettingsKeys. SETTINGS_KEY_TAKE_ULTIMAKER_THUMBNAIL_AFTER_PRINT] = True settings[SettingsKeys.SETTINGS_KEY_DATABASE_PATH] = "" settings[SettingsKeys.SETTINGS_KEY_SNAPSHOT_PATH] = "" return settings ##~~ TemplatePlugin mixin def get_template_configs(self): return [ dict(type="tab", name="Print Job History"), dict(type="settings", custom_bindings=True) ] def get_template_vars(self): return dict(apikey=self._settings.global_get(["api", "key"])) ##~~ AssetPlugin mixin def get_assets(self): # Define your plugin's asset files to automatically include in the # core UI here. return dict(js=[ "js/PrintJobHistory.js", "js/PrintJobHistory-APIClient.js", "js/PrintJobHistory-PluginCheckDialog.js", "js/PrintJobHistory-EditJobDialog.js", "js/PrintJobHistory-ComponentFactory.js", "js/quill.min.js", "js/TableItemHelper.js" ], css=["css/PrintJobHistory.css", "css/quill.snow.css"], less=["less/PrintJobHistory.less"]) ##~~ Softwareupdate hook def get_update_information(self): # Define the configuration for your plugin to use with the Software Update # Plugin here. See https://github.com/foosel/OctoPrint/wiki/Plugin:-Software-Update # for details. return dict(PrintJobHistory=dict( displayName="PrintJobHistory Plugin", displayVersion=self._plugin_version, # version check: github repository type="github_release", user="******", repo="OctoPrint-PrintJobHistory", current=self._plugin_version, # update method: pip pip= "https://github.com/OllisGit/OctoPrint-PrintJobHistory/releases/latest/download/master.zip" )) # Increase upload-size (default 100kb) for uploading images def bodysize_hook(self, current_max_body_sizes, *args, **kwargs): return [("POST", r"/upload/", 5 * 1024 * 1024)] # size in bytes # For Streaming I need a special ResponseHandler def route_hook(self, server_routes, *args, **kwargs): from octoprint.server.util.tornado import LargeResponseHandler, UrlProxyHandler, path_validation_factory from octoprint.util import is_hidden_path return [ # (r'myvideofeed', StreamHandler, dict(url=self._settings.global_get(["webcam", "snapshot"]), # as_attachment=True)), (r"mysnapshot", UrlProxyHandler, dict(url=self._settings.global_get(["webcam", "snapshot"]), as_attachment=True)) ]
def parseCSV(csvFile4Import, updateParsingStatus, errorCollection, logger, deleteAfterParsing=True): result = list() # List with printJobModels lineNumber = 0 try: with open(csvFile4Import) as csv_file: csv_reader = csv.reader(csv_file, delimiter=',') lineNumber = 0 for row in csv_reader: lineNumber += 1 # import time # time.sleep(1) updateParsingStatus(str(lineNumber)) if lineNumber == 1: # createColumnOrderFromHeader(row) # mandatoryFieldCount = 0 mandatoryFieldAvaiable = list() columnIndex = 0 for column in row: column = column.strip() if column in ALL_COLUMNS: columnOrderInFile[columnIndex] = ALL_COLUMNS[column] if column in mandatoryFieldNames: mandatoryFieldAvaiable.append(column) # mandatoryFieldCount += 1 columnIndex += 1 if len(mandatoryFieldAvaiable) != len(mandatoryFieldNames): # if mandatoryFieldCount != len(mandatoryFieldNames): # identify missing files # mandatoryFieldMissing = mandatoryFieldNames - mandatoryFieldAvaiable mandatoryFieldMissing = list( set(mandatoryFieldNames) - set(mandatoryFieldAvaiable) ) errorCollection.append("Mandatory column is missing! <br/><b>'" + "".join(mandatoryFieldMissing) + "'</b><br/>") break else: printJobModel = PrintJobModel() # parse line with header defined order columnIndex = 0 for columnValue in row: if columnIndex in columnOrderInFile: csvColumn = columnOrderInFile[columnIndex] if not csvColumn == None: columnValue = columnValue.strip() # check if mandatory value is missing if (len(columnValue) == 0): columnName = csvColumn.columnLabel if columnName in mandatoryFieldNames: errorCollection.append("["+str(lineNumber)+"] Mandatory value for column '" + columnName + "' is missing!") pass else: csvColumn.parseAndAssignFieldValue(columnValue, printJobModel, errorCollection, lineNumber) pass columnIndex += 1 if (len(errorCollection) != 0): logger.error("Reading error line '" + str(lineNumber) + "' in Column '" + column + "' ") else: result.append(printJobModel) pass except Exception as e: errorMessage = "CSV Parsing error. Line:'" + str(lineNumber) + "' Error:'" + str(e) + "' File:'" + csvFile4Import + "'" errorCollection.append(errorMessage) logger.error(errorMessage) finally: if (deleteAfterParsing): logger.info("Removing uploded csv temp-file") try: os.remove(csvFile4Import) except Exception: pass return result