Skip to content

Commit

Permalink
1.1.1 (#497)
Browse files Browse the repository at this point in the history
* add ability to configure graph height in visualization settings, #462
* add min, max, and variance values of graphed mesh, #286
* add OctoDash support, create Custom Action with `[!WEB]http://127.0.0.1:5000/plugin/bedlevelvisualizer/bedlevelvisualizer` as the command.
* adjust the tables for better theme support, #479
* add option for showing mesh data on tab, #496
* remove tooltip hover on tables, #490
* add Prusa adjustment values to graph (still needs verification), #242
* add appearance > title setting to automatically downloaded snapshots, #494
* update docs and screenshots, #335, #358, #468
  • Loading branch information
jneilliii authored Jan 1, 2022
1 parent 56b374d commit 8fa14d5
Show file tree
Hide file tree
Showing 12 changed files with 490 additions and 107 deletions.
41 changes: 35 additions & 6 deletions octoprint_bedlevelvisualizer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class bedlevelvisualizer(
octoprint.plugin.WizardPlugin,
octoprint.plugin.SimpleApiPlugin,
octoprint.plugin.EventHandlerPlugin,
octoprint.plugin.BlueprintPlugin,
):
INTERVAL = 2.0
MAX_HISTORY = 10
Expand All @@ -32,6 +33,7 @@ def __init__(self):
self.old_marlin_offset = 0
self.repetier_firmware = False
self.mesh = []
self.bed = {}
self.bed_type = None
self.box = []
self.flip_x = False
Expand Down Expand Up @@ -90,6 +92,7 @@ def get_settings_defaults(self):
mesh_unit=1,
reverse=False,
showdegree=False,
show_stored_mesh_on_tab=False,
imperial=False,
descending_y=False,
descending_x=False,
Expand All @@ -101,7 +104,9 @@ def get_settings_defaults(self):
colorscale='[[0, "rebeccapurple"],[0.4, "rebeccapurple"],[0.45, "blue"],[0.5, "green"],[0.55, "yellow"],[0.6, "red"],[1, "red"]]',
save_snapshots=False,
camera_position="-1.25,-1.25,0.25",
date_locale_format=""
date_locale_format="",
graph_height="450px",
show_prusa_adjustments=False
)

