Refactor message hooking
This commit is contained in:
@@ -22,7 +22,6 @@ class API(octoprint.plugin.SimpleApiPlugin):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def apiGateWay(self, command, data):
|
def apiGateWay(self, command, data):
|
||||||
self._logger.debug("api command [%s] received payload [%s]", command, data)
|
|
||||||
if command == CMD_ESTEPS_LOAD_STEPS:
|
if command == CMD_ESTEPS_LOAD_STEPS:
|
||||||
self._logger.debug("Load steps from EEPROM")
|
self._logger.debug("Load steps from EEPROM")
|
||||||
if not self._printer.is_ready():
|
if not self._printer.is_ready():
|
||||||
@@ -38,11 +37,11 @@ class API(octoprint.plugin.SimpleApiPlugin):
|
|||||||
# Issue M92 command
|
# Issue M92 command
|
||||||
self._printer.commands("M92")
|
self._printer.commands("M92")
|
||||||
|
|
||||||
m92Event.wait()
|
m92Event.wait(5)
|
||||||
|
|
||||||
return flask.jsonify({
|
return flask.jsonify({
|
||||||
"data": self.data["steps"]
|
"data": self.data["steps"]
|
||||||
})
|
})
|
||||||
|
|
||||||
if command == CMD_ESTEPS_START_EXTRUSION:
|
if command == CMD_ESTEPS_START_EXTRUSION:
|
||||||
self._logger.debug("Heating the extruder [%s]", data)
|
self._logger.debug("Heating the extruder [%s]", data)
|
||||||
if not self._printer.is_ready():
|
if not self._printer.is_ready():
|
||||||
@@ -53,10 +52,8 @@ class API(octoprint.plugin.SimpleApiPlugin):
|
|||||||
|
|
||||||
# Register event to be trigger when temp is achieved
|
# Register event to be trigger when temp is achieved
|
||||||
self.registerEventTemp("T0", int(data["extrudeTemp"]), self.startExtrusion, data["extrudeLength"], data["extrudeSpeed"])
|
self.registerEventTemp("T0", int(data["extrudeTemp"]), self.startExtrusion, data["extrudeLength"], data["extrudeSpeed"])
|
||||||
|
|
||||||
# Heating the tool
|
# Heating the tool
|
||||||
self._printer.commands("M104 S%(extrudeTemp)s" % data)
|
self._printer.commands("M104 S%(extrudeTemp)s" % data)
|
||||||
return
|
|
||||||
|
|
||||||
if command == CMD_ESTEPS_SAVE:
|
if command == CMD_ESTEPS_SAVE:
|
||||||
eStepsSettings = self._settings.get(['eSteps'])
|
eStepsSettings = self._settings.get(['eSteps'])
|
||||||
|
|||||||
@@ -8,17 +8,51 @@ import flask
|
|||||||
import octoprint.plugin
|
import octoprint.plugin
|
||||||
|
|
||||||
CMD_PID_SAVE = "pid_save"
|
CMD_PID_SAVE = "pid_save"
|
||||||
|
CMD_PID_START = "pid_start"
|
||||||
|
|
||||||
|
regexPID = "Kp:\s*(?P<P>\d{1,3}.\d{1,3})\s*Ki:\s*(?P<I>\d{1,3}.\d{1,3})\s*Kd:\s*(?P<D>\d{1,3}.\d{1,3})"
|
||||||
|
regexGetPid = "\s*Kp:\s*(?P<p>\d{1,3}.\d{1,3})\s*Ki:\s*(?P<i>\d{1,3}.\d{1,3})\s*Kd:\s*(?P<d>\d{1,3}.\d{1,3})"
|
||||||
|
PIDStarted = "PID Autotune start"
|
||||||
|
PIDStoped = "PID Autotune finished!"
|
||||||
|
PIDStopedP = "#define DEFAULT_Kp\s*(?P<P>\d{1,3}.\d{1,3})"
|
||||||
|
PIDStopedI = "#define DEFAULT_Ki\s*(?P<I>\d{1,3}.\d{1,3})"
|
||||||
|
PIDStopedD = "#define DEFAULT_Kd\s*(?P<D>\d{1,3}.\d{1,3})"
|
||||||
|
regexFinished = "PID Autotune finished!.*\n#define DEFAULT_Kp\s*(?P<P>\d{1,3}.\d{1,3}).*\n#define DEFAULT_Ki\s*(?P<I>\d{1,3}.\d{1,3})\n#define DEFAULT_Kd\s*(?P<D>\d{1,3}.\d{1,3})"
|
||||||
class API(octoprint.plugin.SimpleApiPlugin):
|
class API(octoprint.plugin.SimpleApiPlugin):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def apiCommands():
|
def apiCommands():
|
||||||
return {
|
return {
|
||||||
CMD_PID_SAVE : ["fanSpeed", "noCycles" "hotEndIndex", "targetTemp"]
|
CMD_PID_SAVE : [],
|
||||||
|
CMD_PID_START: ["fanSpeed", "noCycles", "hotEndIndex", "targetTemp"]
|
||||||
}
|
}
|
||||||
|
|
||||||
def apiGateWay(self, command, data):
|
def apiGateWay(self, command, data):
|
||||||
self._logger.debug("DIPGateway")
|
self._logger.debug("DIPGateway")
|
||||||
|
if command == CMD_PID_START:
|
||||||
|
self.pidCycles = []
|
||||||
|
|
||||||
|
for i in range(0,data['noCycles']):
|
||||||
|
self.registerRegexMsg(regexGetPid, self.m106CodeResponse)
|
||||||
|
|
||||||
|
self._printer.commands(["M106 S%(fanSpeed)s" % data, "M303 C%(noCycles)s E%(hotEndIndex)s S%(targetTemp)s U1" % data])
|
||||||
|
self._logger.debug("cycles %s", self.pidCycles)
|
||||||
|
|
||||||
if command == CMD_PID_SAVE:
|
if command == CMD_PID_SAVE:
|
||||||
self._logger.debug("DIPSave-")
|
self._logger.debug("DIPSave-")
|
||||||
|
return flask.jsonify({
|
||||||
|
"data": self.pidCycles
|
||||||
|
})
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def m106CodeResponse(self, line):
|
||||||
|
self._logger.debug("m106CodeResponse: %s", line)
|
||||||
|
# isM106Response = re.compile(regexFinished).match(line)
|
||||||
|
# if isM106Response:
|
||||||
|
# p = isM106Response.group("P")
|
||||||
|
# i = isM106Response.group("I")
|
||||||
|
# d = isM106Response.group("D")
|
||||||
|
# self._logger.debug("P:%s, I:%s, d:%d", p, i, d)
|
||||||
|
# self._logger.debug("line: %s", line)
|
||||||
|
self.pidCycles.append(line)
|
||||||
|
self._logger.debug("cycles %s", self.pidCycles)
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import traceback
|
||||||
|
from ast import Try
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
|
|
||||||
from octoprint_CalibrationTools import EStepsApi, PIDAutoTune
|
from octoprint_CalibrationTools import EStepsApi, PIDAutoTune
|
||||||
@@ -33,7 +36,13 @@ class API(EStepsApi.API, PIDAutoTune.API):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def on_api_command(self, command, data):
|
def on_api_command(self, command, data):
|
||||||
|
try:
|
||||||
self._logger.debug("API command [%s] received payload [%s]", command, data)
|
self._logger.debug("API command [%s] received payload [%s]", command, data)
|
||||||
for key, api in self.commandsRegistration.items():
|
for key, api in self.commandsRegistration.items():
|
||||||
if command in api["commands"]:
|
if command in api["commands"]:
|
||||||
return api["cls"].apiGateWay(self, command, data)
|
return api["cls"].apiGateWay(self, command, data)
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error(traceback.format_exc())
|
||||||
|
return flask.abort(500, {
|
||||||
|
"msg": "An error curred"
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
from ast import arg
|
|
||||||
|
|
||||||
|
import collections
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import types
|
import types
|
||||||
import collections
|
|
||||||
|
|
||||||
|
|
||||||
class Hooks():
|
class Hooks():
|
||||||
@@ -15,20 +14,26 @@ class Hooks():
|
|||||||
gCodeWaiters = []
|
gCodeWaiters = []
|
||||||
|
|
||||||
def gCodeReceived(self, comm, line, *args, **kwargs):
|
def gCodeReceived(self, comm, line, *args, **kwargs):
|
||||||
if len(self.gCodeWaiters) <= 0 and not line.startswith('echo:'):
|
try:
|
||||||
|
if len(self.gCodeWaiters) <= 0:
|
||||||
return line
|
return line
|
||||||
|
|
||||||
reg = re.compile("echo:\s*(?P<gCode>M\d{1,4})")
|
|
||||||
mCommand = reg.match(line)
|
|
||||||
if mCommand:
|
|
||||||
gCode = mCommand.group("gCode")
|
|
||||||
for waiter in self.gCodeWaiters:
|
for waiter in self.gCodeWaiters:
|
||||||
if gCode.upper() == waiter["cmd"]:
|
reg = waiter["regex"]
|
||||||
arg = (line, *waiter["args"])
|
waiter["callCount"] = waiter["callCount"] + 1
|
||||||
|
if reg.match(line):
|
||||||
|
args = (line, *waiter["args"])
|
||||||
if isinstance(waiter["func"], types.FunctionType):
|
if isinstance(waiter["func"], types.FunctionType):
|
||||||
arg = (self, *arg)
|
args = (self, *args)
|
||||||
threading.Thread(target=waiter["func"], args=arg).start()
|
threading.Thread(target=waiter["func"], args=args).start()
|
||||||
self.gCodeWaiters.remove(waiter)
|
waiter["dead"] = True
|
||||||
|
break
|
||||||
|
if waiter["callCount"] >= 3:
|
||||||
|
self._logger.warning("Hanging thread: Removing waiter regex: %(regex)s" % waiter)
|
||||||
|
waiter["dead"] = True
|
||||||
|
self.gCodeWaiters = [w for w in self.gCodeWaiters if "dead" not in w or not w["dead"]]
|
||||||
|
except Exception as e:
|
||||||
|
self._logger.error(traceback.format_exc())
|
||||||
|
self.gCodeWaiters = []
|
||||||
return line
|
return line
|
||||||
|
|
||||||
def firmwareInfo(self, comm_instance, firmware_name, firmware_data, *args, **kwargs):
|
def firmwareInfo(self, comm_instance, firmware_name, firmware_data, *args, **kwargs):
|
||||||
@@ -79,11 +84,20 @@ class Hooks():
|
|||||||
|
|
||||||
# Registering a gCodeWaiter
|
# Registering a gCodeWaiter
|
||||||
def registerGCodeWaiter(self, command, func, *arguments):
|
def registerGCodeWaiter(self, command, func, *arguments):
|
||||||
if command is None or not re.compile("(?P<gCode>M\d{1,4})").match(command.upper()) or func is None or not isinstance(func, collections.Callable):
|
reg = re.compile(".*\s*(?P<gCode>[M,G]\d{1,4})")
|
||||||
self._logger.warn("registerGCodeAnswer: Attempt to register gCodeAnswer without a function or gCode command")
|
if command is None or not reg.match(command.upper()):
|
||||||
|
self._logger.warn("registerGCodeAnswer: Attempt to register gCodeAnswer without a function or valid gCode command")
|
||||||
return
|
return
|
||||||
|
self.registerRegexMsg(".*\s*(?P<gCode>[M,G]\d{1,4})", func, *arguments)
|
||||||
|
|
||||||
|
def registerRegexMsg(self, regex, func, *arguments):
|
||||||
|
if regex is None or func is None or not isinstance(func, collections.Callable):
|
||||||
|
self._logger.warn("registerRegexMsg: Attempt to register gCodeAnswer without a function or regex")
|
||||||
|
return
|
||||||
|
|
||||||
self.gCodeWaiters.append({
|
self.gCodeWaiters.append({
|
||||||
"cmd": command.upper(),
|
"regex": re.compile(regex),
|
||||||
"func": func,
|
"func": func,
|
||||||
"args": arguments
|
"args": arguments,
|
||||||
|
"callCount": 0
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,10 +3,11 @@ $(function () {
|
|||||||
var self = this;
|
var self = this;
|
||||||
self.loginStateViewModel = parameters[0];
|
self.loginStateViewModel = parameters[0];
|
||||||
self.settingsViewModel = parameters[1];
|
self.settingsViewModel = parameters[1];
|
||||||
|
self.controlViewModel = parameters[2];
|
||||||
|
|
||||||
self.bedCurrentTemp = ko.observable(0);
|
self.bedCurrentTemp = ko.observable(0);
|
||||||
self.bedCurrentTarget = ko.observable(0);
|
self.bedCurrentTarget = ko.observable(0);
|
||||||
self.is_admin = ko.observable(false);
|
self.isAdmin = ko.observable(false);
|
||||||
self.pid = {
|
self.pid = {
|
||||||
fanSpeed: ko.observable(255),
|
fanSpeed: ko.observable(255),
|
||||||
noCycles: ko.observable(5),
|
noCycles: ko.observable(5),
|
||||||
@@ -24,7 +25,30 @@ $(function () {
|
|||||||
self.pid.noCycles(self.settingsViewModel.settings.plugins.CalibrationTools.pid.noCycles());
|
self.pid.noCycles(self.settingsViewModel.settings.plugins.CalibrationTools.pid.noCycles());
|
||||||
self.pid.hotEndIndex(self.settingsViewModel.settings.plugins.CalibrationTools.pid.hotEndIndex());
|
self.pid.hotEndIndex(self.settingsViewModel.settings.plugins.CalibrationTools.pid.hotEndIndex());
|
||||||
self.pid.targetTemp(self.settingsViewModel.settings.plugins.CalibrationTools.pid.targetTemp());
|
self.pid.targetTemp(self.settingsViewModel.settings.plugins.CalibrationTools.pid.targetTemp());
|
||||||
self.is_admin(self.loginStateViewModel.isAdmin());
|
self.isAdmin(self.loginStateViewModel.isAdmin());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.startPidHotEnd = function () {
|
||||||
|
OctoPrint.simpleApiCommand("CalibrationTools", "pid_start", {
|
||||||
|
"fanSpeed": self.pid.fanSpeed(),
|
||||||
|
"noCycles": self.pid.noCycles(),
|
||||||
|
"hotEndIndex": self.pid.hotEndIndex(),
|
||||||
|
"targetTemp": self.pid.targetTemp()
|
||||||
|
}).done(function (response) {
|
||||||
|
new PNotify({
|
||||||
|
title: "PID HotEnd tuning has started",
|
||||||
|
text: "In progress",
|
||||||
|
type: "info"
|
||||||
|
});
|
||||||
|
console.log(response);
|
||||||
|
}).fail(function (response) {
|
||||||
|
new PNotify({
|
||||||
|
title: "Error on starting extrusion ",
|
||||||
|
text: response.responseJSON.error,
|
||||||
|
type: "error",
|
||||||
|
hide: false
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OCTOPRINT_VIEWMODELS.push({
|
OCTOPRINT_VIEWMODELS.push({
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||||
<div class="span6"></div>
|
<div class="span6"></div>
|
||||||
<div class="span6">
|
<div class="span6">
|
||||||
<button class="btn btn-success" data-bind="click: $root.startExtrusion, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
<button class="btn btn-success" data-bind="click: $root.startExtrusion, enable: $root.is_admin() && $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||||
title="This will trigger M90, M83, G1 E100 F50, M82, G90 in order for extruding filament">
|
title="This will trigger M90, M83, G1 E100 F50, M82, G90 in order for extruding filament">
|
||||||
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
||||||
Start extrusion
|
Start extrusion
|
||||||
@@ -82,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="span6">
|
<div class="span6">
|
||||||
<div class="input-prepend input-append">
|
<div class="input-prepend input-append">
|
||||||
{{ snipped.linkToMarlin("M92", "Marlin website") }}
|
{{ snipped.linkToMarlin("M092", "Marlin website") }}
|
||||||
<span class="add-on" title="Command to change number of steps/mm for E axe" data-bind="text: $root.results.newStepsDisplay"></span>
|
<span class="add-on" title="Command to change number of steps/mm for E axe" data-bind="text: $root.results.newStepsDisplay"></span>
|
||||||
{{ snipped.m500Icon() }}
|
{{ snipped.m500Icon() }}
|
||||||
</div>
|
</div>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||||
<div class="span6"></div>
|
<div class="span6"></div>
|
||||||
<div class="span6">
|
<div class="span6">
|
||||||
<button class="btn btn-primary" data-bind="click: $root.saveESteps, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
<button class="btn btn-primary" data-bind="click: $root.saveESteps, enable: $root.is_admin() && $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||||
title="Saves the new calculated value of steps/mm on printer EEPROM">
|
title="Saves the new calculated value of steps/mm on printer EEPROM">
|
||||||
<i class="fas fa-save" data-color="#000000"></i>  
|
<i class="fas fa-save" data-color="#000000"></i>  
|
||||||
Save the new value
|
Save the new value
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ Current bed temperature: <span data-bind="text: bedCurrentTemp"></span>° Be
|
|||||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||||
<div class="span5"></div>
|
<div class="span5"></div>
|
||||||
<div class="span7">
|
<div class="span7">
|
||||||
<button class="btn btn-success" data-bind="click: $root.pidHotEndTune, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
<button class="btn btn-success" data-bind="click: $root.startPidHotEnd, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())"
|
||||||
title="This will trigger PID auto tuning (M106 Sx; M303 Ex Sx U1; M500)">
|
title="This will trigger PID auto tuning (M106 Sx; M303 Ex Sx U1; M500)">
|
||||||
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
||||||
Start PID tunning
|
Start PID tunning
|
||||||
|
|||||||
Reference in New Issue
Block a user