add mqtt message monitoring in bambu dialog
This commit is contained in:
parent
4e6c8ce35e
commit
dae681f7dd
2 changed files with 109 additions and 22 deletions
|
|
@ -13,6 +13,7 @@ self.kiri.load(api => {
|
|||
const defams = ";; DEFINE BAMBU-AMS ";
|
||||
|
||||
let init = false;
|
||||
let status = {};
|
||||
let bound, device, printers, select, selected;
|
||||
let btn_del, in_host, in_code, in_serial;
|
||||
let host, password, serial, amsmap, socket = {
|
||||
|
|
@ -31,7 +32,20 @@ self.kiri.load(api => {
|
|||
socket.open = false;
|
||||
};
|
||||
ws.onmessage = msg => {
|
||||
console.log({ msg: msg.data });
|
||||
let data = JSON.parse(msg.data);
|
||||
let { serial, message, error } = data;
|
||||
if (error) {
|
||||
console.log({ serial, error });
|
||||
} else if (serial) {
|
||||
let rec = status[serial] = deepMerge(status[serial] || {}, message);
|
||||
if (selected?.rec.serial === serial) {
|
||||
printer_render(rec);
|
||||
} else {
|
||||
console.log('update', serial, rec);
|
||||
}
|
||||
} else {
|
||||
console.log('ignored', serial, data);
|
||||
}
|
||||
};
|
||||
},
|
||||
stop() {
|
||||
|
|
@ -51,6 +65,18 @@ self.kiri.load(api => {
|
|||
}
|
||||
};
|
||||
|
||||
function deepMerge(target, source) {
|
||||
const result = structuredClone(target);
|
||||
Object.keys(source).forEach((key) => {
|
||||
if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
||||
result[key] = deepMerge(result[key] || {}, source[key]);
|
||||
} else {
|
||||
result[key] = source[key];
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
function printer_add() {
|
||||
let name = prompt('printer name');
|
||||
if (!name) {
|
||||
|
|
@ -93,6 +119,10 @@ self.kiri.load(api => {
|
|||
monitor_start(rec);
|
||||
}
|
||||
|
||||
function printer_render(rec) {
|
||||
$('bbl_rec').value = JSON.stringify(rec, undefined, 2);
|
||||
}
|
||||
|
||||
function render_list() {
|
||||
h.bind(select, Object.keys(printers).map(name => {
|
||||
return h.option({
|
||||
|
|
@ -107,6 +137,13 @@ self.kiri.load(api => {
|
|||
socket.send({ cmd: "monitor", ...rec });
|
||||
}
|
||||
|
||||
function monitor_keepalive() {
|
||||
// console.log({ keepalive: selected });
|
||||
if (selected?.rec?.serial) {
|
||||
socket.send({ cmd: "keepalive", serial: selected.rec.serial });
|
||||
}
|
||||
}
|
||||
|
||||
function monitor_stop() {
|
||||
socket.stop();
|
||||
}
|
||||
|
|
@ -128,7 +165,7 @@ self.kiri.load(api => {
|
|||
h.button('bambu printer manager'),
|
||||
h.div({ class: "frow gap3" }, [
|
||||
h.div({ class: "t-body t-inset fcol gap3 pad4" }, [
|
||||
h.select({ id: "bbl_sel", style: "height: auto", size: 5 }, []),
|
||||
h.select({ id: "bbl_sel", style: "height: 100%", size: 5 }, []),
|
||||
h.div({ class: "grid gap3", style: "grid-template-columns: 1fr 1fr" }, [
|
||||
h.button({
|
||||
_: '+',
|
||||
|
|
@ -155,7 +192,11 @@ self.kiri.load(api => {
|
|||
h.input({ id: "bbl_serial", size: 20, class: "t-left" })
|
||||
]),
|
||||
h.div({ class: "t-body t-inset frow gap4 pad4 grow" }, [
|
||||
|
||||
h.textarea({
|
||||
id: "bbl_rec",
|
||||
style: "width: 100%; resize: none",
|
||||
rows: 30, cols: 65
|
||||
})
|
||||
])
|
||||
])
|
||||
])
|
||||
|
|
@ -254,5 +295,7 @@ self.kiri.load(api => {
|
|||
});
|
||||
};
|
||||
|
||||
setInterval(monitor_keepalive, 5000);
|
||||
|
||||
api.bambu = { send, sendok, amsmap };
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ module.exports = async (server) => {
|
|||
const confdir = util.confdir();
|
||||
const mqtt = require("mqtt");
|
||||
const mcache = {};
|
||||
const wsopen = [];
|
||||
|
||||
class MQTT {
|
||||
#timer;
|
||||
|
|
@ -24,7 +25,7 @@ module.exports = async (server) => {
|
|||
rejectUnauthorized: false
|
||||
}
|
||||
|
||||
constructor(host, code, serial, onready) {
|
||||
constructor(host, code, serial, onready, onerror, onmessage) {
|
||||
this.#options.host = host;
|
||||
this.#options.password = code;
|
||||
this.#serial = serial;
|
||||
|
|
@ -33,29 +34,36 @@ module.exports = async (server) => {
|
|||
client.on("connect", () => {
|
||||
let report = this.#topic_report = `device/${serial}/report`;
|
||||
let request = this.#topic_request = `device/${serial}/request`;
|
||||
util.log({ report, request });
|
||||
// util.log({ report, request });
|
||||
client.subscribe(report, (err) => {
|
||||
util.log('mqtt_subd', err);
|
||||
util.log('mqtt_subd', this.#serial, err);
|
||||
onready(this);
|
||||
this.#uptime();
|
||||
this.keepalive();
|
||||
});
|
||||
});
|
||||
|
||||
client.on("message", (topic, message) => {
|
||||
util.log('mqtt_recv', JSON.parse(message.toString()));
|
||||
message = JSON.parse(message.toString());
|
||||
if (onmessage) {
|
||||
onmessage(message);
|
||||
} else {
|
||||
util.log('mqtt_recv', this.#serial, message);
|
||||
}
|
||||
});
|
||||
|
||||
client.on("error", error => onerror(error));
|
||||
}
|
||||
|
||||
#uptime() {
|
||||
keepalive() {
|
||||
clearTimeout(this.#timer);
|
||||
this.#timer = setTimeout(() => { this.end() }, 30000);
|
||||
}
|
||||
|
||||
async send(msg) {
|
||||
if (this.#client) {
|
||||
util.log('mqtt_send', msg);
|
||||
util.log('mqtt_send', this.#serial, msg);
|
||||
this.#client.publish(this.#topic_request, JSON.stringify(msg));
|
||||
this.#uptime();
|
||||
this.keepalive();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
@ -64,7 +72,7 @@ module.exports = async (server) => {
|
|||
|
||||
end() {
|
||||
if (this.#client) {
|
||||
util.log('mqtt end');
|
||||
util.log('mqtt end', this.#serial);
|
||||
this.#client.end();
|
||||
this.#client = undefined;
|
||||
}
|
||||
|
|
@ -74,7 +82,7 @@ module.exports = async (server) => {
|
|||
}
|
||||
}
|
||||
|
||||
function get_mqtt(host, code, serial) {
|
||||
function get_mqtt(host, code, serial, onmsg, onconn) {
|
||||
const fns = {};
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
Object.assign(fns, { resolve, reject });
|
||||
|
|
@ -82,12 +90,15 @@ module.exports = async (server) => {
|
|||
|
||||
let mqtt = mcache[serial];
|
||||
if (mqtt) {
|
||||
return fns.resolve(mqtt);
|
||||
fns.resolve(mqtt);
|
||||
} else {
|
||||
mqtt = new MQTT(host, code, serial, obj => {
|
||||
mcache[serial] = obj;
|
||||
fns.resolve(obj);
|
||||
})
|
||||
if (onconn) {
|
||||
onconn(mqtt);
|
||||
}
|
||||
}, error => fns.reject(error), onmsg);
|
||||
}
|
||||
|
||||
return promise;
|
||||
|
|
@ -158,7 +169,9 @@ module.exports = async (server) => {
|
|||
const data = req.app.post;
|
||||
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) : undefined;
|
||||
const mqtt_conn = serial ? get_mqtt(host, password, serial, message => {
|
||||
util.log('mqtt_recv', JSON.parse(message.toString()));
|
||||
}) : undefined;
|
||||
ftp_send({ host, password, filename, data })
|
||||
.then(() => {
|
||||
if (serial) {
|
||||
|
|
@ -195,20 +208,51 @@ module.exports = async (server) => {
|
|||
};
|
||||
|
||||
server.ws.register("/bambu", function(ws, req) {
|
||||
console.log('ws open', req.url);
|
||||
wsopen.push(ws);
|
||||
util.log('ws open', wsopen.length, req.url);
|
||||
ws.on('message', msg => {
|
||||
msg = JSON.parse(msg);
|
||||
console.log(msg);
|
||||
switch (msg.cmd) {
|
||||
let { cmd, host, code, serial } = msg;
|
||||
switch (cmd) {
|
||||
case "monitor":
|
||||
get_mqtt(msg.host, msg.code, msg.serial).then(mqtt => {
|
||||
console.log({ monitor: mqtt });
|
||||
get_mqtt(host, code, serial, message => {
|
||||
// util.log({ mqtt_msg: serial });
|
||||
wsopen.forEach(ws => ws.send(JSON.stringify({ serial, message })));
|
||||
}, mqtt => {
|
||||
// on open only
|
||||
}).then(mqtt => {
|
||||
// util.log({ mqtt_mon: mqtt });
|
||||
// request all printer state info
|
||||
mqtt.send({
|
||||
pushing: {
|
||||
sequence_id: "0",
|
||||
command: "pushall"
|
||||
}
|
||||
});
|
||||
// request system info
|
||||
mqtt.send({
|
||||
info: {
|
||||
command: "get_version"
|
||||
}
|
||||
});
|
||||
}).catch(error => {
|
||||
util.log({ mqtt_err: error });
|
||||
ws.send(JSON.stringify({
|
||||
serial,
|
||||
error: error.message || error.toString()
|
||||
}));
|
||||
});
|
||||
break;
|
||||
case "keepalive":
|
||||
// util.log({ keepalive: serial });
|
||||
mcache[serial]?.keepalive();
|
||||
break;
|
||||
}
|
||||
});
|
||||
ws.on('close', () => {
|
||||
console.log('WS CLOSE');
|
||||
let io = wsopen.indexOf(ws);
|
||||
if (io >= 0) wsopen.splice(io, 1);
|
||||
util.log('ws close', wsopen.length);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue