camstreamerlib 1.8.0 → 1.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CamOverlayAPI.d.ts +15 -8
- package/CamOverlayAPI.js +72 -26
- package/HTTPRequest.d.ts +2 -1
- package/README.md +1 -1
- package/package.json +1 -1
package/CamOverlayAPI.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare type CamOverlayOptions = {
|
|
|
10
10
|
auth?: string;
|
|
11
11
|
serviceName?: string;
|
|
12
12
|
serviceID?: number;
|
|
13
|
-
camera?: number;
|
|
13
|
+
camera?: number | number[];
|
|
14
14
|
};
|
|
15
15
|
export declare type Field = {
|
|
16
16
|
field_name: string;
|
|
@@ -44,11 +44,15 @@ export declare type Service = {
|
|
|
44
44
|
schedule: string;
|
|
45
45
|
name: string;
|
|
46
46
|
identifier: string;
|
|
47
|
-
|
|
47
|
+
cameraList: number[];
|
|
48
48
|
};
|
|
49
49
|
export declare type ServiceList = {
|
|
50
50
|
services: Service[];
|
|
51
51
|
};
|
|
52
|
+
export declare enum ImageType {
|
|
53
|
+
PNG = 0,
|
|
54
|
+
JPEG = 1
|
|
55
|
+
}
|
|
52
56
|
export declare class CamOverlayAPI extends EventEmitter {
|
|
53
57
|
private tls;
|
|
54
58
|
private tlsInsecure;
|
|
@@ -57,7 +61,7 @@ export declare class CamOverlayAPI extends EventEmitter {
|
|
|
57
61
|
private auth;
|
|
58
62
|
private serviceName;
|
|
59
63
|
private serviceID;
|
|
60
|
-
private
|
|
64
|
+
private cameraList;
|
|
61
65
|
private callId;
|
|
62
66
|
private sendMessages;
|
|
63
67
|
private ws;
|
|
@@ -73,17 +77,20 @@ export declare class CamOverlayAPI extends EventEmitter {
|
|
|
73
77
|
showCairoImage(cairoImage: string, posX: number, posY: number): Promise<CairoResponse>;
|
|
74
78
|
showCairoImageAbsolute(cairoImage: string, posX: number, posY: number, width: number, height: number): Promise<CairoResponse>;
|
|
75
79
|
removeImage(): Promise<CairoResponse>;
|
|
76
|
-
sendMessage
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
+
private sendMessage;
|
|
81
|
+
private sendBinaryMessage;
|
|
82
|
+
private reportMsg;
|
|
83
|
+
private reportErr;
|
|
84
|
+
private reportClose;
|
|
80
85
|
updateCGText(fields: Field[]): Promise<void>;
|
|
81
86
|
private formCoordinates;
|
|
82
87
|
updateCGImage(path: string, coordinates?: string, x?: number, y?: number): Promise<void>;
|
|
88
|
+
updateCGImageFromData(imageType: ImageType, imageData: Buffer, coordinates?: string, x?: number, y?: number): Promise<void>;
|
|
83
89
|
updateCGImagePos(coordinates?: string, x?: number, y?: number): Promise<void>;
|
|
84
|
-
promiseCGUpdate(action: string, params: string): Promise<void>;
|
|
90
|
+
promiseCGUpdate(action: string, params: string, contentType?: string, data?: Buffer): Promise<void>;
|
|
85
91
|
updateInfoticker(text: string): Promise<void>;
|
|
86
92
|
setEnabled(enabled: boolean): Promise<void>;
|
|
87
93
|
isEnabled(): Promise<boolean>;
|
|
88
94
|
private getBaseVapixConnectionParams;
|
|
95
|
+
private compareCameraList;
|
|
89
96
|
}
|
package/CamOverlayAPI.js
CHANGED
|
@@ -9,14 +9,19 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.CamOverlayAPI = void 0;
|
|
12
|
+
exports.CamOverlayAPI = exports.ImageType = void 0;
|
|
13
13
|
const WebSocket = require("ws");
|
|
14
14
|
const EventEmitter = require("events");
|
|
15
15
|
const Digest_1 = require("./Digest");
|
|
16
16
|
const HTTPRequest_1 = require("./HTTPRequest");
|
|
17
|
+
var ImageType;
|
|
18
|
+
(function (ImageType) {
|
|
19
|
+
ImageType[ImageType["PNG"] = 0] = "PNG";
|
|
20
|
+
ImageType[ImageType["JPEG"] = 1] = "JPEG";
|
|
21
|
+
})(ImageType = exports.ImageType || (exports.ImageType = {}));
|
|
17
22
|
class CamOverlayAPI extends EventEmitter {
|
|
18
23
|
constructor(options) {
|
|
19
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
24
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
20
25
|
super();
|
|
21
26
|
this.ws = null;
|
|
22
27
|
this.tls = (_a = options === null || options === void 0 ? void 0 : options.tls) !== null && _a !== void 0 ? _a : false;
|
|
@@ -25,11 +30,17 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
25
30
|
}
|
|
26
31
|
this.tlsInsecure = (_b = options === null || options === void 0 ? void 0 : options.tlsInsecure) !== null && _b !== void 0 ? _b : false;
|
|
27
32
|
this.ip = (_c = options === null || options === void 0 ? void 0 : options.ip) !== null && _c !== void 0 ? _c : '127.0.0.1';
|
|
28
|
-
this.port = (
|
|
33
|
+
this.port = (_d = options === null || options === void 0 ? void 0 : options.port) !== null && _d !== void 0 ? _d : (this.tls ? 443 : 80);
|
|
29
34
|
this.auth = (_e = options === null || options === void 0 ? void 0 : options.auth) !== null && _e !== void 0 ? _e : '';
|
|
30
35
|
this.serviceName = (_f = options === null || options === void 0 ? void 0 : options.serviceName) !== null && _f !== void 0 ? _f : '';
|
|
31
36
|
this.serviceID = (_g = options === null || options === void 0 ? void 0 : options.serviceID) !== null && _g !== void 0 ? _g : -1;
|
|
32
|
-
this.
|
|
37
|
+
this.cameraList = [0];
|
|
38
|
+
if (Array.isArray(options === null || options === void 0 ? void 0 : options.camera)) {
|
|
39
|
+
this.cameraList = options.camera;
|
|
40
|
+
}
|
|
41
|
+
else if (typeof (options === null || options === void 0 ? void 0 : options.camera) === 'number') {
|
|
42
|
+
this.cameraList = [options.camera];
|
|
43
|
+
}
|
|
33
44
|
this.callId = 0;
|
|
34
45
|
this.sendMessages = {};
|
|
35
46
|
EventEmitter.call(this);
|
|
@@ -37,7 +48,7 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
37
48
|
connect() {
|
|
38
49
|
return __awaiter(this, void 0, void 0, function* () {
|
|
39
50
|
try {
|
|
40
|
-
if (this.serviceID
|
|
51
|
+
if (this.serviceID === -1) {
|
|
41
52
|
this.serviceID = yield this.createService();
|
|
42
53
|
}
|
|
43
54
|
yield this.openWebsocket();
|
|
@@ -70,14 +81,14 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
70
81
|
if (s.id > maxID) {
|
|
71
82
|
maxID = s.id;
|
|
72
83
|
}
|
|
73
|
-
if (s.identifier
|
|
84
|
+
if (s.identifier === this.serviceName && s.name === 'scripter') {
|
|
74
85
|
service = s;
|
|
75
86
|
break;
|
|
76
87
|
}
|
|
77
88
|
}
|
|
78
|
-
if (service
|
|
79
|
-
if (service.
|
|
80
|
-
service.
|
|
89
|
+
if (service !== null) {
|
|
90
|
+
if (service.cameraList === undefined || !this.compareCameraList(service.cameraList)) {
|
|
91
|
+
service.cameraList = this.cameraList;
|
|
81
92
|
yield this.updateServices(servicesJson);
|
|
82
93
|
return service.id;
|
|
83
94
|
}
|
|
@@ -93,7 +104,7 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
93
104
|
schedule: '',
|
|
94
105
|
name: 'scripter',
|
|
95
106
|
identifier: this.serviceName,
|
|
96
|
-
|
|
107
|
+
cameraList: this.cameraList,
|
|
97
108
|
};
|
|
98
109
|
servicesJson.services.push(service);
|
|
99
110
|
yield this.updateServices(servicesJson);
|
|
@@ -119,10 +130,11 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
119
130
|
rejectUnauthorized: !this.tlsInsecure,
|
|
120
131
|
headers: {},
|
|
121
132
|
};
|
|
122
|
-
if (digestHeader
|
|
133
|
+
if (digestHeader !== undefined) {
|
|
123
134
|
options.headers['Authorization'] = Digest_1.Digest.getAuthHeader(userPass[0], userPass[1], 'GET', '/local/camoverlay/ws', digestHeader);
|
|
124
135
|
}
|
|
125
136
|
this.ws = new WebSocket(addr, 'cairo-api', options);
|
|
137
|
+
this.ws.binaryType = 'arraybuffer';
|
|
126
138
|
this.ws.on('open', () => {
|
|
127
139
|
this.reportMsg('Websocket opened');
|
|
128
140
|
resolve();
|
|
@@ -142,7 +154,7 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
142
154
|
}
|
|
143
155
|
});
|
|
144
156
|
this.ws.on('unexpected-response', (req, res) => __awaiter(this, void 0, void 0, function* () {
|
|
145
|
-
if (res.statusCode
|
|
157
|
+
if (res.statusCode === 401 && res.headers['www-authenticate'] !== undefined)
|
|
146
158
|
this.openWebsocket(res.headers['www-authenticate']).then(resolve, reject);
|
|
147
159
|
else {
|
|
148
160
|
reject('Error: status code: ' + res.statusCode + ', ' + res.data);
|
|
@@ -165,16 +177,16 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
165
177
|
return this.sendMessage({ command: 'write_text', params: params });
|
|
166
178
|
}
|
|
167
179
|
uploadImageData(imgBuffer) {
|
|
168
|
-
return this.
|
|
180
|
+
return this.sendBinaryMessage({
|
|
169
181
|
command: 'upload_image_data',
|
|
170
|
-
params: [
|
|
171
|
-
});
|
|
182
|
+
params: [],
|
|
183
|
+
}, imgBuffer);
|
|
172
184
|
}
|
|
173
185
|
uploadFontData(fontBuffer) {
|
|
174
|
-
return this.
|
|
186
|
+
return this.sendBinaryMessage({
|
|
175
187
|
command: 'upload_font_data',
|
|
176
188
|
params: [fontBuffer.toString('base64')],
|
|
177
|
-
});
|
|
189
|
+
}, fontBuffer);
|
|
178
190
|
}
|
|
179
191
|
showCairoImage(cairoImage, posX, posY) {
|
|
180
192
|
return this.sendMessage({
|
|
@@ -203,6 +215,24 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
203
215
|
}
|
|
204
216
|
});
|
|
205
217
|
}
|
|
218
|
+
sendBinaryMessage(msgJson, data) {
|
|
219
|
+
return new Promise((resolve, reject) => {
|
|
220
|
+
try {
|
|
221
|
+
this.sendMessages[this.callId] = { resolve, reject };
|
|
222
|
+
msgJson['call_id'] = this.callId++;
|
|
223
|
+
const jsonBuffer = Buffer.from(JSON.stringify(msgJson));
|
|
224
|
+
const header = new ArrayBuffer(5);
|
|
225
|
+
const headerView = new DataView(header);
|
|
226
|
+
headerView.setInt8(0, 1);
|
|
227
|
+
headerView.setInt32(1, jsonBuffer.byteLength);
|
|
228
|
+
const msgBuffer = Buffer.concat([Buffer.from(header), jsonBuffer, data]);
|
|
229
|
+
this.ws.send(msgBuffer);
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
this.reportErr(new Error(`Send binary message error: ${err}`));
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
206
236
|
reportMsg(msg) {
|
|
207
237
|
this.emit('msg', msg);
|
|
208
238
|
}
|
|
@@ -213,6 +243,10 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
213
243
|
this.emit('close');
|
|
214
244
|
}
|
|
215
245
|
reportClose() {
|
|
246
|
+
for (const callId in this.sendMessages) {
|
|
247
|
+
this.sendMessages[callId].reject(new Error('Connection lost'));
|
|
248
|
+
}
|
|
249
|
+
this.sendMessages = {};
|
|
216
250
|
this.emit('close');
|
|
217
251
|
}
|
|
218
252
|
updateCGText(fields) {
|
|
@@ -220,30 +254,38 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
220
254
|
for (let field of fields) {
|
|
221
255
|
const name = field.field_name;
|
|
222
256
|
field_specs += `&${name}=${field.text}`;
|
|
223
|
-
if (field.color
|
|
257
|
+
if (field.color !== undefined) {
|
|
224
258
|
field_specs += `&${name}_color=${field.color}`;
|
|
225
259
|
}
|
|
226
260
|
}
|
|
227
261
|
return this.promiseCGUpdate('update_text', field_specs);
|
|
228
262
|
}
|
|
229
263
|
formCoordinates(coordinates, x, y) {
|
|
230
|
-
return coordinates
|
|
264
|
+
return coordinates !== '' ? `&coord_system=${coordinates}&pos_x=${x}&pos_y=${y}` : '';
|
|
231
265
|
}
|
|
232
266
|
updateCGImage(path, coordinates = '', x = 0, y = 0) {
|
|
233
267
|
const coord = this.formCoordinates(coordinates, x, y);
|
|
234
268
|
const update = `&image=${path}`;
|
|
235
269
|
return this.promiseCGUpdate('update_image', update + coord);
|
|
236
270
|
}
|
|
271
|
+
updateCGImageFromData(imageType, imageData, coordinates = '', x = 0, y = 0) {
|
|
272
|
+
const coord = this.formCoordinates(coordinates, x, y);
|
|
273
|
+
const contentType = imageType === ImageType.PNG ? 'image/png' : 'image/jpeg';
|
|
274
|
+
return this.promiseCGUpdate('update_image', coord, contentType, imageData);
|
|
275
|
+
}
|
|
237
276
|
updateCGImagePos(coordinates = '', x = 0, y = 0) {
|
|
238
277
|
const coord = this.formCoordinates(coordinates, x, y);
|
|
239
278
|
return this.promiseCGUpdate('update_image', coord);
|
|
240
279
|
}
|
|
241
|
-
promiseCGUpdate(action, params) {
|
|
280
|
+
promiseCGUpdate(action, params, contentType, data) {
|
|
242
281
|
return __awaiter(this, void 0, void 0, function* () {
|
|
243
282
|
const options = this.getBaseVapixConnectionParams();
|
|
244
283
|
options.method = 'POST';
|
|
245
284
|
options.path = encodeURI(`/local/camoverlay/api/customGraphics.cgi?action=${action}&service_id=${this.serviceID}${params}`);
|
|
246
|
-
|
|
285
|
+
if (contentType && data) {
|
|
286
|
+
options.headers = { 'Content-Type': contentType };
|
|
287
|
+
}
|
|
288
|
+
yield (0, HTTPRequest_1.httpRequest)(options, data);
|
|
247
289
|
});
|
|
248
290
|
}
|
|
249
291
|
updateInfoticker(text) {
|
|
@@ -251,7 +293,7 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
251
293
|
const options = this.getBaseVapixConnectionParams();
|
|
252
294
|
options.method = 'GET';
|
|
253
295
|
options.path = `/local/camoverlay/api/infoticker.cgi?service_id=${this.serviceID}&text=${text}`;
|
|
254
|
-
yield (0, HTTPRequest_1.httpRequest)(options
|
|
296
|
+
yield (0, HTTPRequest_1.httpRequest)(options);
|
|
255
297
|
});
|
|
256
298
|
}
|
|
257
299
|
setEnabled(enabled) {
|
|
@@ -259,7 +301,7 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
259
301
|
const options = this.getBaseVapixConnectionParams();
|
|
260
302
|
options.method = 'POST';
|
|
261
303
|
options.path = encodeURI(`/local/camoverlay/api/enabled.cgi?id_${this.serviceID}=${enabled ? 1 : 0}`);
|
|
262
|
-
yield (0, HTTPRequest_1.httpRequest)(options
|
|
304
|
+
yield (0, HTTPRequest_1.httpRequest)(options);
|
|
263
305
|
});
|
|
264
306
|
}
|
|
265
307
|
isEnabled() {
|
|
@@ -267,11 +309,11 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
267
309
|
const options = this.getBaseVapixConnectionParams();
|
|
268
310
|
options.method = 'GET';
|
|
269
311
|
options.path = '/local/camoverlay/api/services.cgi?action=get';
|
|
270
|
-
const response = (yield (0, HTTPRequest_1.httpRequest)(options
|
|
312
|
+
const response = (yield (0, HTTPRequest_1.httpRequest)(options));
|
|
271
313
|
const data = JSON.parse(response);
|
|
272
314
|
for (let service of data.services) {
|
|
273
|
-
if (service.id
|
|
274
|
-
return service.enabled
|
|
315
|
+
if (service.id === this.serviceID) {
|
|
316
|
+
return service.enabled === 1;
|
|
275
317
|
}
|
|
276
318
|
}
|
|
277
319
|
throw new Error('Service not found.');
|
|
@@ -286,5 +328,9 @@ class CamOverlayAPI extends EventEmitter {
|
|
|
286
328
|
rejectUnauthorized: !this.tlsInsecure,
|
|
287
329
|
};
|
|
288
330
|
}
|
|
331
|
+
compareCameraList(cameraList) {
|
|
332
|
+
return (this.cameraList.length === cameraList.length &&
|
|
333
|
+
this.cameraList.every((element, index) => element === cameraList[index]));
|
|
334
|
+
}
|
|
289
335
|
}
|
|
290
336
|
exports.CamOverlayAPI = CamOverlayAPI;
|
package/HTTPRequest.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import * as http from 'http';
|
|
3
4
|
export declare type HttpRequestOptions = {
|
|
4
5
|
method?: string;
|
|
@@ -13,4 +14,4 @@ export declare type HttpRequestOptions = {
|
|
|
13
14
|
};
|
|
14
15
|
rejectUnauthorized?: boolean;
|
|
15
16
|
};
|
|
16
|
-
export declare function httpRequest(options: HttpRequestOptions, postData?: string, noWaitForData?: boolean): Promise<string | http.IncomingMessage>;
|
|
17
|
+
export declare function httpRequest(options: HttpRequestOptions, postData?: Buffer | string, noWaitForData?: boolean): Promise<string | http.IncomingMessage>;
|
package/README.md
CHANGED
|
@@ -197,7 +197,7 @@ Module for easy control of CamOverlay drawing API. For more details on supported
|
|
|
197
197
|
|
|
198
198
|
### methods
|
|
199
199
|
#### CameraVapix(options)
|
|
200
|
-
Options parameter contains access to the camera, service name, service ID and camera. If service ID is not specified, service is automatically created/selected based on serviceName. Specify video channel using parameter camera (in which View Area overlay will be shown). If omitted the default value camera=0 is used.
|
|
200
|
+
Options parameter contains access to the camera, service name, service ID and camera. If service ID is not specified, service is automatically created/selected based on serviceName. Specify video channel using parameter camera (in which View Area overlay will be shown). If you need to specify multiple video channels, you can use an array: `camera=[0,1]`. If omitted the default value `camera=0` is used.
|
|
201
201
|
```javascript
|
|
202
202
|
options = {
|
|
203
203
|
'ip': '127.0.0.1',
|