restructure frames util so it can be used as a class on the back end

This commit is contained in:
Stewart Allen 2025-02-03 14:49:49 -05:00
commit d1815d8103
2 changed files with 77 additions and 52 deletions

View file

@ -3,61 +3,85 @@
* and stores the resulting jpeg stream into frame files * and stores the resulting jpeg stream into frame files
*/ */
const hexer = require('hexer'); const EventEmitter = require('events');
const util = require('util');
const args = process.argv.slice(2);
const tls = require('tls'); const tls = require('tls');
const fs = require('fs');
const [host, code, prefix] = args;
if (!(host && code)) { class FrameStream extends EventEmitter {
console.log('usage: frames [host] [code] (file-prefix)'); #remoteSocket;
return;
constructor(host, code) {
super();
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);
let frame;
const remoteSocket = this.#remoteSocket = tls.connect({
host,
port: 6000,
rejectUnauthorized: false
}, () => {
// send authentication to start jpeg frame stream
remoteSocket.write(Buffer.from(abuf));
this.emit('connect', host);
});
remoteSocket.on('data', (data) => {
if (data.length === 16) {
if (frame) {
this.emit('frame', frame);
frame = undefined;
}
} else {
frame = frame ? Buffer.concat([frame, data]) : data;
}
});
remoteSocket.on('error', (error) => {
clientSocket.destroy();
this.emit('error', error);
});
remoteSocket.on('close', () => {
this.emit('close');
})
}
close() {
this.#remoteSocket.end();
}
} }
const abuf = new ArrayBuffer(80); if (require.main === module) {
const view = new DataView(abuf); const fs = require('fs');
const encoder = new TextEncoder(); const args = process.argv.slice(2);
const userBytes = encoder.encode('bblp'); const [host, code, prefix] = args;
const codeBytes = encoder.encode(code);
view.setInt32(0, 0x0040, true); if (!(host && code)) {
view.setInt32(4, 0x3000, true); console.log('usage: frames [host] [code] (file-prefix)');
new Uint8Array(abuf, 0x10, userBytes.length).set(userBytes); return;
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.log('frames extraction from', host);
console.error('Remote connection error:', err.message);
clientSocket.destroy(); let ind = 0;
}); new FrameStream(host, code)
.on('connect', host => {
console.log('connected to', host);
})
.on('frame', jpeg => {
fs.writeFileSync(`${prefix || "frame"}-${(++ind).toString().padStart(5, 0)}.jpg`, jpeg);
console.log('received frame', ind);
});
}
module.exports = { FrameStream };

View file

@ -1,5 +1,6 @@
const { Client } = require('@gridspace/basic-ftp'); const { Client } = require('@gridspace/basic-ftp');
const { Readable } = require('stream'); const { Readable } = require('stream');
const { FrameStream } = require('./frames');
module.exports = async (server) => { module.exports = async (server) => {