camstreamerlib 4.0.0-beta.47 → 4.0.0-beta.48
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/README.md +123 -30
- package/cjs/CamSwitcherAPI.js +1 -1
- package/cjs/PlaneTrackerAPI.js +4 -0
- package/cjs/index.js +18 -9
- package/cjs/internal/WsEvents.js +6 -5
- package/cjs/node/CamOverlayDrawingAPI.js +10 -10
- package/cjs/node/CamScripterAPICameraEventsGenerator.js +9 -9
- package/cjs/node/Digest.test.js +13 -0
- package/cjs/node/VapixEvents.js +9 -9
- package/cjs/node/WsClient.js +20 -13
- package/cjs/types/CamOverlayAPI/pipSchema.js +1 -1
- package/cjs/types/PlaneTrackerAPI.js +4 -1
- package/cjs/types/ws/CamOverlayEvents.js +19 -0
- package/cjs/types/ws/CamStreamerEvents.js +32 -0
- package/cjs/types/ws/PlaneTrackerEvents.js +77 -0
- package/cjs/web/DefaultClient.js +6 -2
- package/cjs/web/WsClient.js +13 -15
- package/cjs/ws/CamOverlayEvents.js +24 -0
- package/cjs/ws/CamStreamerEvents.js +24 -0
- package/cjs/ws/CamSwitcherEvents.js +24 -0
- package/cjs/ws/PlaneTrackerEvents.js +22 -0
- package/esm/CamSwitcherAPI.js +1 -1
- package/esm/PlaneTrackerAPI.js +5 -1
- package/esm/index.js +12 -6
- package/esm/internal/WsEvents.js +6 -5
- package/esm/node/CamOverlayDrawingAPI.js +10 -10
- package/esm/node/CamScripterAPICameraEventsGenerator.js +9 -9
- package/esm/node/Digest.test.js +11 -0
- package/esm/node/VapixEvents.js +9 -9
- package/esm/node/WsClient.js +20 -13
- package/esm/types/CamOverlayAPI/pipSchema.js +1 -1
- package/esm/types/PlaneTrackerAPI.js +3 -0
- package/esm/types/ws/CamOverlayEvents.js +16 -0
- package/esm/types/ws/CamStreamerEvents.js +29 -0
- package/esm/types/ws/PlaneTrackerEvents.js +74 -0
- package/esm/web/DefaultClient.js +6 -2
- package/esm/web/WsClient.js +13 -15
- package/esm/ws/CamOverlayEvents.js +20 -0
- package/esm/ws/CamStreamerEvents.js +20 -0
- package/esm/ws/CamSwitcherEvents.js +20 -0
- package/esm/ws/PlaneTrackerEvents.js +18 -0
- package/package.json +1 -1
- package/types/CamSwitcherAPI.d.ts +1 -1
- package/types/PlaneTrackerAPI.d.ts +2 -1
- package/types/index.d.ts +12 -6
- package/types/internal/WsEvents.d.ts +3 -5
- package/types/internal/types.d.ts +7 -6
- package/types/node/CamScripterAPICameraEventsGenerator.d.ts +2 -2
- package/types/node/Digest.test.d.ts +1 -0
- package/types/node/VapixEvents.d.ts +2 -2
- package/types/node/WsClient.d.ts +9 -19
- package/types/types/CamOverlayAPI/CamOverlayAPI.d.ts +5 -5
- package/types/types/CamOverlayAPI/pipSchema.d.ts +2 -2
- package/types/types/CamOverlayDrawingAPI.d.ts +2 -2
- package/types/types/PlaneTrackerAPI.d.ts +8 -0
- package/types/types/ws/CamOverlayEvents.d.ts +88 -0
- package/types/types/ws/CamStreamerEvents.d.ts +249 -0
- package/types/types/ws/PlaneTrackerEvents.d.ts +947 -0
- package/types/web/DefaultClient.d.ts +2 -0
- package/types/web/WsClient.d.ts +9 -5
- package/types/ws/CamOverlayEvents.d.ts +8 -0
- package/types/ws/CamStreamerEvents.d.ts +8 -0
- package/types/ws/CamSwitcherEvents.d.ts +8 -0
- package/types/ws/PlaneTrackerEvents.d.ts +9 -0
- package/cjs/CamSwitcherEvents.js +0 -11
- package/esm/CamSwitcherEvents.js +0 -7
- package/types/CamSwitcherEvents.d.ts +0 -8
- /package/cjs/types/{CamSwitcherEvents.js → ws/CamSwitcherEvents.js} +0 -0
- /package/esm/types/{CamSwitcherEvents.js → ws/CamSwitcherEvents.js} +0 -0
- /package/types/types/{CamSwitcherEvents.d.ts → ws/CamSwitcherEvents.d.ts} +0 -0
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ptrEventsSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const apiFlightDataSchema = zod_1.z.object({
|
|
6
|
+
icao: zod_1.z.string(),
|
|
7
|
+
lat: zod_1.z.number(),
|
|
8
|
+
lon: zod_1.z.number(),
|
|
9
|
+
heading: zod_1.z.number(),
|
|
10
|
+
groundSpeed: zod_1.z.number(),
|
|
11
|
+
altitudeAMSL: zod_1.z.number(),
|
|
12
|
+
cameraDistance: zod_1.z.number(),
|
|
13
|
+
autoTrackingOrder: zod_1.z.number(),
|
|
14
|
+
whiteListed: zod_1.z.boolean(),
|
|
15
|
+
blackListed: zod_1.z.boolean(),
|
|
16
|
+
priorityListed: zod_1.z.boolean(),
|
|
17
|
+
autoSelectionIgnored: zod_1.z.boolean(),
|
|
18
|
+
signalQuality: zod_1.z.number(),
|
|
19
|
+
emergencyState: zod_1.z.boolean(),
|
|
20
|
+
emergencyStatusMessage: zod_1.z.string(),
|
|
21
|
+
});
|
|
22
|
+
const apiUserSchema = zod_1.z.object({
|
|
23
|
+
userId: zod_1.z.string(),
|
|
24
|
+
userName: zod_1.z.string(),
|
|
25
|
+
userPriority: zod_1.z.number(),
|
|
26
|
+
ip: zod_1.z.string(),
|
|
27
|
+
});
|
|
28
|
+
const ptrEventsDataSchema = zod_1.z.discriminatedUnion('type', [
|
|
29
|
+
zod_1.z.object({
|
|
30
|
+
type: zod_1.z.literal('CAMERA_POSITION'),
|
|
31
|
+
lat: zod_1.z.number(),
|
|
32
|
+
lon: zod_1.z.number(),
|
|
33
|
+
azimuth: zod_1.z.number().min(0).max(360),
|
|
34
|
+
elevation: zod_1.z.number().min(-90).max(90),
|
|
35
|
+
fov: zod_1.z.number(),
|
|
36
|
+
}),
|
|
37
|
+
zod_1.z.object({
|
|
38
|
+
type: zod_1.z.literal('TRACKING_START'),
|
|
39
|
+
icao: zod_1.z.string(),
|
|
40
|
+
}),
|
|
41
|
+
zod_1.z.object({
|
|
42
|
+
type: zod_1.z.literal('TRACKING_STOP'),
|
|
43
|
+
}),
|
|
44
|
+
zod_1.z.object({
|
|
45
|
+
type: zod_1.z.literal('FLIGHT_LIST'),
|
|
46
|
+
list: zod_1.z.array(apiFlightDataSchema),
|
|
47
|
+
}),
|
|
48
|
+
zod_1.z.object({
|
|
49
|
+
type: zod_1.z.literal('USER_ACTION'),
|
|
50
|
+
ip: zod_1.z.string(),
|
|
51
|
+
params: zod_1.z.object({
|
|
52
|
+
userId: zod_1.z.string(),
|
|
53
|
+
userName: zod_1.z.string(),
|
|
54
|
+
userPriority: zod_1.z.number(),
|
|
55
|
+
}),
|
|
56
|
+
cgi: zod_1.z.string(),
|
|
57
|
+
postJsonBody: zod_1.z.any(),
|
|
58
|
+
}),
|
|
59
|
+
zod_1.z.object({
|
|
60
|
+
type: zod_1.z.literal('CONNECTED_USERS'),
|
|
61
|
+
users: zod_1.z.array(apiUserSchema),
|
|
62
|
+
}),
|
|
63
|
+
zod_1.z.object({
|
|
64
|
+
type: zod_1.z.literal('FORCE_TRACKING_STATUS'),
|
|
65
|
+
enabled: zod_1.z.boolean(),
|
|
66
|
+
icao: zod_1.z.string().optional(),
|
|
67
|
+
}),
|
|
68
|
+
zod_1.z.object({
|
|
69
|
+
type: zod_1.z.literal('API_LOCK_STATUS'),
|
|
70
|
+
isLocked: zod_1.z.boolean(),
|
|
71
|
+
user: apiUserSchema.optional(),
|
|
72
|
+
}),
|
|
73
|
+
]);
|
|
74
|
+
exports.ptrEventsSchema = zod_1.z.discriminatedUnion('type', [
|
|
75
|
+
zod_1.z.object({ type: zod_1.z.literal('init'), data: ptrEventsDataSchema }),
|
|
76
|
+
...ptrEventsDataSchema.options,
|
|
77
|
+
]);
|
package/cjs/web/DefaultClient.js
CHANGED
|
@@ -3,6 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DefaultClient = void 0;
|
|
4
4
|
const utils_1 = require("../internal/utils");
|
|
5
5
|
class DefaultClient {
|
|
6
|
+
domain;
|
|
7
|
+
constructor(domain = '') {
|
|
8
|
+
this.domain = domain;
|
|
9
|
+
}
|
|
6
10
|
get = (params) => {
|
|
7
11
|
return this.fetchWithTimeout((0, utils_1.addParametersToPath)(params.path, params.parameters), {
|
|
8
12
|
method: 'GET',
|
|
@@ -16,11 +20,11 @@ class DefaultClient {
|
|
|
16
20
|
headers: params.headers,
|
|
17
21
|
}, params.timeout);
|
|
18
22
|
};
|
|
19
|
-
async fetchWithTimeout(
|
|
23
|
+
async fetchWithTimeout(path, options, timeout) {
|
|
20
24
|
const controller = new AbortController();
|
|
21
25
|
const timeoutId = timeout !== undefined ? setTimeout(() => controller.abort(), timeout) : null;
|
|
22
26
|
try {
|
|
23
|
-
return await fetch(
|
|
27
|
+
return await fetch(`${this.domain}${path}`, { ...options, signal: controller.signal });
|
|
24
28
|
}
|
|
25
29
|
finally {
|
|
26
30
|
if (timeoutId) {
|
package/cjs/web/WsClient.js
CHANGED
|
@@ -4,13 +4,11 @@ exports.WsClient = void 0;
|
|
|
4
4
|
const REFRESH_TIMEOUT = 5000;
|
|
5
5
|
class WsClient {
|
|
6
6
|
getUrl;
|
|
7
|
-
getAuthToken;
|
|
8
7
|
isDestroyed = false;
|
|
9
8
|
ws = null;
|
|
10
9
|
restartTimeout = null;
|
|
11
|
-
constructor(getUrl
|
|
10
|
+
constructor(getUrl) {
|
|
12
11
|
this.getUrl = getUrl;
|
|
13
|
-
this.getAuthToken = getAuthToken;
|
|
14
12
|
}
|
|
15
13
|
init() {
|
|
16
14
|
if (this.isDestroyed) {
|
|
@@ -18,17 +16,9 @@ class WsClient {
|
|
|
18
16
|
}
|
|
19
17
|
this.destroyWebsocket();
|
|
20
18
|
const ws = new WebSocket(this.getUrl(), 'events');
|
|
21
|
-
ws.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
ws.send(JSON.stringify({ authorization: token }));
|
|
25
|
-
}
|
|
26
|
-
catch (error) {
|
|
27
|
-
console.error('Error sending auth token:', error);
|
|
28
|
-
ws.close();
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
ws.onmessage = (e) => this.onmessage(e);
|
|
19
|
+
ws.binaryType = 'arraybuffer';
|
|
20
|
+
ws.onopen = () => this.onOpen();
|
|
21
|
+
ws.onmessage = (e) => this.onMessage(e.data);
|
|
32
22
|
ws.onclose = () => {
|
|
33
23
|
this.restartTimeout = window.setTimeout(() => this.init(), REFRESH_TIMEOUT);
|
|
34
24
|
};
|
|
@@ -37,7 +27,15 @@ class WsClient {
|
|
|
37
27
|
send = (msg) => {
|
|
38
28
|
this.ws?.send(msg);
|
|
39
29
|
};
|
|
40
|
-
|
|
30
|
+
onMessage = (_) => { };
|
|
31
|
+
onOpen = () => { };
|
|
32
|
+
onClose = () => { };
|
|
33
|
+
onError = (error) => {
|
|
34
|
+
console.error(error);
|
|
35
|
+
};
|
|
36
|
+
reconnect = () => {
|
|
37
|
+
this.ws?.close();
|
|
38
|
+
};
|
|
41
39
|
destroy = () => {
|
|
42
40
|
this.isDestroyed = true;
|
|
43
41
|
this.destroyWebsocket();
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamOverlayEvents = void 0;
|
|
4
|
+
const WsEvents_1 = require("../internal/WsEvents");
|
|
5
|
+
const CamOverlayEvents_1 = require("../types/ws/CamOverlayEvents");
|
|
6
|
+
class CamOverlayEvents extends WsEvents_1.WsEvents {
|
|
7
|
+
getAuthToken;
|
|
8
|
+
constructor(ws, getAuthToken) {
|
|
9
|
+
super(CamOverlayEvents_1.coEventsSchema, ws);
|
|
10
|
+
this.getAuthToken = getAuthToken;
|
|
11
|
+
this.ws.onOpen = this.sendInitMsg;
|
|
12
|
+
}
|
|
13
|
+
sendInitMsg = async () => {
|
|
14
|
+
try {
|
|
15
|
+
const token = await this.getAuthToken();
|
|
16
|
+
this.ws.send(JSON.stringify({ authorization: token }));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error('Error on open:', error);
|
|
20
|
+
this.ws.reconnect();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
exports.CamOverlayEvents = CamOverlayEvents;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamStreamerEvents = void 0;
|
|
4
|
+
const WsEvents_1 = require("../internal/WsEvents");
|
|
5
|
+
const CamStreamerEvents_1 = require("../types/ws/CamStreamerEvents");
|
|
6
|
+
class CamStreamerEvents extends WsEvents_1.WsEvents {
|
|
7
|
+
getAuthToken;
|
|
8
|
+
constructor(ws, getAuthToken) {
|
|
9
|
+
super(CamStreamerEvents_1.csEventsSchema, ws);
|
|
10
|
+
this.getAuthToken = getAuthToken;
|
|
11
|
+
this.ws.onOpen = this.sendInitMsg;
|
|
12
|
+
}
|
|
13
|
+
sendInitMsg = async () => {
|
|
14
|
+
try {
|
|
15
|
+
const token = await this.getAuthToken();
|
|
16
|
+
this.ws.send(JSON.stringify({ authorization: token }));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error('Error on open:', error);
|
|
20
|
+
this.ws.reconnect();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
exports.CamStreamerEvents = CamStreamerEvents;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CamSwitcherEvents = void 0;
|
|
4
|
+
const WsEvents_1 = require("../internal/WsEvents");
|
|
5
|
+
const CamSwitcherEvents_1 = require("../types/ws/CamSwitcherEvents");
|
|
6
|
+
class CamSwitcherEvents extends WsEvents_1.WsEvents {
|
|
7
|
+
getAuthToken;
|
|
8
|
+
constructor(ws, getAuthToken) {
|
|
9
|
+
super(CamSwitcherEvents_1.cswEventsSchema, ws);
|
|
10
|
+
this.getAuthToken = getAuthToken;
|
|
11
|
+
this.ws.onOpen = this.sendInitMsg;
|
|
12
|
+
}
|
|
13
|
+
sendInitMsg = async () => {
|
|
14
|
+
try {
|
|
15
|
+
const token = await this.getAuthToken();
|
|
16
|
+
this.ws.send(JSON.stringify({ authorization: token }));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error('Error on open:', error);
|
|
20
|
+
this.ws.reconnect();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
exports.CamSwitcherEvents = CamSwitcherEvents;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlaneTrackerEvents = void 0;
|
|
4
|
+
const WsEvents_1 = require("../internal/WsEvents");
|
|
5
|
+
const PlaneTrackerEvents_1 = require("../types/ws/PlaneTrackerEvents");
|
|
6
|
+
class PlaneTrackerEvents extends WsEvents_1.WsEvents {
|
|
7
|
+
_apiUser;
|
|
8
|
+
constructor(ws, _apiUser) {
|
|
9
|
+
super(PlaneTrackerEvents_1.ptrEventsSchema, ws);
|
|
10
|
+
this._apiUser = _apiUser;
|
|
11
|
+
this.ws.onOpen = this.sendInitMsg;
|
|
12
|
+
}
|
|
13
|
+
sendInitMsg = () => {
|
|
14
|
+
this.ws.send(JSON.stringify({
|
|
15
|
+
type: 'USER_INFO',
|
|
16
|
+
userId: this._apiUser.userId,
|
|
17
|
+
userName: this._apiUser.userName,
|
|
18
|
+
userPriority: this._apiUser.userPriority,
|
|
19
|
+
}));
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
exports.PlaneTrackerEvents = PlaneTrackerEvents;
|
package/esm/CamSwitcherAPI.js
CHANGED
|
@@ -19,7 +19,7 @@ export class CamSwitcherAPI {
|
|
|
19
19
|
}
|
|
20
20
|
static getProxyPath = () => `${BASE_PATH}/proxy.cgi`;
|
|
21
21
|
static getWsEventsPath = () => `/local/camswitcher/events`;
|
|
22
|
-
static getClipPreviewPath = (
|
|
22
|
+
static getClipPreviewPath = (clipId, storage) => `${BASE_PATH}/clip_preview.cgi?clip_name=${clipId}&storage=${storage}`;
|
|
23
23
|
getClient(proxyParams) {
|
|
24
24
|
return proxyParams ? new ProxyClient(this.client, proxyParams) : this.client;
|
|
25
25
|
}
|
package/esm/PlaneTrackerAPI.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { paramToUrl, responseStringify } from './internal/utils';
|
|
3
|
-
import { blackListSchema, cameraSettingsSchema, flightInfoSchema, mapInfoSchema, priorityListSchema, serverSettingsSchema, trackingModeSchema, whiteListSchema, wsAliasResponseSchema, zonesSchema, } from './types/PlaneTrackerAPI';
|
|
3
|
+
import { blackListSchema, cameraSettingsSchema, flightInfoSchema, getIcaoSchema, mapInfoSchema, priorityListSchema, serverSettingsSchema, trackingModeSchema, whiteListSchema, wsAliasResponseSchema, zonesSchema, } from './types/PlaneTrackerAPI';
|
|
4
4
|
import { ImportSettingsError, ParsingBlobError, ResetCalibrationError } from './errors/errors';
|
|
5
5
|
import { ProxyClient } from './internal/ProxyClient';
|
|
6
6
|
import { cameraListSchema } from './types/GenetecAgent';
|
|
@@ -110,6 +110,10 @@ export class PlaneTrackerAPI {
|
|
|
110
110
|
timeout: options?.timeout,
|
|
111
111
|
});
|
|
112
112
|
}
|
|
113
|
+
async getIcao(by, value, options) {
|
|
114
|
+
const res = await this._getJson(`${BASE_PATH}/package/getIcao.cgi`, { [by]: value }, options);
|
|
115
|
+
return getIcaoSchema.parse(res).icao;
|
|
116
|
+
}
|
|
113
117
|
async getPriorityList(options) {
|
|
114
118
|
const res = await this._getJson(`${BASE_PATH}/package/getPriorityList.cgi`, undefined, options);
|
|
115
119
|
return priorityListSchema.parse(res);
|
package/esm/index.js
CHANGED
|
@@ -4,17 +4,23 @@ export * from './internal/utils';
|
|
|
4
4
|
export * from './internal/versionCompare';
|
|
5
5
|
export * from './internal/ProxyClient';
|
|
6
6
|
export * from './types/common';
|
|
7
|
-
export { CamOverlayAPI } from './CamOverlayAPI';
|
|
8
|
-
export * from './types/CamOverlayAPI';
|
|
9
|
-
export { CamScripterAPI } from './CamScripterAPI';
|
|
10
|
-
export * from './types/CamScripterAPI';
|
|
11
7
|
export { CamStreamerAPI } from './CamStreamerAPI';
|
|
12
8
|
export * from './types/CamStreamerAPI';
|
|
9
|
+
export { CamStreamerEvents } from './ws/CamStreamerEvents';
|
|
10
|
+
export * from './types/ws/CamStreamerEvents';
|
|
11
|
+
export { CamOverlayAPI } from './CamOverlayAPI';
|
|
12
|
+
export * from './types/CamOverlayAPI';
|
|
13
|
+
export { CamOverlayEvents } from './ws/CamOverlayEvents';
|
|
14
|
+
export * from './types/ws/CamOverlayEvents';
|
|
13
15
|
export { CamSwitcherAPI } from './CamSwitcherAPI';
|
|
14
16
|
export * from './types/CamSwitcherAPI';
|
|
15
|
-
export { CamSwitcherEvents } from './CamSwitcherEvents';
|
|
16
|
-
export * from './types/CamSwitcherEvents';
|
|
17
|
+
export { CamSwitcherEvents } from './ws/CamSwitcherEvents';
|
|
18
|
+
export * from './types/ws/CamSwitcherEvents';
|
|
17
19
|
export { PlaneTrackerAPI } from './PlaneTrackerAPI';
|
|
18
20
|
export * from './types/PlaneTrackerAPI';
|
|
21
|
+
export { PlaneTrackerEvents } from './ws/PlaneTrackerEvents';
|
|
22
|
+
export * from './types/ws/PlaneTrackerEvents';
|
|
23
|
+
export { CamScripterAPI } from './CamScripterAPI';
|
|
24
|
+
export * from './types/CamScripterAPI';
|
|
19
25
|
export { VapixAPI } from './VapixAPI';
|
|
20
26
|
export * from './types/VapixAPI';
|
package/esm/internal/WsEvents.js
CHANGED
|
@@ -6,7 +6,7 @@ export class WsEvents {
|
|
|
6
6
|
constructor(zodSchema, ws) {
|
|
7
7
|
this.zodSchema = zodSchema;
|
|
8
8
|
this.ws = ws;
|
|
9
|
-
this.ws.
|
|
9
|
+
this.ws.onMessage = (e) => this.onMessage(e);
|
|
10
10
|
}
|
|
11
11
|
get isDestroyed() {
|
|
12
12
|
return this._isDestroyed;
|
|
@@ -34,12 +34,12 @@ export class WsEvents {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
-
onMessage(
|
|
37
|
+
onMessage(incomeData) {
|
|
38
38
|
if (this.isDestroyed) {
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
41
|
try {
|
|
42
|
-
const eventData = JSON.parse(
|
|
42
|
+
const eventData = JSON.parse(incomeData.toString());
|
|
43
43
|
const data = this.zodSchema.parse(eventData);
|
|
44
44
|
if (isInitEvent(data)) {
|
|
45
45
|
this.processMessage(data.data, true);
|
|
@@ -48,7 +48,7 @@ export class WsEvents {
|
|
|
48
48
|
this.processMessage(data, false);
|
|
49
49
|
}
|
|
50
50
|
catch (error) {
|
|
51
|
-
console.error('Error parsing event data:',
|
|
51
|
+
console.error('Error parsing event data:', incomeData.toString(), error);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
processMessage(event, isInit) {
|
|
@@ -58,7 +58,8 @@ export class WsEvents {
|
|
|
58
58
|
}
|
|
59
59
|
destroy() {
|
|
60
60
|
this._isDestroyed = true;
|
|
61
|
-
this.ws.
|
|
61
|
+
this.ws.onMessage = () => { };
|
|
62
|
+
this.ws.onOpen = () => Promise.reject(new Error('Websocket is destroyed'));
|
|
62
63
|
this.ws.destroy();
|
|
63
64
|
this.listeners = {};
|
|
64
65
|
}
|
|
@@ -41,7 +41,7 @@ export class CamOverlayDrawingAPI extends EventEmitter {
|
|
|
41
41
|
this.startMsgsTimeoutCheck();
|
|
42
42
|
}
|
|
43
43
|
disconnect() {
|
|
44
|
-
this.ws.
|
|
44
|
+
this.ws.destroy();
|
|
45
45
|
this.stopMsgsTimeoutCheck();
|
|
46
46
|
}
|
|
47
47
|
isConnected() {
|
|
@@ -98,23 +98,23 @@ export class CamOverlayDrawingAPI extends EventEmitter {
|
|
|
98
98
|
tlsInsecure: this.tlsInsecure,
|
|
99
99
|
};
|
|
100
100
|
this.ws = new WsClient(options);
|
|
101
|
-
this.ws.
|
|
101
|
+
this.ws.onOpen = () => {
|
|
102
102
|
console.log('CamOverlay connection opened');
|
|
103
103
|
this.wsConnected = true;
|
|
104
104
|
this.emit('open');
|
|
105
|
-
}
|
|
106
|
-
this.ws.
|
|
107
|
-
this.ws.
|
|
105
|
+
};
|
|
106
|
+
this.ws.onMessage = (data) => this.incomingWsMessageHandler(data.toString());
|
|
107
|
+
this.ws.onError = (error) => {
|
|
108
108
|
this.reportError(error);
|
|
109
|
-
}
|
|
110
|
-
this.ws.
|
|
109
|
+
};
|
|
110
|
+
this.ws.onClose = () => {
|
|
111
111
|
console.log('CamOverlay connection closed');
|
|
112
112
|
this.wsConnected = false;
|
|
113
113
|
this.reportClose();
|
|
114
|
-
}
|
|
114
|
+
};
|
|
115
115
|
}
|
|
116
116
|
incomingWsMessageHandler(msgData) {
|
|
117
|
-
const dataJSON = JSON.parse(msgData
|
|
117
|
+
const dataJSON = JSON.parse(msgData);
|
|
118
118
|
let errorResponse;
|
|
119
119
|
if ('error' in dataJSON) {
|
|
120
120
|
errorResponse = dataJSON;
|
|
@@ -171,7 +171,7 @@ export class CamOverlayDrawingAPI extends EventEmitter {
|
|
|
171
171
|
headerView.setInt8(0, 1);
|
|
172
172
|
headerView.setInt32(1, jsonBuffer.byteLength);
|
|
173
173
|
const msgBuffer = Buffer.concat([Buffer.from(header), jsonBuffer, data]);
|
|
174
|
-
this.ws.send(msgBuffer);
|
|
174
|
+
this.ws.send(msgBuffer.buffer);
|
|
175
175
|
this.sendMessages[this.callId] = { resolve, reject, sentTimestamp: Date.now() };
|
|
176
176
|
}
|
|
177
177
|
catch (err) {
|
|
@@ -31,7 +31,7 @@ export class CamScripterAPICameraEventsGenerator extends EventEmitter {
|
|
|
31
31
|
this.startMsgsTimeoutCheck();
|
|
32
32
|
}
|
|
33
33
|
disconnect() {
|
|
34
|
-
this.ws.
|
|
34
|
+
this.ws.destroy();
|
|
35
35
|
this.stopMsgsTimeoutCheck();
|
|
36
36
|
}
|
|
37
37
|
declareEvent(eventDeclaration) {
|
|
@@ -67,21 +67,21 @@ export class CamScripterAPICameraEventsGenerator extends EventEmitter {
|
|
|
67
67
|
protocol: 'camera-events',
|
|
68
68
|
};
|
|
69
69
|
this.ws = new WsClient(options);
|
|
70
|
-
this.ws.
|
|
70
|
+
this.ws.onOpen = () => {
|
|
71
71
|
this.wsConnected = true;
|
|
72
72
|
this.emit('open');
|
|
73
|
-
}
|
|
74
|
-
this.ws.
|
|
75
|
-
this.ws.
|
|
73
|
+
};
|
|
74
|
+
this.ws.onMessage = (data) => this.incomingWsMessageHandler(data.toString());
|
|
75
|
+
this.ws.onError = (error) => {
|
|
76
76
|
this.reportErr(error);
|
|
77
|
-
}
|
|
78
|
-
this.ws.
|
|
77
|
+
};
|
|
78
|
+
this.ws.onClose = () => {
|
|
79
79
|
this.wsConnected = false;
|
|
80
80
|
this.reportClose();
|
|
81
|
-
}
|
|
81
|
+
};
|
|
82
82
|
}
|
|
83
83
|
incomingWsMessageHandler(msgData) {
|
|
84
|
-
const dataJSON = JSON.parse(msgData
|
|
84
|
+
const dataJSON = JSON.parse(msgData);
|
|
85
85
|
let errorResponse;
|
|
86
86
|
if ('error' in dataJSON) {
|
|
87
87
|
errorResponse = dataJSON;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Digest } from './Digest';
|
|
2
|
+
import { describe, test, expect } from '@jest/globals';
|
|
3
|
+
describe('Digest', () => {
|
|
4
|
+
describe('getAuthHeader', () => {
|
|
5
|
+
test('Checks, that Digest.getAuthHeader() returns correct value.', () => {
|
|
6
|
+
const testString = 'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"';
|
|
7
|
+
const value = 'Digest username="root",realm="testrealm@host.com",nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093",uri="www.cz",response="63f54af3ce5cf193a7435d5c68625472",qop=auth,nc=00000001,cnonce="162d50aa594e9648"';
|
|
8
|
+
expect(new Digest().getAuthHeader('root', 'pass', 'GET', 'www.cz', testString)).toBe(value);
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
});
|
package/esm/node/VapixEvents.js
CHANGED
|
@@ -23,7 +23,7 @@ export class VapixEvents extends EventEmitter {
|
|
|
23
23
|
this.ws.open();
|
|
24
24
|
}
|
|
25
25
|
disconnect() {
|
|
26
|
-
this.ws.
|
|
26
|
+
this.ws.destroy();
|
|
27
27
|
}
|
|
28
28
|
createWsClient() {
|
|
29
29
|
const options = {
|
|
@@ -36,7 +36,7 @@ export class VapixEvents extends EventEmitter {
|
|
|
36
36
|
address: '/vapix/ws-data-stream?sources=events',
|
|
37
37
|
};
|
|
38
38
|
this.ws = new WsClient(options);
|
|
39
|
-
this.ws.
|
|
39
|
+
this.ws.onOpen = () => {
|
|
40
40
|
const topics = [];
|
|
41
41
|
const eventNames = this.eventNames();
|
|
42
42
|
for (const eventName of eventNames) {
|
|
@@ -55,8 +55,8 @@ export class VapixEvents extends EventEmitter {
|
|
|
55
55
|
},
|
|
56
56
|
};
|
|
57
57
|
this.ws.send(JSON.stringify(topicFilter));
|
|
58
|
-
}
|
|
59
|
-
this.ws.
|
|
58
|
+
};
|
|
59
|
+
this.ws.onMessage = (data) => {
|
|
60
60
|
const dataJSON = JSON.parse(data.toString());
|
|
61
61
|
if (dataJSON.method === 'events:configure') {
|
|
62
62
|
if (dataJSON.error === undefined) {
|
|
@@ -70,13 +70,13 @@ export class VapixEvents extends EventEmitter {
|
|
|
70
70
|
}
|
|
71
71
|
const eventName = dataJSON.params.notification.topic;
|
|
72
72
|
this.emit(eventName, dataJSON);
|
|
73
|
-
}
|
|
74
|
-
this.ws.
|
|
73
|
+
};
|
|
74
|
+
this.ws.onError = (error) => {
|
|
75
75
|
this.emit('error', error);
|
|
76
|
-
}
|
|
77
|
-
this.ws.
|
|
76
|
+
};
|
|
77
|
+
this.ws.onClose = () => {
|
|
78
78
|
this.emit('close');
|
|
79
|
-
}
|
|
79
|
+
};
|
|
80
80
|
}
|
|
81
81
|
isReservedEventName(eventName) {
|
|
82
82
|
return eventName === 'open' || eventName === 'close' || eventName === 'error';
|
package/esm/node/WsClient.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import EventEmitter from 'events';
|
|
2
1
|
import WebSocket from 'ws';
|
|
3
2
|
import { Digest } from './Digest';
|
|
4
|
-
export class WsClient
|
|
3
|
+
export class WsClient {
|
|
5
4
|
user;
|
|
6
5
|
pass;
|
|
7
6
|
address;
|
|
@@ -14,7 +13,6 @@ export class WsClient extends EventEmitter {
|
|
|
14
13
|
ws;
|
|
15
14
|
isClosed = false;
|
|
16
15
|
constructor(options) {
|
|
17
|
-
super();
|
|
18
16
|
const tls = options.tls ?? false;
|
|
19
17
|
const tlsInsecure = options.tlsInsecure ?? false;
|
|
20
18
|
const ip = options.ip ?? '127.0.0.1';
|
|
@@ -46,10 +44,10 @@ export class WsClient extends EventEmitter {
|
|
|
46
44
|
}
|
|
47
45
|
this.ws.binaryType = 'arraybuffer';
|
|
48
46
|
this.isAlive = true;
|
|
49
|
-
this.pingTimer = setInterval(
|
|
47
|
+
this.pingTimer = setInterval(() => {
|
|
50
48
|
if ((this.ws && this.ws.readyState !== WebSocket.OPEN) || this.isAlive === false) {
|
|
51
|
-
this.
|
|
52
|
-
|
|
49
|
+
this.onError(new Error('Connection timeout'));
|
|
50
|
+
this.closeWsConnection();
|
|
53
51
|
}
|
|
54
52
|
else {
|
|
55
53
|
this.isAlive = false;
|
|
@@ -72,23 +70,32 @@ export class WsClient extends EventEmitter {
|
|
|
72
70
|
this.open(res.headers['www-authenticate']);
|
|
73
71
|
}
|
|
74
72
|
else {
|
|
75
|
-
this.
|
|
73
|
+
this.onError(new Error('Status code: ' + res.statusCode));
|
|
76
74
|
this.closeWsConnection();
|
|
77
75
|
}
|
|
78
76
|
});
|
|
79
|
-
this.ws.on('open', () => this.
|
|
80
|
-
this.ws.on('message', (data) =>
|
|
77
|
+
this.ws.on('open', () => this.onOpen());
|
|
78
|
+
this.ws.on('message', (data, isBinary) => {
|
|
79
|
+
const message = isBinary ? data : data.toString();
|
|
80
|
+
this.onMessage(message);
|
|
81
|
+
});
|
|
81
82
|
this.ws.on('error', (error) => {
|
|
82
|
-
this.
|
|
83
|
+
this.onError(error);
|
|
83
84
|
this.closeWsConnection();
|
|
84
85
|
});
|
|
85
86
|
this.ws.on('close', () => this.closeWsConnection());
|
|
86
87
|
}
|
|
87
88
|
catch (error) {
|
|
88
|
-
this.
|
|
89
|
+
this.onError(error instanceof Error ? error : new Error('Unknown error'));
|
|
89
90
|
this.closeWsConnection();
|
|
90
91
|
}
|
|
91
92
|
}
|
|
93
|
+
onMessage = (_) => { };
|
|
94
|
+
onOpen = () => { };
|
|
95
|
+
onClose = () => { };
|
|
96
|
+
onError = (error) => {
|
|
97
|
+
console.error(error);
|
|
98
|
+
};
|
|
92
99
|
send(data) {
|
|
93
100
|
if (this.ws === undefined) {
|
|
94
101
|
throw new Error("This websocket hasn't been opened yet.");
|
|
@@ -97,7 +104,7 @@ export class WsClient extends EventEmitter {
|
|
|
97
104
|
this.ws.send(data);
|
|
98
105
|
}
|
|
99
106
|
}
|
|
100
|
-
|
|
107
|
+
destroy() {
|
|
101
108
|
if (this.isClosed) {
|
|
102
109
|
return;
|
|
103
110
|
}
|
|
@@ -127,7 +134,7 @@ export class WsClient extends EventEmitter {
|
|
|
127
134
|
wsCopy.terminate();
|
|
128
135
|
}
|
|
129
136
|
}, 5000);
|
|
130
|
-
this.
|
|
137
|
+
this.onClose();
|
|
131
138
|
}
|
|
132
139
|
catch (err) {
|
|
133
140
|
console.error(err);
|
|
@@ -24,7 +24,7 @@ export const pipSchema = serviceCommonSchema.extend({
|
|
|
24
24
|
z.literal('overlays=image'),
|
|
25
25
|
z.literal('overlays=application'),
|
|
26
26
|
]),
|
|
27
|
-
rotate: z.union([z.literal(0), z.literal(90), z.literal(180), z.literal(270)]),
|
|
27
|
+
rotate: z.union([z.literal(0), z.literal(90), z.literal(180), z.literal(270)]).default(0),
|
|
28
28
|
dewarping: z.object({
|
|
29
29
|
enabled: z.boolean(),
|
|
30
30
|
rectangle: z.array(z.tuple([z.number(), z.number()])),
|
|
@@ -231,6 +231,9 @@ export const serverSettingsSchema = z.object({
|
|
|
231
231
|
tiltRealKnownPoint: 90,
|
|
232
232
|
}),
|
|
233
233
|
});
|
|
234
|
+
export const getIcaoSchema = z.object({
|
|
235
|
+
icao: z.string(),
|
|
236
|
+
});
|
|
234
237
|
export const trackingModeSchema = z.object({
|
|
235
238
|
mode: z.union([z.literal('MANUAL'), z.literal('AUTOMATIC')]),
|
|
236
239
|
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const coEventsDataSchema = z.discriminatedUnion('type', [
|
|
3
|
+
z.object({ type: z.literal('authorization'), state: z.string() }),
|
|
4
|
+
z.object({
|
|
5
|
+
type: z.literal('ServiceStart'),
|
|
6
|
+
serviceId: z.number(),
|
|
7
|
+
}),
|
|
8
|
+
z.object({
|
|
9
|
+
type: z.literal('ServiceStop'),
|
|
10
|
+
serviceId: z.number(),
|
|
11
|
+
}),
|
|
12
|
+
]);
|
|
13
|
+
export const coEventsSchema = z.discriminatedUnion('type', [
|
|
14
|
+
z.object({ type: z.literal('init'), data: coEventsDataSchema }),
|
|
15
|
+
...coEventsDataSchema.options,
|
|
16
|
+
]);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const csEventsDataSchema = z.discriminatedUnion('type', [
|
|
3
|
+
z.object({ type: z.literal('authorization'), state: z.string() }),
|
|
4
|
+
z.object({
|
|
5
|
+
type: z.literal('StreamState'),
|
|
6
|
+
streamID: z.number(),
|
|
7
|
+
enabled: z.union([z.literal(0), z.literal(1)]),
|
|
8
|
+
active: z.union([z.literal(0), z.literal(1)]),
|
|
9
|
+
automationState: z.union([z.literal(0), z.literal(1)]),
|
|
10
|
+
isStreaming: z.union([z.literal(0), z.literal(1)]),
|
|
11
|
+
}),
|
|
12
|
+
z.object({
|
|
13
|
+
type: z.literal('CS_API_SUCCESS'),
|
|
14
|
+
apiCall: z.string(),
|
|
15
|
+
message: z.string(),
|
|
16
|
+
streamID: z.string(),
|
|
17
|
+
}),
|
|
18
|
+
z.object({
|
|
19
|
+
type: z.literal('CS_API_ERROR'),
|
|
20
|
+
apiCall: z.string(),
|
|
21
|
+
message: z.string(),
|
|
22
|
+
streamID: z.string(),
|
|
23
|
+
code: z.string(),
|
|
24
|
+
}),
|
|
25
|
+
]);
|
|
26
|
+
export const csEventsSchema = z.discriminatedUnion('type', [
|
|
27
|
+
z.object({ type: z.literal('init'), data: csEventsDataSchema }),
|
|
28
|
+
...csEventsDataSchema.options,
|
|
29
|
+
]);
|