fix video state management. rework ams tray display and popup
This commit is contained in:
parent
ac1982b923
commit
071997884e
5 changed files with 149 additions and 29 deletions
|
|
@ -11,8 +11,10 @@ self.kiri.load(api => {
|
|||
let init = false;
|
||||
let status = {};
|
||||
let monitors = [];
|
||||
let showing = false;
|
||||
let video_on = false;
|
||||
let bound, device, printers, select, selected, conn_alert, export_select;
|
||||
let video_auto = false;
|
||||
let bound, device, printers, select, selected, conn_alert, export_select, tray_info;
|
||||
let btn_del, in_host, in_code, in_serial, filelist, print_ams_select = 'auto';
|
||||
let ptype, host, password, serial, amsmap, socket = {
|
||||
open: false,
|
||||
|
|
@ -45,6 +47,8 @@ self.kiri.load(api => {
|
|||
});
|
||||
return;
|
||||
}
|
||||
// receiving a frame will show the video feed (for debugging)
|
||||
set_video_visible(true);
|
||||
const img = new Image();
|
||||
img.src = `data:image/jpeg;base64,${frame}`;
|
||||
img.onload = () => {
|
||||
|
|
@ -103,6 +107,10 @@ self.kiri.load(api => {
|
|||
}
|
||||
};
|
||||
|
||||
function range(length, start = 0) {
|
||||
return Array.from({ length }, (_, i) => i + start);
|
||||
}
|
||||
|
||||
function deepMerge(target, source) {
|
||||
// console.log({ target, source });
|
||||
if (!source) {
|
||||
|
|
@ -172,6 +180,10 @@ self.kiri.load(api => {
|
|||
function printer_video_set(bool) {
|
||||
video_on = bool;
|
||||
set_frames(selected?.rec?.serial, bool);
|
||||
set_video_visible(bool);
|
||||
}
|
||||
|
||||
function set_video_visible(bool) {
|
||||
ui.setVisible($('bbl_video_frame'), bool);
|
||||
ui.setClass($('bbl_vid_toggle'), 'bred', bool);
|
||||
const canvas = $('bbl_video');
|
||||
|
|
@ -180,10 +192,11 @@ self.kiri.load(api => {
|
|||
}
|
||||
|
||||
function printer_select(name = '') {
|
||||
let isvid = video_on;
|
||||
printer_video_set(false);
|
||||
for (let [ printer, rec ] of Object.entries(printers)) {
|
||||
rec.selected = printer === name;
|
||||
}
|
||||
printer_video_set(false);
|
||||
btn_del.disabled = false;
|
||||
let rec = printers[name] || {};
|
||||
selected = { name, rec };
|
||||
|
|
@ -193,6 +206,7 @@ self.kiri.load(api => {
|
|||
in_host.onkeypress = in_host.onblur = printer_update;
|
||||
in_code.onkeypress = in_code.onblur = printer_update;
|
||||
in_serial.onkeypress = in_serial.onblur = printer_update;
|
||||
printer_video_set(isvid);
|
||||
monitor_start(rec);
|
||||
printer_render();
|
||||
file_list();
|
||||
|
|
@ -261,25 +275,35 @@ self.kiri.load(api => {
|
|||
print_ams_select = ev.target.value;
|
||||
};
|
||||
});
|
||||
let tdiv = $('bbl_ams_trays');
|
||||
tdiv.setAttribute("style",[
|
||||
"gap: 5px;",
|
||||
"display:grid",
|
||||
`grid-template-columns:repeat(4,1fr)`,
|
||||
`grid-template-rows:repeat(${ams.ams.length},auto)`
|
||||
].join(';'))
|
||||
h.bind(tdiv, trays.map(tray => h.button({
|
||||
_: tray.tray_type,
|
||||
class:`a-center${tray.tray_color?'':' checker'}`,
|
||||
style: [
|
||||
tray_now === tray.id ? `border-color: red` : undefined,
|
||||
tray.tray_color ? undefined : `border-style: dashed`,
|
||||
`background-color:#${tray.tray_color||'000'}`,
|
||||
`color:#${calcFG(tray.tray_color||'000')}`,
|
||||
`min-height:10px`,
|
||||
`aspect-ratio:1`
|
||||
].filter(v => v).join(';')
|
||||
})))
|
||||
range(16).map(id => {
|
||||
let btn = $(`bbl_tray_${id}`);
|
||||
ui.setVisible(btn, id < trays.length);
|
||||
$('bbl_ams_trays').style.gridTemplateRows = `repeat(${trays.length / 4},auto)`;
|
||||
if (id < trays.length) {
|
||||
let { style } = btn;
|
||||
let { tray_color, tray_type } = trays[id];
|
||||
if (tray_color) {
|
||||
style.color = `#${calcFG(tray_color)}`;
|
||||
style.backgroundColor = `#${tray_color}`;
|
||||
btn.classList.remove('checker');
|
||||
} else {
|
||||
style.color = '';
|
||||
style.backgroundColor = '';
|
||||
btn.classList.add('checker');
|
||||
}
|
||||
if (btn.tray_type !== tray_type) {
|
||||
// otherwise rewriting the text kills the popup
|
||||
btn.tray_type = btn.innerText = tray_type || '';
|
||||
}
|
||||
if (tray_now == id) {
|
||||
style.borderColor = 'red';
|
||||
style.borderStyle = 'dashed';
|
||||
} else {
|
||||
style.borderColor = '';
|
||||
style.borderStyle = '';
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$('bbl_ams_tray').innerHTML = '';
|
||||
$('bbl_file_spool').innerHTML = '';
|
||||
|
|
@ -746,8 +770,81 @@ self.kiri.load(api => {
|
|||
});
|
||||
} }),
|
||||
]),
|
||||
h.div({ id: "bbl_ams_trays" })
|
||||
h.div({
|
||||
id: "bbl_ams_trays",
|
||||
"style": [
|
||||
"gap: 5px;",
|
||||
"display:grid",
|
||||
`grid-template-columns:repeat(4,1fr)`,
|
||||
`grid-template-rows:repeat(4,auto)`
|
||||
].join(';')
|
||||
}, range(16).map(id => h.button({
|
||||
_: id,
|
||||
id: `bbl_tray_${id}`,
|
||||
class:`a-center hide`,
|
||||
style: [
|
||||
`min-height:10px`,
|
||||
`aspect-ratio:1`,
|
||||
`position:relative`
|
||||
].join(';'),
|
||||
onclick(ev) {
|
||||
let { target } = ev;
|
||||
if (target.nodeName === 'BUTTON') {
|
||||
target.appendChild(tray_info);
|
||||
ui.setVisible(tray_info, true);
|
||||
}
|
||||
},
|
||||
onmouseleave() {
|
||||
ui.setVisible(tray_info, false);
|
||||
}
|
||||
})))
|
||||
]),
|
||||
|
||||
h.div({ id: "bbl_tray_info",
|
||||
class: "t-body f-col gap3 pad5 hide",
|
||||
style: [
|
||||
"position:absolute",
|
||||
"top:100%",
|
||||
"right:0",
|
||||
"transform:translateX(30%)",
|
||||
"padding:10px !important",
|
||||
"z-index:1000",
|
||||
].join(';')
|
||||
}, [
|
||||
h.div({ class: "var-row" }, [
|
||||
// h.label('filament'),
|
||||
h.select({ id: "bbl_tray_type", onchange() {
|
||||
cmd_direct({
|
||||
print: {
|
||||
command: 'ams_change_filament',
|
||||
curr_temp: 220,
|
||||
tar_temp: 220,
|
||||
target: parseInt(new_tray)
|
||||
}
|
||||
});
|
||||
}}, api.bambu.filament.map(row => h.option({
|
||||
_: row[1],
|
||||
value: row[0]
|
||||
}))),
|
||||
]),
|
||||
h.div({ class: "var-row" }, [
|
||||
// home_flag bit 11 (0x400)
|
||||
h.label(''),
|
||||
h.span('#'),
|
||||
h.input({ value: "001122", size: 6 }),
|
||||
h.select({ id: "bbl_tray_color", onchange() {
|
||||
cmd_direct({
|
||||
print: {
|
||||
auto_switch_filament: $('bbl_ams_spool').checked,
|
||||
command: 'print_option',
|
||||
sequence_id: '123',
|
||||
option: $('bbl_ams_spool').checked ? 1 : 0
|
||||
}
|
||||
})
|
||||
}})
|
||||
]),
|
||||
]),
|
||||
|
||||
h.div({ class: "t-body t-inset f-col gap3 pad4 grow" }, [
|
||||
h.div({ class: "set-header", onclick() {
|
||||
file_list();
|
||||
|
|
@ -850,6 +947,7 @@ self.kiri.load(api => {
|
|||
in_host = modal.bbl_host;
|
||||
in_code = modal.bbl_code;
|
||||
in_serial = modal.bbl_serial;
|
||||
tray_info = modal.bbl_tray_info;
|
||||
api.ui.modals['bambu'] = modal['mod-bambu'];
|
||||
btn_del.disabled = true;
|
||||
select.onchange = (ev => printer_select(select.value));
|
||||
|
|
@ -877,19 +975,25 @@ self.kiri.load(api => {
|
|||
}
|
||||
}
|
||||
printer_render({ files: [] });
|
||||
printer_video_set(video_auto);
|
||||
printer_select();
|
||||
socket.start();
|
||||
render_list();
|
||||
get_ams_map(api.conf.get());
|
||||
showing = true;
|
||||
});
|
||||
|
||||
api.event.on("modal.hide", which => {
|
||||
api.event.on("modal.hide", () => {
|
||||
if (selected?.rec.modified) {
|
||||
api.conf.save();
|
||||
}
|
||||
printer_video_set(false);
|
||||
selected = undefined;
|
||||
status = {};
|
||||
if (showing) {
|
||||
video_auto = video_on;
|
||||
printer_video_set(false);
|
||||
selected = undefined;
|
||||
showing = false;
|
||||
status = {};
|
||||
}
|
||||
});
|
||||
|
||||
api.event.on("device.selected", devsel => {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@
|
|||
* and stores the resulting jpeg stream into frame files
|
||||
*/
|
||||
|
||||
const { bblCA } = require('./certificates');
|
||||
const EventEmitter = require('events');
|
||||
const tls = require('tls');
|
||||
const { bblCA } = require('./certificates');
|
||||
const debug = false;
|
||||
|
||||
class FrameStream extends EventEmitter {
|
||||
#remoteSocket;
|
||||
|
|
@ -40,11 +41,13 @@ class FrameStream extends EventEmitter {
|
|||
remoteSocket.write(Buffer.from(abuf));
|
||||
this.emit('connect', host);
|
||||
});
|
||||
debug && console.log('start frames', serial);
|
||||
|
||||
remoteSocket.on('data', (data) => {
|
||||
if (data.length === 16) {
|
||||
if (frame) {
|
||||
this.emit('frame', frame);
|
||||
debug && console.log('frame', serial);
|
||||
frame = undefined;
|
||||
}
|
||||
} else {
|
||||
|
|
@ -58,6 +61,7 @@ class FrameStream extends EventEmitter {
|
|||
});
|
||||
|
||||
remoteSocket.on('close', () => {
|
||||
debug && console.log('close frames', serial);
|
||||
this.emit('close');
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ module.exports = async (server) => {
|
|||
const mcache = {};
|
||||
const wsopen = [];
|
||||
const found = {};
|
||||
const video = {};
|
||||
const useCA = false;
|
||||
const debug = false;
|
||||
|
||||
|
|
@ -64,6 +65,7 @@ module.exports = async (server) => {
|
|||
}
|
||||
|
||||
set_frames(bool) {
|
||||
video[this.#serial] = bool;
|
||||
if (this.#frames && !bool) {
|
||||
this.#frames.end();
|
||||
this.#frames = undefined;
|
||||
|
|
@ -112,6 +114,7 @@ module.exports = async (server) => {
|
|||
util.log('mqtt end', this.#serial);
|
||||
this.#client.end();
|
||||
this.#client = undefined;
|
||||
this.set_frames(false);
|
||||
}
|
||||
this.#topic_report = undefined;
|
||||
this.#topic_request = undefined;
|
||||
|
|
@ -139,6 +142,7 @@ module.exports = async (server) => {
|
|||
if (onconn) {
|
||||
onconn(mqtt);
|
||||
}
|
||||
mcache[serial]?.set_frames(video[serial]);
|
||||
}, error => fns.reject(error), onmsg);
|
||||
}
|
||||
|
||||
|
|
@ -261,8 +265,9 @@ module.exports = async (server) => {
|
|||
}
|
||||
}
|
||||
|
||||
// insert script before all others in kiri client
|
||||
// insert scripts before all others in kiri client
|
||||
server.inject("kiri", "bambu.js");
|
||||
server.inject("kiri", "filament.js");
|
||||
|
||||
function o2s(obj) {
|
||||
return JSON.stringify(obj);
|
||||
|
|
@ -420,6 +425,7 @@ module.exports = async (server) => {
|
|||
case "frames":
|
||||
debug && util.log('request frames', serial, frames);
|
||||
mcache[serial]?.set_frames(frames);
|
||||
video[serial] = frames;
|
||||
break;
|
||||
case "keepalive":
|
||||
// util.log({ keepalive: serial });
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@ FDM.export = function(print, online, ondone, ondebug) {
|
|||
subst.tool_count = tools_used.length;
|
||||
|
||||
// encodes an array offset as a single "on" bit in an
|
||||
// 8 byte array then converts the array to base64 which
|
||||
// 8 byte array, then converts the array to base64 which
|
||||
// is what Bambu's M624 uses to flag an object as currently
|
||||
// being printed. the array is presented at the top of the
|
||||
// gcode as a comment: "; model label id: {model_labels}"
|
||||
|
|
|
|||
|
|
@ -654,6 +654,9 @@ details[open] summary::after {
|
|||
.font-smol {
|
||||
font-size: smaller;
|
||||
}
|
||||
.font-tiny {
|
||||
font-size: x-small;
|
||||
}
|
||||
.gap1 {
|
||||
gap: 1px;
|
||||
}
|
||||
|
|
@ -678,6 +681,9 @@ details[open] summary::after {
|
|||
.pad4 {
|
||||
padding: 4px !important;
|
||||
}
|
||||
.pad5 {
|
||||
padding: 5px !important;
|
||||
}
|
||||
.h100 {
|
||||
height: 100%;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue