diff --git a/octoprint_SpoolManager/api/SpoolManagerAPI.py b/octoprint_SpoolManager/api/SpoolManagerAPI.py index 7bfa97c..9c17228 100644 --- a/octoprint_SpoolManager/api/SpoolManagerAPI.py +++ b/octoprint_SpoolManager/api/SpoolManagerAPI.py @@ -12,7 +12,7 @@ import tempfile import threading import qrcode -from io import BytesIO # for handling byte strings +from io import BytesIO # for handling byte strings from math import pi as PI from octoprint_SpoolManager import DatabaseManager @@ -22,26 +22,34 @@ from octoprint_SpoolManager.common.SettingsKeys import SettingsKeys from octoprint_SpoolManager.common.EventBusKeys import EventBusKeys + class SpoolManagerAPI(octoprint.plugin.BlueprintPlugin): def is_blueprint_csrf_protected(self): return True - def _sendCSVUploadStatusToClient(self, importStatus, currenLineNumber, backupFilePath, successMessages, errorCollection): - - self._sendDataToClient(dict(action="csvImportStatus", - importStatus = importStatus, - currenLineNumber = currenLineNumber, - backupFilePath = backupFilePath, - successMessages=successMessages, - errorCollection = errorCollection - ) - ) + def _sendCSVUploadStatusToClient( + self, + importStatus, + currenLineNumber, + backupFilePath, + successMessages, + errorCollection, + ): + self._sendDataToClient( + dict( + action="csvImportStatus", + importStatus=importStatus, + currenLineNumber=currenLineNumber, + backupFilePath=backupFilePath, + successMessages=successMessages, + errorCollection=errorCollection, + ) + ) def _updateSpoolModelFromJSONData(self, spoolModel, jsonData): - spoolModel.version = self._toIntFromJSONOrNone("version", jsonData) # if statement is needed because assigning None is alos detected as an dirtyField - if (self._getValueFromJSONOrNone("databaseId", jsonData) != None): + if self._getValueFromJSONOrNone("databaseId", jsonData) != None: spoolModel.databaseId = self._getValueFromJSONOrNone("databaseId", jsonData) spoolModel.isTemplate = self._getValueFromJSONOrNone("isTemplate", jsonData) @@ -51,19 +59,35 @@ def _updateSpoolModelFromJSONData(self, spoolModel, jsonData): spoolModel.material = self._getValueFromJSONOrNone("material", jsonData) spoolModel.density = self._toFloatFromJSONOrNone("density", jsonData) spoolModel.diameter = self._toFloatFromJSONOrNone("diameter", jsonData) - spoolModel.diameterTolerance = self._toFloatFromJSONOrNone("diameterTolerance", jsonData) + spoolModel.diameterTolerance = self._toFloatFromJSONOrNone( + "diameterTolerance", jsonData + ) spoolModel.colorName = self._getValueFromJSONOrNone("colorName", jsonData) spoolModel.color = self._getValueFromJSONOrNone("color", jsonData) - spoolModel.flowRateCompensation = self._toIntFromJSONOrNone("flowRateCompensation", jsonData) + spoolModel.flowRateCompensation = self._toIntFromJSONOrNone( + "flowRateCompensation", jsonData + ) spoolModel.temperature = self._toIntFromJSONOrNone("temperature", jsonData) - spoolModel.bedTemperature = self._toIntFromJSONOrNone("bedTemperature", jsonData) - spoolModel.enclosureTemperature = self._toIntFromJSONOrNone("enclosureTemperature", jsonData) - spoolModel.offsetTemperature = self._toIntFromJSONOrNone("offsetTemperature", jsonData) - spoolModel.offsetBedTemperature = self._toIntFromJSONOrNone("offsetBedTemperature", jsonData) - spoolModel.offsetEnclosureTemperature = self._toIntFromJSONOrNone("offsetEnclosureTemperature", jsonData) + spoolModel.bedTemperature = self._toIntFromJSONOrNone( + "bedTemperature", jsonData + ) + spoolModel.enclosureTemperature = self._toIntFromJSONOrNone( + "enclosureTemperature", jsonData + ) + spoolModel.offsetTemperature = self._toIntFromJSONOrNone( + "offsetTemperature", jsonData + ) + spoolModel.offsetBedTemperature = self._toIntFromJSONOrNone( + "offsetBedTemperature", jsonData + ) + spoolModel.offsetEnclosureTemperature = self._toIntFromJSONOrNone( + "offsetEnclosureTemperature", jsonData + ) spoolModel.totalWeight = self._toFloatFromJSONOrNone("totalWeight", jsonData) spoolModel.spoolWeight = self._toFloatFromJSONOrNone("spoolWeight", jsonData) - spoolModel.remainingWeight = self._toFloatFromJSONOrNone("remainingWeight", jsonData) + spoolModel.remainingWeight = self._toFloatFromJSONOrNone( + "remainingWeight", jsonData + ) spoolModel.totalLength = self._toIntFromJSONOrNone("totalLength", jsonData) spoolModel.usedLength = self._toIntFromJSONOrNone("usedLength", jsonData) spoolModel.usedWeight = self._toFloatFromJSONOrNone("usedWeight", jsonData) @@ -72,22 +96,31 @@ def _updateSpoolModelFromJSONData(self, spoolModel, jsonData): # spoolModel.firstUse = StringUtils.transformToDateTimeOrNone(self._getValueFromJSONOrNone("firstUse", jsonData)) # spoolModel.lastUse = StringUtils.transformToDateTimeOrNone(self._getValueFromJSONOrNone("lastUse", jsonData)) # spoolModel.purchasedOn = StringUtils.transformToDateTimeOrNone(self._getValueFromJSONOrNone("purchasedOn", jsonData)) - spoolModel.firstUse = StringUtils.transformFromIsoToDateTimeOrNone(self._getValueFromJSONOrNone("firstUseKO", jsonData)) - spoolModel.lastUse = StringUtils.transformFromIsoToDateTimeOrNone(self._getValueFromJSONOrNone("lastUseKO", jsonData)) - spoolModel.purchasedOn = StringUtils.transformFromIsoToDateTimeOrNone(self._getValueFromJSONOrNone("purchasedOnKO", jsonData)) - - spoolModel.purchasedFrom = self._getValueFromJSONOrNone("purchasedFrom", jsonData) + spoolModel.firstUse = StringUtils.transformFromIsoToDateTimeOrNone( + self._getValueFromJSONOrNone("firstUseKO", jsonData) + ) + spoolModel.lastUse = StringUtils.transformFromIsoToDateTimeOrNone( + self._getValueFromJSONOrNone("lastUseKO", jsonData) + ) + spoolModel.purchasedOn = StringUtils.transformFromIsoToDateTimeOrNone( + self._getValueFromJSONOrNone("purchasedOnKO", jsonData) + ) + + spoolModel.purchasedFrom = self._getValueFromJSONOrNone( + "purchasedFrom", jsonData + ) spoolModel.cost = self._toFloatFromJSONOrNone("cost", jsonData) spoolModel.costUnit = self._getValueFromJSONOrNone("costUnit", jsonData) spoolModel.labels = json.dumps(self._getValueFromJSONOrNone("labels", jsonData)) spoolModel.noteText = self._getValueFromJSONOrNone("noteText", jsonData) - spoolModel.noteDeltaFormat = json.dumps(self._getValueFromJSONOrNone("noteDeltaFormat", jsonData)) + spoolModel.noteDeltaFormat = json.dumps( + self._getValueFromJSONOrNone("noteDeltaFormat", jsonData) + ) spoolModel.noteHtml = self._getValueFromJSONOrNone("noteHtml", jsonData) pass - def _getValueFromJSONOrNone(self, key, json): if key in json: return json[key] @@ -95,13 +128,20 @@ def _getValueFromJSONOrNone(self, key, json): def _toFloatFromJSONOrNone(self, key, json): value = self._getValueFromJSONOrNone(key, json) - if (value != None): - if (StringUtils.isNotEmpty(value)): + if value != None: + if StringUtils.isNotEmpty(value): try: value = float(value) except Exception as e: errorMessage = str(e) - self._logger.error("could not transform value '"+str(value)+"' for key '"+key+"' to float:" + errorMessage) + self._logger.error( + "could not transform value '" + + str(value) + + "' for key '" + + key + + "' to float:" + + errorMessage + ) value = None else: value = None @@ -109,13 +149,20 @@ def _toFloatFromJSONOrNone(self, key, json): def _toIntFromJSONOrNone(self, key, json): value = self._getValueFromJSONOrNone(key, json) - if (value != None): - if (StringUtils.isNotEmpty(value)): + if value != None: + if StringUtils.isNotEmpty(value): try: value = int(value) except Exception as e: errorMessage = str(e) - self._logger.error("could not transform value '"+str(value)+"' for key '"+key+"' to int:" + errorMessage) + self._logger.error( + "could not transform value '" + + str(value) + + "' for key '" + + key + + "' to int:" + + errorMessage + ) value = None else: value = None @@ -132,28 +179,34 @@ def _toIntFromJSONOrNone(self, key, json): def loadSelectedSpools(self): spoolModelList = [] - databaseIds = self._settings.get([SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS]) + databaseIds = self._settings.get( + [SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS] + ) for toolIndex, databaseId in enumerate(databaseIds): spoolModel = None - if (databaseId != None): + if databaseId != None: self._databaseManager.connectoToDatabase() spoolModel = self._databaseManager.loadSpool(databaseId) self._databaseManager.closeDatabase() - if (spoolModel == None): + if spoolModel == None: self._logger.warning( - "Last selected Spool for Tool %d from plugin-settings not found in database. Maybe deleted in the meantime." % i) + "Last selected Spool for Tool %d from plugin-settings not found in database. Maybe deleted in the meantime." + % i + ) spoolModelList.append(spoolModel) - if (spoolModel != None): + if spoolModel != None: eventPayload = { "toolId": toolIndex, "databaseId": spoolModel.databaseId, "spoolName": spoolModel.displayName, "material": spoolModel.material, "colorName": spoolModel.colorName, - "remainingWeight": spoolModel.remainingWeight + "remainingWeight": spoolModel.remainingWeight, } - self._sendPayload2EventBus(EventBusKeys.EVENT_BUS_SPOOL_SELECTED, eventPayload) + self._sendPayload2EventBus( + EventBusKeys.EVENT_BUS_SPOOL_SELECTED, eventPayload + ) return spoolModelList @@ -182,25 +235,33 @@ def _createSpoolModelFromLegacy(self, allSpoolLegacyList): spoolModel.density = densityFloat spoolModel.diameter = diameterFloat spoolModel.cost = costFloat - spoolModel.costUnit = self._filamentManagerPluginImplementation._settings.get(["currencySymbol"]) + spoolModel.costUnit = ( + self._filamentManagerPluginImplementation._settings.get( + ["currencySymbol"] + ) + ) spoolModel.totalWeight = totalWeightFloat spoolModel.usedWeight = usedWeightFloat - spoolModel.usedLength = self._calculateUsedLength(spoolModel.usedWeight, spoolModel.density, spoolModel.diameter) + spoolModel.usedLength = self._calculateUsedLength( + spoolModel.usedWeight, spoolModel.density, spoolModel.diameter + ) allSpoolModels.append(spoolModel) return allSpoolModels def _calculateUsedLength(self, usedWeight, density, diameter): - if (diameter == None or density == None or usedWeight == None): - self._logger.info("Could not calculate used length because some values (usedWeigth, density, diameter) were missing") + if diameter == None or density == None or usedWeight == None: + self._logger.info( + "Could not calculate used length because some values (usedWeigth, density, diameter) were missing" + ) return None radius = diameter / 2.0 volume = (usedWeight) / density length = (volume * 1000) / PI * radius * radius lengthRounded = int(round(length)) - return lengthRounded; + return lengthRounded def _resetSelectedSpools(self): self._settings.set([SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS], []) @@ -212,30 +273,41 @@ def _selectSpool(self, toolIndex, databaseId): # 2. databaseId == -1 toolIndex != -1 remove spool from tool | # 3. databaseId != -1 toolIndex == -1 remove tool from spool || - databaseIds = self._settings.get([SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS]) + databaseIds = self._settings.get( + [SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS] + ) spoolModel = None - if (databaseId != -1): + if databaseId != -1: spoolModel = self._databaseManager.loadSpool(databaseId) - if (spoolModel != None): + if spoolModel != None: self._logger.info( - "Store selected spool %s for tool %d in settings." % - (spoolModel.displayName, toolIndex) + "Store selected spool %s for tool %d in settings." + % (spoolModel.displayName, toolIndex) ) # assign model to selected toolId - if (toolIndex != -1): - databaseIds = databaseIds + [None] * (toolIndex + 1 - len(databaseIds)) # pad list to the needed length - idx = 0; + if toolIndex != -1: + databaseIds = databaseIds + [None] * ( + toolIndex + 1 - len(databaseIds) + ) # pad list to the needed length + idx = 0 for selectedSpoolDBId in databaseIds: - if (selectedSpoolDBId == databaseId): + if selectedSpoolDBId == databaseId: databaseIds[idx] = None # check if tool changed, if yes inform user about the switch - if (idx != toolIndex): + if idx != toolIndex: # spool was already assigned and is now used for different tool - self._sendMessageToClient("warning", - "Spool swapped", - "Spool '"+spoolModel.displayName+"' was switched from Tool "+str(idx)+" to Tool "+str(toolIndex), - autoclose=True) + self._sendMessageToClient( + "warning", + "Spool swapped", + "Spool '" + + spoolModel.displayName + + "' was switched from Tool " + + str(idx) + + " to Tool " + + str(toolIndex), + autoclose=True, + ) pass else: databaseIds[idx] = selectedSpoolDBId @@ -248,15 +320,17 @@ def _selectSpool(self, toolIndex, databaseId): "spoolName": spoolModel.displayName, "material": spoolModel.material, "colorName": spoolModel.colorName, - "remainingWeight": spoolModel.remainingWeight + "remainingWeight": spoolModel.remainingWeight, } - self._sendPayload2EventBus(EventBusKeys.EVENT_BUS_SPOOL_SELECTED, eventPayload) + self._sendPayload2EventBus( + EventBusKeys.EVENT_BUS_SPOOL_SELECTED, eventPayload + ) else: # spool present, but no toolId -> remove spool from current toolIndex i = 0 while i < len(databaseIds): - if (databaseIds[i] == databaseId): + if databaseIds[i] == databaseId: databaseIds[i] = None eventPayload = { "toolId": i, @@ -264,37 +338,42 @@ def _selectSpool(self, toolIndex, databaseId): "spoolName": spoolModel.displayName, "material": spoolModel.material, "colorName": spoolModel.colorName, - "remainingWeight": spoolModel.remainingWeight + "remainingWeight": spoolModel.remainingWeight, } - self._sendPayload2EventBus(EventBusKeys.EVENT_BUS_SPOOL_DESELECTED, eventPayload) + self._sendPayload2EventBus( + EventBusKeys.EVENT_BUS_SPOOL_DESELECTED, eventPayload + ) break i += 1 pass else: self._logger.warning( - "Selected Spool with id %d for tool %d not in database anymore. Maybe deleted in the meantime." % - (databaseId, toolIndex) + "Selected Spool with id %d for tool %d not in database anymore. Maybe deleted in the meantime." + % (databaseId, toolIndex) ) # remove spool from current toolIndex i = 0 while i < len(databaseIds): - if (databaseIds[i] == databaseId): + if databaseIds[i] == databaseId: databaseIds[i] = None else: - if (toolIndex == -1): - self._logger.warn("databaseId and toolId is -1. This should not happen, strange!!!") + if toolIndex == -1: + self._logger.warn( + "databaseId and toolId is -1. This should not happen, strange!!!" + ) return None # remove current spool from toolIndex - if (toolIndex < len(databaseIds)): + if toolIndex < len(databaseIds): databaseIds[toolIndex] = None - eventPayload = { - "toolId": toolIndex, - "databaseId": None - } - self._sendPayload2EventBus(EventBusKeys.EVENT_BUS_SPOOL_DESELECTED, eventPayload) + eventPayload = {"toolId": toolIndex, "databaseId": None} + self._sendPayload2EventBus( + EventBusKeys.EVENT_BUS_SPOOL_DESELECTED, eventPayload + ) - self._settings.set([SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS], databaseIds) + self._settings.set( + [SettingsKeys.SETTINGS_KEY_SELECTED_SPOOLS_DATABASE_IDS], databaseIds + ) self._settings.save() # only check filament for the spool that was changed, as to not spam the user with warnings (for a specific toolIndex) @@ -307,34 +386,42 @@ def _selectSpool(self, toolIndex, databaseId): @octoprint.plugin.BlueprintPlugin.route("/sampleCSV", methods=["GET"]) def sampleCSV(self): - allSpoolModels = list() spoolModel = CSVExportImporter.createSampleSpoolModel() allSpoolModels.append(spoolModel) - return Response(CSVExportImporter.transform2CSV(allSpoolModels), - mimetype='text/csv', - headers={'Content-Disposition': 'attachment; filename=SpoolManager-SAMPLE.csv'}) + return Response( + CSVExportImporter.transform2CSV(allSpoolModels), + mimetype="text/csv", + headers={ + "Content-Disposition": "attachment; filename=SpoolManager-SAMPLE.csv" + }, + ) ############################################################################################## ALLOWED TO PRINT @octoprint.plugin.BlueprintPlugin.route("/allowedToPrint", methods=["GET"]) def allowed_to_print(self): - - checkForSelectedSpool = self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_WARN_IF_SPOOL_NOT_SELECTED]) - checkForFilamentLength = self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_WARN_IF_FILAMENT_NOT_ENOUGH]) - reminderSelectingSpool = self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_REMINDER_SELECTING_SPOOL]) + checkForSelectedSpool = self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_WARN_IF_SPOOL_NOT_SELECTED] + ) + checkForFilamentLength = self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_WARN_IF_FILAMENT_NOT_ENOUGH] + ) + reminderSelectingSpool = self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_REMINDER_SELECTING_SPOOL] + ) spoolModels = self.loadSelectedSpools() metaOrAttributesMissing = False result = { - 'noSpoolSelected': [], - 'filamentNotEnough': [], - 'reminderSpoolSelection': [], + "noSpoolSelected": [], + "filamentNotEnough": [], + "reminderSpoolSelection": [], } filamentLengthPresentInMeta = self._readingFilamentMetaData() printer_profile = self._printer_profile_manager.get_current_or_default() - printerProfileToolCount = printer_profile['extruder']['count'] + printerProfileToolCount = printer_profile["extruder"]["count"] # for toolIndex, filamentLength in enumerate(self.metaDataFilamentLengths): for toolIndex in range(printerProfileToolCount): # we go over the filamentlength because those are what matters for this print @@ -343,16 +430,22 @@ def allowed_to_print(self): # if this tool is not used (no filaLenght) in this print, everything is fine continue - spoolModel = spoolModels[toolIndex] if toolIndex < len(spoolModels) else None + spoolModel = ( + spoolModels[toolIndex] if toolIndex < len(spoolModels) else None + ) infoData = { "toolIndex": toolIndex, - "spoolName": spoolModel.displayName if spoolModel else '(no spool selected)', - "material": spoolModel.material if spoolModel else '', - "remainingWeight": spoolModel.remainingWeight if spoolModel else '', - "toolOffset": spoolModel.offsetTemperature if spoolModel else '', - "bedOffset": spoolModel.offsetBedTemperature if spoolModel else '', - "enclosureOffset": spoolModel.offsetEnclosureTemperature if spoolModel else '' + "spoolName": spoolModel.displayName + if spoolModel + else "(no spool selected)", + "material": spoolModel.material if spoolModel else "", + "remainingWeight": spoolModel.remainingWeight if spoolModel else "", + "toolOffset": spoolModel.offsetTemperature if spoolModel else "", + "bedOffset": spoolModel.offsetBedTemperature if spoolModel else "", + "enclosureOffset": spoolModel.offsetEnclosureTemperature + if spoolModel + else "", } requiredWeightResult = self.checkRemainingFilament(toolIndex) @@ -370,26 +463,36 @@ def allowed_to_print(self): # "notEnough": notEnough, # "spoolSelected": True # ] - if (requiredWeightResult["metaDataMissing"] == True or requiredWeightResult["attributesMissing"] == True): + if ( + requiredWeightResult["metaDataMissing"] == True + or requiredWeightResult["attributesMissing"] == True + ): metaOrAttributesMissing = True detailedSpoolResult = None - if ("detailedSpoolResult" in requiredWeightResult and len(requiredWeightResult["detailedSpoolResult"]) > 0): + if ( + "detailedSpoolResult" in requiredWeightResult + and len(requiredWeightResult["detailedSpoolResult"]) > 0 + ): detailedSpoolResult = requiredWeightResult["detailedSpoolResult"][0] - if spoolModel is not None and detailedSpoolResult is not None and detailedSpoolResult["spoolSelected"] == True: - if (detailedSpoolResult["requiredLength"] > 0): - if (detailedSpoolResult["notEnough"] == True): + if ( + spoolModel is not None + and detailedSpoolResult is not None + and detailedSpoolResult["spoolSelected"] == True + ): + if detailedSpoolResult["requiredLength"] > 0: + if detailedSpoolResult["notEnough"] == True: # if not enough or needed amount could not calculated - result['filamentNotEnough'].append(infoData) + result["filamentNotEnough"].append(infoData) # add every spool for reminding, if more the 0gr is needed - result['reminderSpoolSelection'].append(infoData) + result["reminderSpoolSelection"].append(infoData) elif checkForSelectedSpool: - if (detailedSpoolResult is not None): - if (detailedSpoolResult["requiredLength"] > 0): - result['noSpoolSelected'].append(infoData) + if detailedSpoolResult is not None: + if detailedSpoolResult["requiredLength"] > 0: + result["noSpoolSelected"].append(infoData) else: - result['noSpoolSelected'].append(infoData) + result["noSpoolSelected"].append(infoData) # if (metaNotPresent or # attributesMissing or @@ -409,44 +512,59 @@ def allowed_to_print(self): # result['noSpoolSelected'].append(infoData) # check if the user want a popup - if (checkForFilamentLength == False): - result['filamentNotEnough'] = [] + if checkForFilamentLength == False: + result["filamentNotEnough"] = [] - if (reminderSelectingSpool == False): + if reminderSelectingSpool == False: # no popup, because turned off by user - result['reminderSpoolSelection'] = [] - - - return flask.jsonify({ - "result": result, - "metaOrAttributesMissing": metaOrAttributesMissing, - "toolOffsetEnabled": self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_TOOL_OFFSET_ENABLED]), - "bedOffsetEnabled": self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_BED_OFFSET_ENABLED]), - "enclosureOffsetEnabled": self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_ENCLOSURE_OFFSET_ENABLED]), - }) - + result["reminderSpoolSelection"] = [] + + return flask.jsonify( + { + "result": result, + "metaOrAttributesMissing": metaOrAttributesMissing, + "toolOffsetEnabled": self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_TOOL_OFFSET_ENABLED] + ), + "bedOffsetEnabled": self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_BED_OFFSET_ENABLED] + ), + "enclosureOffsetEnabled": self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_ENCLOSURE_OFFSET_ENABLED] + ), + } + ) ############################################################################################# START PRINT CONFIRMED @octoprint.plugin.BlueprintPlugin.route("/startPrintConfirmed", methods=["GET"]) def start_print_confirmed(self): spoolModels = self.loadSelectedSpools() printer_profile = self._printer_profile_manager.get_current_or_default() - printerProfileToolCount = printer_profile['extruder']['count'] + printerProfileToolCount = printer_profile["extruder"]["count"] # for toolIndex, filamentLength in enumerate(self.metaDataFilamentLengths): for toolIndex in range(printerProfileToolCount): - spoolModel = spoolModels[toolIndex] if toolIndex < len(spoolModels) else None - if (spoolModel != None): + spoolModel = ( + spoolModels[toolIndex] if toolIndex < len(spoolModels) else None + ) + if spoolModel != None: # - assign temp-offset here, because after the print is started (event: ) it is too late Events.PRINT_STARTED try: self.set_temp_offsets(toolIndex, spoolModel) except Exception as e: - self._logger.exception("Temperature offsets for Spool '"+str(spoolModel.displayName)+"' failed to set!") - self._sendMessageToClient("warning", "Temperature offsets for Spool '"+str(spoolModel.displayName)+"' failed to set!", str(e)) - - return flask.jsonify({ - "result": "goForIt" - }) - + self._logger.exception( + "Temperature offsets for Spool '" + + str(spoolModel.displayName) + + "' failed to set!" + ) + self._sendMessageToClient( + "warning", + "Temperature offsets for Spool '" + + str(spoolModel.displayName) + + "' failed to set!", + str(e), + ) + + return flask.jsonify({"result": "goForIt"}) ##################################################################################################### SELECT SPOOL @octoprint.plugin.BlueprintPlugin.route("/selectSpool", methods=["PUT"]) @@ -458,9 +576,13 @@ def select_spool(self): if self._printer.is_printing(): # changing a spool mid-print? we want to know - commitCurrentSpoolValues = self._getValueFromJSONOrNone("commitCurrentSpoolValues", jsonData) + commitCurrentSpoolValues = self._getValueFromJSONOrNone( + "commitCurrentSpoolValues", jsonData + ) if commitCurrentSpoolValues is None: - self._logger.warning("selectSpool endpoint called mid-print without commitCurrentState parameter - this shouldn't happen") + self._logger.warning( + "selectSpool endpoint called mid-print without commitCurrentState parameter - this shouldn't happen" + ) abort(409) if commitCurrentSpoolValues: @@ -470,24 +592,27 @@ def select_spool(self): spoolModel = self._selectSpool(toolIndex, databaseId) spoolModelAsDict = None - if (spoolModel != None): + if spoolModel != None: spoolModelAsDict = Transformer.transformSpoolModelToDict(spoolModel) try: self.set_temp_offsets(toolIndex, spoolModel) except Exception as e: - self._sendMessageToClient("warning", "Temperature offsets failed to set!", str(e)) + self._sendMessageToClient( + "warning", "Temperature offsets failed to set!", str(e) + ) self.checkRemainingFilament() - return flask.jsonify({ - "selectedSpool": spoolModelAsDict - }) + return flask.jsonify({"selectedSpool": spoolModelAsDict}) ##################################################################################################### SELECT SPOOL BY QR from octoprint.server.util.flask import no_firstrun_access, restricted_access - @octoprint.plugin.BlueprintPlugin.route("/selectSpoolByQRCode/", methods=["GET"]) + + @octoprint.plugin.BlueprintPlugin.route( + "/selectSpoolByQRCode/", methods=["GET"] + ) @no_firstrun_access def selectSpoolByQRCode(self, databaseId): self._logger.info("API select spool by QR code" + str(databaseId)) @@ -499,20 +624,24 @@ def selectSpoolByQRCode(self, databaseId): spoolModel = None - if ("qrPreviewId" == databaseId): - #Just pick a single spool - spoolModel = self._databaseManager.loadFirstSingleSpool(); + if "qrPreviewId" == databaseId: + # Just pick a single spool + spoolModel = self._databaseManager.loadFirstSingleSpool() databaseId = spoolModel.databaseId # TODO QR-Code pre-select always tool0 and then the edit-dialog is shown. Better approach: show dialog and the user could choose spoolModel = self._selectSpool(0, databaseId) spoolModelAsDict = None - if (spoolModel != None): + if spoolModel != None: spoolModelAsDict = Transformer.transformSpoolModelToDict(spoolModel) - #Take us back to the SpoolManager plugin tab - redirectURLWithSpoolSelection = flask.url_for("index", _external=True)+"#tab_plugin_SpoolManager-spoolId"+str(databaseId) - return flask.redirect(redirectURLWithSpoolSelection,307) + # Take us back to the SpoolManager plugin tab + redirectURLWithSpoolSelection = ( + flask.url_for("index", _external=True) + + "#tab_plugin_SpoolManager-spoolId" + + str(databaseId) + ) + return flask.redirect(redirectURLWithSpoolSelection, 307) else: abort(404) @@ -521,39 +650,53 @@ def is_blueprint_protected(self): return False # No API key required to request API access ##################################################################################################### GENERATE QR FOR SPOOL - @octoprint.plugin.BlueprintPlugin.route("/generateQRCode/", methods=["GET"]) + @octoprint.plugin.BlueprintPlugin.route( + "/generateQRCode/", methods=["GET"] + ) def generateSpoolQRCode(self, databaseId): - - if (databaseId == "qrPreviewId" or self._databaseManager.loadSpool(databaseId) is not None): - self._logger.info("API generate QR code for Spool with databaseId: " +str(databaseId)) + if ( + databaseId == "qrPreviewId" + or self._databaseManager.loadSpool(databaseId) is not None + ): + self._logger.info( + "API generate QR code for Spool with databaseId: " + str(databaseId) + ) requestParameters = request.args fillColor = None backgroundColor = None - if ("fillColor" in requestParameters and "backgroundColor" in requestParameters): + if ( + "fillColor" in requestParameters + and "backgroundColor" in requestParameters + ): fillColor = requestParameters["fillColor"] backgroundColor = requestParameters["backgroundColor"] else: - fillColor = self._settings.get([SettingsKeys.SETTINGS_KEY_QR_CODE_FILL_COLOR]) - backgroundColor = self._settings.get([SettingsKeys.SETTINGS_KEY_QR_CODE_BACKGROUND_COLOR]) + fillColor = self._settings.get( + [SettingsKeys.SETTINGS_KEY_QR_CODE_FILL_COLOR] + ) + backgroundColor = self._settings.get( + [SettingsKeys.SETTINGS_KEY_QR_CODE_BACKGROUND_COLOR] + ) # verify color codes from PIL import ImageColor - if (fillColor.startswith("#")): + + if fillColor.startswith("#"): fillColor = ImageColor.getcolor(fillColor, "RGB") - if (backgroundColor.startswith("#")): + if backgroundColor.startswith("#"): backgroundColor = ImageColor.getcolor(backgroundColor, "RGB") # windowLocation = request.args.get("windowlocation") from PIL import Image + imageFileLocation = self._basefolder + "/static/images/SPMByOlli.png" - olliImage = Image.open(imageFileLocation)#.crop((175, 90, 235, 150)) + olliImage = Image.open(imageFileLocation) # .crop((175, 90, 235, 150)) # https://note.nkmk.me/en/python-pillow-qrcode/ qrMaker = qrcode.QRCode( - border=4, - error_correction=qrcode.constants.ERROR_CORRECT_H + border=4, error_correction=qrcode.constants.ERROR_CORRECT_H ) # spoolSelectionUrl = flask.url_for("plugin.SpoolManager.selectSpoolByQRCode", _external=True, _scheme="https", databaseId=databaseId) @@ -561,27 +704,45 @@ def generateSpoolQRCode(self, databaseId): useURLPrefix = None qrCodeUrlPrefix = None - if ("useURLPrefix" in requestParameters): + if "useURLPrefix" in requestParameters: useURLPrefix = True qrCodeUrlPrefix = requestParameters["urlPrefix"] - if (useURLPrefix == None): - useURLPrefix = self._settings.get_boolean([SettingsKeys.SETTINGS_KEY_QR_CODE_USE_URL_PREFIX]) + if useURLPrefix == None: + useURLPrefix = self._settings.get_boolean( + [SettingsKeys.SETTINGS_KEY_QR_CODE_USE_URL_PREFIX] + ) - if (useURLPrefix): - if (qrCodeUrlPrefix == None): - qrCodeUrlPrefix = self._settings.get([SettingsKeys.SETTINGS_KEY_QR_CODE_URL_PREFIX]) + if useURLPrefix: + if qrCodeUrlPrefix == None: + qrCodeUrlPrefix = self._settings.get( + [SettingsKeys.SETTINGS_KEY_QR_CODE_URL_PREFIX] + ) - spoolSelectionUrl = qrCodeUrlPrefix + "/plugin/SpoolManager/selectSpoolByQRCode/"+databaseId + spoolSelectionUrl = ( + qrCodeUrlPrefix + + "/plugin/SpoolManager/selectSpoolByQRCode/" + + databaseId + ) else: - spoolSelectionUrl = flask.url_for("plugin.SpoolManager.selectSpoolByQRCode", _external=True, databaseId=databaseId) + spoolSelectionUrl = flask.url_for( + "plugin.SpoolManager.selectSpoolByQRCode", + _external=True, + databaseId=databaseId, + ) qrMaker.add_data(spoolSelectionUrl) - qrMaker.make(fit=True, ) - + qrMaker.make( + fit=True, + ) - img_qr_big = qrMaker.make_image(fill_color=fillColor, back_color=backgroundColor).convert('RGB') - pos = ((img_qr_big.size[0] - olliImage.size[0]) // 2, (img_qr_big.size[1] - olliImage.size[1]) // 2) + img_qr_big = qrMaker.make_image( + fill_color=fillColor, back_color=backgroundColor + ).convert("RGB") + pos = ( + (img_qr_big.size[0] - olliImage.size[0]) // 2, + (img_qr_big.size[1] - olliImage.size[1]) // 2, + ) img_qr_big.paste(olliImage, pos) # img_qr_big.save('data/dst/qr_lena2.png') @@ -593,50 +754,80 @@ def generateSpoolQRCode(self, databaseId): qr_io = BytesIO() # qrImage.save(qr_io, 'JPEG', quality=100) - img_qr_big.save(qr_io, 'JPEG', quality=100) + img_qr_big.save(qr_io, "JPEG", quality=100) qr_io.seek(0) - return send_file(qr_io, mimetype='image/jpeg') + return send_file(qr_io, mimetype="image/jpeg") else: abort(404) - - @octoprint.plugin.BlueprintPlugin.route("/generateQRCodeView/", methods=["GET"]) + @octoprint.plugin.BlueprintPlugin.route( + "/generateQRCodeView/", methods=["GET"] + ) def generateSpoolQRCodeHTMLView(self, databaseId): htmlContent = "" - spoolModel = self._databaseManager.loadSpool(databaseId); - if (spoolModel is not None): - self._logger.info("Generate HTML iew for QR-Code") - htmlContent = \ - "

