initial commit

This commit is contained in:
sergiuToporjinschi
2022-01-29 18:22:33 +02:00
parent ae0c51416a
commit b5cd1b4c22
23 changed files with 808 additions and 0 deletions
+142
View File
@@ -0,0 +1,142 @@
# coding=utf-8
from __future__ import absolute_import
### (Don't forget to remove me)
# This is a basic skeleton for your plugin's __init__.py. You probably want to adjust the class name of your plugin
# as well as the plugin mixins it's subclassing from. This is really just a basic skeleton to get you started,
# defining your plugin as a template plugin, settings and asset plugin. Feel free to add or remove mixins
# as necessary.
#
# Take a look at the documentation on what other plugin mixins are available.
import octoprint.plugin
import re
from octoprint_CalibrationTools import (
api
)
class CalibrationtoolsPlugin(octoprint.plugin.StartupPlugin,
octoprint.plugin.TemplatePlugin,
octoprint.plugin.SettingsPlugin,
octoprint.plugin.AssetPlugin,
octoprint.plugin.SimpleApiPlugin
):
collectCommand = False
m92Data = {
"X": 0,
"Y": 0,
"Z": 0,
"E": 0
}
def initialize(self):
self.collectCommand = False
self._api = api.API(self)
def on_after_startup(self):
self._logger.info("----------------[CalibrationTools]----------------")
self.collectCommand = True
self._printer.commands("M92")
# API handling
def get_api_commands(self):
self._logger.info("get_api_commands")
return self._api.get_api_commands()
def on_api_command(self, command, data):
self._logger.info("on_api_command")
return self._api.on_api_command(command, data)
def on_api_get(self, request):
self._logger.info("on_api_get")
return self._api.on_api_get(request)
##~~ AssetPlugin mixin
def get_assets(self):
# Define your plugin's asset files to automatically include in the
# core UI here.
return {
"js": ["js/CalibrationTools.js"],
"css": ["css/style.css"]
}
# self._printer.commands(commands)
# extrude(amount, speed=None, tags=None, *args, **kwargs)
# set_temperature(heater, value, tags=None, *args, **kwargs)
##~~ Softwareupdate hook
def comm_protocol_gcode_received(self, comm, line, *args, **kwargs):
if not self.collectCommand: return line
reg = re.compile("echo:\s*(?P<command>(?P<gCode>M\d{1,3}) X(?P<xVal>\d{1,3}.\d{1,3}) Y(?P<yVal>\d{1,3}.\d{1,3}) Z(?P<zVal>\d{1,3}.\d{1,3}) E(?P<eVal>\d{1,3}.\d{1,3}))")
isM92command = reg.match(line)
if isM92command:
command = isM92command.group("command")
if isM92command.group("gCode") == "M92":
xValue = isM92command.group("xVal")
yValue = isM92command.group("yVal")
zValue = isM92command.group("zVal")
eValue = isM92command.group("eVal")
self.m92Data["X"] = float(xValue)
self.m92Data["Y"] = float(yValue)
self.m92Data["Z"] = float(zValue)
self.m92Data["E"] = float(eValue)
# Send the new data to the UI to be reloaded
self._logger.info(line)
self._logger.info("gCode: %s", command)
self._logger.info("X: %s", xValue)
self._logger.info("Y: %s", yValue)
self._logger.info("Z: %s", zValue)
self._logger.info("E: %s", eValue)
self._logger.info("Finished data collection, updating UI")
self.collectCommand = False
return line
def comm_protocol_gcode_sending(self, comm, phase, cmd, cmd_type, gcode, subcode=None, tags=None, *args, **kwargs):
# https://docs.octoprint.org/en/master/plugins/hooks.html#protocol_gcodephase_hook
if cmd == "M92":
self._logger.info("{} detected, collecting data".format(cmd))
self.collectCommand = True
def get_update_information(self):
# Define the configuration for your plugin to use with the Software Update
# Plugin here. See https://docs.octoprint.org/en/master/bundledplugins/softwareupdate.html
# for details.
return {
"CalibrationTools": {
"displayName": "Calibration Tools",
"displayVersion": self._plugin_version,
# version check: github repository
"type": "github_release",
"user": "SergiuToporjinschi",
"repo": "OctoPrint-CalibrationTools",
"current": self._plugin_version,
# update method: pip
"pip": "https://github.com/SergiuToporjinschi/OctoPrint-CalibrationTools/archive/{target_version}.zip",
}
}
# If you want your plugin to be registered within OctoPrint under a different name than what you defined in setup.py
# ("OctoPrint-PluginSkeleton"), you may define that here. Same goes for the other metadata derived from setup.py that
# can be overwritten via __plugin_xyz__ control properties. See the documentation for that.
__plugin_name__ = "Calibration Tools"
# Starting with OctoPrint 1.4.0 OctoPrint will also support to run under Python 3 in addition to the deprecated
# Python 2. New plugins should make sure to run under both versions for now. Uncomment one of the following
# compatibility flags according to what Python versions your plugin supports!
#__plugin_pythoncompat__ = ">=2.7,<3" # only python 2
#__plugin_pythoncompat__ = ">=3,<4" # only python 3
__plugin_pythoncompat__ = ">=2.7,<4" # python 2 and 3
def __plugin_load__():
global __plugin_implementation__
__plugin_implementation__ = CalibrationtoolsPlugin()
global __plugin_hooks__
__plugin_hooks__ = {
"octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
}
+36
View File
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, unicode_literals
import flask
CMD_LOAD_STEPS_EEPROM = "loadSteps"
class API:
def __init__(self, plugin):
self._settings = plugin._settings # noqa
self._logger = plugin._logger # noqa
self._printer = plugin._printer # noqa
self.m92Data = plugin.m92Data # noqa
self._plugin = plugin
@staticmethod
def get_api_commands():
return {
CMD_LOAD_STEPS_EEPROM: []
}
def on_api_get(self, request):
self._logger.info("on api get")
return flask.jsonify(
{
"data": self.m92Data
}
)
def on_api_command(self, command, data):
if command == CMD_LOAD_STEPS_EEPROM:
self._logger.info("CMD_LOAD_STEPS_EEPROM")
self._printer.commands("M92")
return flask.jsonify({
"data": self.m92Data
})
@@ -0,0 +1,82 @@
#tab_plugin_CalibrationTools .main {
margin-bottom: 30px;
}
#tab_plugin_CalibrationTools .header {
margin-bottom: 13px;
}
#tab_plugin_CalibrationTools .title {
text-align: center;
font-weight: bold;
padding: 2px;
border: 1px solid;
border-color: #ddd;
border-radius: 4px;
}
#tab_plugin_CalibrationTools .tab-content {
border: none;
}
#tab_plugin_CalibrationTools ul.nav li:first-child > a {
border-radius: 4px 4px 0 0;
border-top: 1px solid #ddd !important;
}
#tab_plugin_CalibrationTools ul.nav li:last-child > a {
border-radius: 0 0 4px 4px;
}
#tab_plugin_CalibrationTools ul.nav li > a {
border: 1px solid #ddd;
border-top: 0;
background-clip: border-box;
}
#tab_plugin_CalibrationTools .card {
box-shadow: 0 0.125rem 0.25rem rgb(0 0 0 / 8%) !important;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem;
padding: 1.25rem 0.5rem;
margin-bottom: 10px;
}
#tab_plugin_CalibrationTools .icon a, #tab_plugin_CalibrationTools .icon a i {
vertical-align: middle;
cursor: pointer;
}
#tab_plugin_CalibrationTools input:disabled {
cursor: text;
}
/*
#tab_plugin_CalibrationTools .container {
display: flex;
flex-direction: column;
}
#tab_plugin_CalibrationTools .container .row {
display: flex;
flex-direction: row;
margin-left: 0px;
flex-basis: 40px;
align-items: baseline;
}
#tab_plugin_CalibrationTools .settings_icon {
float: right;
}
#tab_plugin_CalibrationTools .eSteps_container .title {
flex-basis: 30%;
}
#tab_plugin_CalibrationTools .eSteps_container .val {
max-width: 60px;
}
#tab_plugin_CalibrationTools .numberInputField {
width: 60px;
} */
@@ -0,0 +1,106 @@
//Notification
// new PNotify({
// title: "Success",
// text: _.sprintf(text, {
// command: _.escape(commandSpec.name)
// }),
// type: "success"
// });
$(function () {
function CalibrationToolsViewModel(parameters) {
var self = this;
self.loginStateViewModel = parameters[0];
self.settingsViewModel = parameters[1];
self.controlViewModel = parameters[2];
self.terminalViewModel = parameters[3];
self.access = parameters[4];
self.is_admin = ko.observable(false);
self.steps = ko.observable();
self.steps["X"] = ko.observable();
self.steps["Y"] = ko.observable();
self.steps["Z"] = ko.observable();
self.steps["E"] = ko.observable();
self.results = {};
self.results["remainedLength"] = ko.observable(20);
self.results["markLength"] = ko.observable(120);
self.results["actualExtrusion"] = ko.computed(function () {
return (self.results.markLength() - self.results.remainedLength()).toFixed(3);
});
self.results["newSteps"] = ko.computed(function () {
return (self.steps.E() / self.results.actualExtrusion() * 100).toFixed(3);
});
self.onBeforeBinding = self.onUserLoggedIn = self.onUserLoggedOut = function () {
self.is_admin(self.loginStateViewModel.isAdmin());
}
/**open settings*/
self.openCalibrationSettings = function () {
$('a#navbar_show_settings').click();
$('li#settings_plugin_CalibrationTools_link a').click();
$("#settings_plugin_CalibrationTools").click();
}
self.from_json = function (response) {
self.steps["X"](response.data.X);
self.steps["Y"](response.data.Y);
self.steps["Z"](response.data.Z);
self.steps["E"](response.data.E);
}
self.calibrateESteps = function () {
// OctoPrint.simpleApiCommand("loadSteps")
// OctoPrint.control.sendGcodeWithParameters("M92").done(function (responseM92) {
// OctoPrint.simpleApiGet("CalibrationTools").done(function (response) {
// console.log("CalibrationTools");
// self.from_json(response);
// });
// });
console.log("calibrateESteps");
console.log(self.steps.E(), self.results.remainedLength(), self.results.newSteps());
}
self.loadStepsFromEPROM = function () {
OctoPrint.simpleApiCommand("CalibrationTools","loadSteps").done(function (response) {
self.from_json(response);
})
// OctoPrint.simpleApiGet("CalibrationTools").done(function (response) {
// console.log("CalibrationTools");
// self.from_json(response);
// });
}
self.tempRestart = function () {
OctoPrint.system.executeCommand("core", "restart");
}
self.runCommand = function () {
OctoPrint.control.sendGcodeWithParameters("G90");
}
self.onAllBound = self.onEventConnected = function () {
OctoPrint.simpleApiGet("CalibrationTools").done(function (response) {
console.log("CalibrationTools");
self.from_json(response);
});
}
}
// This is how our plugin registers itself with the application, by adding some configuration
// information to the global variable OCTOPRINT_VIEWMODELS
OCTOPRINT_VIEWMODELS.push({
// This is the constructor to call for instantiating the plugin
construct: CalibrationToolsViewModel,
// This is a list of dependencies to inject into the plugin, the order which you request
// here is the order in which the dependencies will be injected into your view model upon
// instantiation via the parameters argument
dependencies: ["loginStateViewModel", "settingsViewModel", "controlViewModel", "terminalViewModel", "accessViewModel"],
// Finally, this is the list of selectors for all elements we want this view model to be bound to.
elements: ["#tab_plugin_CalibrationTools"]
});
});
@@ -0,0 +1,7 @@
<div class="container">
<h3>Something in settings</h3>
<div class="row"><span class="title col">Actual extrusion: </span> <span class="val col" data-bind="text: $root.results.actualExtrusion"></span></div>
<div class="row"><span class="title col">New steps value: </span> <span class="val col" data-bind="text: $root.results.newSteps"> </span></div>
<div class="row"><span class="title col">Extrusion marking length: </span> <input class="val col" type="number" step="0.01" class="numberInputField" data-bind="value: $root.results.markLength" ></div>
<div class="row"><span class="title col">Measured value: </span> <input class="val col" type="number" step="0.01" class="numberInputField" data-bind="value: $root.results.remainedLength" ></div>
</div>
@@ -0,0 +1,38 @@
<div class="octo-tab-content">
<div class="row-fluid header">
<div class="span3 title">
<p>Calibration</p>
</div>
<div class="span8 title">
<!-- <button class="btn" data-bind="click: $root.tempRestart">
RESTART
</button> -->
</div>
<div class="span1 icon">
<a data-bind="click: $root.openCalibrationSettings">
<i class="fas fa-cog fa-lg" data-color="#ddd"></i>
</a>
</div>
</div>
<div class="main row-fluid">
<div class="span3">
<ul class="nav nav-list">
<li class="active">
<a data-toggle="tab" href="#calibration_documentation">Documentation</a>
</li>
<li>
<a data-toggle="tab" href="#calibration_x-y-z">X-Y-Z</a>
</li>
<li>
<a data-toggle="tab" href="#calibration_eSteps">E-Steps</a>
</li>
<li>
<a data-toggle="tab" href="#calibration_pid">PID</a>
</li>
</ul>
</div>
<div class="span9">
{% include "tabs/tab-content.jinja2" %}
</div>
</div>
</div>
@@ -0,0 +1,34 @@
{% macro subSection(title, spaceBefore) %}
{% if (spaceBefore) %} <br><br> {% endif %}
<strong>{{ _(title) }}</strong>
<hr>
{% endmacro %}
{% macro card(content, class) %}
<div class="card">
<p class="{{ class }}">{{ _(content) }}</p>
</div>
{% endmacro %}
{% macro quote(content, class) %}
<blockquote>
<p class="{{ class }}">{{ _(content) }}</p>
</blockquote>
{% endmacro %}
{% macro field(label, number, binding, enable, unit) %}
<div class="row-fluid">
<div class="span6">
<label for="{{ label }}" class="pull-right" style="margin-top: 5px;">
{{ _(label) }}
</label>
</div>
<div class="span6">
<div class="input-append">
<input type="{{ number }}" id="{{ label }}" class="input-small" step="0.01" data-bind="value: {{ binding }}, enable: {{ enable }}">
<span class="add-on">{{ _(unit) }}</span>
</div>
</div>
</div>
{% endmacro %}
@@ -0,0 +1,15 @@
<div class="tab-content">
<div id="calibration_documentation" class="tab-pane active">
{% include "tabs/tab-doc.jinja2" %}
</div>
<div id="calibration_x-y-z" visible="false" class="tab-pane">
{% include "tabs/tab-xyz.jinja2" %}
</div>
<div id="calibration_eSteps" visible="false" class="tab-pane">
{% include "tabs/tab-esteps.jinja2" %}
</div>
<div id="calibration_pid" visible="false" class="tab-pane">
{% include "tabs/tab-pind.jinja2" %}
</div>
</div>
@@ -0,0 +1,3 @@
Something in documentation tab...
@@ -0,0 +1,38 @@
{% import "macros.jinja2" as snipped %}
{{ snipped.subSection("EEPROM values") }}
{{ snipped.field("E steps", "number", "$root.steps.E", "false", "steps/mm") }}
<div class="row-fluid">
<div class="span6"></div>
<div class="span6">
<button class="btn" data-bind="click: $root.loadStepsFromEPROM, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())">
<i class="fas fa-sync-alt" style="color:false" data-color="false"></i>&nbsp&nbsp
Load EEPROM data
</button>
</div>
</div>
{{ snipped.subSection("Compute", true) }}
{{ snipped.field("Actual extrusion", "number", "$root.results.actualExtrusion", "false", "mm") }}
{{ snipped.field("New steps value", "number", "$root.results.newSteps", "false", "steps/mm") }}
{{ snipped.field("Extrusion marking length", "number", "$root.results.markLength", "true", "mm") }}
{{ snipped.field("Measured value", "number", "$root.results.remainedLength", "true", "mm") }}
<div class="row-fluid">
<div class="span6"></div>
<div class="span6">
<button class="btn btn-primary" data-bind="click: $root.calibrateESteps, enable: $root.controlViewModel.isOperational() && (!$root.controlViewModel.isPrinting())">
<i class="fas fa-play" data-color="#000000"></i>&nbsp&nbsp
Start calibration
</button>
</div>
</div>
{{ snipped.subSection("Process description", true) }}
{{ snipped.quote("
First <a href='https://teachingtechyt.github.io/calibration.html#esteps' target='_blank'>Read this</a><br><br>
This calibration is best done with the extruder detached from the hot end, so no restriction is present on the movement. If it is convenient, you can partially disassemble the printer so the output of the extruder is
open and the filament exits in free air. If this is inconvenient, the process below aims to minimise restrictions by extruding very slowly and with a slightly higher temperature. The results from this should still be
reliable.
", "text-warning" ) }}
@@ -0,0 +1 @@
Something in pid tab...
@@ -0,0 +1 @@
Something in xyz tab...