allow spool select / override for bbl print jobs

This commit is contained in:
Stewart Allen 2025-02-12 17:44:25 -05:00
commit 0fb9607bf2
5 changed files with 104 additions and 30 deletions

View file

@ -13,7 +13,7 @@ self.kiri.load(api => {
let monitors = []; let monitors = [];
let video_on = false; let video_on = false;
let bound, device, printers, select, selected, conn_alert, export_select; let bound, device, printers, select, selected, conn_alert, export_select;
let btn_del, in_host, in_code, in_serial, filelist; let btn_del, in_host, in_code, in_serial, filelist, print_ams_select = 'auto';
let ptype, host, password, serial, amsmap, socket = { let ptype, host, password, serial, amsmap, socket = {
open: false, open: false,
q: [], q: [],
@ -243,6 +243,22 @@ self.kiri.load(api => {
h.option({ _: 'none', value: '255' }), h.option({ _: 'none', value: '255' }),
...options ...options
]); ]);
[ "print-bambu-spool", "bbl_file_spool" ].forEach(dropdown => {
h.bind($(dropdown),[
h.option({ _: 'external', value: '', _selected: print_ams_select === '' }),
h.option({ _: 'ams auto', value: 'auto', _selected: print_ams_select === 'auto' }),
...trays.map(tray => {
return h.option({
_: `ams tray ${tray.id}`,
_selected: print_ams_select === tray.id,
value: tray.id,
});
})
]);
$(dropdown).onchange = (ev) => {
print_ams_select = ev.target.value;
};
});
let tdiv = $('bbl_ams_trays'); let tdiv = $('bbl_ams_trays');
tdiv.setAttribute("style",[ tdiv.setAttribute("style",[
"gap: 5px;", "gap: 5px;",
@ -263,6 +279,9 @@ self.kiri.load(api => {
}))) })))
} else { } else {
$('bbl_ams_tray').innerHTML = ''; $('bbl_ams_tray').innerHTML = '';
$('bbl_file_spool').innerHTML = '';
$('print-bambu-spool').innerHTML = '';
print_ams_select = 'auto';
} }
let state = (gcode_state || 'unknown').toLowerCase(); let state = (gcode_state || 'unknown').toLowerCase();
$('bbl_noz').value = nozzle_diameter || ''; $('bbl_noz').value = nozzle_diameter || '';
@ -431,9 +450,17 @@ self.kiri.load(api => {
function file_print(path) { function file_print(path) {
if (selected?.rec?.host && path) { if (selected?.rec?.host && path) {
let spool = print_ams_select;
let { host, code, serial } = selected.rec; let { host, code, serial } = selected.rec;
console.log({ file_print: path, host, code, serial, amsmap }); console.log({ file_print: path, host, code, serial, spool, amsmap });
socket.send({ cmd: "file-print", path, host, code, serial, amsmap }); socket.send({
cmd: "file-print",
path,
host,
code,
serial,
amsmap: spool === 'auto' && amsmap ? amsmap : spool
});
} }
} }
@ -743,16 +770,11 @@ self.kiri.load(api => {
h.label('date'), h.label('date'),
h.input({ id: "bbl_file_date", size: 12, readonly }) h.input({ id: "bbl_file_date", size: 12, readonly })
]), ]),
h.div({ class: "var-row" }, [
h.label('spool'),
h.select({ id: "bbl_file_spool" })
]),
h.div({ class: "grow" }), h.div({ class: "grow" }),
h.button({
_: 'delete',
id: "bbl_file_delete",
class: "f-col a-center t-center",
disabled: true,
onclick() {
console.log({ deleting: selected.file.path });
file_delete(selected.file.path);
}}),
h.button({ h.button({
_: 'print', _: 'print',
id: "bbl_file_print", id: "bbl_file_print",
@ -763,6 +785,15 @@ self.kiri.load(api => {
file_print(selected.file.path); file_print(selected.file.path);
api.alerts.show(`printing: ${selected.file.path}`,2); api.alerts.show(`printing: ${selected.file.path}`,2);
}}), }}),
h.button({
_: 'delete',
id: "bbl_file_delete",
class: "f-col a-center t-center",
disabled: true,
onclick() {
console.log({ deleting: selected.file.path });
file_delete(selected.file.path);
}}),
]), ]),
h.div({ class: "t-body t-inset f-col gap3 pad4" }, [ h.div({ class: "t-body t-inset f-col gap3 pad4" }, [
h.label({ class: "set-header dev-sel" }, [ h.label({ class: "set-header dev-sel" }, [
@ -796,8 +827,8 @@ self.kiri.load(api => {
select.onchange = (ev => printer_select(select.value)); select.onchange = (ev => printer_select(select.value));
filelist.onchange = (ev => { filelist.onchange = (ev => {
let file = selected.file = selected.status.files[filelist.selectedIndex]; let file = selected.file = selected.status.files[filelist.selectedIndex];
$('bbl_file_size').value = file.size; $('bbl_file_size').value = file?.size ?? '';
$('bbl_file_date').value = file.date; $('bbl_file_date').value = file?.date ?? '';
$('bbl_file_delete').disabled = $('bbl_file_delete').disabled =
$('bbl_file_print').disabled = false; $('bbl_file_print').disabled = false;
}); });
@ -876,29 +907,32 @@ self.kiri.load(api => {
api.modal.show('bambu'); api.modal.show('bambu');
} }
devlist.onchange = () => { devlist.onchange = () => {
let info = printers[devlist.value]; let info = printers[devlist.value] || {};
host = info.host; host = info.host;
ptype = info.type; ptype = info.type;
serial = info.serial; serial = info.serial;
password = info.code; password = info.code;
export_select = devlist.value; export_select = devlist.value;
$('print-bambu-spool').innerHMTL = '<option>loading...</option>';
$('print-bambu-1').disabled = $('print-bambu-1').disabled =
$('print-bambu-2').disabled = $('print-bambu-2').disabled =
(host && serial && password) ? false : true; (host && serial && password) ? false : true;
get_ams_map(settings); get_ams_map(settings);
printer_select(export_select);
console.log({ bambu: serial, ptype, host, amsmap }); console.log({ bambu: serial, ptype, host, amsmap });
}; };
} }
function send(filename, gcode, start) { function send(filename, gcode, start) {
const spool = print_ams_select;
const baseUrl = '/api/bambu_send'; const baseUrl = '/api/bambu_send';
const url = new URL(baseUrl, window.location.origin); const url = new URL(baseUrl, window.location.origin);
url.searchParams.append('host', host); url.searchParams.append('host', host);
url.searchParams.append('code', password); url.searchParams.append('code', password);
url.searchParams.append('filename', filename); url.searchParams.append('filename', filename);
url.searchParams.append('serial', serial); url.searchParams.append('serial', serial);
url.searchParams.append('ams', amsmap);
url.searchParams.append('start', start ?? false); url.searchParams.append('start', start ?? false);
url.searchParams.append('ams', spool === 'auto' && amsmap ? amsmap : spool);
const alert = api.alerts.show('Sending to Bambu Printer'); const alert = api.alerts.show('Sending to Bambu Printer');

View file

@ -18,6 +18,7 @@ class FrameStream extends EventEmitter {
const encoder = new TextEncoder(); const encoder = new TextEncoder();
const userBytes = encoder.encode('bblp'); const userBytes = encoder.encode('bblp');
const codeBytes = encoder.encode(code); const codeBytes = encoder.encode(code);
const useCA = false;
view.setInt32(0, 0x0040, true); view.setInt32(0, 0x0040, true);
view.setInt32(4, 0x3000, true); view.setInt32(4, 0x3000, true);
@ -25,12 +26,16 @@ class FrameStream extends EventEmitter {
new Uint8Array(abuf, 0x30, codeBytes.length).set(codeBytes); new Uint8Array(abuf, 0x30, codeBytes.length).set(codeBytes);
let frame; let frame;
const remoteSocket = this.#remoteSocket = tls.connect({ const remoteSocket = this.#remoteSocket = tls.connect(Object.assign({}, {
host, host,
port: 6000, port: 6000
}, useCA ? {
ca: bblCA, ca: bblCA,
servername: serial servername: serial
}, () => { } : {
rejectUnauthorized: false,
checkServerIdentity: () => {}
}), () => {
// send authentication to start jpeg frame stream // send authentication to start jpeg frame stream
remoteSocket.write(Buffer.from(abuf)); remoteSocket.write(Buffer.from(abuf));
this.emit('connect', host); this.emit('connect', host);

View file

@ -11,6 +11,7 @@ module.exports = async (server) => {
const mcache = {}; const mcache = {};
const wsopen = []; const wsopen = [];
const found = {}; const found = {};
const useCA = false;
const debug = false; const debug = false;
class MQTT { class MQTT {
@ -21,12 +22,15 @@ module.exports = async (server) => {
#frames; #frames;
#topic_report; #topic_report;
#topic_request; #topic_request;
#options = { #options = Object.assign({}, {
protocol: 'mqtts', protocol: 'mqtts',
port: 8883, port: 8883,
username: 'bblp', username: 'bblp',
}, useCA ? {
ca: bblCA ca: bblCA
} } : {
rejectUnauthorized: false
});
constructor(host, code, serial, onready, onerror, onmessage) { constructor(host, code, serial, onready, onerror, onmessage) {
this.#options.host = host; this.#options.host = host;
@ -74,7 +78,10 @@ module.exports = async (server) => {
keepalive() { keepalive() {
clearTimeout(this.#timer); clearTimeout(this.#timer);
this.#timer = setTimeout(() => { this.end() }, 30000); this.#timer = setTimeout(() => {
util.log('keepalive expired', this.#serial);
this.end();
}, 300000);
} }
keepconn() { keepconn() {
@ -102,7 +109,7 @@ module.exports = async (server) => {
end() { end() {
if (this.#client) { if (this.#client) {
debug && util.log('mqtt end', this.#serial); util.log('mqtt end', this.#serial);
this.#client.end(); this.#client.end();
this.#client = undefined; this.#client = undefined;
} }
@ -144,7 +151,7 @@ module.exports = async (server) => {
const host = args.host || "localhost"; const host = args.host || "localhost";
const user = args.user || "bblp"; const user = args.user || "bblp";
const password = args.password || args.code || ''; const password = args.password || args.code || '';
// client.ftp.verbose = true; client.ftp.verbose = debug;
try { try {
await client.access({ await client.access({
port, port,
@ -152,7 +159,12 @@ module.exports = async (server) => {
user, user,
password, password,
secure: "implicit", secure: "implicit",
secureOptions: { ca: bblCA, servername: args.serial } secureOptions: useCA ? {
ca: bblCA,
servername: args.serial
} : {
rejectUnauthorized: false
}
}); });
} catch (error) { } catch (error) {
util.log({ ftp_error: error }); util.log({ ftp_error: error });
@ -219,10 +231,10 @@ module.exports = async (server) => {
vibration_cali: false vibration_cali: false
} }
}; };
if (amsmap) { if (amsmap && amsmap !== 'auto') {
cmd.print.ams_mapping = amsmap.split(',').map(v => parseInt(v)); cmd.print.ams_mapping = amsmap.split(',').map(v => parseInt(v));
} }
debug && util.log({ file_print: cmd }); util.log({ file_print: cmd });
get_mqtt(host, code, serial, message => { get_mqtt(host, code, serial, message => {
debug && util.log('mqtt_recv', message); debug && util.log('mqtt_recv', message);
wsend({ serial, message }); wsend({ serial, message });
@ -404,7 +416,7 @@ module.exports = async (server) => {
if_mqtt(serial, direct); if_mqtt(serial, direct);
break; break;
case "frames": case "frames":
util.log('request frames', serial, frames); debug && util.log('request frames', serial, frames);
mcache[serial]?.set_frames(frames); mcache[serial]?.set_frames(frames);
break; break;
case "keepalive": case "keepalive":

View file

@ -529,7 +529,7 @@ function exportGCodeDialog(gcode, sections, info, names) {
} }
function gen3mf(then, ptype = 'unknown') { function gen3mf(then, ptype = 'unknown') {
console.log({ gen3mf_target: ptype }); console.log({ gen3mf_printer_type: ptype });
let now = new Date(); let now = new Date();
let ymd = [ let ymd = [
now.getFullYear(), now.getFullYear(),
@ -583,6 +583,27 @@ function exportGCodeDialog(gcode, sections, info, names) {
'</Relationships>' '</Relationships>'
].join('\n') ].join('\n')
},{ },{
// name: `Metadata/plate_1.json`,
// data: JSON.toString({
// "bbox_all": [ 115.199992, 115.199992, 140.799992, 140.799992 ],
// "bbox_objects": [
// {
// "area": 655.3599853515625,
// "bbox": [ 115.199992, 115.199992, 140.799992, 140.799992 ],
// "id": 42,
// "layer_height": 0.25,
// "name": "Cube"
// }
// ],
// "bed_type": "textured_plate",
// "filament_colors": ["#FFFFFF"],
// "filament_ids": [0],
// "first_extruder": 0,
// "is_seq_print": false,
// "nozzle_diameter": 0.6,
// "version": 2
// })
// },{
name: `Metadata/model_settings.config`, name: `Metadata/model_settings.config`,
data: [ data: [
'<?xml version="1.0" encoding="UTF-8"?>', '<?xml version="1.0" encoding="UTF-8"?>',

View file

@ -633,8 +633,10 @@
<div id="bambu-output" class="f-col"> <div id="bambu-output" class="f-col">
<div class="header"><label>send to bambu</label></div> <div class="header"><label>send to bambu</label></div>
<div class="f-row box gap4 a-center"> <div class="f-row box gap4 a-center">
<label class="grow0">printer</label> <label class="grow0 pad3">printer</label>
<select id="print-bambu-device"></select> <select id="print-bambu-device"></select>
<label class="grow0 pad3">spool</label>
<select id="print-bambu-spool"></select>
<button id="print-bambu-1" class="grow" disabled>send</button> <button id="print-bambu-1" class="grow" disabled>send</button>
<button id="print-bambu-2" class="grow" disabled>send + print</button> <button id="print-bambu-2" class="grow" disabled>send + print</button>
</div> </div>