Skip to content

Commit fa45d54

Browse files
committed
Add klipper service restart button
1 parent 1827962 commit fa45d54

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

octoprint_moonraker_connector/__init__.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from urllib.parse import urljoin
44

55
import requests
6+
import subprocess
67
from flask import jsonify
78
from flask_babel import gettext
89

@@ -93,6 +94,22 @@ def on_api_get(self, request):
9394
)
9495
return jsonify(response.model_dump(by_alias=True))
9596

97+
def get_api_commands(self):
98+
return dict(
99+
restart_klipper_service=[]
100+
)
101+
102+
def on_api_command(self, command, data):
103+
if command == "restart_klipper_service":
104+
self._logger.info(f"Command '{command}' received")
105+
if hasattr(self, "_client") and self._client.is_connected():
106+
self._client.restart_klipper_service(self)
107+
108+
return jsonify(success=True, message="Restart sent")
109+
else:
110+
self._logger.warning("Moonraker client not connected.")
111+
return jsonify(success=False, message="Moonraker client not connected.")
112+
96113
def is_api_protected(self):
97114
return True
98115

octoprint_moonraker_connector/client.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -621,6 +621,17 @@ def on_printer_objects_subscribed(future: Future) -> None:
621621

622622
##~~ Method calls & callbacks
623623

624+
def restart_klipper_service(self) -> Future:
625+
def on_result(future: Future) -> None:
626+
try:
627+
results = future.result()
628+
except Exception as e:
629+
self._logger.exception(f"Error while restarting klipper service: {e}")
630+
631+
self.call_method("machine.service.restart", {"service": "klipper"}).add_done_callback(
632+
on_result
633+
)
634+
624635
def query_printer_objects(self, objs: list[str] = None) -> Future:
625636
if objs is None:
626637
objs = self._subbed_objs

octoprint_moonraker_connector/static/js/moonraker_connector.js

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,30 @@ $(function () {
1515
OctoPrint.control.sendGcode('FIRMWARE_RESTART');
1616
}
1717

18+
self.btnKlipperRestartClick = function() {
19+
showConfirmationDialog({
20+
message: gettext("<strong>This will restart the Klipper service.</strong></p><p>This might disrupt any ongoing operations related to Klipper."),
21+
onproceed: function() {
22+
OctoPrint.simpleApiCommand(
23+
"moonraker_connector",
24+
"restart_klipper_service"
25+
).done(function(response) {
26+
new PNotify({
27+
title: gettext("Success"),
28+
text: gettext("System command sent: ") + response.command,
29+
type: "success"
30+
});
31+
}).fail(function(jqXHR, textStatus, errorThrown) {
32+
new PNotify({
33+
title: gettext("Error"),
34+
text: gettext("Failed to execute command: ") + jqXHR.responseJSON.message,
35+
type: "error"
36+
});
37+
});
38+
}
39+
});
40+
}
41+
1842
self.initializeButton = function() {
1943
var buttonContainer = $('#job_print')[0].parentElement;
2044
var container = document.createElement("div");
@@ -24,39 +48,66 @@ $(function () {
2448

2549
var btnRestart = document.createElement("button");
2650
btnRestart.id = "job_restart";
27-
btnRestart.title = "Reload configuration file and performs an internal reset of the host software. It does not clear the error state from the micro-controller.";
51+
btnRestart.title = gettext("Reload configuration file and performs an internal reset of the host software. It does not clear the error state from the micro-controller.");
2852
btnRestart.classList.add("btn");
2953
btnRestart.classList.add("span6");
3054
btnRestart.addEventListener("click", self.btnRestartClick);
3155

3256
var btnRestartIcon = document.createElement("i");
33-
btnRestartIcon.classList.add("fa", "fa-redo");
57+
btnRestartIcon.classList.add("fas", "fa-sync-alt");
58+
btnRestartIcon.style.marginRight = "5px";
3459
btnRestart.appendChild(btnRestartIcon);
3560

3661
var btnRestartText = document.createElement("span");
37-
btnRestartText.textContent = " Restart";
62+
btnRestartText.textContent = gettext("Restart");
3863
btnRestart.appendChild(btnRestartText);
3964

4065
container.appendChild(btnRestart);
4166

4267
var btnFirmwareRestart = document.createElement("button");
4368
btnFirmwareRestart.id = "job_firmware_restart";
44-
btnFirmwareRestart.title = "Reload configuration file and performs an internal reset of the host software, but it also clears any error states from the micro-controller.";
69+
btnFirmwareRestart.title = gettext("Reload configuration file and performs an internal reset of the host software, but it also clears any error states from the micro-controller.");
4570
btnFirmwareRestart.classList.add("btn");
4671
btnFirmwareRestart.classList.add("span6");
4772
btnFirmwareRestart.addEventListener("click", self.btnFirmwareRestartClick);
4873

4974
var btnFirmwareRestartIcon = document.createElement("i");
50-
btnFirmwareRestartIcon.classList.add("fa", "fa-sync");
75+
btnFirmwareRestartIcon.classList.add("fas", "fa-microchip");
76+
btnFirmwareRestartIcon.style.marginRight = "5px";
5177
btnFirmwareRestart.appendChild(btnFirmwareRestartIcon);
5278

5379
var btnFirmwareRestartText = document.createElement("span");
54-
btnFirmwareRestartText.textContent = " Firmware Restart";
80+
btnFirmwareRestartText.textContent = gettext("Firmware Restart");
5581
btnFirmwareRestart.appendChild(btnFirmwareRestartText);
5682

5783
container.appendChild(btnFirmwareRestart);
5884

5985
buttonContainer.after(container);
86+
87+
var container2 = document.createElement("div");
88+
container2.classList.add("row-fluid", "print-control");
89+
container2.style.marginTop = "10px";
90+
container2.setAttribute("data-bind", "visible: $root.loginState.hasPermissionKo($root.access.permissions.PRINT)");
91+
92+
var btnKlipperRestart = document.createElement("button");
93+
btnKlipperRestart.id = "job_klipper_restart";
94+
btnKlipperRestart.title = gettext("Restart klipper process.");
95+
btnKlipperRestart.classList.add("btn");
96+
btnKlipperRestart.classList.add("span12");
97+
btnKlipperRestart.addEventListener("click", self.btnKlipperRestartClick);
98+
99+
var btnKlipperRestartIcon = document.createElement("i");
100+
btnKlipperRestartIcon.classList.add("fas", "fa-power-off");
101+
btnKlipperRestartIcon.style.marginRight = "5px";
102+
btnKlipperRestart.appendChild(btnKlipperRestartIcon);
103+
104+
var btnKlipperRestartText = document.createElement("span");
105+
btnKlipperRestartText.textContent = gettext("Restart Klipper");
106+
btnKlipperRestart.appendChild(btnKlipperRestartText);
107+
108+
container2.appendChild(btnKlipperRestart);
109+
110+
container.after(container2);
60111
};
61112

62113
self.webcams = ko.observableArray([]);

0 commit comments

Comments
 (0)