modularize print export
This commit is contained in:
parent
36682581f0
commit
c74dd09643
8 changed files with 505 additions and 445 deletions
|
|
@ -756,6 +756,7 @@ var gs_kiri_cam = exports;
|
|||
let center = BASE.newPoint(0,0,slice.z);
|
||||
let offset = (tabWidth + toolDiam) / 2;
|
||||
let ints = [];
|
||||
let segs = [];
|
||||
while (count-- > 0) {
|
||||
let slope = BASE.newSlopeFromAngle(angle);
|
||||
let normal = BASE.newSlopeFromAngle(angle + 90);
|
||||
|
|
@ -770,10 +771,11 @@ var gs_kiri_cam = exports;
|
|||
ints.push(int2);
|
||||
}
|
||||
angle -= angle_inc;
|
||||
// segs.push(newPolygon([c1,o1]));
|
||||
// segs.push(newPolygon([c2,o2]));
|
||||
}
|
||||
if (ints.length) {
|
||||
ints.push(ints.shift());
|
||||
let segs = [];
|
||||
for (let i=0; i<ints.length; i+=2) {
|
||||
segs.push(trace.emitSegment(ints[i], ints[i+1]));
|
||||
}
|
||||
|
|
|
|||
424
js/kiri-export.js
Normal file
424
js/kiri-export.js
Normal file
|
|
@ -0,0 +1,424 @@
|
|||
/** Copyright Stewart Allen -- All Rights Reserved */
|
||||
|
||||
"use strict";
|
||||
|
||||
let gs_kiri_export = exports;
|
||||
|
||||
(function() {
|
||||
|
||||
if (!self.kiri) self.kiri = { };
|
||||
if (self.kiri.export) return;
|
||||
|
||||
let KIRI = self.kiri,
|
||||
WIN = self.window,
|
||||
DOC = self.document,
|
||||
LOC = self.location,
|
||||
API = KIRI.api,
|
||||
SDB = API.sdb,
|
||||
UI = API.ui,
|
||||
UC = API.uc,
|
||||
STATS = API.stats,
|
||||
MODES = API.const.MODES,
|
||||
printSeq = parseInt(SDB['kiri-print-seq'] || SDB['print-seq'] || "0") + 1;
|
||||
|
||||
KIRI.export = exportPrint;
|
||||
|
||||
function exportPrint() {
|
||||
let currentPrint = API.print.get();
|
||||
if (!currentPrint) {
|
||||
API.function.print(exportPrint);
|
||||
return;
|
||||
}
|
||||
STATS.add(`ua_${API.mode.get_lower()}_export`);
|
||||
switch (API.mode.get()) {
|
||||
case 'LASER': return exportPrintLaser(currentPrint);
|
||||
case 'FDM': return exportPrintGCODE(currentPrint);
|
||||
case 'CAM': return exportPrintGCODE(currentPrint);
|
||||
}
|
||||
}
|
||||
|
||||
function exportPrintGCODE(currentPrint) {
|
||||
if (!currentPrint) {
|
||||
API.function.print(exportPrint);
|
||||
return;
|
||||
}
|
||||
currentPrint.exportGCode(true, function(gcode) {
|
||||
exportGCode(gcode,currentPrint);
|
||||
});
|
||||
}
|
||||
|
||||
function exportPrintLaser(currentPrint) {
|
||||
if (!currentPrint) {
|
||||
API.function.print(exportPrintLaser);
|
||||
return;
|
||||
}
|
||||
|
||||
let filename = "laser-"+(new Date().getTime().toString(36));
|
||||
|
||||
function download_svg() {
|
||||
saveAs(new Blob(
|
||||
[currentPrint.exportSVG($('print-color').value)],
|
||||
{type:"application/octet-stream"}),
|
||||
$('print-filename').value + ".svg");
|
||||
}
|
||||
|
||||
function download_dxf() {
|
||||
saveAs(new Blob(
|
||||
[currentPrint.exportDXF()],
|
||||
{type:"application/octet-stream"}),
|
||||
$('print-filename').value + ".dxf");
|
||||
}
|
||||
|
||||
function download_gcode() {
|
||||
saveAs(new Blob(
|
||||
[currentPrint.exportLaserGCode()],
|
||||
{type:"application/octet-stream"}),
|
||||
$('print-filename').value + ".gcode");
|
||||
}
|
||||
|
||||
API.ajax("/kiri/output-laser.html", function(html) {
|
||||
let segments = 0;
|
||||
currentPrint.output.forEach(layer => { segments += layer.length });
|
||||
UI.print.innerHTML = html;
|
||||
$('print-filename').value = filename;
|
||||
$('print-lines').value = segments;
|
||||
$('print-close').onclick = API.modal.hide;
|
||||
$('print-svg').onclick = download_svg;
|
||||
$('print-dxf').onclick = download_dxf;
|
||||
$('print-lg').onclick = download_gcode;
|
||||
API.modal.show('print');
|
||||
});
|
||||
}
|
||||
|
||||
function exportGCode(gcode, currentPrint) {
|
||||
SDB['kiri-print-seq'] = printSeq++;
|
||||
|
||||
let settings = API.conf.get(),
|
||||
MODE = API.mode.get_id(),
|
||||
pre = (MODE === MODES.CAM ? "cnc-" : "print-") + (printSeq.toString().padStart(3,"0")),
|
||||
filename = pre,// + (new Date().getTime().toString(36)),
|
||||
fileext = settings.device.gcodeFExt || "gcode",
|
||||
codeproc = settings.device.gcodeProc,
|
||||
octo_host,
|
||||
octo_apik,
|
||||
grid_host,
|
||||
grid_apik,
|
||||
grid_target,
|
||||
grid_targets = {},
|
||||
grid_local,
|
||||
grid_uuid;
|
||||
|
||||
// run gcode post processor function (when supplied and valid)
|
||||
if (codeproc && self[codeproc]) {
|
||||
gcode = self[codeproc](gcode);
|
||||
}
|
||||
|
||||
function getBlob() {
|
||||
return new Blob(
|
||||
[gcode],
|
||||
{type:"application/octet-stream"});
|
||||
}
|
||||
|
||||
function sendto_octoprint() {
|
||||
if (!(octo_host && octo_apik)) return;
|
||||
|
||||
let form = new FormData(),
|
||||
ajax = new XMLHttpRequest(),
|
||||
host = octo_host.value.toLowerCase(),
|
||||
apik = octo_apik.value;
|
||||
|
||||
if (host.indexOf("http") !== 0) {
|
||||
API.show.alert("host missing protocol (http:// or https://)");
|
||||
return;
|
||||
}
|
||||
if (SECURE && !isSecure(host)) {
|
||||
API.show.alert("host must begin with 'https' on a secure site");
|
||||
return;
|
||||
}
|
||||
|
||||
SDB['octo-host'] = host.trim();
|
||||
SDB['octo-apik'] = apik.trim();
|
||||
|
||||
filename = $('print-filename').value;
|
||||
form.append("file", getBlob(), filename+"."+fileext);
|
||||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState === 4) {
|
||||
let status = ajax.status;
|
||||
STATS.add(`ua_${getModeLower()}_print_octo_${status}`);
|
||||
if (status >= 200 && status < 300) {
|
||||
API.modal.hide();
|
||||
} else {
|
||||
API.show.alert("octoprint error\nstatus: "+status+"\nmessage: "+ajax.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
ajax.upload.addEventListener('progress', function(evt) {
|
||||
setProgress(Math.ceil(evt.loaded/evt.total), "sending");
|
||||
});
|
||||
ajax.open("POST", host+"/api/files/local");
|
||||
ajax.setRequestHeader("X-Api-Key", apik);
|
||||
ajax.send(form);
|
||||
}
|
||||
|
||||
function gridhost_tracker(host,key) {
|
||||
ajax(host+"/api/check?key="+key, function(data) {
|
||||
data = js2o(data);
|
||||
DBUG.log(data);
|
||||
if (!(data.done || data.error)) {
|
||||
setTimeout(function() { gridhost_tracker(host,key) }, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function gridlocal_probe(ev, devs) {
|
||||
if (ev && ev.code !== 'Enter') return;
|
||||
|
||||
if (!devs && API.probe.local(gridlocal_probe)) return;
|
||||
|
||||
grid_local = devs;
|
||||
|
||||
let html = [];
|
||||
for (let uuid in devs) {
|
||||
let dev = devs[uuid];
|
||||
html.push(`<option id="gl-${uuid}" value="${uuid}">${dev.stat.device.name}</option>`);
|
||||
}
|
||||
$('grid-local').innerHTML = html.join('\n');
|
||||
}
|
||||
|
||||
function sendto_gridlocal() {
|
||||
let uuid = $('grid-local').value;
|
||||
let dev = grid_local[uuid];
|
||||
if (dev) {
|
||||
let file = $('print-filename').value;
|
||||
fetch(
|
||||
`/api/grid_send?uuid=${uuid}&file=${encodeURIComponent(file + "." + fileext)}`,
|
||||
{method: "POST", body: gcode}
|
||||
)
|
||||
.then(t => t.text())
|
||||
.then(t => {
|
||||
STATS.add(`ua_${getModeLower()}_print_local_ok`);
|
||||
console.log({grid_spool_said: t});
|
||||
})
|
||||
.catch(e => {
|
||||
STATS.add(`ua_${getModeLower()}_print_local_err`);
|
||||
console.log({grid_local_spool_error: e});
|
||||
})
|
||||
.finally(() => {
|
||||
API.modal.hide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function admin_gridlocal() {
|
||||
let dev = grid_local[$('grid-local').value];
|
||||
if (dev && dev.stat && dev.stat.device) {
|
||||
let dsd = dev.stat.device;
|
||||
window.open(`http://${dsd.addr[0]}:${dsd.port || 4080}`, "_grid_admin");
|
||||
}
|
||||
}
|
||||
|
||||
function gridhost_probe(ev, set_host) {
|
||||
if (ev && ev.code !== 'Enter') return;
|
||||
if (!(grid_host && grid_apik)) return;
|
||||
|
||||
if (set_host) grid_host.value = set_host;
|
||||
|
||||
let xhtr = new XMLHttpRequest(),
|
||||
host = grid_host.value,
|
||||
apik = grid_apik.value,
|
||||
target = grid_target.value;
|
||||
|
||||
if (!apik) $('gpapik').style.display = 'none';
|
||||
|
||||
if (!host && API.probe.grid(gridhost_probe)) return;
|
||||
|
||||
if (!host) return;
|
||||
|
||||
xhtr.onreadystatechange = function() {
|
||||
if (xhtr.readyState === 4) {
|
||||
if (xhtr.status >= 200 && xhtr.status < 300) {
|
||||
SDB['grid-host'] = host;
|
||||
SDB['grid-apik'] = apik;
|
||||
let res = JSON.parse(xhtr.responseText);
|
||||
let sel = false;
|
||||
let match = false;
|
||||
let first = null;
|
||||
let html = [];
|
||||
grid_targets = {};
|
||||
for (let key in res) {
|
||||
first = first || key;
|
||||
if (!SDB['grid-target']) {
|
||||
SDB['grid-target'] = key;
|
||||
sel = true;
|
||||
} else {
|
||||
sel = SDB['grid-target'] === key;
|
||||
}
|
||||
match = match || sel;
|
||||
grid_targets[html.length] = key;
|
||||
html.push(
|
||||
"<option id='gpo-'" + key + " value='" +key + "'" +
|
||||
(sel ? " selected" : "") +
|
||||
">" +
|
||||
(res[key].comment || key) +
|
||||
"</option>"
|
||||
);
|
||||
}
|
||||
if (!match) {
|
||||
SDB['grid-target'] = first;
|
||||
}
|
||||
grid_target.innerHTML = html.join('\n');
|
||||
} else if (xhtr.status === 401) {
|
||||
$('gpapik').style.display = '';
|
||||
} else {
|
||||
SDB.removeItem('grid-host');
|
||||
SDB.removeItem('grid-apik');
|
||||
console.log("invalid grid:host url");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhtr.open("GET", host + "/api/active?key=" + apik);
|
||||
xhtr.send();
|
||||
}
|
||||
|
||||
function sendto_gridhost() {
|
||||
if (!(grid_host && grid_apik)) return;
|
||||
|
||||
let xhtr = new XMLHttpRequest(),
|
||||
host = grid_host.value,
|
||||
apik = grid_apik.value,
|
||||
target = SDB['grid-target'] || '';
|
||||
|
||||
if (target === '') {
|
||||
API.show.alert('invalid or missing target');
|
||||
return;
|
||||
}
|
||||
if (host.indexOf("http") !== 0) {
|
||||
API.show.alert("host missing protocol (http:// or https://)");
|
||||
return;
|
||||
}
|
||||
if (host.indexOf("://") < 0) {
|
||||
API.show.alert("host:port malformed");
|
||||
return;
|
||||
}
|
||||
if (SECURE && !isSecure(host)) {
|
||||
API.show.alert("host must begin with 'https' on a secure site");
|
||||
return;
|
||||
}
|
||||
|
||||
SDB['grid-host'] = host.trim();
|
||||
SDB['grid-apik'] = apik.trim();
|
||||
|
||||
xhtr.onreadystatechange = function() {
|
||||
if (xhtr.readyState === 4) {
|
||||
let status = xhtr.status;
|
||||
STATS.add(`ua_${getModeLower()}_print_grid_${status}`);
|
||||
if (status >= 200 && status < 300) {
|
||||
let json = js2o(xhtr.responseText);
|
||||
gridhost_tracker(host,json.key);
|
||||
API.ajax(host+"/api/wait?key="+json.key, function(data) {
|
||||
data = js2o(data);
|
||||
DBUG.log(data);
|
||||
API.show.alert("print to "+target+": "+data.status, 600);
|
||||
});
|
||||
} else {
|
||||
API.show.alert("grid:host error\nstatus: "+status+"\nmessage: "+xhtr.responseText, 10000);
|
||||
}
|
||||
setProgress(0);
|
||||
}
|
||||
};
|
||||
xhtr.upload.addEventListener('progress', function(evt) {
|
||||
setProgress(Math.ceil(evt.loaded/evt.total), "sending");
|
||||
});
|
||||
filename = $('print-filename').value;
|
||||
xhtr.open("POST",
|
||||
host + "/api/print?" +
|
||||
"filename=" + filename +
|
||||
"&target=" + target +
|
||||
"&key=" + apik +
|
||||
"&time=" + Math.round(currentPrint.time) +
|
||||
"&length=" + Math.round(currentPrint.distance) +
|
||||
"&image=" + filename
|
||||
);
|
||||
xhtr.setRequestHeader("Content-Type", "text/plain");
|
||||
xhtr.send(screenShot ? [gcode,screenShot].join("\0") : gcode);
|
||||
API.modal.hide();
|
||||
}
|
||||
|
||||
function download() {
|
||||
filename = $('print-filename').value;
|
||||
saveAs(getBlob(), filename + "." + fileext);
|
||||
}
|
||||
|
||||
function pad(v) {
|
||||
v = v.toString();
|
||||
return v.length < 2 ? '0' + v : v;
|
||||
}
|
||||
|
||||
function calcWeight() {
|
||||
try {
|
||||
$('print-weight').value = (
|
||||
UTIL.round((Math.PI * UTIL.sqr(currentPrint.settings.device.filamentSize/2)) * currentPrint.distance * 1.25 / 1000, 2)
|
||||
);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
function calcTime() {
|
||||
let floor = Math.floor,
|
||||
time = floor(currentPrint.time),
|
||||
hours = floor(time / 3600),
|
||||
newtime = time - hours * 3600,
|
||||
mins = floor(newtime / 60),
|
||||
secs = newtime - mins * 60;
|
||||
|
||||
$('mill-time').value = $('print-time').value = [pad(hours),pad(mins),pad(secs)].join(':');
|
||||
}
|
||||
|
||||
API.ajax("/kiri/output-gcode.html", function(html) {
|
||||
UI.print.innerHTML = html;
|
||||
$('print-close').onclick = API.modal.hide;
|
||||
$('print-download').onclick = download;
|
||||
$('print-octoprint').onclick = sendto_octoprint;
|
||||
$('print-gridhost').onclick = sendto_gridhost;
|
||||
$('print-gridlocal').onclick = sendto_gridlocal;
|
||||
$('admin-gridlocal').onclick = admin_gridlocal;
|
||||
$('print-filament-row').style.display = MODE === MODES.FDM ? '' : 'none';
|
||||
$('mill-info').style.display = MODE === MODES.CAM ? '' : 'none';
|
||||
$('print-filename').value = filename;
|
||||
$('print-filesize').value = currentPrint.bytes;
|
||||
$('print-filament').value = Math.round(currentPrint.distance);
|
||||
$('grid-host').onkeyup = gridhost_probe;
|
||||
$('grid-apik').onkeyup = gridhost_probe;
|
||||
calcTime();
|
||||
if (MODE === MODES.FDM) calcWeight();
|
||||
octo_host = $('octo-host');
|
||||
octo_apik = $('octo-apik');
|
||||
if (MODE === MODES.CAM) {
|
||||
$('send-to-octoprint').style.display = 'none';
|
||||
} else {
|
||||
$('send-to-octoprint').style.display = '';
|
||||
}
|
||||
// hide octoprint when hard-coded in the url
|
||||
if (API.const.OCTO) {
|
||||
$('ophost').style.display = 'none';
|
||||
$('opapik').style.display = 'none';
|
||||
$('ophint').style.display = 'none';
|
||||
$('send-to-gridhost').style.display = 'none';
|
||||
}
|
||||
octo_host.value = SDB['octo-host'] || '';
|
||||
octo_apik.value = SDB['octo-apik'] || '';
|
||||
grid_host = $('grid-host');
|
||||
grid_apik = $('grid-apik');
|
||||
grid_target = $('grid-target');
|
||||
grid_target.onchange = function(ev) {
|
||||
SDB['grid-target'] = grid_targets[grid_target.selectedIndex];
|
||||
};
|
||||
grid_host.value = SDB['grid-host'] || '';
|
||||
grid_apik.value = SDB['grid-apik'] || '';
|
||||
gridhost_probe();
|
||||
gridlocal_probe();
|
||||
API.modal.show('print');
|
||||
});
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -1497,13 +1497,13 @@ var gs_kiri_init = exports;
|
|||
|
||||
// import octoprint settings from url
|
||||
if (SETUP.ophost) {
|
||||
OCTOPRINT = {
|
||||
let ohost = API.const.OCTO = {
|
||||
host: SETUP.ophost[0],
|
||||
apik: SETUP.opkey ? SETUP.opkey[0] : ''
|
||||
};
|
||||
SDB['octo-host'] = OCTOPRINT.host;
|
||||
SDB['octo-apik'] = OCTOPRINT.apik;
|
||||
console.log({octoprint:OCTOPRINT});
|
||||
SDB['octo-host'] = ohost.host;
|
||||
SDB['octo-apik'] = ohost.apik;
|
||||
console.log({octoprint:ohost});
|
||||
}
|
||||
|
||||
// mode passed on url
|
||||
|
|
|
|||
458
js/kiri.js
458
js/kiri.js
|
|
@ -50,7 +50,6 @@ self.kiri.license = exports.LICENSE;
|
|||
selectedMeshes = [],
|
||||
localFilterKey ='kiri-gcode-filters',
|
||||
localFilters = js2o(SDB.getItem(localFilterKey)) || [],
|
||||
OCTOPRINT = null,
|
||||
// ---------------
|
||||
widget_selected_color = 0xbbff00,
|
||||
widget_deselected_color = 0xffff00,
|
||||
|
|
@ -63,7 +62,6 @@ self.kiri.license = exports.LICENSE;
|
|||
sliced_opacity = 0.0,
|
||||
sliced_opacity_cam = 0.25,
|
||||
// ---------------
|
||||
printSeq = parseInt(SDB['kiri-print-seq'] || SDB['print-seq'] || "0") + 1,
|
||||
renderMode = 4,
|
||||
viewMode = VIEWS.ARRANGE,
|
||||
layoutOnAdd = true,
|
||||
|
|
@ -184,7 +182,7 @@ self.kiri.license = exports.LICENSE;
|
|||
function: {
|
||||
slice: prepareSlices,
|
||||
print: preparePrint,
|
||||
export: exportPrint,
|
||||
export: function() { KIRI.export() },
|
||||
clear: clearWidgetCache
|
||||
},
|
||||
hide: {
|
||||
|
|
@ -207,6 +205,10 @@ self.kiri.license = exports.LICENSE;
|
|||
movedSet : function(b) { mouseMoved = b }
|
||||
},
|
||||
opacity,
|
||||
print: {
|
||||
get: function() { return currentPrint },
|
||||
clear: clearPrint
|
||||
},
|
||||
probe: {
|
||||
local : function() { return false },
|
||||
grid : function() { return false },
|
||||
|
|
@ -667,401 +669,9 @@ self.kiri.license = exports.LICENSE;
|
|||
updateSliderMax(true);
|
||||
showSlices();
|
||||
|
||||
if (typeof(callback) === 'function') callback();
|
||||
})
|
||||
}
|
||||
|
||||
function exportPrint() {
|
||||
if (!currentPrint) {
|
||||
preparePrint(exportPrint);
|
||||
return;
|
||||
}
|
||||
STATS.add(`ua_${getModeLower()}_export`);
|
||||
switch (settings.mode) {
|
||||
case 'LASER': return exportPrintLaser();
|
||||
case 'FDM': return exportPrintGCODE();
|
||||
case 'CAM': return exportPrintGCODE();
|
||||
}
|
||||
}
|
||||
|
||||
function exportPrintGCODE() {
|
||||
if (!currentPrint) {
|
||||
preparePrint(exportPrint);
|
||||
return;
|
||||
}
|
||||
currentPrint.exportGCode(true, function(gcode) {
|
||||
exportGCode(gcode);
|
||||
});
|
||||
}
|
||||
|
||||
function exportPrintLaser() {
|
||||
if (!currentPrint) {
|
||||
preparePrint(exportPrintLaser);
|
||||
return;
|
||||
}
|
||||
|
||||
var filename = "laser-"+(new Date().getTime().toString(36));
|
||||
|
||||
function download_svg() {
|
||||
saveAs(new Blob(
|
||||
[currentPrint.exportSVG($('print-color').value)],
|
||||
{type:"application/octet-stream"}),
|
||||
$('print-filename').value + ".svg");
|
||||
}
|
||||
|
||||
function download_dxf() {
|
||||
saveAs(new Blob(
|
||||
[currentPrint.exportDXF()],
|
||||
{type:"application/octet-stream"}),
|
||||
$('print-filename').value + ".dxf");
|
||||
}
|
||||
|
||||
function download_gcode() {
|
||||
saveAs(new Blob(
|
||||
[currentPrint.exportLaserGCode()],
|
||||
{type:"application/octet-stream"}),
|
||||
$('print-filename').value + ".gcode");
|
||||
}
|
||||
|
||||
ajax("/kiri/output-laser.html", function(html) {
|
||||
let segments = 0;
|
||||
currentPrint.output.forEach(layer => { segments += layer.length });
|
||||
UI.print.innerHTML = html;
|
||||
$('print-filename').value = filename;
|
||||
$('print-lines').value = segments;
|
||||
$('print-close').onclick = hideModal;
|
||||
$('print-svg').onclick = download_svg;
|
||||
$('print-dxf').onclick = download_dxf;
|
||||
$('print-lg').onclick = download_gcode;
|
||||
showModal('print');
|
||||
});
|
||||
}
|
||||
|
||||
function exportGCode(gcode) {
|
||||
SDB['kiri-print-seq'] = printSeq++;
|
||||
|
||||
var pre = (MODE === MODES.CAM ? "cnc-" : "print-") + (printSeq.toString().padStart(3,"0")),
|
||||
filename = pre,// + (new Date().getTime().toString(36)),
|
||||
fileext = settings.device.gcodeFExt || "gcode",
|
||||
codeproc = settings.device.gcodeProc,
|
||||
octo_host,
|
||||
octo_apik,
|
||||
grid_host,
|
||||
grid_apik,
|
||||
grid_target,
|
||||
grid_targets = {},
|
||||
grid_local,
|
||||
grid_uuid;
|
||||
|
||||
// run gcode post processor function (when supplied and valid)
|
||||
if (codeproc && self[codeproc]) {
|
||||
gcode = self[codeproc](gcode);
|
||||
}
|
||||
|
||||
function getBlob() {
|
||||
return new Blob(
|
||||
[gcode],
|
||||
{type:"application/octet-stream"});
|
||||
}
|
||||
|
||||
function sendto_octoprint() {
|
||||
if (!(octo_host && octo_apik)) return;
|
||||
|
||||
var form = new FormData(),
|
||||
ajax = new XMLHttpRequest(),
|
||||
host = octo_host.value.toLowerCase(),
|
||||
apik = octo_apik.value;
|
||||
|
||||
if (host.indexOf("http") !== 0) {
|
||||
alert2("host missing protocol (http:// or https://)");
|
||||
return;
|
||||
if (typeof(callback) === 'function') {
|
||||
callback();
|
||||
}
|
||||
if (SECURE && !isSecure(host)) {
|
||||
alert2("host must begin with 'https' on a secure site");
|
||||
return;
|
||||
}
|
||||
|
||||
SDB['octo-host'] = host.trim();
|
||||
SDB['octo-apik'] = apik.trim();
|
||||
|
||||
filename = $('print-filename').value;
|
||||
form.append("file", getBlob(), filename+"."+fileext);
|
||||
ajax.onreadystatechange = function() {
|
||||
if (ajax.readyState === 4) {
|
||||
var status = ajax.status;
|
||||
STATS.add(`ua_${getModeLower()}_print_octo_${status}`);
|
||||
if (status >= 200 && status < 300) {
|
||||
hideModal();
|
||||
} else {
|
||||
alert2("octoprint error\nstatus: "+status+"\nmessage: "+ajax.responseText);
|
||||
}
|
||||
}
|
||||
};
|
||||
ajax.upload.addEventListener('progress', function(evt) {
|
||||
setProgress(Math.ceil(evt.loaded/evt.total), "sending");
|
||||
});
|
||||
ajax.open("POST", host+"/api/files/local");
|
||||
ajax.setRequestHeader("X-Api-Key", apik);
|
||||
ajax.send(form);
|
||||
}
|
||||
|
||||
function gridhost_tracker(host,key) {
|
||||
ajax(host+"/api/check?key="+key, function(data) {
|
||||
data = js2o(data);
|
||||
DBUG.log(data);
|
||||
if (!(data.done || data.error)) {
|
||||
setTimeout(function() { gridhost_tracker(host,key) }, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function gridlocal_probe(ev, devs) {
|
||||
if (ev && ev.code !== 'Enter') return;
|
||||
|
||||
if (!devs && API.probe.local(gridlocal_probe)) return;
|
||||
|
||||
grid_local = devs;
|
||||
|
||||
let html = [];
|
||||
for (let uuid in devs) {
|
||||
let dev = devs[uuid];
|
||||
html.push(`<option id="gl-${uuid}" value="${uuid}">${dev.stat.device.name}</option>`);
|
||||
}
|
||||
$('grid-local').innerHTML = html.join('\n');
|
||||
}
|
||||
|
||||
function sendto_gridlocal() {
|
||||
let uuid = $('grid-local').value;
|
||||
let dev = grid_local[uuid];
|
||||
if (dev) {
|
||||
let file = $('print-filename').value;
|
||||
fetch(
|
||||
`/api/grid_send?uuid=${uuid}&file=${encodeURIComponent(file + "." + fileext)}`,
|
||||
{method: "POST", body: gcode}
|
||||
)
|
||||
.then(t => t.text())
|
||||
.then(t => {
|
||||
STATS.add(`ua_${getModeLower()}_print_local_ok`);
|
||||
console.log({grid_spool_said: t});
|
||||
})
|
||||
.catch(e => {
|
||||
STATS.add(`ua_${getModeLower()}_print_local_err`);
|
||||
console.log({grid_local_spool_error: e});
|
||||
})
|
||||
.finally(() => {
|
||||
hideModal();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function admin_gridlocal() {
|
||||
let dev = grid_local[$('grid-local').value];
|
||||
if (dev && dev.stat && dev.stat.device) {
|
||||
let dsd = dev.stat.device;
|
||||
window.open(`http://${dsd.addr[0]}:${dsd.port || 4080}`, "_grid_admin");
|
||||
}
|
||||
}
|
||||
|
||||
function gridhost_probe(ev, host) {
|
||||
if (ev && ev.code !== 'Enter') return;
|
||||
if (!(grid_host && grid_apik)) return;
|
||||
|
||||
if (host) grid_host.value = host;
|
||||
|
||||
var xhtr = new XMLHttpRequest(),
|
||||
host = grid_host.value,
|
||||
apik = grid_apik.value,
|
||||
target = grid_target.value;
|
||||
|
||||
if (!apik) $('gpapik').style.display = 'none';
|
||||
|
||||
if (!host && API.probe.grid(gridhost_probe)) return;
|
||||
|
||||
if (!host) return;
|
||||
|
||||
xhtr.onreadystatechange = function() {
|
||||
if (xhtr.readyState === 4) {
|
||||
if (xhtr.status >= 200 && xhtr.status < 300) {
|
||||
SDB['grid-host'] = host;
|
||||
SDB['grid-apik'] = apik;
|
||||
var res = JSON.parse(xhtr.responseText);
|
||||
var sel = false;
|
||||
var match = false;
|
||||
var first = null;
|
||||
var html = [];
|
||||
grid_targets = {};
|
||||
for (var key in res) {
|
||||
first = first || key;
|
||||
if (!SDB['grid-target']) {
|
||||
SDB['grid-target'] = key;
|
||||
sel = true;
|
||||
} else {
|
||||
sel = SDB['grid-target'] === key;
|
||||
}
|
||||
match = match || sel;
|
||||
grid_targets[html.length] = key;
|
||||
html.push(
|
||||
"<option id='gpo-'" + key + " value='" +key + "'" +
|
||||
(sel ? " selected" : "") +
|
||||
">" +
|
||||
(res[key].comment || key) +
|
||||
"</option>"
|
||||
);
|
||||
}
|
||||
if (!match) {
|
||||
SDB['grid-target'] = first;
|
||||
}
|
||||
grid_target.innerHTML = html.join('\n');
|
||||
} else if (xhtr.status === 401) {
|
||||
$('gpapik').style.display = '';
|
||||
} else {
|
||||
SDB.removeItem('grid-host');
|
||||
SDB.removeItem('grid-apik');
|
||||
console.log("invalid grid:host url");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
xhtr.open("GET", host + "/api/active?key=" + apik);
|
||||
xhtr.send();
|
||||
}
|
||||
|
||||
function sendto_gridhost() {
|
||||
if (!(grid_host && grid_apik)) return;
|
||||
|
||||
var xhtr = new XMLHttpRequest(),
|
||||
host = grid_host.value,
|
||||
apik = grid_apik.value,
|
||||
target = SDB['grid-target'] || '';
|
||||
|
||||
if (target === '') {
|
||||
alert2('invalid or missing target');
|
||||
return;
|
||||
}
|
||||
if (host.indexOf("http") !== 0) {
|
||||
alert2("host missing protocol (http:// or https://)");
|
||||
return;
|
||||
}
|
||||
if (host.indexOf("://") < 0) {
|
||||
alert2("host:port malformed");
|
||||
return;
|
||||
}
|
||||
if (SECURE && !isSecure(host)) {
|
||||
alert2("host must begin with 'https' on a secure site");
|
||||
return;
|
||||
}
|
||||
|
||||
SDB['grid-host'] = host.trim();
|
||||
SDB['grid-apik'] = apik.trim();
|
||||
|
||||
xhtr.onreadystatechange = function() {
|
||||
if (xhtr.readyState === 4) {
|
||||
var status = xhtr.status;
|
||||
STATS.add(`ua_${getModeLower()}_print_grid_${status}`);
|
||||
if (status >= 200 && status < 300) {
|
||||
var json = js2o(xhtr.responseText);
|
||||
gridhost_tracker(host,json.key);
|
||||
ajax(host+"/api/wait?key="+json.key, function(data) {
|
||||
data = js2o(data);
|
||||
DBUG.log(data);
|
||||
alert2("print to "+target+": "+data.status, 600);
|
||||
});
|
||||
} else {
|
||||
alert2("grid:host error\nstatus: "+status+"\nmessage: "+xhtr.responseText, 10000);
|
||||
}
|
||||
setProgress(0);
|
||||
}
|
||||
};
|
||||
xhtr.upload.addEventListener('progress', function(evt) {
|
||||
setProgress(Math.ceil(evt.loaded/evt.total), "sending");
|
||||
});
|
||||
filename = $('print-filename').value;
|
||||
xhtr.open("POST",
|
||||
host + "/api/print?" +
|
||||
"filename=" + filename +
|
||||
"&target=" + target +
|
||||
"&key=" + apik +
|
||||
"&time=" + Math.round(currentPrint.time) +
|
||||
"&length=" + Math.round(currentPrint.distance) +
|
||||
"&image=" + filename
|
||||
);
|
||||
xhtr.setRequestHeader("Content-Type", "text/plain");
|
||||
xhtr.send(screenShot ? [gcode,screenShot].join("\0") : gcode);
|
||||
hideModal();
|
||||
}
|
||||
|
||||
function download() {
|
||||
filename = $('print-filename').value;
|
||||
saveAs(getBlob(), filename + "." + fileext);
|
||||
}
|
||||
|
||||
function pad(v) {
|
||||
v = v.toString();
|
||||
return v.length < 2 ? '0' + v : v;
|
||||
}
|
||||
|
||||
function calcWeight() {
|
||||
try {
|
||||
$('print-weight').value = (
|
||||
UTIL.round((Math.PI * UTIL.sqr(currentPrint.settings.device.filamentSize/2)) * currentPrint.distance * 1.25 / 1000, 2)
|
||||
);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
function calcTime() {
|
||||
var floor = Math.floor,
|
||||
time = floor(currentPrint.time),
|
||||
hours = floor(time / 3600),
|
||||
newtime = time - hours * 3600,
|
||||
mins = floor(newtime / 60),
|
||||
secs = newtime - mins * 60;
|
||||
|
||||
$('mill-time').value = $('print-time').value = [pad(hours),pad(mins),pad(secs)].join(':');
|
||||
}
|
||||
|
||||
ajax("/kiri/output-gcode.html", function(html) {
|
||||
UI.print.innerHTML = html;
|
||||
$('print-close').onclick = hideModal;
|
||||
$('print-download').onclick = download;
|
||||
$('print-octoprint').onclick = sendto_octoprint;
|
||||
$('print-gridhost').onclick = sendto_gridhost;
|
||||
$('print-gridlocal').onclick = sendto_gridlocal;
|
||||
$('admin-gridlocal').onclick = admin_gridlocal;
|
||||
$('print-filament-row').style.display = MODE === MODES.FDM ? '' : 'none';
|
||||
$('mill-info').style.display = MODE === MODES.CAM ? '' : 'none';
|
||||
$('print-filename').value = filename;
|
||||
$('print-filesize').value = currentPrint.bytes;
|
||||
$('print-filament').value = Math.round(currentPrint.distance);
|
||||
$('grid-host').onkeyup = gridhost_probe;
|
||||
$('grid-apik').onkeyup = gridhost_probe;
|
||||
calcTime();
|
||||
if (MODE === MODES.FDM) calcWeight();
|
||||
octo_host = $('octo-host');
|
||||
octo_apik = $('octo-apik');
|
||||
if (MODE === MODES.CAM) {
|
||||
$('send-to-octoprint').style.display = 'none';
|
||||
} else {
|
||||
$('send-to-octoprint').style.display = '';
|
||||
}
|
||||
if (OCTOPRINT) {
|
||||
$('ophost').style.display = 'none';
|
||||
$('opapik').style.display = 'none';
|
||||
$('ophint').style.display = 'none';
|
||||
$('send-to-gridhost').style.display = 'none';
|
||||
}
|
||||
octo_host.value = SDB['octo-host'] || '';
|
||||
octo_apik.value = SDB['octo-apik'] || '';
|
||||
grid_host = $('grid-host');
|
||||
grid_apik = $('grid-apik');
|
||||
grid_target = $('grid-target');
|
||||
grid_target.onchange = function(ev) {
|
||||
SDB['grid-target'] = grid_targets[grid_target.selectedIndex];
|
||||
};
|
||||
grid_host.value = SDB['grid-host'] || '';
|
||||
grid_apik.value = SDB['grid-apik'] || '';
|
||||
gridhost_probe();
|
||||
gridlocal_probe();
|
||||
showModal('print');
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -1154,7 +764,9 @@ self.kiri.license = exports.LICENSE;
|
|||
setProgress(0);
|
||||
showSlices(preserveLayer);
|
||||
setOpacity(settings.mode === 'CAM' ? sliced_opacity_cam : sliced_opacity);
|
||||
if (callback && typeof callback === 'function') callback();
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
// update slider window
|
||||
updateDialogLeft();
|
||||
|
|
@ -1753,22 +1365,6 @@ self.kiri.license = exports.LICENSE;
|
|||
SDB.setItem('ws-settings', JSON.stringify(settings));
|
||||
}
|
||||
|
||||
function saveWorkspace() {
|
||||
saveSettings();
|
||||
var newWidgets = [],
|
||||
oldWidgets = js2o(SDB.getItem('ws-widgets'), []);
|
||||
forAllWidgets(function(widget) {
|
||||
newWidgets.push(widget.id);
|
||||
oldWidgets.remove(widget.id);
|
||||
widget.saveState();
|
||||
});
|
||||
SDB.setItem('ws-widgets', o2js(newWidgets));
|
||||
oldWidgets.forEach(function(wid) {
|
||||
Widget.deleteFromState(wid);
|
||||
});
|
||||
alert2("workspace saved", 1);
|
||||
}
|
||||
|
||||
function loadFiles(files) {
|
||||
for (var i=0; i<files.length; i++) {
|
||||
var reader = new FileReader(),
|
||||
|
|
@ -1803,16 +1399,20 @@ self.kiri.license = exports.LICENSE;
|
|||
// alert2("drag/drop STL files onto platform to import\nreload page to return to last saved state");
|
||||
}
|
||||
|
||||
// kiri api
|
||||
function getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
// kiri api
|
||||
function putSettings(newset) {
|
||||
settings = newset;
|
||||
saveSettings()
|
||||
restoreWorkspace(null, true);
|
||||
function saveWorkspace() {
|
||||
saveSettings();
|
||||
var newWidgets = [],
|
||||
oldWidgets = js2o(SDB.getItem('ws-widgets'), []);
|
||||
forAllWidgets(function(widget) {
|
||||
newWidgets.push(widget.id);
|
||||
oldWidgets.remove(widget.id);
|
||||
widget.saveState();
|
||||
});
|
||||
SDB.setItem('ws-widgets', o2js(newWidgets));
|
||||
oldWidgets.forEach(function(wid) {
|
||||
Widget.deleteFromState(wid);
|
||||
});
|
||||
alert2("workspace saved", 1);
|
||||
}
|
||||
|
||||
function restoreWorkspace(ondone, skipwidgets) {
|
||||
|
|
@ -1917,6 +1517,16 @@ self.kiri.license = exports.LICENSE;
|
|||
showDialog("catalog");
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
function putSettings(newset) {
|
||||
settings = newset;
|
||||
saveSettings()
|
||||
restoreWorkspace(null, true);
|
||||
}
|
||||
|
||||
function editNamedSetting(e) {
|
||||
var mode = getMode(),
|
||||
name = e.target.getAttribute("name"),
|
||||
|
|
|
|||
|
|
@ -809,7 +809,8 @@ let ver = require('../js/license.js'),
|
|||
"kiri-work",
|
||||
"kiri-conf",
|
||||
"kiri",
|
||||
"kiri-init"
|
||||
"kiri-init",
|
||||
"kiri-export"
|
||||
],
|
||||
meta : [
|
||||
"license",
|
||||
|
|
|
|||
|
|
@ -104,10 +104,11 @@
|
|||
</div>
|
||||
<!-- CAM tools dialog -->
|
||||
<div id="tools" class="dialog">
|
||||
<div id="tools-body" class="flow-col">
|
||||
<div id="tools-body" class="flow-col">
|
||||
<div id="tool-labels" class="flow-row">
|
||||
<label>tools</label>
|
||||
<label>details</label>
|
||||
<label>tool</label>
|
||||
<label>detail</label>
|
||||
<label>view</label>
|
||||
</div>
|
||||
<div id="tool-cols" class="flow-row">
|
||||
<div id="tool-list" class="flow-col">
|
||||
|
|
@ -116,8 +117,9 @@
|
|||
<div id="tool-info" class="flow-col">
|
||||
<div class="flow-row"><label>type</label>
|
||||
<select id="tool-type">
|
||||
<option value="endmill" selected>endmill</option>
|
||||
<option value="ballmill">ballmill</option>
|
||||
<option value="endmill" selected>end</option>
|
||||
<option value="ballmill">ball</option>
|
||||
<option value="taper">taper</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flow-row"><label>name</label><input id="tool-name" size=8></input></div>
|
||||
|
|
@ -129,7 +131,11 @@
|
|||
<div class="grouphead">shaft</div>
|
||||
<div class="flow-row" title="shaft diameter"><label>diameter</label><input id="tool-sdiam" size=5></input></div>
|
||||
<div class="flow-row" title="shaft length"><label>length</label><input id="tool-slen" size=5></input></div>
|
||||
<div class="grouphead">taper</div>
|
||||
<div class="flow-row" title="taper angle"><label>angle</label><input id="tool-tangle" size=5></input></div>
|
||||
<div class="flow-row" title="tip width"><label>width</label><input id="tool-twidth" size=5></input></div>
|
||||
</div>
|
||||
<div id="tool-view" class="flow-col"></div>
|
||||
</div>
|
||||
<div id="tool-action" class="flow-row">
|
||||
<button id="tool-add">+</button>
|
||||
|
|
|
|||
|
|
@ -339,6 +339,9 @@ button.selected {
|
|||
|
||||
/** tool dialog */
|
||||
|
||||
#tools:hover,#tools-body:hover {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
#tools {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -361,22 +364,30 @@ button.selected {
|
|||
padding-bottom: 5px;
|
||||
border: 0;
|
||||
}
|
||||
#tool-labels span {
|
||||
width: 200px;
|
||||
padding: 2px 5px 2px 5px;
|
||||
margin: 0 5px 5px 5px;
|
||||
background-color: #eee;
|
||||
border-radius: 5px;
|
||||
border: 1px solid #aaa;
|
||||
text-align: center;
|
||||
#tool-labels label:nth-child(1) {
|
||||
width: 125px;
|
||||
}
|
||||
#tool-labels label:nth-child(2) {
|
||||
width: 175px;
|
||||
}
|
||||
#tool-labels label:nth-child(3) {
|
||||
width: 100px;
|
||||
}
|
||||
#tool-cols > div {
|
||||
width: 200px;
|
||||
padding: 5px;
|
||||
margin: 5px;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 5px;
|
||||
}
|
||||
#tool-cols > div:nth-child(1) {
|
||||
width: 125px;
|
||||
}
|
||||
#tool-cols > div:nth-child(2) {
|
||||
width: 175px;
|
||||
}
|
||||
#tool-cols > div:nth-child(3) {
|
||||
width: 100px;
|
||||
}
|
||||
#tool-info > div {
|
||||
margin-top: 2px;
|
||||
margin-bottom: 2px;
|
||||
|
|
@ -422,6 +433,9 @@ button.selected {
|
|||
|
||||
/** device dialog */
|
||||
|
||||
#devices:hover,#devices-body:hover {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
#devices {
|
||||
text-align: center;
|
||||
}
|
||||
|
|
@ -708,7 +722,6 @@ button[import="1"] {
|
|||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
#selected {
|
||||
position: fixed;
|
||||
z-index: 10000;
|
||||
|
|
|
|||
|
|
@ -202,6 +202,10 @@ button[del] {
|
|||
margin-right: 2px !important;
|
||||
}
|
||||
|
||||
#control-left:hover, #control-right:hover {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
/** ******************************************************************
|
||||
* ID
|
||||
******************************************************************* */
|
||||
|
|
|
|||
Loading…
Reference in a new issue