From 58a2bc140897314aa020914406d683e8ee65226a Mon Sep 17 00:00:00 2001 From: moggieuk <32878385+moggieuk@users.noreply.github.com> Date: Mon, 10 Feb 2025 18:55:19 +0700 Subject: [PATCH 01/10] Added additional essential metdata for single extruder multi-material printing. This is critical to new Mainsail functionality to map tools to MMU spools when using Happy Hare (Klipper MMU driver) --- moonraker/components/file_manager/metadata.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index af48d7b08..26bf6bea3 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -193,6 +193,18 @@ def parse_filament_name(self) -> Optional[str]: def parse_filament_type(self) -> Optional[str]: return None + def parse_filament_color(self) -> Optional[str]: + return None + + def parse_extruder_color(self) -> Optional[str]: + return None + + def parse_filament_temp(self) -> Optional[str]: + return None + + def parse_referenced_tools(self) -> Optional[str]: + return None + def parse_estimated_time(self) -> Optional[float]: return None @@ -381,6 +393,18 @@ def parse_filament_name(self) -> Optional[str]: r";\sfilament_settings_id\s=\s(%S)", self.footer_data ) + def parse_filament_color(self) -> Optional[str]: + return regex_find_string(r"^;\s*filament_colour\s*=\s(%S)", self.footer_data) + + def parse_extruder_color(self) -> Optional[str]: + return regex_find_string(r"^;\s*extruder_colour\s*=\s(%S)", self.footer_data) + + def parse_filament_temp(self) -> Optional[str]: + return regex_find_string(r"^;\s*(nozzle_)?temperature\s*=\s(%S)", self.footer_data) + + def parse_referenced_tools(self) -> Optional[str]: + return regex_find_string(r"^;\s*referenced_tools\s*=\s(%S)", self.footer_data) + def parse_estimated_time(self) -> Optional[float]: time_match = re.search( r';\sestimated\sprinting\stime.*', self.footer_data) From c7f4bf44e35d5cde43d1bacd974d4f10e52d3e62 Mon Sep 17 00:00:00 2001 From: moggieuk <32878385+moggieuk@users.noreply.github.com> Date: Mon, 10 Feb 2025 19:09:25 +0700 Subject: [PATCH 02/10] Expanded SUPPORTED metadata tokens --- moonraker/components/file_manager/metadata.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index 26bf6bea3..072dd1bd9 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -964,6 +964,10 @@ def parse_first_layer_bed_temp(self) -> Optional[float]: 'chamber_temp', 'filament_name', 'filament_type', + 'filament_color', + 'extruder_color', + 'filament_temp', + 'referenced_tools', 'filament_total', 'filament_weight_total', 'thumbnails'] From ecb6191cd1a9e1d6f1157ff3de85aea83b60d113 Mon Sep 17 00:00:00 2001 From: Moggie Date: Mon, 10 Feb 2025 19:49:15 +0700 Subject: [PATCH 03/10] matched regex to moonraker style --- moonraker/components/file_manager/metadata.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index 072dd1bd9..63047a1bd 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -394,16 +394,16 @@ def parse_filament_name(self) -> Optional[str]: ) def parse_filament_color(self) -> Optional[str]: - return regex_find_string(r"^;\s*filament_colour\s*=\s(%S)", self.footer_data) + return regex_find_string(r";\sfilament_colour\s=\s(%S)", self.footer_data) def parse_extruder_color(self) -> Optional[str]: - return regex_find_string(r"^;\s*extruder_colour\s*=\s(%S)", self.footer_data) + return regex_find_string(r";\sextruder_colour\s=\s(%S)", self.footer_data) def parse_filament_temp(self) -> Optional[str]: - return regex_find_string(r"^;\s*(nozzle_)?temperature\s*=\s(%S)", self.footer_data) + return regex_find_string(r";\s(?:nozzle_)?temperature\s=\s(%S)", self.footer_data) def parse_referenced_tools(self) -> Optional[str]: - return regex_find_string(r"^;\s*referenced_tools\s*=\s(%S)", self.footer_data) + return regex_find_string(r";\sreferenced_tools\s=\s(%S)", self.footer_data) def parse_estimated_time(self) -> Optional[float]: time_match = re.search( From 2853912b1e8d488c0f579978fdce5cfb23450e3e Mon Sep 17 00:00:00 2001 From: Moggie Date: Mon, 10 Feb 2025 19:56:59 +0700 Subject: [PATCH 04/10] added additional single_extruder_multi_material metadata --- moonraker/components/file_manager/metadata.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index 63047a1bd..f8fbc778c 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -205,6 +205,9 @@ def parse_filament_temp(self) -> Optional[str]: def parse_referenced_tools(self) -> Optional[str]: return None + def parse_single_extruder_multi_material(self) -> Optional[int]: + return None + def parse_estimated_time(self) -> Optional[float]: return None @@ -405,6 +408,9 @@ def parse_filament_temp(self) -> Optional[str]: def parse_referenced_tools(self) -> Optional[str]: return regex_find_string(r";\sreferenced_tools\s=\s(%S)", self.footer_data) + def parse_single_extruder_multi_material(self) -> Optional[int]: + return regex_find_int(r";\ssingle_extruder_multi_material\s=\s(%D)", self.footer_data) + def parse_estimated_time(self) -> Optional[float]: time_match = re.search( r';\sestimated\sprinting\stime.*', self.footer_data) @@ -968,6 +974,7 @@ def parse_first_layer_bed_temp(self) -> Optional[float]: 'extruder_color', 'filament_temp', 'referenced_tools', + 'single_extruder_multi_material', 'filament_total', 'filament_weight_total', 'thumbnails'] From 8abc252ddb6a7f15f98459375291b57f1f47daa9 Mon Sep 17 00:00:00 2001 From: moggieuk <32878385+moggieuk@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:23:41 +0700 Subject: [PATCH 05/10] module: Added additional metadata to aid tool selection on single extruder multi-material prints The added metadata is ssential for single extruder multi-material printing. It is used in new Mainsail functionality to map tools to MMU spools when using Happy Hare (Klipper MMU driver) Signed-off-by: Paul Morgan (moggieuk@hotmail.com) --- moonraker/components/file_manager/metadata.py | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index af48d7b08..f8fbc778c 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -193,6 +193,21 @@ def parse_filament_name(self) -> Optional[str]: def parse_filament_type(self) -> Optional[str]: return None + def parse_filament_color(self) -> Optional[str]: + return None + + def parse_extruder_color(self) -> Optional[str]: + return None + + def parse_filament_temp(self) -> Optional[str]: + return None + + def parse_referenced_tools(self) -> Optional[str]: + return None + + def parse_single_extruder_multi_material(self) -> Optional[int]: + return None + def parse_estimated_time(self) -> Optional[float]: return None @@ -381,6 +396,21 @@ def parse_filament_name(self) -> Optional[str]: r";\sfilament_settings_id\s=\s(%S)", self.footer_data ) + def parse_filament_color(self) -> Optional[str]: + return regex_find_string(r";\sfilament_colour\s=\s(%S)", self.footer_data) + + def parse_extruder_color(self) -> Optional[str]: + return regex_find_string(r";\sextruder_colour\s=\s(%S)", self.footer_data) + + def parse_filament_temp(self) -> Optional[str]: + return regex_find_string(r";\s(?:nozzle_)?temperature\s=\s(%S)", self.footer_data) + + def parse_referenced_tools(self) -> Optional[str]: + return regex_find_string(r";\sreferenced_tools\s=\s(%S)", self.footer_data) + + def parse_single_extruder_multi_material(self) -> Optional[int]: + return regex_find_int(r";\ssingle_extruder_multi_material\s=\s(%D)", self.footer_data) + def parse_estimated_time(self) -> Optional[float]: time_match = re.search( r';\sestimated\sprinting\stime.*', self.footer_data) @@ -940,6 +970,11 @@ def parse_first_layer_bed_temp(self) -> Optional[float]: 'chamber_temp', 'filament_name', 'filament_type', + 'filament_color', + 'extruder_color', + 'filament_temp', + 'referenced_tools', + 'single_extruder_multi_material', 'filament_total', 'filament_weight_total', 'thumbnails'] From cf07e22b6a70a0a5aefda26562b8b4d87eef9663 Mon Sep 17 00:00:00 2001 From: moggieuk <32878385+moggieuk@users.noreply.github.com> Date: Mon, 17 Feb 2025 22:35:56 +0700 Subject: [PATCH 06/10] Shortened lines for linter check --- moonraker/components/file_manager/metadata.py | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index f8fbc778c..31ce9aab4 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -389,7 +389,9 @@ def parse_filament_weight_total(self) -> Optional[float]: ) def parse_filament_type(self) -> Optional[str]: - return regex_find_string(r";\sfilament_type\s=\s(%S)", self.footer_data) + return regex_find_string( + r";\sfilament_type\s=\s(%S)", self.footer_data + ) def parse_filament_name(self) -> Optional[str]: return regex_find_string( @@ -397,19 +399,29 @@ def parse_filament_name(self) -> Optional[str]: ) def parse_filament_color(self) -> Optional[str]: - return regex_find_string(r";\sfilament_colour\s=\s(%S)", self.footer_data) + return regex_find_string( + r";\sfilament_colour\s=\s(%S)", self.footer_data + ) def parse_extruder_color(self) -> Optional[str]: - return regex_find_string(r";\sextruder_colour\s=\s(%S)", self.footer_data) + return regex_find_string( + r";\sextruder_colour\s=\s(%S)", self.footer_data + ) def parse_filament_temp(self) -> Optional[str]: - return regex_find_string(r";\s(?:nozzle_)?temperature\s=\s(%S)", self.footer_data) + return regex_find_string( + r";\s(?:nozzle_)?temperature\s=\s(%S)", self.footer_data + ) def parse_referenced_tools(self) -> Optional[str]: - return regex_find_string(r";\sreferenced_tools\s=\s(%S)", self.footer_data) + return regex_find_string( + r";\sreferenced_tools\s=\s(%S)", self.footer_data + ) def parse_single_extruder_multi_material(self) -> Optional[int]: - return regex_find_int(r";\ssingle_extruder_multi_material\s=\s(%D)", self.footer_data) + return regex_find_int( + r";\ssingle_extruder_multi_material\s=\s(%D)", + self.footer_data) def parse_estimated_time(self) -> Optional[float]: time_match = re.search( From 18e1882f104b17fe7d7ad0306a04623bd8c14e90 Mon Sep 17 00:00:00 2001 From: moggieuk <32878385+moggieuk@users.noreply.github.com> Date: Thu, 20 Feb 2025 19:16:55 +0700 Subject: [PATCH 07/10] Added documentation for new file metadata variables --- docs/external_api/file_manager.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/external_api/file_manager.md b/docs/external_api/file_manager.md index 5b2df6d0f..f8a7d3ecd 100644 --- a/docs/external_api/file_manager.md +++ b/docs/external_api/file_manager.md @@ -253,7 +253,6 @@ GET /server/files/metadata?filename=tools/drill.gcode /// api-response-spec open: True - | Field | Type | Description | | ----------------------- | :------: | ------------------------------------------------------------ | | `size` | int | The gcode file size in bytes. | @@ -273,10 +272,15 @@ GET /server/files/metadata?filename=tools/drill.gcode | `first_layer_extr_temp` | float | The configured first layer extruder temperature, in Celsius. | | `first_layer_bed_temp` | float | The configured first layer bed temperature, in Celsius. | | `chamber_temp` | float | The configured chamber temperature, in Celsius. | -| `filament_name` | str | The name of the filament used. | -| `filament_type` | str | The type of filament used, ie: `PLA`. | +| `filament_name` | str | The name(s) of the filament used. | +| `filament_color` | str | The colors(s) of the filament used in #RRGGBB format. | +| `extruder_color` | str | The slicer defined extruder color(s) for the print. | +| `filament_temp` | str | The base temperature(s) of filament used, in Celsius. | +| `filament_type` | str | The type(s) of filament used, ie: `PLA`. | | `filament_total` | float | The total length filament used in mm. | | `filament_weight_total` | float | The total weight of filament used in grams. | +| `single_extruder_multi_material` | int | Identifies a multimaterial print with single extruder. | +| `referenced_tools` | string | Comma separated list of a tool numbers used in the print. | | `thumbnails` | [object] | A list of `Thumbnail Info` objects. | | | | #thumbnail-info-spec |+ | `job_id` | string? | The last `history` job ID associated with the gcode. | @@ -1211,4 +1215,4 @@ Not Available The body of the response contains the contents of `moonraker.log`. -/// \ No newline at end of file +/// From add4b9987834eb0b2b7fa3d0ac1ee0a0347691ed Mon Sep 17 00:00:00 2001 From: Moggie Date: Wed, 26 Feb 2025 17:20:29 +0700 Subject: [PATCH 08/10] Return new metadata as typed arrays. Updated api documentation to match --- docs/external_api/file_manager.md | 14 ++-- moonraker/components/file_manager/metadata.py | 70 ++++++++++++------- 2 files changed, 53 insertions(+), 31 deletions(-) diff --git a/docs/external_api/file_manager.md b/docs/external_api/file_manager.md index f8a7d3ecd..786cee0e4 100644 --- a/docs/external_api/file_manager.md +++ b/docs/external_api/file_manager.md @@ -272,15 +272,15 @@ GET /server/files/metadata?filename=tools/drill.gcode | `first_layer_extr_temp` | float | The configured first layer extruder temperature, in Celsius. | | `first_layer_bed_temp` | float | The configured first layer bed temperature, in Celsius. | | `chamber_temp` | float | The configured chamber temperature, in Celsius. | -| `filament_name` | str | The name(s) of the filament used. | -| `filament_color` | str | The colors(s) of the filament used in #RRGGBB format. | -| `extruder_color` | str | The slicer defined extruder color(s) for the print. | -| `filament_temp` | str | The base temperature(s) of filament used, in Celsius. | -| `filament_type` | str | The type(s) of filament used, ie: `PLA`. | +| `filament_name` | string | The name(s) of the filaments contained in print. | +| `filament_colors` | [string] | List of filament colors used in #RRGGBB format. | +| `extruder_colors` | [string] | List of slicer defined extruder colors for the print. | +| `filament_temps` | [int] | List of base temperatures for filaments, in Celsius. | +| `filament_type` | string | The type(s) of filament used, ie: `PLA`. | | `filament_total` | float | The total length filament used in mm. | | `filament_weight_total` | float | The total weight of filament used in grams. | -| `single_extruder_multi_material` | int | Identifies a multimaterial print with single extruder. | -| `referenced_tools` | string | Comma separated list of a tool numbers used in the print. | +| `mmu_print` | int | Identifies a multimaterial print with single extruder. | +| `referenced_tools` | [int] | List of tool numbers used in the print. | | `thumbnails` | [object] | A list of `Thumbnail Info` objects. | | | | #thumbnail-info-spec |+ | `job_id` | string? | The last `history` job ID associated with the gcode. | diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index 31ce9aab4..6c110246a 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -67,6 +67,15 @@ def regex_find_ints(pattern: str, data: str) -> List[int]: pass return [] +def regex_find_strings(pattern: str, separators: str, data: str) -> List[str]: + pattern = pattern.replace(r"(%S)", r"(.*)") + separators = re.escape(separators) + delimiters = rf"[{separators}]" + match = re.search(pattern, data) + if match and match.group(1): + return re.split(delimiters, match.group(1).strip('"')) + return [] + def regex_find_float(pattern: str, data: str) -> Optional[float]: pattern = pattern.replace(r"(%F)", r"([0-9]*\.?[0-9]+)") match = re.search(pattern, data) @@ -193,19 +202,19 @@ def parse_filament_name(self) -> Optional[str]: def parse_filament_type(self) -> Optional[str]: return None - def parse_filament_color(self) -> Optional[str]: + def parse_filament_colors(self) -> Optional[List[str]]: return None - def parse_extruder_color(self) -> Optional[str]: + def parse_extruder_colors(self) -> Optional[List[str]]: return None - def parse_filament_temp(self) -> Optional[str]: + def parse_filament_temps(self) -> Optional[List[int]]: return None - def parse_referenced_tools(self) -> Optional[str]: + def parse_referenced_tools(self) -> Optional[List[str]]: return None - def parse_single_extruder_multi_material(self) -> Optional[int]: + def parse_mmu_print(self) -> Optional[int]: return None def parse_estimated_time(self) -> Optional[float]: @@ -393,35 +402,48 @@ def parse_filament_type(self) -> Optional[str]: r";\sfilament_type\s=\s(%S)", self.footer_data ) + def parse_filament_type(self) -> Optional[str]: + return regex_find_string( + r";\sfilament_type\s=\s(%S)", self.footer_data + ) + def parse_filament_name(self) -> Optional[str]: return regex_find_string( r";\sfilament_settings_id\s=\s(%S)", self.footer_data ) - def parse_filament_color(self) -> Optional[str]: - return regex_find_string( - r";\sfilament_colour\s=\s(%S)", self.footer_data + def parse_filament_colors(self) -> Optional[List[str]]: + return regex_find_strings( + r";\sfilament_colour\s=\s(%S)", ",;", self.footer_data ) - def parse_extruder_color(self) -> Optional[str]: - return regex_find_string( - r";\sextruder_colour\s=\s(%S)", self.footer_data + def parse_extruder_colors(self) -> Optional[List[str]]: + return regex_find_strings( + r";\sextruder_colour\s=\s(%S)", ",;", self.footer_data ) - def parse_filament_temp(self) -> Optional[str]: - return regex_find_string( - r";\s(?:nozzle_)?temperature\s=\s(%S)", self.footer_data + def parse_filament_temps(self) -> Optional[List[int]]: + temps = regex_find_strings( + r";\s(?:nozzle_)?temperature\s=\s(%S)", ",;", self.footer_data ) + try: + return [int(t) for t in temps] + except ValueError: + return None - def parse_referenced_tools(self) -> Optional[str]: - return regex_find_string( - r";\sreferenced_tools\s=\s(%S)", self.footer_data + def parse_referenced_tools(self) -> Optional[List[str]]: + tools = regex_find_strings( + r";\sreferenced_tools\s=\s(%S)", ",;", self.footer_data ) + try: + return [int(t) for t in tools] + except ValueError: + return None - def parse_single_extruder_multi_material(self) -> Optional[int]: + def parse_mmu_print(self) -> Optional[int]: return regex_find_int( - r";\ssingle_extruder_multi_material\s=\s(%D)", - self.footer_data) + r";\ssingle_extruder_multi_material\s=\s(%D)", self.footer_data + ) def parse_estimated_time(self) -> Optional[float]: time_match = re.search( @@ -982,11 +1004,11 @@ def parse_first_layer_bed_temp(self) -> Optional[float]: 'chamber_temp', 'filament_name', 'filament_type', - 'filament_color', - 'extruder_color', - 'filament_temp', + 'filament_colors', + 'extruder_colors', + 'filament_temps', 'referenced_tools', - 'single_extruder_multi_material', + 'mmu_print', 'filament_total', 'filament_weight_total', 'thumbnails'] From f9974077ab55eca503cdf8f1c9f5b9e0ed94d261 Mon Sep 17 00:00:00 2001 From: Moggie Date: Wed, 26 Feb 2025 21:25:04 +0700 Subject: [PATCH 09/10] Removed duplicate method --- moonraker/components/file_manager/metadata.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index 4a3774b31..c7167c765 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -409,11 +409,6 @@ def parse_filament_type(self) -> Optional[str]: r";\sfilament_type\s=\s(%S)", self.footer_data ) - def parse_filament_type(self) -> Optional[str]: - return regex_find_string( - r";\sfilament_type\s=\s(%S)", self.footer_data - ) - def parse_filament_name(self) -> Optional[str]: return regex_find_string( r";\sfilament_settings_id\s=\s(%S)", self.footer_data From 8eec1376e137fa13df6bc25f35577764405fa314 Mon Sep 17 00:00:00 2001 From: Moggie Date: Wed, 26 Feb 2025 21:31:35 +0700 Subject: [PATCH 10/10] fixed type --- moonraker/components/file_manager/metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moonraker/components/file_manager/metadata.py b/moonraker/components/file_manager/metadata.py index c7167c765..04b1288e7 100644 --- a/moonraker/components/file_manager/metadata.py +++ b/moonraker/components/file_manager/metadata.py @@ -222,7 +222,7 @@ def parse_extruder_colors(self) -> Optional[List[str]]: def parse_filament_temps(self) -> Optional[List[int]]: return None - def parse_referenced_tools(self) -> Optional[List[str]]: + def parse_referenced_tools(self) -> Optional[List[int]]: return None def parse_mmu_print(self) -> Optional[int]: @@ -433,7 +433,7 @@ def parse_filament_temps(self) -> Optional[List[int]]: except ValueError: return None - def parse_referenced_tools(self) -> Optional[List[str]]: + def parse_referenced_tools(self) -> Optional[List[int]]: tools = regex_find_strings( r";\sreferenced_tools\s=\s(%S)", ",;", self.footer_data )