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)
Beispiel #3
0
    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
Beispiel #11
0
    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
Beispiel #13
0
 def loadPrintJob(self, databaseId):
     return PrintJobModel.get_by_id(databaseId)
Beispiel #14
0
 def loadAllPrintJobs(self):
     return PrintJobModel.select().order_by(
         PrintJobModel.printStartDateTime.desc())
Beispiel #15
0
 def createWithDefaults(self):
     newPrintJobModel = PrintJobModel()
     totalFilament = FilamentModel()
     totalFilament.toolId = "total"
     newPrintJobModel.addFilamentModel(totalFilament)
     return newPrintJobModel
Beispiel #16
0
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