Merge branch 'devel' into gcodestreaming
Conflicts: octoprint/printer.py octoprint/static/js/ui.js octoprint/templates/index.jinja2 octoprint/util/comm.pymaster
commit
8be1329a71
|
@ -177,7 +177,7 @@ class Printer():
|
||||||
if self._selectedFile is None:
|
if self._selectedFile is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
self._setCurrentZ(-1)
|
self._setCurrentZ(None)
|
||||||
self._comm.startPrint()
|
self._comm.startPrint()
|
||||||
|
|
||||||
def togglePausePrint(self):
|
def togglePausePrint(self):
|
||||||
|
|
|
@ -43,7 +43,7 @@ default_settings = {
|
||||||
"waitForWaitOnConnect": False,
|
"waitForWaitOnConnect": False,
|
||||||
"alwaysSendChecksum": False,
|
"alwaysSendChecksum": False,
|
||||||
"resetLineNumbersWithPrefixedN": False,
|
"resetLineNumbersWithPrefixedN": False,
|
||||||
"sdSupport": False
|
"sdSupport": True
|
||||||
},
|
},
|
||||||
"folder": {
|
"folder": {
|
||||||
"uploads": None,
|
"uploads": None,
|
||||||
|
|
|
@ -223,42 +223,31 @@
|
||||||
var assumeNonDC = false;
|
var assumeNonDC = false;
|
||||||
|
|
||||||
for(var i=0;i<gcode.length;i++){
|
for(var i=0;i<gcode.length;i++){
|
||||||
// for(var len = gcode.length- 1, i=0;i!=len;i++){
|
|
||||||
x=undefined;
|
x=undefined;
|
||||||
y=undefined;
|
y=undefined;
|
||||||
z=undefined;
|
z=undefined;
|
||||||
retract = 0;
|
retract = 0;
|
||||||
|
|
||||||
|
var line = gcode[i].line;
|
||||||
|
var percentage = gcode[i].percentage;
|
||||||
|
|
||||||
extrude=false;
|
extrude=false;
|
||||||
gcode[i] = gcode[i].split(/[\(;]/)[0];
|
line = line.split(/[\(;]/)[0];
|
||||||
|
|
||||||
// prevRetract=0;
|
if(reg.test(line)){
|
||||||
// retract=0;
|
var args = line.split(/\s/);
|
||||||
// if(gcode[i].match(/^(?:G0|G1)\s+/i)){
|
|
||||||
if(reg.test(gcode[i])){
|
|
||||||
var args = gcode[i].split(/\s/);
|
|
||||||
for(j=0;j<args.length;j++){
|
for(j=0;j<args.length;j++){
|
||||||
// console.log(args);
|
|
||||||
// if(!args[j])continue;
|
|
||||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||||
case 'x':
|
case 'x':
|
||||||
x=args[j].slice(1);
|
x=args[j].slice(1);
|
||||||
// if(x === prevX){
|
|
||||||
// x=undefined;
|
|
||||||
// }
|
|
||||||
break;
|
break;
|
||||||
case 'y':
|
case 'y':
|
||||||
y=args[j].slice(1);
|
y=args[j].slice(1);
|
||||||
// if(y===prevY){
|
|
||||||
// y=undefined;
|
|
||||||
// }
|
|
||||||
break;
|
break;
|
||||||
case 'z':
|
case 'z':
|
||||||
z=args[j].slice(1);
|
z=args[j].slice(1);
|
||||||
z = Number(z);
|
z = Number(z);
|
||||||
if(z == prevZ)continue;
|
if(z == prevZ) continue;
|
||||||
// z = Number(z);
|
|
||||||
if(z_heights.hasOwnProperty(z)){
|
if(z_heights.hasOwnProperty(z)){
|
||||||
layer = z_heights[z];
|
layer = z_heights[z];
|
||||||
}else{
|
}else{
|
||||||
|
@ -267,9 +256,6 @@
|
||||||
}
|
}
|
||||||
sendLayer = layer;
|
sendLayer = layer;
|
||||||
sendLayerZ = z;
|
sendLayerZ = z;
|
||||||
// if(parseFloat(prevZ) < )
|
|
||||||
// if(args[j].charAt(1) === "-")layer--;
|
|
||||||
// else layer++;
|
|
||||||
prevZ = z;
|
prevZ = z;
|
||||||
break;
|
break;
|
||||||
case 'e':
|
case 'e':
|
||||||
|
@ -292,13 +278,11 @@
|
||||||
retract = -1;
|
retract = -1;
|
||||||
}
|
}
|
||||||
else if(prev_extrude["abs"]==0){
|
else if(prev_extrude["abs"]==0){
|
||||||
// if(prevRetract <0 )prevRetract=retract;
|
|
||||||
retract = 0;
|
retract = 0;
|
||||||
}else if(prev_extrude["abs"]>0&&prevRetract < 0){
|
}else if(prev_extrude["abs"]>0&&prevRetract < 0){
|
||||||
prevRetract = 0;
|
prevRetract = 0;
|
||||||
retract = 1;
|
retract = 1;
|
||||||
} else {
|
} else {
|
||||||
// prevRetract = retract;
|
|
||||||
retract = 0;
|
retract = 0;
|
||||||
}
|
}
|
||||||
prev_extrude[argChar] = numSlice;
|
prev_extrude[argChar] = numSlice;
|
||||||
|
@ -317,24 +301,24 @@
|
||||||
prev_extrude["abs"] = Math.sqrt((prevX-x)*(prevX-x)+(prevY-y)*(prevY-y));
|
prev_extrude["abs"] = Math.sqrt((prevX-x)*(prevX-x)+(prevY-y)*(prevY-y));
|
||||||
}
|
}
|
||||||
if(!model[layer])model[layer]=[];
|
if(!model[layer])model[layer]=[];
|
||||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i)};
|
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||||
//{x: x, y: y, z: z, extrude: extrude, retract: retract, noMove: false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: i};
|
//{x: x, y: y, z: z, extrude: extrude, retract: retract, noMove: false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: i};
|
||||||
if(typeof(x) !== 'undefined') prevX = x;
|
if(typeof(x) !== 'undefined') prevX = x;
|
||||||
if(typeof(y) !== 'undefined') prevY = y;
|
if(typeof(y) !== 'undefined') prevY = y;
|
||||||
} else if(gcode[i].match(/^(?:M82)/i)){
|
} else if(line.match(/^(?:M82)/i)){
|
||||||
extrudeRelative = false;
|
extrudeRelative = false;
|
||||||
}else if(gcode[i].match(/^(?:G91)/i)){
|
}else if(line.match(/^(?:G91)/i)){
|
||||||
extrudeRelative=true;
|
extrudeRelative=true;
|
||||||
}else if(gcode[i].match(/^(?:G90)/i)){
|
}else if(line.match(/^(?:G90)/i)){
|
||||||
extrudeRelative=false;
|
extrudeRelative=false;
|
||||||
}else if(gcode[i].match(/^(?:M83)/i)){
|
}else if(line.match(/^(?:M83)/i)){
|
||||||
extrudeRelative=true;
|
extrudeRelative=true;
|
||||||
}else if(gcode[i].match(/^(?:M101)/i)){
|
}else if(line.match(/^(?:M101)/i)){
|
||||||
dcExtrude=true;
|
dcExtrude=true;
|
||||||
}else if(gcode[i].match(/^(?:M103)/i)){
|
}else if(line.match(/^(?:M103)/i)){
|
||||||
dcExtrude=false;
|
dcExtrude=false;
|
||||||
}else if(gcode[i].match(/^(?:G92)/i)){
|
}else if(line.match(/^(?:G92)/i)){
|
||||||
var args = gcode[i].split(/\s/);
|
var args = line.split(/\s/);
|
||||||
for(j=0;j<args.length;j++){
|
for(j=0;j<args.length;j++){
|
||||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||||
case 'x':
|
case 'x':
|
||||||
|
@ -354,16 +338,15 @@
|
||||||
else {
|
else {
|
||||||
prev_extrude[argChar] = numSlice;
|
prev_extrude[argChar] = numSlice;
|
||||||
}
|
}
|
||||||
// prevZ = z;
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!model[layer])model[layer]=[];
|
if(!model[layer])model[layer]=[];
|
||||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: parseFloat(x), y: parseFloat(y), z: parseFloat(z), extrude: extrude, retract: parseFloat(retract), noMove: true, extrusion: (extrude||retract)?parseFloat(prev_extrude["abs"]):0, prevX: parseFloat(prevX), prevY: parseFloat(prevY), prevZ: parseFloat(prevZ), speed: parseFloat(lastF),gcodeLine: parseFloat(i)};
|
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: parseFloat(x), y: parseFloat(y), z: parseFloat(z), extrude: extrude, retract: parseFloat(retract), noMove: true, extrusion: (extrude||retract)?parseFloat(prev_extrude["abs"]):0, prevX: parseFloat(prevX), prevY: parseFloat(prevY), prevZ: parseFloat(prevZ), speed: parseFloat(lastF),gcodeLine: parseFloat(i), percentage: percentage};
|
||||||
}else if(gcode[i].match(/^(?:G28)/i)){
|
}else if(line.match(/^(?:G28)/i)){
|
||||||
var args = gcode[i].split(/\s/);
|
var args = line.split(/\s/);
|
||||||
for(j=0;j<args.length;j++){
|
for(j=0;j<args.length;j++){
|
||||||
switch(argChar = args[j].charAt(0).toLowerCase()){
|
switch(argChar = args[j].charAt(0).toLowerCase()){
|
||||||
case 'x':
|
case 'x':
|
||||||
|
@ -405,17 +388,11 @@
|
||||||
}
|
}
|
||||||
prevZ = z;
|
prevZ = z;
|
||||||
}
|
}
|
||||||
// x=0, y=0,z=0,prevZ=0, extrude=false;
|
|
||||||
// if(typeof(prevX) === 'undefined'){prevX=0;}
|
|
||||||
// if(typeof(prevY) === 'undefined'){prevY=0;}
|
|
||||||
|
|
||||||
if(!model[layer])model[layer]=[];
|
if(!model[layer])model[layer]=[];
|
||||||
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i)};
|
if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined'||retract!=0) model[layer][model[layer].length] = {x: Number(x), y: Number(y), z: Number(z), extrude: extrude, retract: Number(retract), noMove: false, extrusion: (extrude||retract)?Number(prev_extrude["abs"]):0, prevX: Number(prevX), prevY: Number(prevY), prevZ: Number(prevZ), speed: Number(lastF), gcodeLine: Number(i), percentage: percentage};
|
||||||
// if(typeof(x) !== 'undefined' || typeof(y) !== 'undefined' ||typeof(z) !== 'undefined') model[layer][model[layer].length] = {x: x, y: y, z: z, extrude: extrude, retract: retract, noMove:false, extrusion: (extrude||retract)?prev_extrude["abs"]:0, prevX: prevX, prevY: prevY, prevZ: prevZ, speed: lastF, gcodeLine: parseFloat(i)};
|
|
||||||
}
|
}
|
||||||
if(typeof(sendLayer) !== "undefined"){
|
if(typeof(sendLayer) !== "undefined"){
|
||||||
// sendLayerToParent(sendLayer, sendLayerZ, i/gcode.length*100);
|
|
||||||
// sendLayer = undefined;
|
|
||||||
|
|
||||||
if(i-lastSend > gcode.length*0.02 && sendMultiLayer.length != 0){
|
if(i-lastSend > gcode.length*0.02 && sendMultiLayer.length != 0){
|
||||||
lastSend = i;
|
lastSend = i;
|
||||||
|
@ -429,13 +406,7 @@
|
||||||
sendLayerZ = undefined;
|
sendLayerZ = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sendMultiLayer[sendMultiLayer.length] = layer;
|
|
||||||
// sendMultiLayerZ[sendMultiLayerZ.length] = z;
|
|
||||||
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
sendMultiLayerToParent(sendMultiLayer, sendMultiLayerZ, i/gcode.length*100);
|
||||||
|
|
||||||
// if(gCodeOptions["sortLayers"])sortLayers();
|
|
||||||
// if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -23,57 +23,73 @@ GCODE.gCodeReader = (function(){
|
||||||
purgeEmptyLayers: true,
|
purgeEmptyLayers: true,
|
||||||
analyzeModel: false
|
analyzeModel: false
|
||||||
};
|
};
|
||||||
var linesCmdIndex = {};
|
|
||||||
|
|
||||||
var prepareGCode = function(){
|
var percentageTree = undefined;
|
||||||
|
|
||||||
|
var prepareGCode = function(totalSize){
|
||||||
if(!lines)return;
|
if(!lines)return;
|
||||||
gcode = [];
|
gcode = [];
|
||||||
var i, tmp;
|
var i, tmp, byteCount;
|
||||||
|
|
||||||
|
byteCount = 0;
|
||||||
for(i=0;i<lines.length;i++){
|
for(i=0;i<lines.length;i++){
|
||||||
// if(lines[i].match(/^(G0|G1|G90|G91|G92|M82|M83|G28)/i))gcode.push(lines[i]);
|
byteCount += lines[i].length + 1; // line length + \n
|
||||||
tmp = lines[i].indexOf(";");
|
tmp = lines[i].indexOf(";");
|
||||||
if(tmp > 1 || tmp === -1) {
|
if(tmp > 1 || tmp === -1) {
|
||||||
gcode.push(lines[i]);
|
gcode.push({line: lines[i], percentage: byteCount * 100 / totalSize});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lines = [];
|
lines = [];
|
||||||
// console.log("GCode prepared");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var sortLayers = function(){
|
var sortLayers = function(){
|
||||||
var sortedZ = [];
|
var sortedZ = [];
|
||||||
var tmpModel = [];
|
var tmpModel = [];
|
||||||
// var cnt = 0;
|
|
||||||
// console.log(z_heights);
|
|
||||||
for(var layer in z_heights){
|
for(var layer in z_heights){
|
||||||
sortedZ[z_heights[layer]] = layer;
|
sortedZ[z_heights[layer]] = layer;
|
||||||
// cnt++;
|
|
||||||
}
|
}
|
||||||
// console.log("cnt is " + cnt);
|
|
||||||
sortedZ.sort(function(a,b){
|
sortedZ.sort(function(a,b){
|
||||||
return a-b;
|
return a-b;
|
||||||
});
|
});
|
||||||
// console.log(sortedZ);
|
|
||||||
// console.log(model.length);
|
|
||||||
for(var i=0;i<sortedZ.length;i++){
|
for(var i=0;i<sortedZ.length;i++){
|
||||||
// console.log("i is " + i +" and sortedZ[i] is " + sortedZ[i] + "and z_heights[] is " + z_heights[sortedZ[i]] );
|
|
||||||
if(typeof(z_heights[sortedZ[i]]) === 'undefined')continue;
|
if(typeof(z_heights[sortedZ[i]]) === 'undefined')continue;
|
||||||
tmpModel[i] = model[z_heights[sortedZ[i]]];
|
tmpModel[i] = model[z_heights[sortedZ[i]]];
|
||||||
}
|
}
|
||||||
model = tmpModel;
|
model = tmpModel;
|
||||||
// console.log(model.length);
|
|
||||||
delete tmpModel;
|
delete tmpModel;
|
||||||
};
|
};
|
||||||
|
|
||||||
var prepareLinesIndex = function(){
|
var prepareLinesIndex = function(){
|
||||||
linesCmdIndex = {};
|
percentageTree = undefined;
|
||||||
|
|
||||||
for (var l in model){
|
for (var l in model) {
|
||||||
for (var i=0; i< model[l].length; i++){
|
for (var i=0; i< model[l].length; i++) {
|
||||||
linesCmdIndex[model[l][i].gcodeLine] = {layer: l, cmd: i};
|
var percentage = model[l][i].percentage;
|
||||||
|
var value = {layer: l, cmd: i};
|
||||||
|
if (!percentageTree) {
|
||||||
|
percentageTree = new AVLTree({key: percentage, value: value}, "key");
|
||||||
|
} else {
|
||||||
|
percentageTree.add({key: percentage, value: value});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
var searchInPercentageTree = function(key) {
|
||||||
|
if (percentageTree === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
var elements = percentageTree.findBest(key);
|
||||||
|
if (elements.length == 0) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements[0];
|
||||||
|
};
|
||||||
|
|
||||||
var purgeLayers = function(){
|
var purgeLayers = function(){
|
||||||
var purge=true;
|
var purge=true;
|
||||||
|
@ -102,13 +118,13 @@ GCODE.gCodeReader = (function(){
|
||||||
return {
|
return {
|
||||||
|
|
||||||
loadFile: function(reader){
|
loadFile: function(reader){
|
||||||
// console.log("loadFile");
|
|
||||||
model = [];
|
model = [];
|
||||||
z_heights = [];
|
z_heights = [];
|
||||||
|
|
||||||
|
var totalSize = reader.target.result.length;
|
||||||
lines = reader.target.result.split(/\n/);
|
lines = reader.target.result.split(/\n/);
|
||||||
reader.target.result = null;
|
reader.target.result = null;
|
||||||
prepareGCode();
|
prepareGCode(totalSize);
|
||||||
|
|
||||||
worker.postMessage({
|
worker.postMessage({
|
||||||
"cmd":"parseGCode",
|
"cmd":"parseGCode",
|
||||||
|
@ -129,32 +145,21 @@ GCODE.gCodeReader = (function(){
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
passDataToRenderer: function(){
|
passDataToRenderer: function(){
|
||||||
// console.log(model);
|
|
||||||
if(gCodeOptions["sortLayers"])sortLayers();
|
if(gCodeOptions["sortLayers"])sortLayers();
|
||||||
// console.log(model);
|
|
||||||
if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
if(gCodeOptions["purgeEmptyLayers"])purgeLayers();
|
||||||
prepareLinesIndex();
|
prepareLinesIndex();
|
||||||
// console.log(model);
|
|
||||||
GCODE.renderer.doRender(model, 0);
|
GCODE.renderer.doRender(model, 0);
|
||||||
// GCODE.renderer3d.setModel(model);
|
|
||||||
|
|
||||||
},
|
},
|
||||||
processLayerFromWorker: function(msg){
|
processLayerFromWorker: function(msg){
|
||||||
// var cmds = msg.cmds;
|
|
||||||
// var layerNum = msg.layerNum;
|
|
||||||
// var zHeightObject = msg.zHeightObject;
|
|
||||||
// var isEmpty = msg.isEmpty;
|
|
||||||
// console.log(zHeightObject);
|
|
||||||
model[msg.layerNum] = msg.cmds;
|
model[msg.layerNum] = msg.cmds;
|
||||||
z_heights[msg.zHeightObject.zValue] = msg.zHeightObject.layer;
|
z_heights[msg.zHeightObject.zValue] = msg.zHeightObject.layer;
|
||||||
// GCODE.renderer.doRender(model, msg.layerNum);
|
|
||||||
},
|
},
|
||||||
processMultiLayerFromWorker: function(msg){
|
processMultiLayerFromWorker: function(msg){
|
||||||
for(var i=0;i<msg.layerNum.length;i++){
|
for(var i=0;i<msg.layerNum.length;i++){
|
||||||
model[msg.layerNum[i]] = msg.model[msg.layerNum[i]];
|
model[msg.layerNum[i]] = msg.model[msg.layerNum[i]];
|
||||||
z_heights[msg.zHeightObject.zValue[i]] = msg.layerNum[i];
|
z_heights[msg.zHeightObject.zValue[i]] = msg.layerNum[i];
|
||||||
}
|
}
|
||||||
// console.log(model);
|
|
||||||
},
|
},
|
||||||
processAnalyzeModelDone: function(msg){
|
processAnalyzeModelDone: function(msg){
|
||||||
min = msg.min;
|
min = msg.min;
|
||||||
|
@ -190,8 +195,13 @@ GCODE.gCodeReader = (function(){
|
||||||
var result = {first: model[layer][fromSegments].gcodeLine, last: model[layer][toSegments].gcodeLine};
|
var result = {first: model[layer][fromSegments].gcodeLine, last: model[layer][toSegments].gcodeLine};
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
getLinesCmdIndex: function(line){
|
getCmdIndexForPercentage: function(percentage) {
|
||||||
return linesCmdIndex[line];
|
var command = searchInPercentageTree(percentage);
|
||||||
|
if (command === undefined) {
|
||||||
|
return undefined
|
||||||
|
} else {
|
||||||
|
return command.value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}());
|
}());
|
||||||
|
|
|
@ -0,0 +1,169 @@
|
||||||
|
// AVLTree ///////////////////////////////////////////////////////////////////
|
||||||
|
// self file is originally from the Concentré XML project (version 0.2.1)
|
||||||
|
// Licensed under GPL and LGPL
|
||||||
|
//
|
||||||
|
// Modified by Jeremy Stephens.
|
||||||
|
//
|
||||||
|
// Taken from: https://gist.github.com/viking/2424106, modified to not only use string literals when searching
|
||||||
|
|
||||||
|
// Pass in the attribute you want to use for comparing
|
||||||
|
function AVLTree(n, attr) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.attr = attr;
|
||||||
|
self.left = null;
|
||||||
|
self.right = null;
|
||||||
|
self.node = n;
|
||||||
|
self.depth = 1;
|
||||||
|
self.elements = [n];
|
||||||
|
|
||||||
|
self.balance = function() {
|
||||||
|
var ldepth = self.left == null ? 0 : self.left.depth;
|
||||||
|
var rdepth = self.right == null ? 0 : self.right.depth;
|
||||||
|
|
||||||
|
if (ldepth > rdepth + 1) {
|
||||||
|
// LR or LL rotation
|
||||||
|
var lldepth = self.left.left == null ? 0 : self.left.left.depth;
|
||||||
|
var lrdepth = self.left.right == null ? 0 : self.left.right.depth;
|
||||||
|
|
||||||
|
if (lldepth < lrdepth) {
|
||||||
|
// LR rotation consists of a RR rotation of the left child
|
||||||
|
self.left.rotateRR();
|
||||||
|
// plus a LL rotation of self node, which happens anyway
|
||||||
|
}
|
||||||
|
self.rotateLL();
|
||||||
|
} else if (ldepth + 1 < rdepth) {
|
||||||
|
// RR or RL rorarion
|
||||||
|
var rrdepth = self.right.right == null ? 0 : self.right.right.depth;
|
||||||
|
var rldepth = self.right.left == null ? 0 : self.right.left.depth;
|
||||||
|
|
||||||
|
if (rldepth > rrdepth) {
|
||||||
|
// RR rotation consists of a LL rotation of the right child
|
||||||
|
self.right.rotateLL();
|
||||||
|
// plus a RR rotation of self node, which happens anyway
|
||||||
|
}
|
||||||
|
self.rotateRR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rotateLL = function() {
|
||||||
|
// the left side is too long => rotate from the left (_not_ leftwards)
|
||||||
|
var nodeBefore = self.node;
|
||||||
|
var elementsBefore = self.elements;
|
||||||
|
var rightBefore = self.right;
|
||||||
|
self.node = self.left.node;
|
||||||
|
self.elements = self.left.elements;
|
||||||
|
self.right = self.left;
|
||||||
|
self.left = self.left.left;
|
||||||
|
self.right.left = self.right.right;
|
||||||
|
self.right.right = rightBefore;
|
||||||
|
self.right.node = nodeBefore;
|
||||||
|
self.right.elements = elementsBefore;
|
||||||
|
self.right.updateInNewLocation();
|
||||||
|
self.updateInNewLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.rotateRR = function() {
|
||||||
|
// the right side is too long => rotate from the right (_not_ rightwards)
|
||||||
|
var nodeBefore = self.node;
|
||||||
|
var elementsBefore = self.elements;
|
||||||
|
var leftBefore = self.left;
|
||||||
|
self.node = self.right.node;
|
||||||
|
self.elements = self.right.elements;
|
||||||
|
self.left = self.right;
|
||||||
|
self.right = self.right.right;
|
||||||
|
self.left.right = self.left.left;
|
||||||
|
self.left.left = leftBefore;
|
||||||
|
self.left.node = nodeBefore;
|
||||||
|
self.left.elements = elementsBefore;
|
||||||
|
self.left.updateInNewLocation();
|
||||||
|
self.updateInNewLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.updateInNewLocation = function() {
|
||||||
|
self.getDepthFromChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.getDepthFromChildren = function() {
|
||||||
|
self.depth = self.node == null ? 0 : 1;
|
||||||
|
if (self.left != null) {
|
||||||
|
self.depth = self.left.depth + 1;
|
||||||
|
}
|
||||||
|
if (self.right != null && self.depth <= self.right.depth) {
|
||||||
|
self.depth = self.right.depth + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.compare = function(n1, n2) {
|
||||||
|
var v1 = n1[self.attr];
|
||||||
|
var v2 = n2[self.attr];
|
||||||
|
if (v1 == v2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (v1 < v2) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.add = function(n) {
|
||||||
|
var o = self.compare(n, self.node);
|
||||||
|
if (o == 0) {
|
||||||
|
self.elements.push(n);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ret = false;
|
||||||
|
if (o == -1) {
|
||||||
|
if (self.left == null) {
|
||||||
|
self.left = new AVLTree(n, self.attr);
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
ret = self.left.add(n);
|
||||||
|
if (ret) {
|
||||||
|
self.balance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (o == 1) {
|
||||||
|
if (self.right == null) {
|
||||||
|
self.right = new AVLTree(n, self.attr);
|
||||||
|
ret = true;
|
||||||
|
} else {
|
||||||
|
ret = self.right.add(n);
|
||||||
|
if (ret) {
|
||||||
|
self.balance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
self.getDepthFromChildren();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.findBest = function(value) {
|
||||||
|
if (value < self.node[self.attr]) {
|
||||||
|
if (self.left != null) {
|
||||||
|
return self.left.findBest(value);
|
||||||
|
}
|
||||||
|
} else if (value > self.node[self.attr]) {
|
||||||
|
if (self.right != null) {
|
||||||
|
return self.right.findBest(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return self.elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.find = function(value) {
|
||||||
|
var elements = self.findBest(value);
|
||||||
|
for (var i = 0; i < elements.length; i++) {
|
||||||
|
if (elements[i][self.attr] == value) {
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -234,7 +234,11 @@ function PrinterStateViewModel(loginStateViewModel) {
|
||||||
var filepos = self.filepos() ? self.filepos() : "-";
|
var filepos = self.filepos() ? self.filepos() : "-";
|
||||||
return filepos + " / " + self.filesize();
|
return filepos + " / " + self.filesize();
|
||||||
});
|
});
|
||||||
|
self.heightString = ko.computed(function() {
|
||||||
|
if (!self.currentHeight())
|
||||||
|
return "-";
|
||||||
|
return self.currentHeight();
|
||||||
|
})
|
||||||
self.progressString = ko.computed(function() {
|
self.progressString = ko.computed(function() {
|
||||||
if (!self.progress())
|
if (!self.progress())
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1077,13 +1081,16 @@ function GcodeViewModel(loginStateViewModel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
self._processData = function(data) {
|
self._processData = function(data) {
|
||||||
if(!self.enabled)return;
|
if (!self.enabled) return;
|
||||||
|
if (!data.job.filename) return;
|
||||||
|
|
||||||
if(self.loadedFilename == data.job.filename) {
|
if(self.loadedFilename && self.loadedFilename == data.job.filename) {
|
||||||
var cmdIndex = GCODE.gCodeReader.getLinesCmdIndex(data.progress.progress);
|
if (data.state.flags && (data.state.flags.printing || data.state.flags.paused)) {
|
||||||
if(cmdIndex){
|
var cmdIndex = GCODE.gCodeReader.getCmdIndexForPercentage(data.progress.progress * 100);
|
||||||
GCODE.renderer.render(cmdIndex.layer, 0, cmdIndex.cmd);
|
if(cmdIndex){
|
||||||
GCODE.ui.updateLayerInfo(cmdIndex.layer);
|
GCODE.renderer.render(cmdIndex.layer, 0, cmdIndex.cmd);
|
||||||
|
GCODE.ui.updateLayerInfo(cmdIndex.layer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.errorCount = 0
|
self.errorCount = 0
|
||||||
} else if (data.job.filename) {
|
} else if (data.job.filename) {
|
||||||
|
@ -1729,43 +1736,48 @@ function ItemListHelper(listType, supportedSorting, supportedFilters, defaultSor
|
||||||
//~~ local storage
|
//~~ local storage
|
||||||
|
|
||||||
self._saveCurrentSortingToLocalStorage = function() {
|
self._saveCurrentSortingToLocalStorage = function() {
|
||||||
self._initializeLocalStorage();
|
if ( self._initializeLocalStorage() ) {
|
||||||
|
var currentSorting = self.currentSorting();
|
||||||
var currentSorting = self.currentSorting();
|
if (currentSorting !== undefined)
|
||||||
if (currentSorting !== undefined)
|
localStorage[self.listType + "." + "currentSorting"] = currentSorting;
|
||||||
localStorage[self.listType + "." + "currentSorting"] = currentSorting;
|
else
|
||||||
else
|
localStorage[self.listType + "." + "currentSorting"] = undefined;
|
||||||
localStorage[self.listType + "." + "currentSorting"] = undefined;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self._loadCurrentSortingFromLocalStorage = function() {
|
self._loadCurrentSortingFromLocalStorage = function() {
|
||||||
self._initializeLocalStorage();
|
if ( self._initializeLocalStorage() ) {
|
||||||
|
if (_.contains(_.keys(supportedSorting), localStorage[self.listType + "." + "currentSorting"]))
|
||||||
if (_.contains(_.keys(supportedSorting), localStorage[self.listType + "." + "currentSorting"]))
|
self.currentSorting(localStorage[self.listType + "." + "currentSorting"]);
|
||||||
self.currentSorting(localStorage[self.listType + "." + "currentSorting"]);
|
else
|
||||||
else
|
self.currentSorting(defaultSorting);
|
||||||
self.currentSorting(defaultSorting);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self._saveCurrentFiltersToLocalStorage = function() {
|
self._saveCurrentFiltersToLocalStorage = function() {
|
||||||
self._initializeLocalStorage();
|
if ( self._initializeLocalStorage() ) {
|
||||||
|
var filters = _.intersection(_.keys(self.supportedFilters), self.currentFilters());
|
||||||
var filters = _.intersection(_.keys(self.supportedFilters), self.currentFilters());
|
localStorage[self.listType + "." + "currentFilters"] = JSON.stringify(filters);
|
||||||
localStorage[self.listType + "." + "currentFilters"] = JSON.stringify(filters);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self._loadCurrentFiltersFromLocalStorage = function() {
|
self._loadCurrentFiltersFromLocalStorage = function() {
|
||||||
self._initializeLocalStorage();
|
if ( self._initializeLocalStorage() ) {
|
||||||
|
self.currentFilters(_.intersection(_.keys(self.supportedFilters), JSON.parse(localStorage[self.listType + "." + "currentFilters"])));
|
||||||
self.currentFilters(_.intersection(_.keys(self.supportedFilters), JSON.parse(localStorage[self.listType + "." + "currentFilters"])));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self._initializeLocalStorage = function() {
|
self._initializeLocalStorage = function() {
|
||||||
|
if (!Modernizr.localstorage)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (localStorage[self.listType + "." + "currentSorting"] !== undefined && localStorage[self.listType + "." + "currentFilters"] !== undefined && JSON.parse(localStorage[self.listType + "." + "currentFilters"]) instanceof Array)
|
if (localStorage[self.listType + "." + "currentSorting"] !== undefined && localStorage[self.listType + "." + "currentFilters"] !== undefined && JSON.parse(localStorage[self.listType + "." + "currentFilters"]) instanceof Array)
|
||||||
return;
|
return true;
|
||||||
|
|
||||||
localStorage[self.listType + "." + "currentSorting"] = self.defaultSorting;
|
localStorage[self.listType + "." + "currentSorting"] = self.defaultSorting;
|
||||||
localStorage[self.listType + "." + "currentFilters"] = JSON.stringify(self.defaultFilters);
|
localStorage[self.listType + "." + "currentFilters"] = JSON.stringify(self.defaultFilters);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
self._loadCurrentFiltersFromLocalStorage();
|
self._loadCurrentFiltersFromLocalStorage();
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
File: <strong data-bind="text: filename"></strong> <strong data-bind="visible: sd">(SD)</strong><br>
|
File: <strong data-bind="text: filename"></strong> <strong data-bind="visible: sd">(SD)</strong><br>
|
||||||
Filament: <strong data-bind="text: filament"></strong><br>
|
Filament: <strong data-bind="text: filament"></strong><br>
|
||||||
Estimated Print Time: <strong data-bind="text: estimatedPrintTime"></strong><br>
|
Estimated Print Time: <strong data-bind="text: estimatedPrintTime"></strong><br>
|
||||||
Height: <strong data-bind="text: currentHeight"></strong><br>
|
Height: <strong data-bind="text: heightString"></strong><br>
|
||||||
Print Time: <strong data-bind="text: printTime"></strong><br>
|
Print Time: <strong data-bind="text: printTime"></strong><br>
|
||||||
Print Time Left: <strong data-bind="text: printTimeLeft"></strong><br>
|
Print Time Left: <strong data-bind="text: printTimeLeft"></strong><br>
|
||||||
Printed: <strong data-bind="text: byteString"></strong><br>
|
Printed: <strong data-bind="text: byteString"></strong><br>
|
||||||
|
@ -579,6 +579,7 @@
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/modernizr.custom.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/modernizr.custom.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/underscore.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/underscore.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/knockout.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/knockout.js') }}"></script>
|
||||||
|
<script type="text/javascript" src="{{ url_for('static', filename='js/avltree.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap-modalmanager.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap-modalmanager.js') }}"></script>
|
||||||
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap-modal.js') }}"></script>
|
<script type="text/javascript" src="{{ url_for('static', filename='js/bootstrap/bootstrap-modal.js') }}"></script>
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
__author__ = "Gina Häußge <osd@foosel.net>"
|
__author__ = "Gina Häußge <osd@foosel.net>"
|
||||||
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
def getFormattedSize(num):
|
def getFormattedSize(num):
|
||||||
"""
|
"""
|
||||||
Taken from http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size
|
Taken from http://stackoverflow.com/questions/1094841/reusable-library-to-get-human-readable-version-of-file-size
|
||||||
|
@ -38,4 +40,7 @@ def getClass(name):
|
||||||
m = __import__(module)
|
m = __import__(module)
|
||||||
for comp in parts[1:]:
|
for comp in parts[1:]:
|
||||||
m = getattr(m, comp)
|
m = getattr(m, comp)
|
||||||
return m
|
return m
|
||||||
|
|
||||||
|
def matchesGcode(line, gcode):
|
||||||
|
return re.search("^\s*%s\D" % gcode, line, re.I)
|
|
@ -16,6 +16,8 @@ import serial
|
||||||
from octoprint.util.avr_isp import stk500v2
|
from octoprint.util.avr_isp import stk500v2
|
||||||
from octoprint.util.avr_isp import ispBase
|
from octoprint.util.avr_isp import ispBase
|
||||||
|
|
||||||
|
from octoprint.util import matchesGcode
|
||||||
|
|
||||||
from octoprint.settings import settings
|
from octoprint.settings import settings
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -358,7 +360,7 @@ class MachineCom(object):
|
||||||
self._bedTargetTemp = 0
|
self._bedTargetTemp = 0
|
||||||
self._commandQueue = queue.Queue()
|
self._commandQueue = queue.Queue()
|
||||||
self._logQueue = queue.Queue(256)
|
self._logQueue = queue.Queue(256)
|
||||||
self._currentZ = -1
|
self._currentZ = None
|
||||||
self._heatupWaitStartTime = 0
|
self._heatupWaitStartTime = 0
|
||||||
self._heatupWaitTimeLost = 0.0
|
self._heatupWaitTimeLost = 0.0
|
||||||
|
|
||||||
|
@ -846,20 +848,20 @@ class MachineCom(object):
|
||||||
with self._sendingLock:
|
with self._sendingLock:
|
||||||
if self._serial is None:
|
if self._serial is None:
|
||||||
return
|
return
|
||||||
if 'M109' in cmd or 'M190' in cmd:
|
if matchesGcode(cmd, "M109") or matchesGcode(cmd, "M190"):
|
||||||
self._heatupWaitStartTime = time.time()
|
self._heatupWaitStartTime = time.time()
|
||||||
if 'M104' in cmd or 'M109' in cmd:
|
if matchesGcode(cmd, "M104") or matchesGcode(cmd, "M109"):
|
||||||
try:
|
try:
|
||||||
self._targetTemp = float(re.search('S([0-9]+)', cmd).group(1))
|
self._targetTemp = float(re.search('S([0-9]+)', cmd).group(1))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if 'M140' in cmd or 'M190' in cmd:
|
if matchesGcode(cmd, "M140") or matchesGcode(cmd, "M190"):
|
||||||
try:
|
try:
|
||||||
self._bedTargetTemp = float(re.search('S([0-9]+)', cmd).group(1))
|
self._bedTargetTemp = float(re.search('S([0-9]+)', cmd).group(1))
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if "M110" in cmd:
|
if matchesGcode(cmd, "M110"):
|
||||||
newLineNumber = None
|
newLineNumber = None
|
||||||
if " N" in cmd:
|
if " N" in cmd:
|
||||||
try:
|
try:
|
||||||
|
@ -945,17 +947,19 @@ class MachineCom(object):
|
||||||
line = line[0]
|
line = line[0]
|
||||||
|
|
||||||
if not self.isStreaming():
|
if not self.isStreaming():
|
||||||
try:
|
try:
|
||||||
if line == 'M0' or line == 'M1':
|
if matchesGcode(line, "M0") or matchesGcode(line, "M1"):
|
||||||
self.setPause(True)
|
self.setPause(True)
|
||||||
line = 'M105' #Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause.
|
line = "M105" # Don't send the M0 or M1 to the machine, as M0 and M1 are handled as an LCD menu pause.
|
||||||
if ('G0' in line or 'G1' in line) and 'Z' in line:
|
if self._printSection in self._feedRateModifier:
|
||||||
z = float(re.search('Z([0-9\.]*)', line).group(1))
|
line = re.sub('F([0-9]*)', lambda m: 'F' + str(int(int(m.group(1)) * self._feedRateModifier[self._printSection])), line)
|
||||||
if self._currentZ != z:
|
if (matchesGcode(line, "G0") or matchesGcode(line, "G1")) and 'Z' in line:
|
||||||
self._currentZ = z
|
z = float(re.search('Z([0-9\.]*)', line).group(1))
|
||||||
self._callback.mcZChange(z)
|
if self._currentZ != z:
|
||||||
except:
|
self._currentZ = z
|
||||||
self._log("Unexpected error: %s" % (getExceptionString()))
|
self._callback.mcZChange(z)
|
||||||
|
except:
|
||||||
|
self._log("Unexpected error: %s" % (getExceptionString()))
|
||||||
self._sendCommand(line, True)
|
self._sendCommand(line, True)
|
||||||
self._callback.mcProgress()
|
self._callback.mcProgress()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue