diff --git a/README.md b/README.md index 86c31b3..ea04772 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ or manually by selecting the latest zip: - Displays an error popup when the MMU throws an error (Only when running 3.0.0+) - Supports retrieving filament data from [Spool Manager](https://plugins.octoprint.org/plugins/SpoolManager/) and [Filament Manager](https://plugins.octoprint.org/plugins/filamentmanager/) if installed. +- Allows remapping of tools to other tools. ## Screenshots @@ -45,6 +46,8 @@ The command interactions are as follows: - `M109`: When the GCODE would send an `M109` (Wait for Hotend Temperature) and the user has selected a filament it sends both the `M109` and `T#` (like `T2`), otherwise it just sends the `M109`. + - `T#`: If the filament remap is enabled it will intercept a `T#` command and alter the number to + match the one provided in settings. - After sent: (gcode_sent_hook) - When the plugin notices a `T#` command it sets the tool internally, so it can be used to display. This is to support multicolor printing. This trigger is also used to show unloading. @@ -53,12 +56,12 @@ The command interactions are as follows: It listens to printer responses and does some substring matching. This is done to identify filament events and printer notifications, so it can update the navbar: (gcode_received_hook) - - `paused for user` - Used to show that the printer needs attention (either error or waiting for - tool selection at printer). - - `MMU not responding` - Used to show that the printer needs attention because of an MMU failure. - - `MMU - ENABLED` / `MMU starts responding` - Used to show printer is "OK". - - `MMU can_load` / `Unloading finished` - Used to show the filament loading message. - - `OO succeeded` - Used to show what filament is loaded. +- `paused for user` - Used to show that the printer needs attention (either error or waiting for + tool selection at printer). +- `MMU not responding` - Used to show that the printer needs attention because of an MMU failure. +- `MMU - ENABLED` / `MMU starts responding` - Used to show printer is "OK". +- `MMU can_load` / `Unloading finished` - Used to show the filament loading message. +- `OO succeeded` - Used to show what filament is loaded. ### MMU2/3 3.X.X @@ -66,28 +69,28 @@ The MMU 3.X.X firmware communicates continuously with the printer. The printer s requests, and the MMU sends back responses. The MMU's responses start with the request letter and data, so it just listens for the Responses. -MMU 3.X.X responses come in this format: +MMU 3.X.X responses come in this format: `MMU2:<(Request Letter)(Request Data) (Response Letter)(Response Data)` - - `(Request Letter)` - A single letter code that represents a request sent from the printer to the MMU. - - It only listens for `T` - Tool, `L` - Load, `U` - Unload, `X` - Reset, `K` - Cut, and `E` - Eject. - - `(Request Data)` - Hexidecimal data that follows the Request Letter. - - It's usually `0`, unless the request involves filament, in which case it is the filament number `[0-4]`. - - `(Response Letter)` - A single letter code that represents a response from the MMU. - - Possible responses are `P` - Processing, `E` - Error, `F` - Finished, `A` - Accepted, - `R` - Rejected, and `B` - Button. - - `(Response Data)` - Hexidecimal data that follows the Response Letter. - - The amount of data varies depending on the Request Letter and Response Letter. - - We only use Response Data to decode `P` - Progress messages, and `E` - Error messages +- `(Request Letter)` - A single letter code that represents a request sent from the printer to the MMU. + - It only listens for `T` - Tool, `L` - Load, `U` - Unload, `X` - Reset, `K` - Cut, and `E` - Eject. +- `(Request Data)` - Hexidecimal data that follows the Request Letter. + - It's usually `0`, unless the request involves filament, in which case it is the filament number `[0-4]`. +- `(Response Letter)` - A single letter code that represents a response from the MMU. + - Possible responses are `P` - Processing, `E` - Error, `F` - Finished, `A` - Accepted, + `R` - Rejected, and `B` - Button. +- `(Response Data)` - Hexidecimal data that follows the Response Letter. + - The amount of data varies depending on the Request Letter and Response Letter. + - We only use Response Data to decode `P` - Progress messages, and `E` - Error messages Several Regex strings are used to parse the MMU 3.X.X responses: - - `MMU2:<[TLUXKE]` - Generic Regex used to catch the responses with the Request Letters that are important. - - `MMU2:<([TLUXKE])(.*) ([PEFARB])(.*)\*` - Used to split the command into the four groups described above. +- `MMU2:<[TLUXKE]` - Generic Regex used to catch the responses with the Request Letters that are important. +- `MMU2:<([TLUXKE])(.*) ([PEFARB])(.*)\*` - Used to split the command into the four groups described above. Additionally, it also listens for these lines: - - `MMU2:Saving and parking` - Used to detect when the printer is waiting for user input after the - MMU fails at auto-retrying after an Error. - - `MMU2:Heater cooldown pending` - The same as above. Might be unnecessary, but included just in case. - - `LCD status changed` - If the printer was paused, this indicates that the pause is probably over. +- `MMU2:Saving and parking` - Used to detect when the printer is waiting for user input after the + MMU fails at auto-retrying after an Error. +- `MMU2:Heater cooldown pending` - The same as above. Might be unnecessary, but included just in case. +- `LCD status changed` - If the printer was paused, this indicates that the pause is probably over. For all instances where command manipulation happens see `__init__.py` for `Gcode Hooks`. Also look at function `_timeout_prompt` where it handles unpausing the printer after the timer and either @@ -255,14 +258,14 @@ If you too would like to add your filament/spool manager as a valid source for t to update the following areas: - `__init__.py` - - Update `on_after_startup()` to detect your plugin. + - Update `on_after_startup()` to detect your plugin. - `templates/prusammu_settings.jinja2` - - Add a link to your plugin in the helptext of `Filament Label Source`. - - Add an `alert` box identifying how filament is set in your plugin. + - Add a link to your plugin in the helptext of `Filament Label Source`. + - Add an `alert` box identifying how filament is set in your plugin. - `static/prusammu.js` - - Set your plugin as a dependency AND optional for `PrusaMMU2ViewModel` (bottom of file) - - Add your plugin in the `self.filamentSources` object. - - Update the `getFilamentList()` function to call your filament/spool function. This will require + - Set your plugin as a dependency AND optional for `PrusaMMU2ViewModel` (bottom of file) + - Add your plugin in the `self.filamentSources` object. + - Update the `getFilamentList()` function to call your filament/spool function. This will require your plugin to expose a javascript function the returns a list of filament and what tool they represent. diff --git a/octoprint_prusammu/__init__.py b/octoprint_prusammu/__init__.py index f6669d5..ec5f8bc 100644 --- a/octoprint_prusammu/__init__.py +++ b/octoprint_prusammu/__init__.py @@ -22,8 +22,8 @@ TIMEOUT_TAG = "{}timeout".format(TAG_PREFIX) FILAMENT_SOURCE_DEFAULT = [ dict(name="Prusa MMU", id=PLUGIN_NAME), - # dict(name="GCode", id="gcode"), ] +TOOL_REGEX = r"^T(\d)" class PrusaMMUPlugin(octoprint.plugin.StartupPlugin, @@ -49,6 +49,8 @@ def __init__(self): defaultFilament=-1, filamentSource=PLUGIN_NAME, filamentSources=[], + filamentMap=[], + useFilamentMap=False, ) # ======== Startup ======== @@ -175,6 +177,17 @@ def _update_navbar(self): def gcode_queuing_hook(self, comm, phase, cmd, cmd_type, gcode, subcode=None, tags=None, *args, **kwarg): + # handle tool remap if enabled + if self.config[SettingsKeys.USE_FILAMENT_MAP] and search(TOOL_REGEX, cmd): + try: + tool = int(search(TOOL_REGEX, cmd).group(1)) + new_tool = int(self.config[SettingsKeys.FILAMENT_MAP][tool]["id"]) + self._log("gcode_queuing_hook_T# command: {} -> T{}".format(cmd, new_tool), debug=True) + return [("T{}".format(new_tool),),] + except Exception as e: + self._log("gcode_queuing_hook_T# ERROR command: {}, {}".format(cmd, str(e)), debug=True) + return #passthrough + # only react to tool change commands and ignore everything if they dont want the dialog if not cmd.startswith("Tx") and not cmd.startswith("M109"): return # passthrough @@ -370,7 +383,7 @@ def gcode_sent_hook(self, comm, phase, cmd, cmd_type, gcode, # Catch when the gcode sends a tool number, this happens when it's set to print in multi try: - x = search(r"T(\d)", cmd) + x = search(TOOL_REGEX, cmd) tool = x.group(1) # This indicates the tool was already loaded and we tried to load it again. The printer should @@ -494,13 +507,8 @@ def get_settings_defaults(self): dict(name="", color="", enabled=True, id=4), dict(name="", color="", enabled=True, id=5), ], - gcodeFilament=[ - dict(name="", color="", id=1), - dict(name="", color="", id=2), - dict(name="", color="", id=3), - dict(name="", color="", id=4), - dict(name="", color="", id=5), - ], + filamentMap=[dict(id=0), dict(id=1), dict(id=2), dict(id=3), dict(id=4)], + useFilamentMap=False, ) def on_settings_save(self, data): @@ -515,11 +523,6 @@ def on_settings_save(self, data): except: data[SettingsKeys.TIMEOUT] = DEFAULT_TIMEOUT - # Always remember gcode filament, we dont care if it's stale it'll be refreshed on load - # TODO: load this data on print load or something. i dunno good luck. - if SettingsKeys.GCODE_FILAMENT not in data: - data[SettingsKeys.GCODE_FILAMENT] = self._settings.get([SettingsKeys.GCODE_FILAMENT]) - self._log("on_settings_save", debug=True) # save settings @@ -543,6 +546,9 @@ def _refresh_config(self): SettingsKeys.DISPLAY_ACTIVE_FILAMENT]) self.config[SettingsKeys.FILAMENT_SOURCE] = self._settings.get([SettingsKeys.FILAMENT_SOURCE]) self.config[SettingsKeys.FILAMENT_SOURCES] = self._settings.get([SettingsKeys.FILAMENT_SOURCES]) + self.config[SettingsKeys.USE_FILAMENT_MAP] = self._settings.get_boolean([ + SettingsKeys.USE_FILAMENT_MAP]) + self.config[SettingsKeys.FILAMENT_MAP] = self._settings.get([SettingsKeys.FILAMENT_MAP]) # ======== SoftwareUpdatePlugin ======== # https://docs.octoprint.org/en/master/bundledplugins/softwareupdate.html diff --git a/octoprint_prusammu/common/SettingsKeys.py b/octoprint_prusammu/common/SettingsKeys.py index ea11949..9a38ece 100644 --- a/octoprint_prusammu/common/SettingsKeys.py +++ b/octoprint_prusammu/common/SettingsKeys.py @@ -13,4 +13,5 @@ class SettingsKeys(): FILAMENT_SOURCE="filamentSource" FILAMENT_SOURCES="filamentSources" FILAMENT="filament" - GCODE_FILAMENT="gcodeFilament" \ No newline at end of file + FILAMENT_MAP="filamentMap" + USE_FILAMENT_MAP="useFilamentMap" \ No newline at end of file diff --git a/octoprint_prusammu/static/prusammu.js b/octoprint_prusammu/static/prusammu.js index ee9a5d2..ccef0be 100644 --- a/octoprint_prusammu/static/prusammu.js +++ b/octoprint_prusammu/static/prusammu.js @@ -379,7 +379,7 @@ $(() => { title: `Prusa MMU: ${mmuError.title} (#${mmuError.code})`, text: `

${mmuError.text}

` + `

${mmuError.url}

`, - type: "warning", + type: "error", hide: false, }); }; @@ -585,18 +585,6 @@ $(() => { } catch(e) { console.error("Create a github issue with the following:", "prusammu Error: getFilament SpoolManager failed.", e); } - } else if (self.settings.filamentSource() === "gcode") { - filament = self.settings.gcodeFilament().map(f => { - return { - enabled: true, - id: parseInt(f.id(), 10), - index: parseInt(f.id(), 10) - 1, - name: f.name(), - type: "", - color: f.color(), - }; - }); - log("getFilament gcode", filament); } // Catchall if we got zero back, default to showing something. diff --git a/octoprint_prusammu/templates/prusammu_settings.jinja2 b/octoprint_prusammu/templates/prusammu_settings.jinja2 index 6bf6ae9..13bc933 100644 --- a/octoprint_prusammu/templates/prusammu_settings.jinja2 +++ b/octoprint_prusammu/templates/prusammu_settings.jinja2 @@ -1,7 +1,7 @@

{{ _("Prusa MMU") }}

-

TITLE (#CODE)

+

TITLE (#CODE)

URL

@@ -36,10 +36,6 @@

Filament Manager:
{{ _("To manage filament use the Filament Manager section in the left sidebar.") }}

{{ _("Note: FilamentManager does not support color so no color will be shown.") }}

- -
-

GCode:
{{ _("Filament names and colors will be extracted from the print file when available.") }}

-
@@ -137,14 +133,14 @@ {{ _("Advanced options") }} -
+

{{ _("Advanced") }}

@@ -153,7 +149,7 @@ {{ _("Index at zero") }} - {{ _("Check to have the filament numbers be 0-4 instead of 1-5. Plugins like Spool Manager as well as the actual gcode refrence them as 0-4.") }} + {{ _("Check to have the filament numbers be 0-4 instead of 1-5. Plugins like Spool Manager as well as the actual GCode refrence them as 0-4.") }}
@@ -167,6 +163,53 @@
+
+
+ + {{ _("Check to have prusammu intercept tool commands and change the tool ID to the mapped one.") }} +
+
+ +
+
+
+
+

IMPORTANT: READ BEFORE USING

+

This feature will ONLY tell the MMU what filament to load when it sees a specific T# command. It WILL NOT make temperature decisions, the printer will follow the temperatures defined in the GCode of the print regardless of what filament is being loaded. Make sure you are always replacing the filament with the same type (like PLA -> PLA, PETG -> PETG, etc) as defined in the GCode. So don't take a GCode sliced for PLA filament and map it to a tool using PETG, it will use the temperature for the PLA! This setting is only used on GCode sliced in multi mode and will be ignored for single mode prints.

+ +

Use at your own risk.

+
+
+
+
+
+
+
+ +
+ +
+
+
+
+
+
+