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.
Files changed (70) hide show
  1. package/README.md +123 -30
  2. package/cjs/CamSwitcherAPI.js +1 -1
  3. package/cjs/PlaneTrackerAPI.js +4 -0
  4. package/cjs/index.js +18 -9
  5. package/cjs/internal/WsEvents.js +6 -5
  6. package/cjs/node/CamOverlayDrawingAPI.js +10 -10
  7. package/cjs/node/CamScripterAPICameraEventsGenerator.js +9 -9
  8. package/cjs/node/Digest.test.js +13 -0
  9. package/cjs/node/VapixEvents.js +9 -9
  10. package/cjs/node/WsClient.js +20 -13
  11. package/cjs/types/CamOverlayAPI/pipSchema.js +1 -1
  12. package/cjs/types/PlaneTrackerAPI.js +4 -1
  13. package/cjs/types/ws/CamOverlayEvents.js +19 -0
  14. package/cjs/types/ws/CamStreamerEvents.js +32 -0
  15. package/cjs/types/ws/PlaneTrackerEvents.js +77 -0
  16. package/cjs/web/DefaultClient.js +6 -2
  17. package/cjs/web/WsClient.js +13 -15
  18. package/cjs/ws/CamOverlayEvents.js +24 -0
  19. package/cjs/ws/CamStreamerEvents.js +24 -0
  20. package/cjs/ws/CamSwitcherEvents.js +24 -0
  21. package/cjs/ws/PlaneTrackerEvents.js +22 -0
  22. package/esm/CamSwitcherAPI.js +1 -1
  23. package/esm/PlaneTrackerAPI.js +5 -1
  24. package/esm/index.js +12 -6
  25. package/esm/internal/WsEvents.js +6 -5
  26. package/esm/node/CamOverlayDrawingAPI.js +10 -10
  27. package/esm/node/CamScripterAPICameraEventsGenerator.js +9 -9
  28. package/esm/node/Digest.test.js +11 -0
  29. package/esm/node/VapixEvents.js +9 -9
  30. package/esm/node/WsClient.js +20 -13
  31. package/esm/types/CamOverlayAPI/pipSchema.js +1 -1
  32. package/esm/types/PlaneTrackerAPI.js +3 -0
  33. package/esm/types/ws/CamOverlayEvents.js +16 -0
  34. package/esm/types/ws/CamStreamerEvents.js +29 -0
  35. package/esm/types/ws/PlaneTrackerEvents.js +74 -0
  36. package/esm/web/DefaultClient.js +6 -2
  37. package/esm/web/WsClient.js +13 -15
  38. package/esm/ws/CamOverlayEvents.js +20 -0
  39. package/esm/ws/CamStreamerEvents.js +20 -0
  40. package/esm/ws/CamSwitcherEvents.js +20 -0
  41. package/esm/ws/PlaneTrackerEvents.js +18 -0
  42. package/package.json +1 -1
  43. package/types/CamSwitcherAPI.d.ts +1 -1
  44. package/types/PlaneTrackerAPI.d.ts +2 -1
  45. package/types/index.d.ts +12 -6
  46. package/types/internal/WsEvents.d.ts +3 -5
  47. package/types/internal/types.d.ts +7 -6
  48. package/types/node/CamScripterAPICameraEventsGenerator.d.ts +2 -2
  49. package/types/node/Digest.test.d.ts +1 -0
  50. package/types/node/VapixEvents.d.ts +2 -2
  51. package/types/node/WsClient.d.ts +9 -19
  52. package/types/types/CamOverlayAPI/CamOverlayAPI.d.ts +5 -5
  53. package/types/types/CamOverlayAPI/pipSchema.d.ts +2 -2
  54. package/types/types/CamOverlayDrawingAPI.d.ts +2 -2
  55. package/types/types/PlaneTrackerAPI.d.ts +8 -0
  56. package/types/types/ws/CamOverlayEvents.d.ts +88 -0
  57. package/types/types/ws/CamStreamerEvents.d.ts +249 -0
  58. package/types/types/ws/PlaneTrackerEvents.d.ts +947 -0
  59. package/types/web/DefaultClient.d.ts +2 -0
  60. package/types/web/WsClient.d.ts +9 -5
  61. package/types/ws/CamOverlayEvents.d.ts +8 -0
  62. package/types/ws/CamStreamerEvents.d.ts +8 -0
  63. package/types/ws/CamSwitcherEvents.d.ts +8 -0
  64. package/types/ws/PlaneTrackerEvents.d.ts +9 -0
  65. package/cjs/CamSwitcherEvents.js +0 -11
  66. package/esm/CamSwitcherEvents.js +0 -7
  67. package/types/CamSwitcherEvents.d.ts +0 -8
  68. /package/cjs/types/{CamSwitcherEvents.js → ws/CamSwitcherEvents.js} +0 -0
  69. /package/esm/types/{CamSwitcherEvents.js → ws/CamSwitcherEvents.js} +0 -0
  70. /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
+ ]);
@@ -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(url, options, timeout) {
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(url, { ...options, signal: controller.signal });
27
+ return await fetch(`${this.domain}${path}`, { ...options, signal: controller.signal });
24
28
  }
25
29
  finally {
26
30
  if (timeoutId) {
@@ -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, getAuthToken) {
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.onopen = async () => {
22
- try {
23
- const token = await this.getAuthToken();
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
- onmessage = (_) => { };
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;
@@ -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 = (id, storage) => `${BASE_PATH}/clip_preview.cgi?clip_name=${id}&storage=${storage}`;
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
  }
@@ -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';
@@ -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.onmessage = (e) => this.onMessage(e);
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(evt) {
37
+ onMessage(incomeData) {
38
38
  if (this.isDestroyed) {
39
39
  return;
40
40
  }
41
41
  try {
42
- const eventData = JSON.parse(evt.data);
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:', evt.data, error);
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.onmessage = () => { };
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.close();
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.on('open', () => {
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.on('message', (msgData) => this.incomingWsMessageHandler(msgData));
107
- this.ws.on('error', (error) => {
105
+ };
106
+ this.ws.onMessage = (data) => this.incomingWsMessageHandler(data.toString());
107
+ this.ws.onError = (error) => {
108
108
  this.reportError(error);
109
- });
110
- this.ws.on('close', () => {
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.toString());
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.close();
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.on('open', () => {
70
+ this.ws.onOpen = () => {
71
71
  this.wsConnected = true;
72
72
  this.emit('open');
73
- });
74
- this.ws.on('message', (msgData) => this.incomingWsMessageHandler(msgData));
75
- this.ws.on('error', (error) => {
73
+ };
74
+ this.ws.onMessage = (data) => this.incomingWsMessageHandler(data.toString());
75
+ this.ws.onError = (error) => {
76
76
  this.reportErr(error);
77
- });
78
- this.ws.on('close', () => {
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.toString());
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
+ });
@@ -23,7 +23,7 @@ export class VapixEvents extends EventEmitter {
23
23
  this.ws.open();
24
24
  }
25
25
  disconnect() {
26
- this.ws.close();
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.on('open', () => {
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.on('message', (data) => {
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.on('error', (error) => {
73
+ };
74
+ this.ws.onError = (error) => {
75
75
  this.emit('error', error);
76
- });
77
- this.ws.on('close', () => {
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';
@@ -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 extends EventEmitter {
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(async () => {
47
+ this.pingTimer = setInterval(() => {
50
48
  if ((this.ws && this.ws.readyState !== WebSocket.OPEN) || this.isAlive === false) {
51
- this.emit('error', new Error('Connection timeout'));
52
- await this.closeWsConnection();
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.emit('error', new Error('Status code: ' + res.statusCode));
73
+ this.onError(new Error('Status code: ' + res.statusCode));
76
74
  this.closeWsConnection();
77
75
  }
78
76
  });
79
- this.ws.on('open', () => this.emit('open'));
80
- this.ws.on('message', (data) => this.emit('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.emit('error', error);
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.emit('error', error instanceof Error ? error : new Error('Unknown error'));
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
- close() {
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.emit('close');
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
+ ]);