Database Id: " + str(databaseId) + "

" \ - "

Spoolname: " + spoolModel.displayName + "

" \ - "" + spoolModel = self._databaseManager.loadSpool(databaseId) + if spoolModel.material is None: + material = "N/A" + else: + material = spoolModel.material + if spoolModel is not None: + self._logger.info("Generate HTML view for QR-Code") + htmlContent = ( + " " + "
" + "

Name: " + spoolModel.displayName + "

" + "

Id: " + str(databaseId) + "

" + "

Material: " + material + "

" + "

Color: " + spoolModel.colorName + "

" + "
" + "" + ) else: htmlContent = "

Spool with database Id not found

" - qrCodeHTMLViewTemplate = ""\ - "" \ - + htmlContent +\ - "" \ - "" + qrCodeHTMLViewTemplate = "" "" + htmlContent + "" "" return Response( - qrCodeHTMLViewTemplate, - mimetype='text/html', - # headers={'Content-Disposition': 'attachment; filename='+reportType+'PrintJobReport-Template.jinja2'} - ) - + qrCodeHTMLViewTemplate, + mimetype="text/html", + # headers={'Content-Disposition': 'attachment; filename='+reportType+'PrintJobReport-Template.jinja2'} + ) ###################################################################################### UPLOAD CSV FILE (in Thread) @octoprint.plugin.BlueprintPlugin.route("/importCSV", methods=["POST"]) def importSpoolData(self): - input_name = "file" - input_upload_path = input_name + "." + self._settings.global_get(["server", "uploads", "pathSuffix"]) + input_upload_path = ( + input_name + + "." + + self._settings.global_get(["server", "uploads", "pathSuffix"]) + ) if input_upload_path in flask.request.values: - importMode = flask.request.form["importCSVMode"] # file was uploaded sourceLocation = flask.request.values[input_upload_path] @@ -647,13 +838,16 @@ def importSpoolData(self): shutil.copy(sourceLocation, archive.name) sourceLocation = archive.name - - thread = threading.Thread(target=self._processCSVUploadAsync, - args=(sourceLocation, - importMode, - self._databaseManager, - self._sendCSVUploadStatusToClient, - self._logger)) + thread = threading.Thread( + target=self._processCSVUploadAsync, + args=( + sourceLocation, + importMode, + self._databaseManager, + self._sendCSVUploadStatusToClient, + self._logger, + ), + ) thread.daemon = True thread.start() @@ -661,13 +855,16 @@ def importSpoolData(self): # os.rename(sourceLocation, targetLocation) pass else: - return flask.make_response("Invalid request, neither a file nor a path of a file to restore provided", 400) - + return flask.make_response( + "Invalid request, neither a file nor a path of a file to restore provided", + 400, + ) return flask.jsonify(started=True) - - def _processCSVUploadAsync(self, path, importCSVMode, databaseManager, sendCSVUploadStatusToClient, logger): + def _processCSVUploadAsync( + self, path, importCSVMode, databaseManager, sendCSVUploadStatusToClient, logger + ): errorCollection = list() # - parsing @@ -678,24 +875,28 @@ def updateParsingStatus(lineNumber): # importStatus, currenLineNumber, backupFilePath, successMessages, errorCollection sendCSVUploadStatusToClient("running", lineNumber, "", "", errorCollection) - resultOfSpools = CSVExportImporter.parseCSV(path, updateParsingStatus, errorCollection, logger) + resultOfSpools = CSVExportImporter.parseCSV( + path, updateParsingStatus, errorCollection, logger + ) - if (len(errorCollection) != 0): + if len(errorCollection) != 0: successMessage = "Some error(s) occurs during parsing! No spools imported!" # importStatus, currenLineNumber, backupFilePath, successMessages, errorCollection - sendCSVUploadStatusToClient("finished", "", "", successMessage, errorCollection) + sendCSVUploadStatusToClient( + "finished", "", "", successMessage, errorCollection + ) return importModeText = "append" backupDatabaseFilePath = None - if (len(resultOfSpools) > 0): + if len(resultOfSpools) > 0: # we could import some jobs # - backup backupDatabaseFilePath = databaseManager.backupDatabaseFile() # - import mode append/replace - if (SettingsKeys.KEY_IMPORTCSV_MODE_REPLACE == importCSVMode): + if SettingsKeys.KEY_IMPORTCSV_MODE_REPLACE == importCSVMode: # delete old database and init a clean database databaseManager.reCreateDatabase() # reset selected spool @@ -709,8 +910,10 @@ def updateParsingStatus(lineNumber): currentSpoolNumber = currentSpoolNumber + 1 updateParsingStatus(currentSpoolNumber) - remainingWeight = Transformer.calculateRemainingWeight(spool.usedWeight, spool.totalWeight) - if (remainingWeight != None): + remainingWeight = Transformer.calculateRemainingWeight( + spool.usedWeight, spool.totalWeight + ) + if remainingWeight != None: spool.remainingWeight = remainingWeight # spool.save() @@ -722,84 +925,99 @@ def updateParsingStatus(lineNumber): errorCollection.append("Nothing to import!") successMessage = "" - if (len(errorCollection) == 0): - successMessage = "All data is successful " + importModeText + " with '" + str(len(resultOfSpools)) + "' spools." + if len(errorCollection) == 0: + successMessage = ( + "All data is successful " + + importModeText + + " with '" + + str(len(resultOfSpools)) + + "' spools." + ) else: successMessage = "Some error(s) occurs! Maybe you need to manually rollback the database!" logger.info(successMessage) - sendCSVUploadStatusToClient("finished", "", backupDatabaseFilePath, successMessage, errorCollection) + sendCSVUploadStatusToClient( + "finished", "", backupDatabaseFilePath, successMessage, errorCollection + ) pass def _buildDatabaseSettingsFromJson(self, jsonData): - databaseSettings = DatabaseManager.DatabaseSettings() - databaseSettings.useExternal = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_USE_EXTERNAL, jsonData) - databaseSettings.type = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_TYPE, jsonData) - databaseSettings.host = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_HOST, jsonData) - databaseSettings.port = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_PORT, jsonData) - databaseSettings.name = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_NAME, jsonData) - databaseSettings.user = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_USER, jsonData) - databaseSettings.password = self._getValueFromJSONOrNone(SettingsKeys.SETTINGS_KEY_DATABASE_PASSWORD, jsonData) + databaseSettings.useExternal = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_USE_EXTERNAL, jsonData + ) + databaseSettings.type = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_TYPE, jsonData + ) + databaseSettings.host = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_HOST, jsonData + ) + databaseSettings.port = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_PORT, jsonData + ) + databaseSettings.name = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_NAME, jsonData + ) + databaseSettings.user = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_USER, jsonData + ) + databaseSettings.password = self._getValueFromJSONOrNone( + SettingsKeys.SETTINGS_KEY_DATABASE_PASSWORD, jsonData + ) return databaseSettings - ####################################################################################### DOWNLOAD DATABASE-FILE @octoprint.plugin.BlueprintPlugin.route("/downloadDatabase", methods=["GET"]) def downloadDatabase(self): - return send_file(self._databaseManager.getDatabaseSettings().fileLocation, - mimetype='application/octet-stream', - attachment_filename='spoolmanager.db', - as_attachment=True) - + return send_file( + self._databaseManager.getDatabaseSettings().fileLocation, + mimetype="application/octet-stream", + attachment_filename="spoolmanager.db", + as_attachment=True, + ) ####################################################################################### DELETE DATABASE - @octoprint.plugin.BlueprintPlugin.route("/deleteDatabase/", methods=["POST"]) + @octoprint.plugin.BlueprintPlugin.route( + "/deleteDatabase/", methods=["POST"] + ) def deleteDatabase(self, databaseType): - databaseSettings = None - if (databaseType == "external"): + if databaseType == "external": jsonData = request.json databaseSettings = self._buildDatabaseSettingsFromJson(jsonData) self._databaseManager.reCreateDatabase(databaseSettings) - return flask.jsonify({ - "result": "success" - }) - - + return flask.jsonify({"result": "success"}) ####################################################################################### LOAD DATABASE METADATA @octoprint.plugin.BlueprintPlugin.route("/loadDatabaseMetaData", methods=["GET"]) def loadDatabaseMetaData(self): - # databaseId = self._getValueFromJSONOrNone("databaseId", jsonData) metaDataResult = self._databaseManager.loadDatabaseMetaInformations(None) - return flask.jsonify({ - "metadata": metaDataResult - }) + return flask.jsonify({"metadata": metaDataResult}) ####################################################################################### TEST DATABASE CONNECTION @octoprint.plugin.BlueprintPlugin.route("/testDatabaseConnection", methods=["PUT"]) def testDatabaseConnection(self): - jsonData = request.json databaseSettings = self._buildDatabaseSettingsFromJson(jsonData) # databaseId = self._getValueFromJSONOrNone("databaseId", jsonData) - metaDataResult = self._databaseManager.loadDatabaseMetaInformations(databaseSettings) + metaDataResult = self._databaseManager.loadDatabaseMetaInformations( + databaseSettings + ) - return flask.jsonify({ - "metadata": metaDataResult - }) + return flask.jsonify({"metadata": metaDataResult}) ############################################################################### CONFIRM DATABASE CONNECTION PROBLEM - @octoprint.plugin.BlueprintPlugin.route("/confirmDatabaseProblemMessage", methods=["PUT"]) + @octoprint.plugin.BlueprintPlugin.route( + "/confirmDatabaseProblemMessage", methods=["PUT"] + ) def confirmDatabaseConnectionProblem(self): - self.databaseConnectionProblemConfirmed = True # return flask.jsonify({ @@ -808,9 +1026,10 @@ def confirmDatabaseConnectionProblem(self): return flask.jsonify() ########################################################################################### EXPORT DATABASE as CSV - @octoprint.plugin.BlueprintPlugin.route("/exportSpools/", methods=["GET"]) + @octoprint.plugin.BlueprintPlugin.route( + "/exportSpools/", methods=["GET"] + ) def exportSpoolsData(self, exportType): - if exportType == "CSV": allSpoolModels = self._databaseManager.loadAllSpoolsByQuery(None) @@ -818,36 +1037,40 @@ def exportSpoolsData(self, exportType): currentDate = now.strftime("%Y%m%d-%H%M") fileName = "SpoolManager-" + currentDate + ".csv" - return Response(CSVExportImporter.transform2CSV(allSpoolModels), - mimetype='text/csv', - headers={'Content-Disposition': 'attachment; filename=' + fileName}) + return Response( + CSVExportImporter.transform2CSV(allSpoolModels), + mimetype="text/csv", + headers={"Content-Disposition": "attachment; filename=" + fileName}, + ) else: - if (exportType == "legacyFilamentManager"): + if exportType == "legacyFilamentManager": allSpoolLegacyList = self._filamentManagerPluginImplementation.filamentManager.get_all_spools() - if (allSpoolLegacyList != None): - - allSpoolModelList = self._createSpoolModelFromLegacy(allSpoolLegacyList) + if allSpoolLegacyList != None: + allSpoolModelList = self._createSpoolModelFromLegacy( + allSpoolLegacyList + ) now = datetime.datetime.now() currentDate = now.strftime("%Y%m%d-%H%M") fileName = "FilamentManager-" + currentDate + ".csv" - return Response(CSVExportImporter.transform2CSV(allSpoolModelList), - mimetype='text/csv', - headers={'Content-Disposition': 'attachment; filename='+fileName}) + return Response( + CSVExportImporter.transform2CSV(allSpoolModelList), + mimetype="text/csv", + headers={ + "Content-Disposition": "attachment; filename=" + fileName + }, + ) pass print("BOOOMM not supported type") pass - - ################################################################################################## LOAD ALL SPOOLS @octoprint.plugin.BlueprintPlugin.route("/loadSpoolsByQuery", methods=["GET"]) def loadAllSpoolsByQuery(self): - self._logger.debug("API Load all spool") # sp1 = SpoolModel() # sp1.displayName = "Spool No.1" @@ -893,7 +1116,9 @@ def loadAllSpoolsByQuery(self): tempateSpoolAsDict = None allTemplateSpools = self._databaseManager.loadSpoolTemplates() - allTemplateSpoolsAsDict = Transformer.transformAllSpoolModelsToDict(allTemplateSpools) + allTemplateSpoolsAsDict = Transformer.transformAllSpoolModelsToDict( + allTemplateSpools + ) # if (allTemplateSpools != None): # for spool in allTemplateSpools: @@ -904,7 +1129,7 @@ def loadAllSpoolsByQuery(self): "vendors": vendors, "materials": materials, "colors": colors, - "labels": labels + "labels": labels, } # catalogs = { # "materials": ["", "ABS", "PLA", "PETG"], @@ -912,21 +1137,26 @@ def loadAllSpoolsByQuery(self): # "labels": ["", "good", "bad"] # } selectedSpoolsAsDicts = [ - (None if selectedSpool is None else Transformer.transformSpoolModelToDict(selectedSpool)) + ( + None + if selectedSpool is None + else Transformer.transformSpoolModelToDict(selectedSpool) + ) for selectedSpool in self.loadSelectedSpools() ] - return flask.jsonify({ - # "databaseConnectionProblem": self._databaseManager.isConnected() == False, - "templateSpools": allTemplateSpoolsAsDict, - "catalogs": catalogs, - "totalItemCount": totalItemCount, - "allSpools": allSpoolsAsDict, - "selectedSpools": selectedSpoolsAsDicts - }) + return flask.jsonify( + { + # "databaseConnectionProblem": self._databaseManager.isConnected() == False, + "templateSpools": allTemplateSpoolsAsDict, + "catalogs": catalogs, + "totalItemCount": totalItemCount, + "allSpools": allSpoolsAsDict, + "selectedSpools": selectedSpoolsAsDicts, + } + ) def _addAdditionalMaterials(self, databaseMaterials): - allMeterials = [ "PLA", "PLA_plus", @@ -944,14 +1174,15 @@ def _addAdditionalMaterials(self, databaseMaterials): "PP", "POM", "PMMA", - "FPE" + "FPE", ] for currentMaterial in allMeterials: - if ( (currentMaterial.upper() in databaseMaterials) == False and (currentMaterial.lower() in databaseMaterials) == False): + if (currentMaterial.upper() in databaseMaterials) == False and ( + currentMaterial.lower() in databaseMaterials + ) == False: databaseMaterials.append(currentMaterial) return databaseMaterials - ####################################################################################################### SAVE SPOOL @octoprint.plugin.BlueprintPlugin.route("/saveSpool", methods=["PUT"]) def saveSpool(self): @@ -960,11 +1191,17 @@ def saveSpool(self): databaseId = self._getValueFromJSONOrNone("databaseId", jsonData) self._databaseManager.connectoToDatabase() - if (databaseId != None): - self._logger.info("Load spool for update with database id '"+str(databaseId)+"'") - spoolModel = self._databaseManager.loadSpool(databaseId, withReusedConnection=True) - if (spoolModel == None): - self._logger.warning("Save spool failed. Inital loading not possible, maybe already deleted.") + if databaseId != None: + self._logger.info( + "Load spool for update with database id '" + str(databaseId) + "'" + ) + spoolModel = self._databaseManager.loadSpool( + databaseId, withReusedConnection=True + ) + if spoolModel == None: + self._logger.warning( + "Save spool failed. Inital loading not possible, maybe already deleted." + ) else: self._updateSpoolModelFromJSONData(spoolModel, jsonData) else: @@ -972,17 +1209,19 @@ def saveSpool(self): spoolModel = SpoolModel() self._updateSpoolModelFromJSONData(spoolModel, jsonData) - newDatabaseId = self._databaseManager.saveSpool(spoolModel, withReusedConnection=True) + newDatabaseId = self._databaseManager.saveSpool( + spoolModel, withReusedConnection=True + ) self._databaseManager.closeDatabase() - if (databaseId == None): + if databaseId == None: # New spool was created eventPayload = { "databaseId": spoolModel.databaseId, "spoolName": spoolModel.displayName, "material": spoolModel.material, "colorName": spoolModel.colorName, - "remainingWeight": spoolModel.remainingWeight + "remainingWeight": spoolModel.remainingWeight, } self._sendPayload2EventBus(EventBusKeys.EVENT_BUS_SPOOL_ADDED, eventPayload) @@ -991,18 +1230,17 @@ def saveSpool(self): return flask.jsonify() - ##################################################################################################### DELETE SPOOL - @octoprint.plugin.BlueprintPlugin.route("/deleteSpool/", methods=["DELETE"]) + @octoprint.plugin.BlueprintPlugin.route( + "/deleteSpool/", methods=["DELETE"] + ) def deleteSpool(self, databaseId): self._logger.info("API Delete spool with database id '" + str(databaseId) + "'") databaseId = self._databaseManager.deleteSpool(databaseId) - if (databaseId != None): - eventPayload = { - "databaseId": databaseId - } - self._sendPayload2EventBus(EventBusKeys.EVENT_BUS_SPOOL_DELETED, eventPayload) + if databaseId != None: + eventPayload = {"databaseId": databaseId} + self._sendPayload2EventBus( + EventBusKeys.EVENT_BUS_SPOOL_DELETED, eventPayload + ) return flask.jsonify() - - diff --git a/octoprint_SpoolManager/templates/SpoolManager_dialog_editSpool.jinja2 b/octoprint_SpoolManager/templates/SpoolManager_dialog_editSpool.jinja2 index 90db1d9..9108d48 100644 --- a/octoprint_SpoolManager/templates/SpoolManager_dialog_editSpool.jinja2 +++ b/octoprint_SpoolManager/templates/SpoolManager_dialog_editSpool.jinja2 @@ -261,10 +261,13 @@ -
+