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 init = false;
|
||||||
let status = {};
|
let status = {};
|
||||||
let monitors = [];
|
let monitors = [];
|
||||||
|
let showing = false;
|
||||||
let video_on = 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 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,
|
||||||
|
|
@ -45,6 +47,8 @@ self.kiri.load(api => {
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// receiving a frame will show the video feed (for debugging)
|
||||||
|
set_video_visible(true);
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = `data:image/jpeg;base64,${frame}`;
|
img.src = `data:image/jpeg;base64,${frame}`;
|
||||||
img.onload = () => {
|
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) {
|
function deepMerge(target, source) {
|
||||||
// console.log({ target, source });
|
// console.log({ target, source });
|
||||||
if (!source) {
|
if (!source) {
|
||||||
|
|
@ -172,6 +180,10 @@ self.kiri.load(api => {
|
||||||
function printer_video_set(bool) {
|
function printer_video_set(bool) {
|
||||||
video_on = bool;
|
video_on = bool;
|
||||||
set_frames(selected?.rec?.serial, bool);
|
set_frames(selected?.rec?.serial, bool);
|
||||||
|
set_video_visible(bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_video_visible(bool) {
|
||||||
ui.setVisible($('bbl_video_frame'), bool);
|
ui.setVisible($('bbl_video_frame'), bool);
|
||||||
ui.setClass($('bbl_vid_toggle'), 'bred', bool);
|
ui.setClass($('bbl_vid_toggle'), 'bred', bool);
|
||||||
const canvas = $('bbl_video');
|
const canvas = $('bbl_video');
|
||||||
|
|
@ -180,10 +192,11 @@ self.kiri.load(api => {
|
||||||
}
|
}
|
||||||
|
|
||||||
function printer_select(name = '') {
|
function printer_select(name = '') {
|
||||||
|
let isvid = video_on;
|
||||||
|
printer_video_set(false);
|
||||||
for (let [ printer, rec ] of Object.entries(printers)) {
|
for (let [ printer, rec ] of Object.entries(printers)) {
|
||||||
rec.selected = printer === name;
|
rec.selected = printer === name;
|
||||||
}
|
}
|
||||||
printer_video_set(false);
|
|
||||||
btn_del.disabled = false;
|
btn_del.disabled = false;
|
||||||
let rec = printers[name] || {};
|
let rec = printers[name] || {};
|
||||||
selected = { name, rec };
|
selected = { name, rec };
|
||||||
|
|
@ -193,6 +206,7 @@ self.kiri.load(api => {
|
||||||
in_host.onkeypress = in_host.onblur = printer_update;
|
in_host.onkeypress = in_host.onblur = printer_update;
|
||||||
in_code.onkeypress = in_code.onblur = printer_update;
|
in_code.onkeypress = in_code.onblur = printer_update;
|
||||||
in_serial.onkeypress = in_serial.onblur = printer_update;
|
in_serial.onkeypress = in_serial.onblur = printer_update;
|
||||||
|
printer_video_set(isvid);
|
||||||
monitor_start(rec);
|
monitor_start(rec);
|
||||||
printer_render();
|
printer_render();
|
||||||
file_list();
|
file_list();
|
||||||
|
|
@ -261,25 +275,35 @@ self.kiri.load(api => {
|
||||||
print_ams_select = ev.target.value;
|
print_ams_select = ev.target.value;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
let tdiv = $('bbl_ams_trays');
|
range(16).map(id => {
|
||||||
tdiv.setAttribute("style",[
|
let btn = $(`bbl_tray_${id}`);
|
||||||
"gap: 5px;",
|
ui.setVisible(btn, id < trays.length);
|
||||||
"display:grid",
|
$('bbl_ams_trays').style.gridTemplateRows = `repeat(${trays.length / 4},auto)`;
|
||||||
`grid-template-columns:repeat(4,1fr)`,
|
if (id < trays.length) {
|
||||||
`grid-template-rows:repeat(${ams.ams.length},auto)`
|
let { style } = btn;
|
||||||
].join(';'))
|
let { tray_color, tray_type } = trays[id];
|
||||||
h.bind(tdiv, trays.map(tray => h.button({
|
if (tray_color) {
|
||||||
_: tray.tray_type,
|
style.color = `#${calcFG(tray_color)}`;
|
||||||
class:`a-center${tray.tray_color?'':' checker'}`,
|
style.backgroundColor = `#${tray_color}`;
|
||||||
style: [
|
btn.classList.remove('checker');
|
||||||
tray_now === tray.id ? `border-color: red` : undefined,
|
} else {
|
||||||
tray.tray_color ? undefined : `border-style: dashed`,
|
style.color = '';
|
||||||
`background-color:#${tray.tray_color||'000'}`,
|
style.backgroundColor = '';
|
||||||
`color:#${calcFG(tray.tray_color||'000')}`,
|
btn.classList.add('checker');
|
||||||
`min-height:10px`,
|
}
|
||||||
`aspect-ratio:1`
|
if (btn.tray_type !== tray_type) {
|
||||||
].filter(v => v).join(';')
|
// 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 {
|
} else {
|
||||||
$('bbl_ams_tray').innerHTML = '';
|
$('bbl_ams_tray').innerHTML = '';
|
||||||
$('bbl_file_spool').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: "t-body t-inset f-col gap3 pad4 grow" }, [
|
||||||
h.div({ class: "set-header", onclick() {
|
h.div({ class: "set-header", onclick() {
|
||||||
file_list();
|
file_list();
|
||||||
|
|
@ -850,6 +947,7 @@ self.kiri.load(api => {
|
||||||
in_host = modal.bbl_host;
|
in_host = modal.bbl_host;
|
||||||
in_code = modal.bbl_code;
|
in_code = modal.bbl_code;
|
||||||
in_serial = modal.bbl_serial;
|
in_serial = modal.bbl_serial;
|
||||||
|
tray_info = modal.bbl_tray_info;
|
||||||
api.ui.modals['bambu'] = modal['mod-bambu'];
|
api.ui.modals['bambu'] = modal['mod-bambu'];
|
||||||
btn_del.disabled = true;
|
btn_del.disabled = true;
|
||||||
select.onchange = (ev => printer_select(select.value));
|
select.onchange = (ev => printer_select(select.value));
|
||||||
|
|
@ -877,19 +975,25 @@ self.kiri.load(api => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printer_render({ files: [] });
|
printer_render({ files: [] });
|
||||||
|
printer_video_set(video_auto);
|
||||||
printer_select();
|
printer_select();
|
||||||
socket.start();
|
socket.start();
|
||||||
render_list();
|
render_list();
|
||||||
get_ams_map(api.conf.get());
|
get_ams_map(api.conf.get());
|
||||||
|
showing = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
api.event.on("modal.hide", which => {
|
api.event.on("modal.hide", () => {
|
||||||
if (selected?.rec.modified) {
|
if (selected?.rec.modified) {
|
||||||
api.conf.save();
|
api.conf.save();
|
||||||
}
|
}
|
||||||
|
if (showing) {
|
||||||
|
video_auto = video_on;
|
||||||
printer_video_set(false);
|
printer_video_set(false);
|
||||||
selected = undefined;
|
selected = undefined;
|
||||||
|
showing = false;
|
||||||
status = {};
|
status = {};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
api.event.on("device.selected", devsel => {
|
api.event.on("device.selected", devsel => {
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@
|
||||||
* and stores the resulting jpeg stream into frame files
|
* and stores the resulting jpeg stream into frame files
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const { bblCA } = require('./certificates');
|
||||||
const EventEmitter = require('events');
|
const EventEmitter = require('events');
|
||||||
const tls = require('tls');
|
const tls = require('tls');
|
||||||
const { bblCA } = require('./certificates');
|
const debug = false;
|
||||||
|
|
||||||
class FrameStream extends EventEmitter {
|
class FrameStream extends EventEmitter {
|
||||||
#remoteSocket;
|
#remoteSocket;
|
||||||
|
|
@ -40,11 +41,13 @@ class FrameStream extends EventEmitter {
|
||||||
remoteSocket.write(Buffer.from(abuf));
|
remoteSocket.write(Buffer.from(abuf));
|
||||||
this.emit('connect', host);
|
this.emit('connect', host);
|
||||||
});
|
});
|
||||||
|
debug && console.log('start frames', serial);
|
||||||
|
|
||||||
remoteSocket.on('data', (data) => {
|
remoteSocket.on('data', (data) => {
|
||||||
if (data.length === 16) {
|
if (data.length === 16) {
|
||||||
if (frame) {
|
if (frame) {
|
||||||
this.emit('frame', frame);
|
this.emit('frame', frame);
|
||||||
|
debug && console.log('frame', serial);
|
||||||
frame = undefined;
|
frame = undefined;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -58,6 +61,7 @@ class FrameStream extends EventEmitter {
|
||||||
});
|
});
|
||||||
|
|
||||||
remoteSocket.on('close', () => {
|
remoteSocket.on('close', () => {
|
||||||
|
debug && console.log('close frames', serial);
|
||||||
this.emit('close');
|
this.emit('close');
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ module.exports = async (server) => {
|
||||||
const mcache = {};
|
const mcache = {};
|
||||||
const wsopen = [];
|
const wsopen = [];
|
||||||
const found = {};
|
const found = {};
|
||||||
|
const video = {};
|
||||||
const useCA = false;
|
const useCA = false;
|
||||||
const debug = false;
|
const debug = false;
|
||||||
|
|
||||||
|
|
@ -64,6 +65,7 @@ module.exports = async (server) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
set_frames(bool) {
|
set_frames(bool) {
|
||||||
|
video[this.#serial] = bool;
|
||||||
if (this.#frames && !bool) {
|
if (this.#frames && !bool) {
|
||||||
this.#frames.end();
|
this.#frames.end();
|
||||||
this.#frames = undefined;
|
this.#frames = undefined;
|
||||||
|
|
@ -112,6 +114,7 @@ module.exports = async (server) => {
|
||||||
util.log('mqtt end', this.#serial);
|
util.log('mqtt end', this.#serial);
|
||||||
this.#client.end();
|
this.#client.end();
|
||||||
this.#client = undefined;
|
this.#client = undefined;
|
||||||
|
this.set_frames(false);
|
||||||
}
|
}
|
||||||
this.#topic_report = undefined;
|
this.#topic_report = undefined;
|
||||||
this.#topic_request = undefined;
|
this.#topic_request = undefined;
|
||||||
|
|
@ -139,6 +142,7 @@ module.exports = async (server) => {
|
||||||
if (onconn) {
|
if (onconn) {
|
||||||
onconn(mqtt);
|
onconn(mqtt);
|
||||||
}
|
}
|
||||||
|
mcache[serial]?.set_frames(video[serial]);
|
||||||
}, error => fns.reject(error), onmsg);
|
}, 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", "bambu.js");
|
||||||
|
server.inject("kiri", "filament.js");
|
||||||
|
|
||||||
function o2s(obj) {
|
function o2s(obj) {
|
||||||
return JSON.stringify(obj);
|
return JSON.stringify(obj);
|
||||||
|
|
@ -420,6 +425,7 @@ module.exports = async (server) => {
|
||||||
case "frames":
|
case "frames":
|
||||||
debug && util.log('request frames', serial, frames);
|
debug && util.log('request frames', serial, frames);
|
||||||
mcache[serial]?.set_frames(frames);
|
mcache[serial]?.set_frames(frames);
|
||||||
|
video[serial] = frames;
|
||||||
break;
|
break;
|
||||||
case "keepalive":
|
case "keepalive":
|
||||||
// util.log({ keepalive: serial });
|
// util.log({ keepalive: serial });
|
||||||
|
|
|
||||||
|
|
@ -137,7 +137,7 @@ FDM.export = function(print, online, ondone, ondebug) {
|
||||||
subst.tool_count = tools_used.length;
|
subst.tool_count = tools_used.length;
|
||||||
|
|
||||||
// encodes an array offset as a single "on" bit in an
|
// 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
|
// is what Bambu's M624 uses to flag an object as currently
|
||||||
// being printed. the array is presented at the top of the
|
// being printed. the array is presented at the top of the
|
||||||
// gcode as a comment: "; model label id: {model_labels}"
|
// gcode as a comment: "; model label id: {model_labels}"
|
||||||
|
|
|
||||||
|
|
@ -654,6 +654,9 @@ details[open] summary::after {
|
||||||
.font-smol {
|
.font-smol {
|
||||||
font-size: smaller;
|
font-size: smaller;
|
||||||
}
|
}
|
||||||
|
.font-tiny {
|
||||||
|
font-size: x-small;
|
||||||
|
}
|
||||||
.gap1 {
|
.gap1 {
|
||||||
gap: 1px;
|
gap: 1px;
|
||||||
}
|
}
|
||||||
|
|
@ -678,6 +681,9 @@ details[open] summary::after {
|
||||||
.pad4 {
|
.pad4 {
|
||||||
padding: 4px !important;
|
padding: 4px !important;
|
||||||
}
|
}
|
||||||
|
.pad5 {
|
||||||
|
padding: 5px !important;
|
||||||
|
}
|
||||||
.h100 {
|
.h100 {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue