Skip to content

Commit

Permalink
Merge pull request #43 from NilsRo/Development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
NilsRo authored Aug 28, 2022
2 parents 48c714e + 7c3eddf commit de86182
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 133 deletions.
15 changes: 8 additions & 7 deletions octoprint_SlicerEstimator/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def on_after_startup(self):
self._update_settings_from_config()
self._cleanup_uninstalled_plugins()

# self.on_settings_migrate(3,1)
# Example for API calls
# helpers = self._plugin_manager.get_helpers("SlicerEstimator",
# "register_plugin",
Expand Down Expand Up @@ -87,13 +88,16 @@ def get_settings_defaults(self):


def get_settings_version(self):
return 2
return 3


def on_settings_migrate(self, target, current):
self._logger.info("SlicerEstimator: Updating Metadata from files...")
metadata_handler = SlicerEstimatorMetadata("local", self._file_manager)
metadata_handler.update_metadata_in_files()

if current is not None:
self._logger.info("SlicerEstimator: Setting migration from version {} to {}".format(current, target))
self._update_metadata_in_files()

if current < 2:
# Move settings to a dynamic dict to support other plugins
Expand Down Expand Up @@ -127,9 +131,6 @@ def get_template_configs(self):

# SECTION: Settings helper
def _update_settings_from_config(self):
self._slicer_conf = self._settings.get(["slicer"])
self._logger.debug("SlicerEstimator: Slicer Setting {}".format(self._slicer_conf))

self._average_prio = self._settings.get(["average_prio"])
self._metadata_list = self._settings.get(["metadata_list"])
self._useDevChannel = self._settings.get(["useDevChannel"])
Expand Down Expand Up @@ -173,7 +174,7 @@ def on_gcode_sent(self, comm_instance, phase, cmd, cmd_type, gcode, *args, **kwa
def on_file_upload(self, path, file_object, links=None, printer_profile=None, allow_overwrite=True, *args, **kwargs):
if not octoprint.filemanager.valid_file_type(path, type="gcode"):
return file_object
filedata = SlicerEstimatorFiledata(path, file_object, self._file_manager)
filedata = SlicerEstimatorFiledata(path, file_object, self)
self._filedata[path] = filedata
return octoprint.filemanager.util.StreamWrapper(file_object.filename, filedata)

Expand Down Expand Up @@ -363,7 +364,7 @@ def get_metadata_file(self, plugin_identifier, target, origin, path):
if target in self._plugins[plugin_identifier]["targets"].keys():
return_list = []
meta_selected = filter(lambda elem: elem["targets"][plugin_identifier][target] == True, self._metadata_list)
additional_metadata = self._file_manager._storage_managers[origin].get_additional_metadata(path, "slicer")
additional_metadata = self._file_manager._storage_managers[origin].get_additional_metadata(path, "slicer_metadata")
if additional_metadata:
for meta_item in meta_selected:
if meta_item["id"] in additional_metadata:
Expand Down
3 changes: 2 additions & 1 deletion octoprint_SlicerEstimator/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
# Slicers
SLICER_PRUSA = "1"
SLICER_CURA = "2"
SLICER_SIMPLIFY3D = "3"
SLICER_SIMPLIFY3D = "3"
SLICER_SUPERSLICER = "4"
66 changes: 37 additions & 29 deletions octoprint_SlicerEstimator/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,15 @@


class SlicerEstimatorMetadata:
def __init__(self, origin, path, file_manager):
def __init__(self, origin, file_manager):
self._origin = origin
self._path = path
self._file_manager = file_manager


# search for material data
def update_metadata(self):
filament = SlicerEstimatorMetadata.find_metadata(self._file_manager.path_on_disk(self._origin, self._path))
self._file_manager._storage_managers[self._origin].set_additional_metadata(self._path, "slicer", filament, overwrite=True)
self._logger.debug(self._file_manager._storage_managers[self._origin].get_additional_metadata(self._path,"slicer"))
def update_metadata(self, path):
metadata = SlicerEstimatorMetadata.find_metadata(self._file_manager.path_on_disk(self._origin, path))
self._file_manager._storage_managers[self._origin].set_additional_metadata(path, "slicer_metadata", metadata, overwrite=True)


def find_metadata(path_on_disk):
Expand All @@ -40,9 +38,9 @@ def find_metadata(path_on_disk):
return filament


# Update all metadata in files
def update_metadata_in_files(file_manager):
results = file_manager._storage_managers["local"].list_files(recursive=True)
# Update metadata in all files
def update_metadata_in_files(self):
results = self._file_manager._storage_managers[self._origin].list_files(recursive=True)
filelist = dict()
if results is not None:
for resultKey in results:
Expand All @@ -51,14 +49,13 @@ def update_metadata_in_files(file_manager):
if results[resultKey]["type"] == "folder":
SlicerEstimatorFileHandling.flatten_files(results[resultKey], filelist)
for path in filelist:
file_manager._storage_managers["local"].remove_additional_metadata(path, "slicer")
metadata = SlicerEstimatorMetadata("local", path, file_manager)
metadata.update_metadata()
self._file_manager._storage_managers[self._origin].remove_additional_metadata(path, "slicer")
self.update_metadata(path)



class SlicerEstimatorFiledata(octoprint.filemanager.util.LineProcessorStream):
def __init__(self, path, file_object, file_manager):
def __init__(self, path, file_object, plugin):
super().__init__(file_object.stream())
self._logger = logging.getLogger("octoprint.plugins.SlicerEstimator")
self.path = path
Expand All @@ -69,8 +66,8 @@ def __init__(self, path, file_object, file_manager):
self._bytes_processed = 0
self._time_list = list()
self._change_list = list() # format GCODE, Time, Progress in file
self._filament = dict()
self._file_manager = file_manager
self._metadata = dict()
self._plugin = plugin


# Line parsing after upload
Expand All @@ -93,21 +90,22 @@ def process_line(self, line):
self._change_list.append([decoded_line[:2], None, self._line_cnt, self._bytes_processed])
elif decoded_line[:13] == ";Slicer info:":
slicer_info = decoded_line[13:].rstrip("\n").split(";")
self._filament[slicer_info[0]] = slicer_info[1].strip()
self._metadata[slicer_info[0]] = slicer_info[1].strip()
elif self.slicer == SLICER_CURA:
if decoded_line[:6] == ";TIME:":
self.printtime = float(line[6:])
if decoded_line[:13] == ";TIME_ELAPSED":
self._time_list.append([self._line_cnt, self.printtime - float(decoded_line[14:])])
return(("@TIME_LEFT " + str(self.printtime - float(decoded_line[14:])) + "\r\n").encode() + line)
elif self.slicer == SLICER_PRUSA:
elif self.slicer == SLICER_PRUSA or self.slicer == SLICER_SUPERSLICER:
if decoded_line[:4] == "M73 ":
re_result = self._regex.match(decoded_line)
if re_result:
# first remaining time is the overall printtime
if self.printtime == -1.0:
self.printtime = float(re_result[2])*60
self._time_list.append([self._line_cnt, float(re_result[2])*60])
return(("@TIME_LEFT " + str(float(re_result[2])*60) + "\r\n").encode() + line)
elif self.slicer == SLICER_SIMPLIFY3D:
re_result = self._regex.match(decoded_line)
if re_result:
Expand All @@ -118,7 +116,7 @@ def process_line(self, line):

# slicer auto selection
def _detect_slicer(self):
line = SlicerEstimatorFileHandling.search_in_file_regex(self._file_object.path,".*(PrusaSlicer|Simplify3D|Cura_SteamEngine).*")
line = SlicerEstimatorFileHandling.search_in_file_regex(self._file_object.path,".*(PrusaSlicer|SuperSlicer|Simplify3D|Cura_SteamEngine).*")
if line:
if "Cura_SteamEngine" in line:
self._logger.info("Detected Cura")
Expand All @@ -127,6 +125,10 @@ def _detect_slicer(self):
self._logger.info("Detected PrusaSlicer")
self._regex = re.compile("M73 P([0-9]+) R([0-9]+).*")
return SLICER_PRUSA
elif "SuperSlicer" in line:
self._logger.info("Detected SuperSlicer")
self._regex = re.compile("M73 P([0-9]+) R([0-9]+).*")
return SLICER_SUPERSLICER
elif "Simplify3D" in line:
self._logger.info("Detected Simplify3D")
self._regex = re.compile("; Build time: ([0-9]+) hours? ([0-9]+) minutes")
Expand All @@ -137,18 +139,24 @@ def _detect_slicer(self):

#Save gathered information to OctoPrint file metadata
def store_metadata(self):
self._file_manager._storage_managers["local"].set_additional_metadata(self.path, "slicer", self._filament, overwrite=True)
self._logger.debug(self._file_manager._storage_managers["local"].get_additional_metadata(self.path,"slicer"))
self._file_manager._storage_managers["local"].set_additional_metadata(self.path, "slicer_filament_change", self._change_list, overwrite=True)
self._logger.debug(self._file_manager._storage_managers["local"].get_additional_metadata(self.path,"slicer_filament_change"))
self._plugin._file_manager._storage_managers["local"].set_additional_metadata(self.path, "slicer_metadata", self._metadata, overwrite=True)
self._logger.debug(self._plugin._file_manager._storage_managers["local"].get_additional_metadata(self.path,"slicer_metadata"))
self._plugin._file_manager._storage_managers["local"].set_additional_metadata(self.path, "slicer_filament_change", self._change_list, overwrite=True)
self._logger.debug(self._plugin._file_manager._storage_managers["local"].get_additional_metadata(self.path,"slicer_filament_change"))

slicer_additional = dict()
slicer_additional["printtime"] = self.printtime
slicer_additional["lines"] = self._line_cnt
slicer_additional["bytes"] = self._bytes_processed
slicer_additional["slicer"] = self.slicer
self._file_manager._storage_managers["local"].set_additional_metadata(self.path, "slicer_additional", slicer_additional, overwrite=True)
self._logger.debug(self._file_manager._storage_managers["local"].get_additional_metadata(self.path,"slicer_additional"))
if self.slicer:
if self.printtime == -1.0:
self._plugin._sendNotificationToClient("no_timecodes_found")
else:
slicer_additional = dict()
slicer_additional["printtime"] = self.printtime
slicer_additional["lines"] = self._line_cnt
slicer_additional["bytes"] = self._bytes_processed
slicer_additional["slicer"] = self.slicer
self._plugin._file_manager._storage_managers["local"].set_additional_metadata(self.path, "slicer_additional", slicer_additional, overwrite=True)
self._logger.debug(self._plugin._file_manager._storage_managers["local"].get_additional_metadata(self.path,"slicer_additional"))
else:
self._logger.debug("No slicer additional informations found in GCODE: {}".format(self.path))



Expand Down
39 changes: 23 additions & 16 deletions octoprint_SlicerEstimator/static/js/SlicerEstimator.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ $(function() {
}
return result;
};

self.filamentChangeTimeFormat = function(changeTime) {
let fmt = self.settingsViewModel.appearance_fuzzyTimes()
? formatFuzzyPrintTime
: formatDuration;
return fmt(changeTime);
};
};

