diff --git a/docs/events/index.rst b/docs/events/index.rst
index b471193f..bc6f1245 100644
--- a/docs/events/index.rst
+++ b/docs/events/index.rst
@@ -477,6 +477,15 @@ PositionUpdate
* ``t``: last tool selected *through OctoPrint*
* ``f``: last feedrate for move commands ``G0``, ``G1`` or ``G28`` sent *through OctoPrint*
+ToolChange
+ A tool change command was sent to the printer. The payload contains the former current tool index and the
+ new current tool index.
+
+ Payload:
+
+ * ``old``: old tool index
+ * ``new``: new tool index
+
Timelapses
----------
diff --git a/src/octoprint/events.py b/src/octoprint/events.py
index c8630e59..78d5f0ab 100644
--- a/src/octoprint/events.py
+++ b/src/octoprint/events.py
@@ -84,6 +84,7 @@ class Events(object):
EJECT = "Eject"
E_STOP = "EStop"
POSITION_UPDATE = "PositionUpdate"
+ TOOL_CHANGE = "ToolChange"
REGISTERED_MESSAGE_RECEIVED = "RegisteredMessageReceived"
# Timelapse
diff --git a/src/octoprint/server/api/settings.py b/src/octoprint/server/api/settings.py
index a5230811..a30d9a45 100644
--- a/src/octoprint/server/api/settings.py
+++ b/src/octoprint/server/api/settings.py
@@ -184,6 +184,8 @@ def getSettings():
"afterPrintDone": None,
"beforePrintPaused": None,
"afterPrintResumed": None,
+ "beforeToolChange": None,
+ "afterToolChange": None,
"snippets": dict()
}
},
diff --git a/src/octoprint/static/js/app/viewmodels/settings.js b/src/octoprint/static/js/app/viewmodels/settings.js
index e481f38d..9f73fab2 100644
--- a/src/octoprint/static/js/app/viewmodels/settings.js
+++ b/src/octoprint/static/js/app/viewmodels/settings.js
@@ -185,6 +185,8 @@ $(function() {
self.scripts_gcode_beforePrintResumed = ko.observable(undefined);
self.scripts_gcode_afterPrinterConnected = ko.observable(undefined);
self.scripts_gcode_beforePrinterDisconnected = ko.observable(undefined);
+ self.scripts_gcode_afterToolChange = ko.observable(undefined);
+ self.scripts_gcode_beforeToolChange = ko.observable(undefined);
self.temperature_profiles = ko.observableArray(undefined);
self.temperature_cutoff = ko.observable(undefined);
diff --git a/src/octoprint/templates/dialogs/settings/gcodescripts.jinja2 b/src/octoprint/templates/dialogs/settings/gcodescripts.jinja2
index 6fc08268..4ed9268d 100644
--- a/src/octoprint/templates/dialogs/settings/gcodescripts.jinja2
+++ b/src/octoprint/templates/dialogs/settings/gcodescripts.jinja2
@@ -29,6 +29,18 @@
+
@@ -39,7 +51,7 @@
+ {{ _('This will only be executed when closing the connection actively. If the connection to the printer is suddenly lost nothing will be sent.') }}
-
{{ _('This will only be executed when closing the connection actively. If the connection to the printer is suddenly lost nothing will be sent.') }}
diff --git a/src/octoprint/util/comm.py b/src/octoprint/util/comm.py
index 02a5e054..088c5869 100644
--- a/src/octoprint/util/comm.py
+++ b/src/octoprint/util/comm.py
@@ -754,7 +754,7 @@ class MachineCom(object):
elif self.isOperational() or force:
return self._sendCommand(cmd, cmd_type=cmd_type, on_sent=on_sent)
- def sendGcodeScript(self, scriptName, replacements=None):
+ def _getGcodeScript(self, scriptName, replacements=None):
context = dict()
if replacements is not None and isinstance(replacements, dict):
context.update(replacements)
@@ -776,13 +776,7 @@ class MachineCom(object):
if template is None:
scriptLines = []
else:
- scriptLines = filter(
- lambda x: x is not None and x.strip() != "",
- map(
- lambda x: process_gcode_line(x, offsets=self._tempOffsets, current_tool=self._currentTool),
- template.split("\n")
- )
- )
+ scriptLines = template.split("\n")
for hook in self._gcodescript_hooks:
try:
@@ -812,6 +806,13 @@ class MachineCom(object):
if suffix:
scriptLines += list(suffix)
+ return filter(lambda x: x is not None and x.strip() != "",
+ map(lambda x: process_gcode_line(x, offsets=self._tempOffsets, current_tool=self._currentTool),
+ scriptLines))
+
+
+ def sendGcodeScript(self, scriptName, replacements=None):
+ scriptLines = self._getGcodeScript(scriptName, replacements=replacements)
for line in scriptLines:
self.sendCommand(line)
return "\n".join(scriptLines)
@@ -2443,10 +2444,23 @@ class MachineCom(object):
##~~ command handlers
+ def _gcode_T_queuing(self, cmd, cmd_type=None):
+ toolMatch = regexes_parameters["intT"].search(cmd)
+ if toolMatch:
+ current_tool = self._currentTool
+ new_tool = int(toolMatch.group("value"))
+
+ before = self._getGcodeScript("beforeToolChange", replacements=dict(tool=dict(old=current_tool, new=new_tool)))
+ after = self._getGcodeScript("afterToolChange", replacements=dict(tool=dict(old=current_tool, new=new_tool)))
+
+ return before + [cmd] + after
+
def _gcode_T_sent(self, cmd, cmd_type=None):
toolMatch = regexes_parameters["intT"].search(cmd)
if toolMatch:
+ old = self._currentTool
self._currentTool = int(toolMatch.group("value"))
+ eventManager().fire(Events.TOOL_CHANGE, dict(old=old, new=self._currentTool))
def _gcode_G0_sent(self, cmd, cmd_type=None):
if "Z" in cmd or "F" in cmd: