Skip to content

Commit

Permalink
Merge pull request #53 from jukebox42/mk4-nav
Browse files Browse the repository at this point in the history
Improve detection for the Prusa version
  • Loading branch information
jukebox42 authored Sep 8, 2024
2 parents c4534ed + 2473ed3 commit 2ccbab7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 97 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ events and printer notifications, so it can update the navbar: (`gcode_received_
"Awaiting user input" until the next tool change.
1. If the Prusa printer prompts the user for a "new version", the select filament modal may not
display. You will still be able to select the filament directly on the printer.
1. `MK3` printers will look like `MK3S` in the debug logs. They operate the same, this was easier
to implement.

## Developer Zone

Expand Down Expand Up @@ -391,6 +393,9 @@ Examples:
I built this plugin for fun, and because I wanted better MMU support. If you catch a bug or think it
needs some work feel free to open a PR or cut an issue, and I'll do my best to review it.

You know how some software grows organically and by the time you realize it's gotten out of control
it's too late? Yeah that's this. Sorry in advance for those of you trying to parse the code.

Special thanks to:
- [@skellied](https://github.com/skellied) for help with the initial release of MMU 3.0.0 support.
- [@Kevman323](https://github.com/Kevman323) for a significant revamp of the MMU 3.0.0 code,
Expand Down
101 changes: 49 additions & 52 deletions octoprint_prusammu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from octoprint_prusammu.common.PluginEventKeys import PluginEventKeys
from octoprint_prusammu.common.SettingsKeys import SettingsKeys
from octoprint_prusammu.common.StateKeys import StateKeys, DEFAULT_STATE
from octoprint_prusammu.common.GcodeProfile import DETECT_MMU, is_pause_line
from octoprint_prusammu.common.PrusaProfile import PrusaProfile, detect_connection_profile


Expand All @@ -37,9 +36,6 @@ class PrusaMMUPlugin(octoprint.plugin.StartupPlugin,
octoprint.plugin.SettingsPlugin):

def __init__(self):
# If the printer reports having an mmu (Only used with MK3.5+)
self.printerHasMmu = False

# Used for MK4 to retain the override.
self.filamentOverride = None

Expand Down Expand Up @@ -171,7 +167,10 @@ def _done_prompt(self, command, tags=set()):
self.states[StateKeys.SELECTED_FILAMENT] = command

# MK4: Enable filament rewrite
if self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3:
if (
self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3 and
self.mmu[MmuKeys.PRUSA_VERSION] is not None
):
self._enable_mk4_remap(command)

self._clean_up_prompt()
Expand Down Expand Up @@ -215,14 +214,20 @@ def _update_navbar(self):
# https://docs.octoprint.org/en/master/plugins/hooks.html#firmware_info_hook

def firmware_info_hook(self, comm_instance, firmware_name, firmware_data, *args, **kwargs):
self._process_firmware(firmware_data["MACHINE_TYPE"])

def _process_firmware(self, machine_type):
# Figure out what Prusa version we are dealing with (defaults to MK3)
self.mmu[MmuKeys.PRUSA_VERSION] = detect_connection_profile(firmware_data["MACHINE_TYPE"])
self._log("firmware_info_hook: {}".format(self.mmu[MmuKeys.PRUSA_VERSION]),
obj=firmware_data, debug=True)
version = detect_connection_profile(machine_type)
self._log("firmware_info_hook: {}".format(version), obj=machine_type, debug=True)

# MK4: The MMU doesn't tell us it's ok so if the printer has one assume it is.
if self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3 and self.printerHasMmu:
self._fire_event(PluginEventKeys.MMU_CHANGE, dict(state=MmuStates.OK))
if self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3:
self._fire_event(PluginEventKeys.MMU_CHANGE, dict(state=MmuStates.OK, prusaVersion=version))
return

# MK3: Just send the version so it's there. This probably already happened but let's go.
self._fire_event(PluginEventKeys.MMU_CHANGE, dict(prusaVersion=version))

# ======== Gcode Hooks ========
# https://docs.octoprint.org/en/master/plugins/hooks.html#octoprint-comm-protocol-gcode-phase
Expand Down Expand Up @@ -259,7 +264,10 @@ def gcode_queuing_hook(self, comm, phase, cmd, cmd_type, gcode,
# MK4 Blocker
# This blocks non-MK3s from proceeding. For MK4 support see above.
# ========
if self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3:
if (
self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3 and
self.mmu[MmuKeys.PRUSA_VERSION] is not None
):
return # passthrough

if cmd.startswith("M1600"):
Expand All @@ -269,7 +277,7 @@ def gcode_queuing_hook(self, comm, phase, cmd, cmd_type, gcode,
if not cmd.startswith("Tx") and not cmd.startswith("M109 S"):
return # passthrough

if is_pause_line(cmd, self.mmu[MmuKeys.PRUSA_VERSION]):
if cmd.startswith("M109 S"):
self._log("gcode_queuing_hook_M109 command: {}".format(cmd), debug=True)
if self.states[StateKeys.SELECTED_FILAMENT] is not None:
tool_cmd = "T{}".format(self.states[StateKeys.SELECTED_FILAMENT])
Expand Down Expand Up @@ -360,48 +368,31 @@ def mk4_gcode_received(self, line):
return

# Loaded, clear previous tool
if (
MMU3MK4Commands.ACTION_DONE in line and
self.lastMmuAction == MmuStates.LOADING
):
if MMU3MK4Commands.ACTION_DONE in line and self.lastMmuAction == MmuStates.LOADING:
self._fire_event(PluginEventKeys.MMU_CHANGE,
dict(state=MmuStates.LOADED, previousTool="",
dict(state=MmuStates.LOADED, previousTool="", tool=self.mmu[MmuKeys.TOOL],
response=MMU3ResponseCodes.FINISHED, responseData="2"))
self.lastMmuAction = MmuStates.LOADED
return

# Unloading
# Unloading (changing tool)
if MMU3MK4Commands.UNLOADING in line:
self._fire_event(PluginEventKeys.MMU_CHANGE,
dict(state=MmuStates.UNLOADING, response=MMU3ResponseCodes.PROCESSING,
responseData="3"))
self.lastMmuAction = MmuStates.UNLOADING
return

# Unloading Final
# Unloading Final (print done)
if MMU3MK4Commands.UNLOADING_FINAL in line:
self._fire_event(PluginEventKeys.MMU_CHANGE,
dict(state=MmuStates.UNLOADING, response=MMU3ResponseCodes.PROCESSING,
responseData="3"))
self.lastMmuAction = MmuStates.UNLOADING_FINAL
return

# Unloaded
if (
MMU3MK4Commands.ACTION_DONE in line and
self.lastMmuAction == MmuStates.UNLOADING
):
self._fire_event(PluginEventKeys.MMU_CHANGE,
dict(state=MmuStates.OK, response=MMU3ResponseCodes.FINISHED,
responseData="2"))
self.lastMmuAction = MmuStates.OK
return

# Unloaded Final
if (
MMU3MK4Commands.ACTION_DONE in line and
self.lastMmuAction == MmuStates.UNLOADING_FINAL
):
if MMU3MK4Commands.ACTION_DONE in line and self.lastMmuAction == MmuStates.UNLOADING_FINAL:
self._fire_event(PluginEventKeys.MMU_CHANGE,
dict(state=MmuStates.OK, response=MMU3ResponseCodes.FINISHED,
responseData="2"))
Expand Down Expand Up @@ -551,26 +542,26 @@ def mk3_gcode_received(self, line):

# Listen for MMU events and update the nav to reflect it
def gcode_received_hook(self, comm, line, *args, **kwargs):
# Detect if we have an MMU. This gets sent BEFORE the firmware info is sent.
if self.mmu[MmuKeys.PRUSA_VERSION] is None and not self.printerHasMmu and line.startswith(DETECT_MMU):
self.printerHasMmu = True
self._log("gcode_received_hook MMU: {}".format(line), debug=True)
# For the MK4, just say it's ok since we don't get an OK anymore.
self._fire_event(PluginEventKeys.MMU_CHANGE, dict(state=MmuStates.OK))
# Another Firmware check in case the actual one fails.
if self.mmu[MmuKeys.PRUSA_VERSION] is None and line.startswith("FIRMWARE_NAME"):
self._log("gcode_received_hook FIRMWARE_NAME: {}".format(line), debug=True)
self._process_firmware(line)
return line

# Until we have a version there's no point in trying to parse
if self.mmu[MmuKeys.PRUSA_VERSION] is None:
return line

# MK3.5/3.9/4
if self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3:
if (
self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3 and
self.mmu[MmuKeys.PRUSA_VERSION] is not None
):
self.mk4_gcode_received(line)
return line

# MK3
self.mk3_gcode_received(line)

return line

def gcode_sent_hook(self, comm, phase, cmd, cmd_type, gcode,
Expand All @@ -594,6 +585,8 @@ def gcode_sent_hook(self, comm, phase, cmd, cmd_type, gcode,

# Store the tool value on the tool. We're about to get a loading call.
self.mmu[MmuKeys.TOOL] = tool
self._log("gcode_sent_hook Tool:{} Prev:{}".format(tool, self.mmu[MmuKeys.PREV_TOOL]),
debug=True)
except:
pass

Expand Down Expand Up @@ -662,20 +655,24 @@ def on_event(self, event, payload=None):
self._show_prompt()
return

if (
event == Events.PRINT_STARTED and self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3 and
self.config[SettingsKeys.ENABLE_PROMPT]
):
if event == Events.PRINT_STARTED:
self._log("on_event {}".format(event), debug=True)
self._show_prompt()
if not self._printer.set_job_on_hold(True):
self._log("PAUSE FAILED?", debug=True)
return
# If we start a print and version is empty then set it to MK3
if self.mmu[MmuKeys.PRUSA_VERSION] is None:
self.mmu[MmuKeys.PRUSA_VERSION] = PrusaProfile.MK3

if (
self.mmu[MmuKeys.PRUSA_VERSION] != PrusaProfile.MK3 and
self.config[SettingsKeys.ENABLE_PROMPT]
):
self._show_prompt()
if not self._printer.set_job_on_hold(True):
self._log("PAUSE FAILED?", debug=True)
return

# Handle disconnected event to set the mmu to Not Found (no printer...)
if event == Events.DISCONNECTED:
self._log("on_event {}".format(event), debug=True)
self.printerHasMmu = False
self._disable_mk4_remap()
self._fire_event(PluginEventKeys.MMU_CHANGE, DEFAULT_MMU_STATE.copy())
return
Expand Down
40 changes: 0 additions & 40 deletions octoprint_prusammu/common/GcodeProfile.py

This file was deleted.

11 changes: 6 additions & 5 deletions octoprint_prusammu/common/PrusaProfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

# The command sent on connection to tell us what type of printer we have
class MachineType():
MK3="Prusa i3 MK3S"
MK3_5="Prusa-MK3.5"
MK3_9="Prusa-MK3.9"
MK4="Prusa-MK4"
MK3="MK3S"
MK3_5="MK3.5"
MK3_9="MK3.9"
MK4="MK4"
MK4S="MK4S"

# Print Profile (or the profile of the printer in the gcode)
class PrusaProfile():
Expand All @@ -22,7 +23,7 @@ def detect_connection_profile(machine_type):
return PrusaProfile.MK3_5
if MachineType.MK3_9 in machine_type:
return PrusaProfile.MK3_9
if MachineType.MK4 in machine_type:
if MachineType.MK4S in machine_type or MachineType.MK4 in machine_type:
return PrusaProfile.MK4
# Fallback to the MK3
return PrusaProfile.MK3
29 changes: 29 additions & 0 deletions test/mmuTestStrings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,32 @@ Note: Make sure you don't send the *XX at the end of lines. Virtual printer lose
===== MK3.5/3.9/4 & MMU 2: 3.0.0 =====
======================================

# Set tool
T0

# Start Loading
!!DEBUG:send MMU2:Feeding to FINDA

# Loading extruder
!!DEBUG:send MMU2:Feeding to extruder

# Loading to tool sensor
!!DEBUG:send MMU2:Feeding to FSensor

# Loading done (after it sees one of the loadings)
!!DEBUG:send MMU2:Disengaging idler

# Send a new tool (for the change below)
T1

# Changing tools (unloading)
!!DEBUG:send MMU2:Unloading to FINDA

# Unloading done (after it sees unloading, send loading after this)
!!DEBUG:send MMU2:Disengaging idler

# Unloading (final unload)
!!DEBUG:send MMU2:Retract from FINDA

# Unloading done (after it sees one of the unloading)
!!DEBUG:send MMU2:Disengaging idler

0 comments on commit 2ccbab7

Please sign in to comment.