// receive data from server
self.onDataUpdaterPluginMessage = function (plugin, data) {
Expand Down Expand Up @@ -64,10 +64,18 @@ $(function() {
hide: false
});
break;
case "no_timecodes_found":
new PNotify({
title: "Slicer Estimator",
text: gettext("No timecodes found. Please check if the remaining time feature in the slicer is active."),
type: "warning",
hide: false
});
break;
}
}
};


// --- Estimator

Expand Down Expand Up @@ -144,7 +152,7 @@ $(function() {

// Overwrite the enableAdditionalData function to handle available metadata
self.filesViewModel.slicerEnableAdditionalData = function(data) {
if (data.slicer != null && Object.keys(data.slicer).length > 0) {
if ((data.slicer_metadata != null && Object.keys(data.slicer_metadata).length > 0) || (data.slicer_filament_change != null && Object.keys(data.slicer_filament_change).length > 0)) {
return true;
} else {
return self.filesViewModel.originalEnableAdditionalData(data);
Expand All @@ -158,8 +166,8 @@ $(function() {
let return_value = "";

//custom metadata
if (data.slicer != null && Object.keys(data.slicer).length > 0) {
for (const [key, value] of Object.entries(data.slicer)) {
if (data.slicer_metadata != null && Object.keys(data.slicer_metadata).length > 0) {
for (const [key, value] of Object.entries(data.slicer_metadata)) {
meta = self.settingsViewModel.settings.plugins.SlicerEstimator.metadata_list().find(elem => elem.id() === key && elem.targets["SlicerEstimator"]["filelist"]() === true);
let description = "No description";
if (meta != null) {
Expand All @@ -177,9 +185,9 @@ $(function() {
let changeType;
if (value[0] == "M600") {
changeType = gettext("filament change (M600)");
} else {
} else {
changeType = gettext("filament") + " (" + gettext("tool") + " " + value[0].substring(1,2) +")";
}
}
return_value += cnt + ". " + changeType + ": " + changeTimeString +'<br>';
}
}
Expand Down Expand Up @@ -212,8 +220,8 @@ $(function() {
self.currentMetadataArr.removeAll();
if (typeof actualFile !== 'undefined') {
enabledMeta.forEach(function(data) {
if (actualFile.slicer != null && Object.keys(actualFile.slicer).length > 0) {
item = actualFile.slicer[data.id()];
if (actualFile.slicer_metadata != null && Object.keys(actualFile.slicer_metadata).length > 0) {
item = actualFile.slicer_metadata[data.id()];
if (item != null) {
let returnArr = [];
returnArr["description"] = data.description;
Expand All @@ -231,7 +239,7 @@ $(function() {
if (changeList != null) {
let cnt = 0
for (let item of changeList) {
let returnArr = [];
let returnArr = [];
let changeType;
let changeTime;
cnt += 1;
Expand All @@ -241,7 +249,7 @@ $(function() {
changeType = gettext("filament change (M600)");
} else {
changeType = gettext("filament") + " (" + gettext("tool") + " " + item[0].substring(1,2) +")";
}
}
returnArr["description"] = cnt + ". " + changeType;
if (item[1] != null) {
// SlicerEstimator based calculation - time
Expand All @@ -264,9 +272,9 @@ $(function() {
changeType = gettext("filament change (M600)");
} else {
changeType = gettext("filament") + " (" + gettext("tool") + " " + changeList[changeList.length - 1][0].substring(1,2) +")";
}
}
returnArr["description"] = gettext("up to") + " " + changeList.length + ". " + changeType;

if (item[1] != null) {
//SlicerEstimator based calculation - time
if (self.printerStateViewModel.printTimeLeft() === null) {
Expand Down Expand Up @@ -306,7 +314,6 @@ $(function() {

//reset metadata list in printerStateViewModel
self.removeMetadata = function() {
debugger
self.filamentChangeArr.removeAll();
self.currentMetadataArr.removeAll();
};
Expand Down Expand Up @@ -346,7 +353,7 @@ $(function() {
// Update available metadata from files in the settings
self.settingsViewModel.crawlMetadata = function() {
self.filesViewModel.filesOnlyList().forEach(function (data) {
Object.keys(data.slicer).forEach(function (slicerData) {
Object.keys(data.slicer_metadata).forEach(function (slicerData) {
if (self.settingsViewModel.settings.plugins.SlicerEstimator.metadata_list().find(elem => elem.id() === slicerData) == null) {
let targets = {};
for (plugin of self.getActivePlugins()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
<ul>
<li><b>Cura</b>: {{ _('With Cura native no changes have to be applied to Cura. The overall print time is read out of a comment in the GCODE. This will update continuously the remaining print time.') }}</li>
<li><b>Simply3D</b>: {{ _('With Simplify3D no changes has to be applied to Simplify3D. The overall print time is read out of a comment in the GCODE. For a correct estimation OctoPrints percentage done is used as there is only the overall print time available.') }}</li>
<li><b>PrusaSlicer</b>: {{ _('Remaining time is read out of M73 commands added by PrusaSlicer. This will update continuously the remaining print time.') }}</li>
<li><b>PrusaSlicer</b>: {{ _('Remaining time is read out of M73 commands. This will update continuously the remaining print time.') }}</li>
<li><b>SuperSlicer</b>: {{ _('Remaining time is read out of M73 commands. This will update continuously the remaining print time.') }}</li>
</ul>
<p>
{{ _('Additional support or a manual is available on <a href="https://github.com/NilsRo/OctoPrint-SlicerEstimator" target="_blank">Github</a>.') }}
Expand Down
Binary file not shown.
Loading

0 comments on commit de86182

Please sign in to comment.