Refactor message hooking
This commit is contained in:
@@ -22,7 +22,6 @@ class API(octoprint.plugin.SimpleApiPlugin):
|
||||
}
|
||||
|
||||
def apiGateWay(self, command, data):
|
||||
self._logger.debug("api command [%s] received payload [%s]", command, data)
|
||||
if command == CMD_ESTEPS_LOAD_STEPS:
|
||||
self._logger.debug("Load steps from EEPROM")
|
||||
if not self._printer.is_ready():
|
||||
@@ -38,11 +37,11 @@ class API(octoprint.plugin.SimpleApiPlugin):
|
||||
# Issue M92 command
|
||||
self._printer.commands("M92")
|
||||
|
||||
m92Event.wait()
|
||||
m92Event.wait(5)
|
||||
|
||||
return flask.jsonify({
|
||||
"data": self.data["steps"]
|
||||
})
|
||||
|
||||
if command == CMD_ESTEPS_START_EXTRUSION:
|
||||
self._logger.debug("Heating the extruder [%s]", data)
|
||||
if not self._printer.is_ready():
|
||||
@@ -53,10 +52,8 @@ class API(octoprint.plugin.SimpleApiPlugin):
|
||||
|
||||
# Register event to be trigger when temp is achieved
|
||||
self.registerEventTemp("T0", int(data["extrudeTemp"]), self.startExtrusion, data["extrudeLength"], data["extrudeSpeed"])
|
||||
|
||||
# Heating the tool
|
||||
self._printer.commands("M104 S%(extrudeTemp)s" % data)
|
||||
return
|
||||
|
||||
if command == CMD_ESTEPS_SAVE:
|
||||
eStepsSettings = self._settings.get(['eSteps'])
|
||||
|
||||
@@ -8,17 +8,51 @@ import flask
|
||||
import octoprint.plugin
|
||||
|
||||
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):
|
||||
|
||||
@staticmethod
|
||||
def apiCommands():
|
||||
return {
|
||||
CMD_PID_SAVE : ["fanSpeed", "noCycles" "hotEndIndex", "targetTemp"]
|
||||
CMD_PID_SAVE : [],
|
||||
CMD_PID_START: ["fanSpeed", "noCycles", "hotEndIndex", "targetTemp"]
|
||||
}
|
||||
|
||||
def apiGateWay(self, command, data):
|
||||
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:
|
||||
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 -*-
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
|
||||
import traceback
|
||||
from ast import Try
|
||||
|
||||
import flask
|
||||
|
||||
from octoprint_CalibrationTools import EStepsApi, PIDAutoTune
|
||||
@@ -33,7 +36,13 @@ class API(EStepsApi.API, PIDAutoTune.API):
|
||||
)
|
||||
|
||||
def on_api_command(self, command, data):
|
||||
self._logger.debug("API command [%s] received payload [%s]", command, data)
|
||||
for key, api in self.commandsRegistration.items():
|
||||
if command in api["commands"]:
|
||||
return api["cls"].apiGateWay(self, command, data)
|
||||
try:
|
||||
self._logger.debug("API command [%s] received payload [%s]", command, data)
|
||||
for key, api in self.commandsRegistration.items():
|
||||
if command in api["commands"]:
|
||||
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 -*-
|
||||
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||
from ast import arg
|
||||
|
||||
import collections
|
||||
import re
|
||||
import threading
|
||||
import traceback
|
||||
import types
|
||||
import collections
|
||||
|
||||
|
||||
class Hooks():
|
||||
@@ -15,20 +14,26 @@ class Hooks():
|
||||
gCodeWaiters = []
|
||||
|
||||
def gCodeReceived(self, comm, line, *args, **kwargs):
|
||||
if len(self.gCodeWaiters) <= 0 and not line.startswith('echo:'):
|
||||
return line
|
||||
|
||||
reg = re.compile("echo:\s*(?P<gCode>M\d{1,4})")
|
||||
mCommand = reg.match(line)
|
||||
if mCommand:
|
||||
gCode = mCommand.group("gCode")
|
||||
try:
|
||||
if len(self.gCodeWaiters) <= 0:
|
||||
return line
|
||||
for waiter in self.gCodeWaiters:
|
||||
if gCode.upper() == waiter["cmd"]:
|
||||
arg = (line, *waiter["args"])
|
||||
reg = waiter["regex"]
|
||||
waiter["callCount"] = waiter["callCount"] + 1
|
||||
if reg.match(line):
|
||||
args = (line, *waiter["args"])
|
||||
if isinstance(waiter["func"], types.FunctionType):
|
||||
arg = (self, *arg)
|
||||
threading.Thread(target=waiter["func"], args=arg).start()
|
||||
self.gCodeWaiters.remove(waiter)
|
||||
args = (self, *args)
|
||||
threading.Thread(target=waiter["func"], args=args).start()
|
||||
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
|
||||
|
||||
def firmwareInfo(self, comm_instance, firmware_name, firmware_data, *args, **kwargs):
|
||||
@@ -79,11 +84,20 @@ class Hooks():
|
||||
|
||||
# Registering a gCodeWaiter
|
||||
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):
|
||||
self._logger.warn("registerGCodeAnswer: Attempt to register gCodeAnswer without a function or gCode command")
|
||||
reg = re.compile(".*\s*(?P<gCode>[M,G]\d{1,4})")
|
||||
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
|
||||
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({
|
||||
"cmd": command.upper(),
|
||||
"regex": re.compile(regex),
|
||||
"func": func,
|
||||
"args": arguments
|
||||
"args": arguments,
|
||||
"callCount": 0
|
||||
})
|
||||
|
||||
@@ -3,10 +3,11 @@ $(function () {
|
||||
var self = this;
|
||||
self.loginStateViewModel = parameters[0];
|
||||
self.settingsViewModel = parameters[1];
|
||||
self.controlViewModel = parameters[2];
|
||||
|
||||
self.bedCurrentTemp = ko.observable(0);
|
||||
self.bedCurrentTarget = ko.observable(0);
|
||||
self.is_admin = ko.observable(false);
|
||||
self.isAdmin = ko.observable(false);
|
||||
self.pid = {
|
||||
fanSpeed: ko.observable(255),
|
||||
noCycles: ko.observable(5),
|
||||
@@ -24,7 +25,30 @@ $(function () {
|
||||
self.pid.noCycles(self.settingsViewModel.settings.plugins.CalibrationTools.pid.noCycles());
|
||||
self.pid.hotEndIndex(self.settingsViewModel.settings.plugins.CalibrationTools.pid.hotEndIndex());
|
||||
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({
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span6"></div>
|
||||
<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">
|
||||
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
||||
Start extrusion
|
||||
@@ -82,7 +82,7 @@
|
||||
</div>
|
||||
<div class="span6">
|
||||
<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>
|
||||
{{ snipped.m500Icon() }}
|
||||
</div>
|
||||
@@ -92,7 +92,7 @@
|
||||
<div class="row-fluid" style="margin-bottom: 5px;">
|
||||
<div class="span6"></div>
|
||||
<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">
|
||||
<i class="fas fa-save" data-color="#000000"></i>  
|
||||
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="span5"></div>
|
||||
<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)">
|
||||
<i class="fas fa-play" style="color:false" data-color="false"></i>  
|
||||
Start PID tunning
|
||||
|
||||
Reference in New Issue
Block a user