camstreamerlib
Version:
Helper library for CamStreamer ACAP applications.
150 lines (149 loc) • 5.56 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CamScripterAPICameraEventsGenerator = void 0;
const EventEmitter = require("events");
const WsClient_1 = require("./internal/WsClient");
class CamScripterAPICameraEventsGenerator extends EventEmitter {
constructor(options) {
var _a, _b, _c, _d, _e, _f;
super();
this.tls = (_a = options === null || options === void 0 ? void 0 : options.tls) !== null && _a !== void 0 ? _a : false;
this.tlsInsecure = (_b = options === null || options === void 0 ? void 0 : options.tlsInsecure) !== null && _b !== void 0 ? _b : false;
this.ip = (_c = options === null || options === void 0 ? void 0 : options.ip) !== null && _c !== void 0 ? _c : '127.0.0.1';
this.port = (_d = options === null || options === void 0 ? void 0 : options.port) !== null && _d !== void 0 ? _d : (this.tls ? 443 : 80);
this.user = (_e = options === null || options === void 0 ? void 0 : options.user) !== null && _e !== void 0 ? _e : '';
this.pass = (_f = options === null || options === void 0 ? void 0 : options.pass) !== null && _f !== void 0 ? _f : '';
this.callId = 0;
this.sendMessages = {};
this.wsConnected = false;
this.createWsClient();
EventEmitter.call(this);
}
connect() {
this.ws.open();
this.startMsgsTimeoutCheck();
}
disconnect() {
this.ws.close();
this.stopMsgsTimeoutCheck();
}
declareEvent(eventDeclaration) {
return this.sendMessage({
call_id: 0,
command: 'declare_event',
data: eventDeclaration,
});
}
undeclareEvent(eventUndeclaration) {
return this.sendMessage({
call_id: 0,
command: 'undeclare_event',
data: eventUndeclaration,
});
}
sendEvent(event) {
return this.sendMessage({
call_id: 0,
command: 'send_event',
data: event,
});
}
createWsClient() {
const options = {
user: this.user,
pass: this.pass,
tlsInsecure: this.tlsInsecure,
tls: this.tls,
ip: this.ip,
port: this.port,
address: `/local/camscripter/ws`,
protocol: 'camera-events',
};
this.ws = new WsClient_1.WsClient(options);
this.ws.on('open', () => {
this.wsConnected = true;
this.emit('open');
});
this.ws.on('message', (msgData) => this.incomingWsMessageHandler(msgData));
this.ws.on('error', (error) => {
this.reportErr(error);
});
this.ws.on('close', () => {
this.wsConnected = false;
this.reportClose();
});
}
incomingWsMessageHandler(msgData) {
const dataJSON = JSON.parse(msgData.toString());
let errorResponse;
if ('error' in dataJSON) {
errorResponse = dataJSON;
}
if (dataJSON.call_id !== undefined && this.sendMessages[dataJSON.call_id] !== undefined) {
if (errorResponse !== undefined) {
this.sendMessages[dataJSON.call_id].reject(new Error(errorResponse.error));
}
else {
this.sendMessages[dataJSON.call_id].resolve(dataJSON);
}
delete this.sendMessages[dataJSON.call_id];
}
if (errorResponse !== undefined) {
this.reconnectWithError(new Error(errorResponse.error));
}
}
sendMessage(msgJson) {
return new Promise((resolve, reject) => {
if (!this.wsConnected) {
throw new Error("Websocket hasn't been opened yet.");
}
try {
msgJson.call_id = ++this.callId;
this.ws.send(JSON.stringify(msgJson));
this.sendMessages[this.callId] = { resolve, reject, sentTimestamp: Date.now() };
}
catch (err) {
const errorMessage = err instanceof Error ? err.message : 'Unknown error';
const error = new Error(`Send message error: ${errorMessage}`);
reject(error);
this.reconnectWithError(error);
}
});
}
startMsgsTimeoutCheck() {
clearInterval(this.timeoutCheckTimer);
this.timeoutCheckTimer = setInterval(() => {
let reconnect = false;
const now = Date.now();
for (const callId in this.sendMessages) {
const msg = this.sendMessages[callId];
if (now - msg.sentTimestamp > 10000) {
reconnect = true;
msg.reject(new Error('Message timeout'));
delete this.sendMessages[callId];
}
}
if (reconnect) {
this.reconnectWithError(new Error('Message timeout'));
}
}, 5000);
}
stopMsgsTimeoutCheck() {
clearInterval(this.timeoutCheckTimer);
}
reconnectWithError(err) {
this.reportErr(err);
this.ws.reconnect();
}
reportErr(err) {
this.emit('error', err);
}
reportClose() {
for (const callId in this.sendMessages) {
this.sendMessages[callId].reject(new Error('Connection lost'));
}
this.sendMessages = {};
this.emit('close');
}
}
exports.CamScripterAPICameraEventsGenerator = CamScripterAPICameraEventsGenerator;