def get_settings_version(self):
Expand Down Expand Up @@ -168,7 +173,7 @@ def get_assets(self):
"js/knockout-sortable.1.2.0.js",
"js/fontawesome-iconpicker.js",
"js/ko.iconpicker.js",
"js/plotly-gl3d.min.js",
"js/plotly.min.js",
"js/bedlevelvisualizer.js",
],
css=[
Expand Down Expand Up @@ -349,7 +354,7 @@ def process_gcode(self, comm, line, *args, **kwargs):
min_y = min([y for x, y in self.box])
max_y = max([y for x, y in self.box])

bed = dict(
self.bed = dict(
type=self.bed_type,
x_min=min_x,
x_max=max_x,
Expand All @@ -358,7 +363,7 @@ def process_gcode(self, comm, line, *args, **kwargs):
z_min=min_z,
z_max=max_z,
)
self._bedlevelvisualizer_logger.debug(bed)
self._bedlevelvisualizer_logger.debug(self.bed)

if self.old_marlin or self.repetier_firmware:
self.print_mesh_debug("initial mesh data: ", self.mesh)
Expand Down Expand Up @@ -441,9 +446,9 @@ def process_gcode(self, comm, line, *args, **kwargs):
self.print_mesh_debug("Final mesh:", self.mesh)

self._plugin_manager.send_plugin_message(
self._identifier, dict(mesh=self.mesh, bed=bed)
self._identifier, dict(mesh=self.mesh, bed=self.bed)
)
self.send_mesh_data_collected_event(self.mesh, bed)
self.send_mesh_data_collected_event(self.mesh, self.bed)

return line

Expand Down Expand Up @@ -530,6 +535,30 @@ def send_mesh_data_collected_event(self, mesh_data, bed_data):
def register_custom_events(*args, **kwargs):
return ["mesh_data_collected"]

# BluePrint routes

@octoprint.plugin.BlueprintPlugin.route("bedlevelvisualizer")
def bedlevelvisualizer_route(self):
try:
if len(self.mesh) > 0:
mesh = self.mesh
self._bedlevelvisualizer_logger.debug("using internal mesh for octodash view: {}".format(mesh))
elif len(self._settings.get(["stored_mesh"])) > 0:
mesh = self._settings.get(["stored_mesh"])
self._bedlevelvisualizer_logger.debug("using stored mesh for octodash view: {}".format(mesh))
bed = self.bed_type
commands = self._settings.get(["command"]).split("\n")
render_kwargs = {"mesh": mesh, "bed": bed, "commands": commands}
except Exception as e:
self._logger.debug("Bed Visualizer error: {}".format(e))
render_kwargs = {"error": "{}".format(e)}
response = flask.make_response(flask.render_template("bedlevelvisualizer_octodash.jinja2", **render_kwargs))
response.headers["X-Frame-Options"] = ""
return response

def is_blueprint_protected(self):
return False

# Software Update Hook

def get_update_information(self):
Expand Down
16 changes: 16 additions & 0 deletions octoprint_bedlevelvisualizer/static/css/bedlevelvisualizer.css
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ div#bedlevelvisualizergraph {
height:100%;
object-fit:contain;
}
/*#tab_plugin_bedlevelvisualizer.fullscreen{
z-index: 9999;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
}*/

.table thead tr.info > th, .table tbody tr td.info, .table tfoot tr.info > th {
background-color: #d9edf7;
Expand All @@ -83,6 +91,14 @@ div#bedlevelvisualizergraph {
color: red;
}

div.raise > div.turn_circle {
background-color: blue;
}

div.lower > div.turn_circle {
background-color: red;
}

.table thead tr.info .x-axis-label, .table tbody tr .x-axis-label, .table tfoot tr.info .x-axis-label, .table tfoot tr .y-axis-label {
color: black;
}
Expand Down
119 changes: 80 additions & 39 deletions octoprint_bedlevelvisualizer/static/js/bedlevelvisualizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ $(function () {
self.mesh_unit = ko.observable();
self.reverse = ko.observable();
self.showdegree = ko.observable();
self.show_stored_mesh_on_tab = ko.observable();
self.imperial = ko.observable();
self.descending_x = ko.observable();
self.descending_y = ko.observable();
Expand All @@ -70,6 +71,10 @@ $(function () {
self.turn = ko.observable(0);
self.graph_z_limits = ko.observable();

self.get_cell_text = function(item) {
return (!item.$parentContext.$parent.len?Math.abs(parseFloat(item.$parentContext.$parent.mesh[item.$root.descending_y()?item.$root.mesh_data_y().length-1-item.$parentContext.$index():item.$parentContext.$index()][item.$root.descending_x()?item.$root.mesh_data_x().length-1-item.$index():item.$index()])):parseFloat(item.$parentContext.$parent.mesh[item.$root.descending_y()?item.$root.mesh_data_y().length-1-item.$parentContext.$index():item.$parentContext.$index()][item.$root.descending_x()?item.$root.mesh_data_x().length-1-item.$index():item.$index()])).toFixed(item.$parentContext.$parent.len);
};

self.onBeforeBinding = function() {
self.mesh_data(self.settingsViewModel.settings.plugins.bedlevelvisualizer.stored_mesh());
self.mesh_data_x(self.settingsViewModel.settings.plugins.bedlevelvisualizer.stored_mesh_x());
Expand All @@ -81,6 +86,7 @@ $(function () {
self.mesh_unit(self.settingsViewModel.settings.plugins.bedlevelvisualizer.mesh_unit());
self.reverse(self.settingsViewModel.settings.plugins.bedlevelvisualizer.reverse());
self.showdegree(self.settingsViewModel.settings.plugins.bedlevelvisualizer.showdegree());
self.show_stored_mesh_on_tab(self.settingsViewModel.settings.plugins.bedlevelvisualizer.show_stored_mesh_on_tab());
self.imperial(self.settingsViewModel.settings.plugins.bedlevelvisualizer.imperial());
self.descending_x(self.settingsViewModel.settings.plugins.bedlevelvisualizer.descending_x());
self.descending_y(self.settingsViewModel.settings.plugins.bedlevelvisualizer.descending_y());
Expand All @@ -105,12 +111,17 @@ $(function () {
self.settingsViewModel.settings.plugins.bedlevelvisualizer.mesh_unit(self.mesh_unit());
self.settingsViewModel.settings.plugins.bedlevelvisualizer.reverse(self.reverse());
self.settingsViewModel.settings.plugins.bedlevelvisualizer.showdegree(self.showdegree());
self.settingsViewModel.settings.plugins.bedlevelvisualizer.show_stored_mesh_on_tab(self.show_stored_mesh_on_tab());
self.settingsViewModel.settings.plugins.bedlevelvisualizer.imperial(self.imperial());
self.settingsViewModel.settings.plugins.bedlevelvisualizer.descending_x(self.descending_x());
self.settingsViewModel.settings.plugins.bedlevelvisualizer.descending_y(self.descending_y());
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.colorscale().length === 0) self.settingsViewModel.settings.plugins.bedlevelvisualizer.colorscale('[[0, "rebeccapurple"],[0.4, "rebeccapurple"],[0.45, "blue"],[0.5, "green"],[0.55, "yellow"],[0.6, "red"],[1, "red"]]');
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.rotation().length === 0) self.settingsViewModel.settings.plugins.bedlevelvisualizer.rotation(0);
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.timeout().length === 0) self.settingsViewModel.settings.plugins.bedlevelvisualizer.timeout(1800);
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.colorscale().length === 0) { self.settingsViewModel.settings.plugins.bedlevelvisualizer.colorscale('[[0, "rebeccapurple"],[0.4, "rebeccapurple"],[0.45, "blue"],[0.5, "green"],[0.55, "yellow"],[0.6, "red"],[1, "red"]]');}
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.rotation().length === 0) {self.settingsViewModel.settings.plugins.bedlevelvisualizer.rotation(0);}
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.timeout().length === 0) {self.settingsViewModel.settings.plugins.bedlevelvisualizer.timeout(1800);}
/* if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.show_prusa_adjustments()) {
self.settingsViewModel.settings.plugins.bedlevelvisualizer.use_relative_offsets(true);
self.settingsViewModel.settings.plugins.bedlevelvisualizer.use_center_origin(true);
}*/
};

self.onSettingsHidden = function() {
Expand Down Expand Up @@ -185,7 +196,7 @@ $(function () {
self.processing(true);
}
if (mesh_data.timeout_override) {
console.log('Resetting timeout to ' + mesh_data.timeout_override + ' seconds.');
// console.log('Resetting timeout to ' + mesh_data.timeout_override + ' seconds.');
clearTimeout(self.timeout);
self.timeout = setTimeout(function() {self.cancelMeshUpdate();new PNotify({title: 'Bed Visualizer Error',text: '<div class="row-fluid">Timeout occured before processing completed. Processing may still be running or there may be a configuration error. Consider increasing the Processing Timeout value in settings and restart OctoPrint.</div>',type: 'error',hide: false});}, (mesh_data.timeout_override*1000));
}
Expand All @@ -194,7 +205,7 @@ $(function () {

self.drawMesh = function (mesh_data_z,store_data,mesh_data_x,mesh_data_y,mesh_data_z_height) {
// console.log(mesh_data_z+'\n'+store_data+'\n'+mesh_data_x+'\n'+mesh_data_y+'\n'+mesh_data_z_height);
console.log(mesh_data_z);
// console.log(mesh_data_z);
clearTimeout(self.timeout);
self.processing(false);
if ( self.save_mesh()) {
Expand Down Expand Up @@ -302,42 +313,71 @@ $(function () {
}
}
}]};
// Prusa Bed Level Correction
let back_half = mesh_data_z.slice(0, mesh_data_z.length/2).join().split(',');
let front_half = mesh_data_z.slice(mesh_data_z.length/2).join().split(',');
let left_half = (back_half.slice(0,back_half.length/2) + front_half.slice(0,front_half.length/2)).split(',');
let right_half = (back_half.slice(back_half.length/2) + front_half.slice(front_half.length/2)).split(',');

let back_half_total = 0;
let front_half_total = 0;
let left_half_total = 0;
let right_half_total = 0;

for(let i=0;i<back_half.length;i++){
back_half_total += parseFloat(back_half[i]);
}

for(let i=0;i<front_half.length;i++){
front_half_total += parseFloat(front_half[i]);
}
// calculate min/max value.
let s_min = Math.min(...mesh_data_z.flat());
let s_max = Math.max(...mesh_data_z.flat());
let s_var = s_max - s_min;

layout.annotations = [{
xref: 'paper',
yref: 'paper',
x: 1,
xanchor: 'right',
y: 0,
yanchor: 'bottom',
text: 'Min: ' + s_min + '<br>Max: ' + s_max + '<br>Var: ' + s_var,
showarrow: false,
font: {
color: foreground_color
}
}];

for(let i=0;i<left_half.length;i++){
left_half_total += parseFloat(left_half[i]);
}
// Prusa Bed Level Correction
if(self.settingsViewModel.settings.plugins.bedlevelvisualizer.show_prusa_adjustments()) {
let back_half = mesh_data_z.slice(0, mesh_data_z.length/2).join().split(',');
let front_half = mesh_data_z.slice(mesh_data_z.length/2).join().split(',');
let left_half = (back_half.slice(0,back_half.length/2) + front_half.slice(0,front_half.length/2)).split(',');
let right_half = (back_half.slice(back_half.length/2) + front_half.slice(front_half.length/2)).split(',');

let back_half_total = 0;
let front_half_total = 0;
let left_half_total = 0;
let right_half_total = 0;

for(let i=0;i<back_half.length;i++){
back_half_total += parseFloat(back_half[i]);
}

for(let i=0;i<right_half.length;i++){
right_half_total += parseFloat(right_half[i]);
}
for(let i=0;i<front_half.length;i++){
front_half_total += parseFloat(front_half[i]);
}

for(let i=0;i<left_half.length;i++){
left_half_total += parseFloat(left_half[i]);
}

let back_half_um = Math.round((back_half_total/back_half.length)*1000);
let front_half_um = Math.round((front_half_total/front_half.length)*1000);
let left_half_um = Math.round((left_half_total/left_half.length)*1000);
let right_half_um = Math.round((right_half_total/right_half.length)*1000);
for(let i=0;i<right_half.length;i++){
right_half_total += parseFloat(right_half[i]);
}

console.log('Back [um]:' + back_half_um);
console.log('Front [um]:' + front_half_um);
console.log('Left [um]:' + left_half_um);
console.log('Right [um]:' + right_half_um);
let back_half_um = Math.round((back_half_total/back_half.length)*1000);
let front_half_um = Math.round((front_half_total/front_half.length)*1000);
let left_half_um = Math.round((left_half_total/left_half.length)*1000);
let right_half_um = Math.round((right_half_total/right_half.length)*1000);
layout.annotations.push({xref: 'paper',
yref: 'paper',
x: 1,
xanchor: 'right',
y: 1,
yanchor: 'top',
text: 'Back [um]:' + back_half_um + '<br>Front [um]:' + front_half_um + '<br>Left [um]:' + left_half_um + '<br>Right [um]:' + right_half_um,
showarrow: false,
font: {
color: foreground_color
}
});
}

// graph surface
Plotly.react('bedlevelvisualizergraph', data, layout, config_options).then(self.postPlotHandler);
Expand All @@ -353,7 +393,8 @@ $(function () {

self.postPlotHandler = function () {
if(self.save_snapshots()){
Plotly.downloadImage('bedlevelvisualizergraph',{filename:moment().format('YYYY-MM-DD_HH-mm-ss')});
var export_filename = ((self.settingsViewModel.settings.appearance.name().length > 0) ? self.settingsViewModel.settings.appearance.name() : 'OctoPrint') + '_' + moment().format('YYYY-MM-DD_HH-mm-ss');
Plotly.downloadImage('bedlevelvisualizergraph',{filename: export_filename});
}
};

Expand Down Expand Up @@ -381,7 +422,7 @@ $(function () {
});

self.timeout = setTimeout(function() {self.cancelMeshUpdate();new PNotify({title: 'Bed Visualizer Error',text: '<div class="row-fluid">Timeout occured before processing completed. Processing may still be running or there may be a configuration error. Consider increasing the Processing Timeout value in settings and restart OctoPrint.</div>',type: 'error',hide: false});}, (parseInt(self.settingsViewModel.settings.plugins.bedlevelvisualizer.timeout())*1000));
console.log(gcode_cmds);
// console.log(gcode_cmds);

OctoPrint.control.sendGcode(gcode_cmds);
};
Expand Down Expand Up @@ -453,7 +494,7 @@ $(function () {
var text = self.selected_command().command();
text += '%(' + data.parameter() + ')s';
self.selected_command().command(text);
console.log(data);
// console.log(data);
};

self.removeParameter = function(data) {
Expand Down
58 changes: 58 additions & 0 deletions octoprint_bedlevelvisualizer/static/js/plotly-2.4.2.min.js

Large diffs are not rendered by default.

65 changes: 65 additions & 0 deletions octoprint_bedlevelvisualizer/static/js/plotly.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit 8fa14d5

Please sign in to comment.