add camera stream to proxy. add frames utility for capturing cam feed

This commit is contained in:
Stewart Allen 2025-02-03 14:10:40 -05:00
commit f31c1529f9
3 changed files with 111 additions and 1 deletions

63
mods/bambu/frames.js Normal file
View file

@ -0,0 +1,63 @@
/**
* this utility takes a BBL printer host and LAN code
* and stores the resulting jpeg stream into frame files
*/
const hexer = require('hexer');
const util = require('util');
const args = process.argv.slice(2);
const tls = require('tls');
const fs = require('fs');
const [host, code, prefix] = args;
if (!(host && code)) {
console.log('usage: frames [host] [code] (file-prefix)');
return;
}
const abuf = new ArrayBuffer(80);
const view = new DataView(abuf);
const encoder = new TextEncoder();
const userBytes = encoder.encode('bblp');
const codeBytes = encoder.encode(code);
view.setInt32(0, 0x0040, true);
view.setInt32(4, 0x3000, true);
new Uint8Array(abuf, 0x10, userBytes.length).set(userBytes);
new Uint8Array(abuf, 0x30, codeBytes.length).set(codeBytes);
const bufr = Buffer.from(abuf);
// console.log(hexer(bufr));
let pic;
let ind = 0;
const remoteSocket = tls.connect({
host,
port: 6000,
rejectUnauthorized: false
}, () => {
// send authentication to start jpeg frame stream
remoteSocket.write(bufr);
});
remoteSocket.on('data', (data) => {
// console.log('-- cam said --', data.length);
// console.log(hexer(data));
if (data.length === 16) {
// start of frame
if (pic) {
// dump last completed frame
fs.writeFileSync(`${prefix || "frame"}-${(++ind).toString().padStart(5,0)}.jpg`, pic);
console.log('received frame', ind);
pic = undefined;
}
} else {
pic = pic ? Buffer.concat([pic,data]) : data;
}
});
remoteSocket.on('error', (err) => {
console.error('Remote connection error:', err.message);
clientSocket.destroy();
});

View file

@ -55,7 +55,6 @@ socket.bind(1900, () => {
});
const [local, name, host, code, serial] = args;
args = args.slice(3);
console.log([
`Broadcasting Bambu Printer Proxy`,
@ -211,3 +210,50 @@ aedes.on('unsubscribe', (subscriptions, client) => {
remoteClient.unsubscribe(sub);
});
});
// pipe the camera feed, too
const camera = tls.createServer(options, (clientSocket) => {
log('Camera Connected', { address: clientSocket.remoteAddress });
const hexer = require('hexer');
const remoteSocket = tls.connect({
host,
port: 6000,
rejectUnauthorized: false
}, () => {
// clientSocket.pipe(remoteSocket).pipe(clientSocket);
});
clientSocket.on('data', (data) => {
remoteSocket.write(data);
// console.log({ client: data, type: typeof data });
// console.log('-- cam client --', data.length);
// console.log(hexer(data));
});
remoteSocket.on('data', (data) => {
clientSocket.write(data);
// console.log({ remote: data, type: typeof data });
// console.log('-- cam remote --', data.length);
// console.log(hexer(data));
});
clientSocket.on('close', () => {
remoteSocket.end();
});
remoteSocket.on('error', (err) => {
console.error('Remote connection error:', err.message);
clientSocket.destroy();
});
clientSocket.on('error', (err) => {
console.error('Client connection error:', err.message);
remoteSocket.destroy();
});
});
camera.listen(6000, () => {
console.log(`TLS Proxy Server listening on port 6000`);
});

View file

@ -10,6 +10,7 @@
"dependencies": {
"@gridspace/basic-ftp": "^5.0.5",
"aedes": "^0.51.3",
"hexer": "^1.5.0",
"mqtt": "^5.10.3"
}
}