Camera connects and attaches

This commit is contained in:
Matt McWilliams 2024-07-11 17:26:14 -04:00
parent c5e03f669e
commit e44fc61106
7 changed files with 228 additions and 37 deletions

View File

@ -2,12 +2,18 @@ export declare class Camera {
private log;
private parser;
private ready;
private connected;
private serial;
private baud;
private next;
private port;
constructor();
private begin;
private filter;
private enumerate;
private connect;
private connectMock;
private onData;
private verify;
private confirm;
}

104
dist/camera/index.js vendored
View File

@ -2,13 +2,17 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.Camera = void 0;
const log_1 = require("../log");
const delay_1 = require("../delay");
const serialport_1 = require("serialport");
const parser_readline_1 = require("@serialport/parser-readline");
class Camera {
constructor() {
this.ready = false;
this.connected = false;
this.serial = null;
this.baud = 57600;
this.next = null;
this.port = null;
this.log = (0, log_1.createLog)('camera');
this.parser = new parser_readline_1.ReadlineParser({ delimiter: '\r\n' });
this.begin();
@ -22,10 +26,7 @@ class Camera {
catch (err) {
this.log.error('Error calling enumerate()', err);
}
if (ports.length === 0) {
this.log.warn('No USB camera devices connected');
return;
}
if (ports.length > 0) {
for (let port of ports) {
this.log.info(`Found USB serial device: ${port} ${selected ? '*' : ''}`);
selected = false;
@ -37,6 +38,18 @@ class Camera {
this.log.error(`Error connecting to ${ports[0]}`, err);
}
}
else {
this.log.warn(`No USB serial devices found, connecting to MOCK...`);
try {
await this.connectMock();
}
catch (err) {
this.log.error(`Error connecting to MOCK USB serial device "/dev/fake"`, err);
}
}
await (0, delay_1.delay)(3000);
await this.verify();
}
filter(port) {
if ((port.manufacturer + '').toLowerCase().indexOf('arduino') !== -1 ||
(port.path + '').toLowerCase().indexOf('usbserial') !== -1 ||
@ -57,24 +70,99 @@ class Camera {
return listed.filter(this.filter).map((port) => port.path);
}
async connect(port) {
this.port = port;
try {
this.serial = new serialport_1.SerialPort({
path: port,
autoOpen: false,
path: this.port,
baudRate: this.baud,
});
}
catch (err) {
this.log.error('Error creating SerialPort object', err);
return;
}
if (this.serial !== null) {
this.serial.pipe(this.parser);
this.parser.on('data', this.onData.bind(this));
}
this.ready = true;
return new Promise(function (resolve, reject) {
this.serial.on('open', () => {
this.log.info(`Connected to USB serial device ${this.port} @ ${this.baud} baud`);
this.connected = true;
return resolve(true);
});
}.bind(this));
}
async connectMock() {
this.port = '/dev/fake';
try {
serialport_1.SerialPortMock.binding.createPort(this.port);
this.serial = new serialport_1.SerialPortMock({
path: this.port,
baudRate: this.baud
});
}
catch (err) {
this.log.error('Error creating SerialPortMock object', err);
return;
}
if (this.serial !== null) {
this.serial.pipe(this.parser);
this.parser.on('data', this.onData.bind(this));
}
return new Promise(function (resolve, reject) {
this.serial.on('open', () => {
this.log.info(`Connected to MOCK USB serial device ${this.port} @ ${this.baud} baud`);
this.connected = true;
return resolve(true);
});
}.bind(this));
}
onData(data) {
this.log.info(`Data received: "${data}"`);
this.log.info(`Received data: "${data}"`);
if (this.next !== null) {
this.next(data);
}
}
async verify() {
try {
await this.confirm('i', 'i');
this.log.info(`Confirmed mcopy device`);
}
catch (err) {
this.log.error(`Error connecting to mcopy device`, err);
return;
}
try {
await this.confirm('m', 'k');
this.log.info(`Confirmed mcopy camera`);
}
catch (err) {
this.log.error(`Error identifying device`, err);
return;
}
this.ready = true;
this.log.info(`Camera connected and ready`);
}
async confirm(cmd, res) {
return new Promise(function (resolve, reject) {
this.next = function (data) {
this.next = null;
if (data === res) {
return resolve(true);
}
else {
return reject(new Error(`Response ${data} !== ${res}`));
}
}.bind(this);
this.log.info(`Send data: "${cmd}"`);
this.serial.write(cmd, (err, results) => {
if (err) {
this.log.error('Error writing to device', err);
return reject(err);
}
});
}.bind(this));
}
}
exports.Camera = Camera;

File diff suppressed because one or more lines are too long

3
dist/index.js vendored
View File

@ -36,11 +36,13 @@ const ws_1 = require("ws");
const log_1 = require("./log");
const files_1 = require("./files");
const ffmpeg_1 = require("./ffmpeg");
const camera_1 = require("./camera");
const log = (0, log_1.createLog)('fm');
const app = (0, express_1.default)();
let wss;
let fd;
let ffmpeg;
let camera;
let index;
let port;
let wsPort;
@ -171,6 +173,7 @@ async function main() {
await settings();
index = await createTemplate('./views/index.hbs');
ffmpeg = new ffmpeg_1.FFMPEG(process.env['FFMPEG']);
camera = new camera_1.Camera();
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
app.listen(port, async () => {
log.info(`filmout_manager HTTP server running on port ${port}`);

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

View File

@ -1,8 +1,10 @@
import { createLog } from '../log';
import type { Logger } from 'winston';
import { delay } from '../delay';
import { SerialPort } from 'serialport';
import { SerialPort, SerialPortMock } from 'serialport';
import { ReadlineParser } from '@serialport/parser-readline';
import { MockBinding } from '@serialport/binding-mock';
interface PortInfo {
path: string;
@ -18,8 +20,11 @@ export class Camera {
private log : Logger;
private parser : ReadlineParser;
private ready : boolean = false;
private serial : any = null;
private connected : boolean = false;
private serial : SerialPort | SerialPortMock = null;
private baud : number = 57600;
private next : Function = null;
private port : string = null;
constructor () {
this.log = createLog('camera');
@ -35,10 +40,7 @@ export class Camera {
} catch (err) {
this.log.error('Error calling enumerate()', err);
}
if (ports.length === 0) {
this.log.warn('No USB camera devices connected');
return;
}
if (ports.length > 0) {
for (let port of ports) {
this.log.info(`Found USB serial device: ${port} ${selected ? '*' : ''}`);
selected = false;
@ -48,6 +50,16 @@ export class Camera {
} catch (err) {
this.log.error(`Error connecting to ${ports[0]}`, err);
}
} else {
this.log.warn(`No USB serial devices found, connecting to MOCK...`)
try {
await this.connectMock();
} catch (err) {
this.log.error(`Error connecting to MOCK USB serial device "/dev/fake"`, err);
}
}
await delay(3000);
await this.verify();
}
private filter (port : PortInfo) {
@ -71,24 +83,100 @@ export class Camera {
}
private async connect (port : string) {
this.port = port;
try {
this.serial = new SerialPort({
path : port,
autoOpen : false,
path : this.port,
baudRate: this.baud,
})
});
} catch (err) {
this.log.error('Error creating SerialPort object', err);
return;
}
if (this.serial !== null) {
this.serial.pipe(this.parser);
this.parser.on('data', this.onData.bind(this));
}
this.ready = true;
return new Promise(function (resolve : Function, reject : Function) {
this.serial.on('open', () => {
this.log.info(`Connected to USB serial device ${this.port} @ ${this.baud} baud`);
this.connected = true;
return resolve(true);
});
}.bind(this));
}
private async connectMock () {
this.port = '/dev/fake';
try {
SerialPortMock.binding.createPort(this.port);
this.serial = new SerialPortMock({
path : this.port,
baudRate: this.baud
});
} catch (err) {
this.log.error('Error creating SerialPortMock object', err);
return;
}
if (this.serial !== null) {
this.serial.pipe(this.parser);
this.parser.on('data', this.onData.bind(this));
}
return new Promise(function (resolve : Function, reject : Function) {
this.serial.on('open', () => {
this.log.info(`Connected to MOCK USB serial device ${this.port} @ ${this.baud} baud`);
this.connected = true;
return resolve(true);
});
}.bind(this));
}
private onData (data : string) {
this.log.info(`Data received: "${data}"`);
this.log.info(`Received data: "${data}"`);
if (this.next !== null) {
this.next(data);
}
}
private async verify () {
try {
await this.confirm('i', 'i');
this.log.info(`Confirmed mcopy device`);
} catch (err) {
this.log.error(`Error connecting to mcopy device`, err);
return;
}
try {
await this.confirm('m', 'k');
this.log.info(`Confirmed mcopy camera`);
} catch (err) {
this.log.error(`Error identifying device`, err);
return;
}
this.ready = true;
this.log.info(`Camera connected and ready`);
}
private async confirm (cmd : string, res : string) : Promise<boolean> {
return new Promise (function (resolve : Function, reject: Function) {
this.next = function (data : string) {
this.next = null;
if (data === res) {
return resolve(true);
} else {
return reject(new Error(`Response ${data} !== ${res}`));
}
}.bind(this);
this.log.info(`Send data: "${cmd}"`);
this.serial.write(cmd, (err : any, results : any) => {
if (err) {
this.log.error('Error writing to device', err);
return reject(err);
}
});
}.bind(this));
}
}

View File

@ -22,12 +22,14 @@ import { Shell } from './shell';
import { delay } from './delay';
import { FD } from './fd';
import { FFMPEG } from './ffmpeg';
import { Camera } from './camera';
const log : Logger = createLog('fm');
const app : Express = express();
let wss : Server;
let fd : FD;
let ffmpeg : FFMPEG;
let camera : Camera;
let index : HandlebarsTemplateDelegate<any>;
let port : number;
@ -160,6 +162,8 @@ async function main () {
await settings();
index = await createTemplate('./views/index.hbs');
ffmpeg = new FFMPEG(process.env['FFMPEG']);
camera = new Camera();
//fd = new FD(process.env['FD'], width, height, process.env['FD_HOST'], parseInt(process.env['FD_PORT']));
app.listen(port, async () => {
log.info(`filmout_manager HTTP server running on port ${port}`);
@ -170,6 +174,8 @@ async function main () {
log.info(`filmout_manager WebSocket server running on port ${wsPort}`);
ffmpeg.listFormats();
}