fix cam trace dup selection, add cam trace merge option, add more bambu print options

This commit is contained in:
Stewart Allen 2025-02-01 18:45:33 -05:00
commit 2e1114510a
12 changed files with 120 additions and 58 deletions

View file

@ -37,7 +37,8 @@ self.kiri.load(api => {
let { serial, message, error } = data;
if (error) {
console.log({ serial, error });
printer_status(`error: ${error}`);
api.alerts.show(`Bambu Error: ${error}`, 3);
// printer_status(`error: ${error}`);
} else if (serial) {
let rec = status[serial] = deepMerge(status[serial] || {}, message);
if (selected?.rec.serial === serial) {
@ -176,9 +177,14 @@ self.kiri.load(api => {
$('bbl_bed_target').value = bed_target_temper?.toFixed(1) ?? '';
if (files) {
h.bind($('bbl_files'), files.map(file => {
let name = file.name
.toLowerCase()
.replace('.gcode','')
.replace('.3mf','');
return h.option({
_: file.name || file,
style: "max-width: 20em"
_: name,
style: "max-width: 20em",
value:`${file.path}${file.name}`
});
}));
rec.files = undefined;
@ -196,7 +202,7 @@ self.kiri.load(api => {
$('bbl_status').value = msg;
}
function render_list() {
function render_list(to) {
let list = Object.keys(printers).map(name => {
return h.option({ _: name, value: name })
});
@ -204,7 +210,7 @@ self.kiri.load(api => {
h.option({ _: '', value: '' }),
...list
]
h.bind(select, list);
h.bind(to || select, list);
}
function monitor_start(rec) {
@ -421,26 +427,35 @@ self.kiri.load(api => {
}
});
function sendok(params = {}) {
host = password = serial = amsmap = undefined;
const { settings } = params;
const ams = settings.device?.gcodePre.filter(line => line.indexOf(defams) === 0)[0];
if (ams) {
try {
amsmap = ams.substring(defams.length).trim().replaceAll(' ','');
} catch (e) {
console.log({ invalid_ams_map: ams });
}
function prep_export(gen3mf, gcode, info, settings) {
if (!settings.device.extras?.bbl) {
$('bambu-output').style.display = 'none';
return;
}
const feature = settings.device?.gcodePre.filter(line => line.indexOf(defhost) === 0)[0];
if (feature) {
[ host, password, serial ] = feature.substring(defhost.length).split(' ').map(v => v.trim());
console.log('BAMBU', { host , password, serial });
if (host && password) {
return true;
}
printers = settings.device.extras.bbl;
let devlist = $('print-bambu-device');
render_list(devlist);
$('bambu-output').style.display = 'flex';
$('print-bambu').onclick = function() {
gen3mf(zip => send(`${$('print-filename').value}.3mf`, zip));
}
return false;
devlist.onchange = () => {
let info = printers[devlist.value];
console.log({ selected: devlist.value, info });
host = info.host;
serial = info.serial;
password = info.code;
$('print-bambu').disabled = (host && serial && password) ? false : true;
const ams = settings.device?.gcodePre.filter(line => line.indexOf(defams) === 0)[0];
if (ams) {
try {
amsmap = ams.substring(defams.length).trim().replaceAll(' ','');
} catch (e) {
console.log({ invalid_ams_map: ams });
}
}
console.log({ bambu: host, serial, amsmap });
};
}
function send(filename, gcode) {
@ -479,5 +494,5 @@ self.kiri.load(api => {
setInterval(monitor_keepalive, 5000);
api.bambu = { send, sendok, amsmap };
api.bambu = { send, amsmap, prep_export };
});

View file

@ -145,8 +145,16 @@ module.exports = async (server) => {
async function ftp_list(args = {}) {
const client = await ftp_open(args);
const list = [];
try { list.push(...(await client.list())) } catch (e) { }
try { list.push(...(await client.list("/cache"))) } catch (e) { }
try {
let files = await client.list();
files.forEach(file => file.path = "/");
list.push(...files);
} catch (e) { }
try {
let files = await client.list("/cache");
files.forEach(file => file.path = "/cache/");
list.push(...files);
} catch (e) { }
client.close();
return list;
}
@ -193,7 +201,8 @@ module.exports = async (server) => {
const { host, password, filename, serial, ams } = query;
const ams_mapping = ams ? ams.split(',').map(v => parseInt(v)) : undefined;
const mqtt_conn = serial ? get_mqtt(host, password, serial, message => {
util.log('mqtt_recv', JSON.parse(message.toString()));
util.log('mqtt_recv', message);
// util.log('mqtt_recv', JSON.parse(message.toString()));
}) : undefined;
ftp_send({ host, password, filename, data })
.then(() => {
@ -271,6 +280,7 @@ module.exports = async (server) => {
.filter(file => file.name.toLowerCase().endsWith(".3mf"))
.map(file => {
return {
path: file.path,
name: file.name,
size: file.size,
date: file.rawModifiedAt

View file

@ -2037,7 +2037,7 @@ class Polygon {
tree = new PolyTree(),
sp1 = this.toClipper(),
sp2 = poly.toClipper(),
minarea = min >= 0 ? min : 0.1;
minarea = min ?? 0.1;
clip.AddPaths(sp1, PathSubject, true);
clip.AddPaths(sp2, PathClip, true);

View file

@ -431,7 +431,7 @@ function subtract(setA, setB, outA, outB, z, minArea, opt = {}) {
let lpre = length(polys);
if (opt.wasm && geo.wasm) {
let min = minarea || 0.01;
let min = minarea ?? 0.01;
// let deepLength = polys.map(p => p.deepLength).reduce((a,v) => a+v);
// if (deepLength < 15000)
try {
@ -632,7 +632,7 @@ function offset(polys, dist, opts = {}) {
let coff = new ClipperOffset(opts.miter, opts.arc),
tree = new PolyTree();
// setup offset
// setup offset
for (let poly of polys) {
// convert to clipper format
poly = poly.toClipper();

View file

@ -1467,6 +1467,7 @@ CAM.init = function(kiri, api) {
offover: 'camTraceOffOver',
dogbone: 'camTraceDogbone',
revbone: 'camTraceDogbone',
merge: 'camTraceMerge',
select: 'camTraceMode'
}).inputs = {
tool: UC.newSelect(LANG.cc_tool, {}, "tools"),
@ -1483,6 +1484,7 @@ CAM.init = function(kiri, api) {
thru: UC.newInput(LANG.cc_thru_s, {title:LANG.cc_thru_l, convert:UC.toFloat, units:true}),
offover: UC.newInput(LANG.cc_offd_s, {title:LANG.cc_offd_l, convert:UC.toFloat, units:true, show:() => poppedRec.offset !== "none"}),
sep: UC.newBlank({class:"pop-sep", modes:MCAM, xshow:zDogSep}),
merge: UC.newBoolean(LANG.co_merg_s, undefined, {title:LANG.co_merg_l}),
bottom: UC.newBoolean(LANG.cf_botm_s, undefined, {title:LANG.cf_botm_l, show:(op,conf) => conf.process.camZBottom}),
dogbone: UC.newBoolean(LANG.co_dogb_s, undefined, {title:LANG.co_dogb_l, show:canDogBones}),
revbone: UC.newBoolean(LANG.co_dogr_s, undefined, {title:LANG.co_dogr_l, show:canDogBonesRev}),

View file

@ -69,6 +69,7 @@ kiri.load(api => {
kiri.client.send("cam_traces", { settings, single }, output => {
const ids = [];
kiri.codec.decode(output).forEach(rec => {
console.log({ rec });
ids.push(rec.id);
widgets[rec.id].traces = rec.traces;
});

View file

@ -1090,6 +1090,7 @@ class OpTrace extends CamOp {
poly2polyEmit(polys, newPoint(0,0,0), (poly, index, count, spoint) => {
routed.push(poly);
});
let output = [];
for (let poly of POLY.nest(routed)) {
let offdist = offset !== 'none' ? offover : 0;
if (!offdist)
@ -1116,15 +1117,24 @@ class OpTrace extends CamOp {
zto -= zThru;
}
for (let z of base.util.lerp(zTop, zto, down)) {
followZ(pi.clone().setZ(z));
output.push(pi.clone().setZ(z));
}
} else {
if (thru) {
pi.setZ(pi.getZ() - thru);
}
followZ(pi);
output.push(pi);
}
}
// merge overlapping output to prevent overcuts
if (op.merge) {
let nest = POLY.nest(output);
let union = POLY.union(nest, 0, true);
output = POLY.flatten(union, [], true);
}
for (let poly of output) {
followZ(poly);
}
break;
case "clear":
const zbo = widget.track.top - widget.track.box.d;

View file

@ -365,7 +365,7 @@ CAM.traces = async function(settings, widget, single) {
let trace = traces[i];
let dz = Math.abs(z - trace.getZ());
// only compare polys farther apart in Z
if (dz < 0.01) {
if (dz > 0.01) {
continue;
}
// do not add duplicates

View file

@ -477,8 +477,7 @@ function exportGCodeDialog(gcode, sections, info, names) {
$('code-preview-head').style.display = preview ? '' : 'none';
$('code-preview').style.display = preview ? '' : 'none';
$('print-download').onclick = download;
$('print-filament-head').style.display = fdm ? '' : 'none';
$('print-filament-info').style.display = fdm ? '' : 'none';
$('print-filament').style.display = fdm ? '' : 'none';
$('print-filename').value = filename;
$('print-filesize').value = util.comma(info.bytes);
$('print-filament').value = Math.round(info.distance);
@ -523,10 +522,10 @@ function exportGCodeDialog(gcode, sections, info, names) {
download3MF.onclick = function() {
gen3mf(zip => api.util.download(zip, `${$('print-filename').value}.3mf`));
};
let downloadBambu = $('print-bambu');
downloadBambu.style.display = api.bambu && api.bambu.sendok({ gcode, info, settings }) ? 'flex' : 'none';
downloadBambu.onclick = function() {
gen3mf(zip => api.bambu.send(`${$('print-filename').value}.3mf`, zip));
// present bambu print options when selected device is bambu
if (api.bambu) {
api.bambu.prep_export(gen3mf, gcode, info, settings);
}
function gen3mf(then) {

View file

@ -107,7 +107,7 @@ button {
cursor: pointer;
text-transform: capitalize;
}
button:hover {
button:not([disabled]):hover {
background-color: var(--main-color);
color: white;
}
@ -118,6 +118,9 @@ button[load] {
button[del] {
margin-left: 5px;
}
button[disabled] {
color: #999;
}
input {
background-color: #f8f8ff;
margin-bottom: 1px;
@ -225,6 +228,9 @@ details[open] > summary::after {
}
/** dark conversion */
.dark button[disabled] {
color: #888;
}
.dark input[disabled] {
border-color: #666;
background-color: #444;
@ -250,7 +256,7 @@ details[open] > summary::after {
background-color: #555;
border: 1px solid #777;
}
button:hover {
.dark button:not([disabled]):hover {
background-color: var(--blue-2);
color: black;
}
@ -670,6 +676,9 @@ button:hover {
.basis-50 {
flex-basis: 50%;
}
.grow0 {
flex-grow: 0 !important;
}
.grow {
flex-grow: 1;
}
@ -1633,7 +1642,7 @@ button:hover {
background-color: rgba(255,255,255,0.5);
border: 1px solid #bbb;
border-radius: 3px;
padding: 20px 10px 10px 10px;
padding: 12px 10px 10px 10px;
}
.mod-print .box select {
min-width: 10em;
@ -1695,9 +1704,10 @@ button:hover {
display: none;
}
#code-preview-textarea {
width: 40em;
height: 12em;
font-size: smaller;
min-width: 50em;
width: 100%;
height: 7em;
font-size: x-small;
font-family: Courier,monospace;
white-space: nowrap;
resize: none;

View file

@ -583,19 +583,25 @@
<div id="mod-local" class="mdialog f-col"></div>
<!-- export dialogs -->
<div id="mod-x-any" class="mod-print mdialog f-col">
<div class="header"><label>export</label></div>
<div id="print-info" class="f-col box">
<div><label>file name</label><input id="print-filename" size="20" spellcheck="false" /></div>
<div><label>file size (bytes)</label><input id="print-filesize" size="12" disabled="true" /></div>
<div><label>time estimate (h:m:s)</label><input id="output-time" size="12" disabled="true" /></div>
<div class="f-row gap4">
<div class="f-col grow">
<div class="header"><label>job</label></div>
<div id="print-info" class="f-col box">
<div><label>file name</label><input id="print-filename" size="20" spellcheck="false" /></div>
<div><label>file size (bytes)</label><input id="print-filesize" size="12" disabled="true" /></div>
<div><label>time estimate (h:m:s)</label><input id="output-time" size="12" disabled="true" /></div>
</div>
</div>
<div id="print-filament" class="f-col">
<div class="header"><label>material</label></div>
<div class="f-col box">
<div><label>filament density (g/cm^3)</label><input id="print-density" size="12" value="1.25" /></div>
<div><label>filament used (mm)</label><input id="print-filament" size="12" disabled="true" /></div>
<div><label>printed weight (g)</label><input id="print-weight" size="12" disabled="true" /></div>
</div>
</div>
</div>
<div id="print-filament-head" class="header"><label>filament</label></div>
<div id="print-filament-info" class="f-col box">
<div><label>filament density (g/cm^3)</label><input id="print-density" size="12" value="1.25" /></div>
<div><label>filament used (mm)</label><input id="print-filament" size="12" disabled="true" /></div>
<div><label>printed weight (g)</label><input id="print-weight" size="12" disabled="true" /></div>
</div>
<div id="code-preview-head" class="header"><label>preview</label></div>
<div id="code-preview-head" class="header"><label>gcode preview</label></div>
<div id="code-preview" class="f-col box">
<div><textarea id="code-preview-textarea"></textarea></div>
</div>
@ -605,7 +611,14 @@
<button id="print-palette" class="grow">palette</button>
<button id="print-zip" class="grow">zip</button>
<button id="print-3mf" class="grow">3mf</button>
<button id="print-bambu" class="grow">bambu</button>
</div>
<div id="bambu-output" class="f-col">
<div class="header"><label>send to bambu</label></div>
<div class="f-row box gap4 a-center">
<label class="grow0">printer</label>
<select id="print-bambu-device"></select>
<button id="print-bambu" class="grow" disabled>send job</button>
</div>
</div>
<div id="send-to-octohead" class="header"><label>octoprint</label></div>
<div id="send-to-octoprint" class="f-col box">

View file

@ -521,6 +521,8 @@ self.kiri.lang['en-us'] = {
// CNC OUTLINE
co_menu: "outline",
co_merg_s: "merge overlap",
co_merg_l: ["merge overlapping lines to prevent overcutting into adjacent solids"],
co_dogb_s: "dogbones",
co_dogb_l: ["insert dogbone cuts","into inside corners"],
co_dogr_s: "reverse bones",