camstreamerlib 4.0.16 → 4.0.17-dev-milestone.1

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.
@@ -1,5 +1,5 @@
1
1
  import { IClient, TResponse } from './internal/types';
2
- import { ICAO, TBlackList, TCameraSettings, TExportDataType, TGetIcaoByOption, TImportDataType, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
2
+ import { ICAO, TBlackList, TCameraSettings, TConnection, TExportDataType, TGetIcaoByOption, TImportDataType, TMilestoneCameraOption, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
3
3
  import { THttpRequestOptions } from './types/common';
4
4
  import { BasicAPI } from './internal/BasicAPI';
5
5
  import { TApiUser } from './types/ws/PlaneTrackerEvents';
@@ -107,6 +107,15 @@ export declare class PlaneTrackerAPI<Client extends IClient<TResponse, any>> ext
107
107
  protocol: "https" | "http" | "https_insecure";
108
108
  sourceKey: string;
109
109
  };
110
+ milestone: {
111
+ ip: string;
112
+ enabled: boolean;
113
+ port: number;
114
+ cameraList: string[];
115
+ pass: string;
116
+ user: string;
117
+ protocol: "https" | "http" | "https_insecure";
118
+ };
110
119
  camstreamerIntegration: {
111
120
  adPlacementEnabled: boolean;
112
121
  adMinIntervalSec: number;
@@ -250,5 +259,7 @@ export declare class PlaneTrackerAPI<Client extends IClient<TResponse, any>> ext
250
259
  }>;
251
260
  setZones(zones: TZones, options?: THttpRequestOptions): Promise<void>;
252
261
  goToCoordinates(lat: number, lon: number, alt?: number, options?: THttpRequestOptions): Promise<void>;
262
+ checkMilestoneConnection(params: TConnection, options?: THttpRequestOptions): Promise<boolean>;
263
+ getMilestoneCameraList(params: TConnection, options?: THttpRequestOptions): Promise<TMilestoneCameraOption[]>;
253
264
  downloadReport(options?: THttpRequestOptions): Promise<string>;
254
265
  }
@@ -196,6 +196,19 @@ class PlaneTrackerAPI extends BasicAPI_1.BasicAPI {
196
196
  }
197
197
  }
198
198
  }
199
+ async checkMilestoneConnection(params, options) {
200
+ try {
201
+ await this._postUrlEncoded(`${BASE_PATH}/package/checkMilestoneConnection.cgi`, { ...params }, options);
202
+ return true;
203
+ }
204
+ catch {
205
+ return false;
206
+ }
207
+ }
208
+ async getMilestoneCameraList(params, options) {
209
+ const res = await this._postUrlEncoded(`${BASE_PATH}/package/getMilestoneCameraList.cgi`, { ...params }, options);
210
+ return PlaneTrackerAPI_1.milestoneCameraListSchema.parse(await res.json());
211
+ }
199
212
  downloadReport(options) {
200
213
  return this._getText(`${BASE_PATH}/report.cgi`, undefined, options);
201
214
  }
@@ -0,0 +1,14 @@
1
+ import { MilestoneAgentOptions, TBookmark, TMilestoneCamera } from '../../types/MilestoneAgent';
2
+ export declare class MilestoneAgent {
3
+ private settings;
4
+ private protocol;
5
+ private sender;
6
+ private token?;
7
+ constructor(options?: MilestoneAgentOptions);
8
+ checkConnection(): Promise<void>;
9
+ getAllCameras(): Promise<TMilestoneCamera[]>;
10
+ sendBookmark(cameraId: string, bookmark: TBookmark): Promise<void>;
11
+ private getCamerasPage;
12
+ private getToken;
13
+ private getRequestOptions;
14
+ }
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MilestoneAgent = void 0;
4
+ const errors_1 = require("../../errors/errors");
5
+ const HttpRequestSender_1 = require("../HttpRequestSender");
6
+ const MilestoneAgent_1 = require("../../types/MilestoneAgent");
7
+ const CLIENT_ID = 'GrantValidatorClient';
8
+ const PAGE_SIZE = 100;
9
+ const TOKEN_EXPIRY_MARGIN_SEC = 60;
10
+ class MilestoneAgent {
11
+ settings;
12
+ protocol;
13
+ sender;
14
+ token;
15
+ constructor(options = {}) {
16
+ this.settings = {
17
+ protocol: options.protocol ?? 'https_insecure',
18
+ ip: options.ip ?? '127.0.0.1',
19
+ port: options.port ?? 443,
20
+ user: options.user ?? '',
21
+ pass: options.pass ?? '',
22
+ timeout: options.timeout ?? 10000,
23
+ };
24
+ this.protocol = this.settings.protocol === 'http' ? 'http:' : 'https:';
25
+ const tlsInsecure = this.settings.protocol === 'https_insecure';
26
+ this.sender = new HttpRequestSender_1.HttpRequestSender({ rejectUnaurhorized: !tlsInsecure });
27
+ }
28
+ async checkConnection() {
29
+ await this.getToken(true);
30
+ await this.getCamerasPage(1, 1);
31
+ }
32
+ async getAllCameras() {
33
+ const cameras = [];
34
+ let page = 1;
35
+ for (;;) {
36
+ const pageCameras = await this.getCamerasPage(page, PAGE_SIZE);
37
+ cameras.push(...pageCameras);
38
+ if (pageCameras.length < PAGE_SIZE) {
39
+ break;
40
+ }
41
+ page += 1;
42
+ }
43
+ return cameras;
44
+ }
45
+ async sendBookmark(cameraId, bookmark) {
46
+ const token = await this.getToken();
47
+ const body = JSON.stringify({
48
+ ...bookmark,
49
+ devicePath: { type: 'cameras', id: cameraId },
50
+ });
51
+ const res = await this.sender.sendRequest(this.getRequestOptions('POST', '/api/rest/v1/bookmarks', token, {
52
+ 'Content-Type': 'application/json',
53
+ }), body);
54
+ if (!res.ok) {
55
+ throw new errors_1.ErrorWithResponse(res);
56
+ }
57
+ }
58
+ async getCamerasPage(page, itemsPerPage) {
59
+ const token = await this.getToken();
60
+ const res = await this.sender.sendRequest(this.getRequestOptions('GET', `/api/rest/v1/cameras?page=${page}&itemsPerPage=${itemsPerPage}`, token));
61
+ if (!res.ok) {
62
+ throw new errors_1.ErrorWithResponse(res);
63
+ }
64
+ const responseBody = await res.text();
65
+ const result = await MilestoneAgent_1.camerasResponseSchema.safeParseAsync(JSON.parse(responseBody));
66
+ if (!result.success) {
67
+ throw new Error('Milestone get cameras failed: ' + JSON.stringify(result.error.issues) + '\n' + responseBody);
68
+ }
69
+ return result.data.array;
70
+ }
71
+ async getToken(forceRefresh = false) {
72
+ const nowSec = Date.now() / 1000;
73
+ if (!forceRefresh && this.token !== undefined && this.token.expiresAt > nowSec) {
74
+ return this.token.value;
75
+ }
76
+ const body = new URLSearchParams({
77
+ grant_type: 'password',
78
+ username: this.settings.user,
79
+ password: this.settings.pass,
80
+ client_id: CLIENT_ID,
81
+ }).toString();
82
+ const res = await this.sender.sendRequest({
83
+ method: 'POST',
84
+ protocol: this.protocol,
85
+ host: this.settings.ip,
86
+ port: this.settings.port,
87
+ path: '/idp/connect/token',
88
+ timeout: this.settings.timeout,
89
+ headers: {
90
+ 'Content-Type': 'application/x-www-form-urlencoded',
91
+ 'Accept': 'application/json',
92
+ },
93
+ }, body);
94
+ if (!res.ok) {
95
+ throw new errors_1.ErrorWithResponse(res);
96
+ }
97
+ const responseBody = await res.text();
98
+ const result = await MilestoneAgent_1.tokenResponseSchema.safeParseAsync(JSON.parse(responseBody));
99
+ if (!result.success) {
100
+ throw new Error('Milestone authorization failed: ' + JSON.stringify(result.error.issues) + '\n' + responseBody);
101
+ }
102
+ this.token = {
103
+ value: result.data.access_token,
104
+ expiresAt: nowSec + result.data.expires_in - TOKEN_EXPIRY_MARGIN_SEC,
105
+ };
106
+ return this.token.value;
107
+ }
108
+ getRequestOptions(method, path, token, extraHeaders) {
109
+ return {
110
+ method,
111
+ protocol: this.protocol,
112
+ host: this.settings.ip,
113
+ port: this.settings.port,
114
+ path,
115
+ timeout: this.settings.timeout,
116
+ headers: {
117
+ Authorization: `Bearer ${token}`,
118
+ Accept: 'application/json',
119
+ ...extraHeaders,
120
+ },
121
+ };
122
+ }
123
+ }
124
+ exports.MilestoneAgent = MilestoneAgent;
@@ -6,6 +6,8 @@ export * from './events/AxisCameraStationEvents';
6
6
  export * from './TimeZoneDaemon';
7
7
  export * from './events/GenetecAgent';
8
8
  export * from '../types/GenetecAgent';
9
+ export * from './events/MilestoneAgent';
10
+ export * from '../types/MilestoneAgent';
9
11
  export { ResourceManager } from './CamOverlayPainter/ResourceManager';
10
12
  export { Painter } from './CamOverlayPainter/Painter';
11
13
  export { Frame } from './CamOverlayPainter/Frame';
package/cjs/node/index.js CHANGED
@@ -23,6 +23,8 @@ __exportStar(require("./events/AxisCameraStationEvents"), exports);
23
23
  __exportStar(require("./TimeZoneDaemon"), exports);
24
24
  __exportStar(require("./events/GenetecAgent"), exports);
25
25
  __exportStar(require("../types/GenetecAgent"), exports);
26
+ __exportStar(require("./events/MilestoneAgent"), exports);
27
+ __exportStar(require("../types/MilestoneAgent"), exports);
26
28
  var ResourceManager_1 = require("./CamOverlayPainter/ResourceManager");
27
29
  Object.defineProperty(exports, "ResourceManager", { enumerable: true, get: function () { return ResourceManager_1.ResourceManager; } });
28
30
  var Painter_1 = require("./CamOverlayPainter/Painter");
@@ -0,0 +1,81 @@
1
+ import { z } from 'zod';
2
+ export type MilestoneAgentOptions = {
3
+ protocol?: 'http' | 'https' | 'https_insecure';
4
+ ip?: string;
5
+ port?: number;
6
+ user?: string;
7
+ pass?: string;
8
+ timeout?: number;
9
+ };
10
+ export declare const tokenResponseSchema: z.ZodObject<{
11
+ access_token: z.ZodString;
12
+ expires_in: z.ZodNumber;
13
+ token_type: z.ZodString;
14
+ }, "strip", z.ZodTypeAny, {
15
+ access_token: string;
16
+ expires_in: number;
17
+ token_type: string;
18
+ }, {
19
+ access_token: string;
20
+ expires_in: number;
21
+ token_type: string;
22
+ }>;
23
+ export type TTokenResponse = z.infer<typeof tokenResponseSchema>;
24
+ export declare const milestoneCameraSchema: z.ZodObject<{
25
+ id: z.ZodString;
26
+ name: z.ZodOptional<z.ZodString>;
27
+ displayName: z.ZodOptional<z.ZodString>;
28
+ enabled: z.ZodOptional<z.ZodBoolean>;
29
+ }, "strip", z.ZodTypeAny, {
30
+ id: string;
31
+ name?: string | undefined;
32
+ enabled?: boolean | undefined;
33
+ displayName?: string | undefined;
34
+ }, {
35
+ id: string;
36
+ name?: string | undefined;
37
+ enabled?: boolean | undefined;
38
+ displayName?: string | undefined;
39
+ }>;
40
+ export type TMilestoneCamera = z.infer<typeof milestoneCameraSchema>;
41
+ export declare const camerasResponseSchema: z.ZodObject<{
42
+ array: z.ZodArray<z.ZodObject<{
43
+ id: z.ZodString;
44
+ name: z.ZodOptional<z.ZodString>;
45
+ displayName: z.ZodOptional<z.ZodString>;
46
+ enabled: z.ZodOptional<z.ZodBoolean>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ id: string;
49
+ name?: string | undefined;
50
+ enabled?: boolean | undefined;
51
+ displayName?: string | undefined;
52
+ }, {
53
+ id: string;
54
+ name?: string | undefined;
55
+ enabled?: boolean | undefined;
56
+ displayName?: string | undefined;
57
+ }>, "many">;
58
+ }, "strip", z.ZodTypeAny, {
59
+ array: {
60
+ id: string;
61
+ name?: string | undefined;
62
+ enabled?: boolean | undefined;
63
+ displayName?: string | undefined;
64
+ }[];
65
+ }, {
66
+ array: {
67
+ id: string;
68
+ name?: string | undefined;
69
+ enabled?: boolean | undefined;
70
+ displayName?: string | undefined;
71
+ }[];
72
+ }>;
73
+ export type TCamerasResponse = z.infer<typeof camerasResponseSchema>;
74
+ export type TBookmark = {
75
+ header: string;
76
+ description: string;
77
+ timeBegin: string;
78
+ timeEnd: string;
79
+ timeTriggered: string;
80
+ reference: string;
81
+ };
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.camerasResponseSchema = exports.milestoneCameraSchema = exports.tokenResponseSchema = void 0;
4
+ const zod_1 = require("zod");
5
+ exports.tokenResponseSchema = zod_1.z.object({
6
+ access_token: zod_1.z.string(),
7
+ expires_in: zod_1.z.number(),
8
+ token_type: zod_1.z.string(),
9
+ });
10
+ exports.milestoneCameraSchema = zod_1.z.object({
11
+ id: zod_1.z.string(),
12
+ name: zod_1.z.string().optional(),
13
+ displayName: zod_1.z.string().optional(),
14
+ enabled: zod_1.z.boolean().optional(),
15
+ });
16
+ exports.camerasResponseSchema = zod_1.z.object({
17
+ array: zod_1.z.array(exports.milestoneCameraSchema),
18
+ });
@@ -33,6 +33,21 @@ export declare const connectionSchema: z.ZodObject<{
33
33
  user: string;
34
34
  protocol: "https" | "http" | "https_insecure";
35
35
  }>;
36
+ export type TConnection = z.infer<typeof connectionSchema>;
37
+ export declare const milestoneCameraListSchema: z.ZodArray<z.ZodObject<{
38
+ index: z.ZodNumber;
39
+ value: z.ZodString;
40
+ label: z.ZodString;
41
+ }, "strip", z.ZodTypeAny, {
42
+ value: string;
43
+ label: string;
44
+ index: number;
45
+ }, {
46
+ value: string;
47
+ label: string;
48
+ index: number;
49
+ }>, "many">;
50
+ export type TMilestoneCameraOption = z.infer<typeof milestoneCameraListSchema>[number];
36
51
  export declare const widgetSchema: z.ZodObject<{
37
52
  enabled: z.ZodDefault<z.ZodBoolean>;
38
53
  coord: z.ZodUnion<[z.ZodLiteral<"top_left">, z.ZodLiteral<"top_right">, z.ZodLiteral<"bottom_left">, z.ZodLiteral<"bottom_right">]>;
@@ -358,6 +373,32 @@ export declare const cameraSettingsSchema: z.ZodObject<{
358
373
  protocol: "https" | "http" | "https_insecure";
359
374
  sourceKey: string;
360
375
  }>>;
376
+ milestone: z.ZodDefault<z.ZodObject<{
377
+ protocol: z.ZodUnion<[z.ZodLiteral<"http">, z.ZodLiteral<"https">, z.ZodLiteral<"https_insecure">]>;
378
+ ip: z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>;
379
+ port: z.ZodNumber;
380
+ user: z.ZodString;
381
+ pass: z.ZodString;
382
+ } & {
383
+ enabled: z.ZodBoolean;
384
+ cameraList: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
385
+ }, "strip", z.ZodTypeAny, {
386
+ ip: string;
387
+ enabled: boolean;
388
+ port: number;
389
+ cameraList: string[];
390
+ pass: string;
391
+ user: string;
392
+ protocol: "https" | "http" | "https_insecure";
393
+ }, {
394
+ ip: string;
395
+ enabled: boolean;
396
+ port: number;
397
+ pass: string;
398
+ user: string;
399
+ protocol: "https" | "http" | "https_insecure";
400
+ cameraList?: string[] | undefined;
401
+ }>>;
361
402
  camstreamerIntegration: z.ZodDefault<z.ZodObject<{
362
403
  adPlacementEnabled: z.ZodBoolean;
363
404
  adMinIntervalSec: z.ZodNumber;
@@ -463,6 +504,15 @@ export declare const cameraSettingsSchema: z.ZodObject<{
463
504
  protocol: "https" | "http" | "https_insecure";
464
505
  sourceKey: string;
465
506
  };
507
+ milestone: {
508
+ ip: string;
509
+ enabled: boolean;
510
+ port: number;
511
+ cameraList: string[];
512
+ pass: string;
513
+ user: string;
514
+ protocol: "https" | "http" | "https_insecure";
515
+ };
466
516
  camstreamerIntegration: {
467
517
  adPlacementEnabled: boolean;
468
518
  adMinIntervalSec: number;
@@ -606,6 +656,15 @@ export declare const cameraSettingsSchema: z.ZodObject<{
606
656
  protocol: "https" | "http" | "https_insecure";
607
657
  sourceKey: string;
608
658
  } | undefined;
659
+ milestone?: {
660
+ ip: string;
661
+ enabled: boolean;
662
+ port: number;
663
+ pass: string;
664
+ user: string;
665
+ protocol: "https" | "http" | "https_insecure";
666
+ cameraList?: string[] | undefined;
667
+ } | undefined;
609
668
  camstreamerIntegration?: {
610
669
  adPlacementEnabled: boolean;
611
670
  adMinIntervalSec: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.REMOTE_ID_CATEGORY_IDS = exports.ADSB_CATEGORY_IDS = exports.domainListSchema = exports.domainIdSchema = exports.zonesSchema = exports.mapInfoSchema = exports.mapTypeSchema = exports.priorityListSchema = exports.blackListSchema = exports.whiteListSchema = exports.priorityListEntrySchema = exports.listEntrySchema = exports.listEntryIdTypeSchema = exports.listEntryDomainSchema = exports.flightInfoSchema = exports.trackingModeSchema = exports.getIcaoSchema = exports.serverSettingsSchema = exports.cameraSettingsSchema = exports.widgetSchema = exports.connectionSchema = exports.wsAliasResponseSchema = void 0;
3
+ exports.REMOTE_ID_CATEGORY_IDS = exports.ADSB_CATEGORY_IDS = exports.domainListSchema = exports.domainIdSchema = exports.zonesSchema = exports.mapInfoSchema = exports.mapTypeSchema = exports.priorityListSchema = exports.blackListSchema = exports.whiteListSchema = exports.priorityListEntrySchema = exports.listEntrySchema = exports.listEntryIdTypeSchema = exports.listEntryDomainSchema = exports.flightInfoSchema = exports.trackingModeSchema = exports.getIcaoSchema = exports.serverSettingsSchema = exports.cameraSettingsSchema = exports.widgetSchema = exports.milestoneCameraListSchema = exports.connectionSchema = exports.wsAliasResponseSchema = void 0;
4
4
  const zod_1 = require("zod");
5
5
  exports.wsAliasResponseSchema = zod_1.z.object({
6
6
  alias: zod_1.z.string(),
@@ -14,6 +14,13 @@ exports.connectionSchema = zod_1.z.object({
14
14
  user: zod_1.z.string(),
15
15
  pass: zod_1.z.string(),
16
16
  });
17
+ exports.milestoneCameraListSchema = zod_1.z
18
+ .object({
19
+ index: zod_1.z.number(),
20
+ value: zod_1.z.string(),
21
+ label: zod_1.z.string(),
22
+ })
23
+ .array();
17
24
  exports.widgetSchema = zod_1.z.object({
18
25
  enabled: zod_1.z.boolean().default(true),
19
26
  coord: zod_1.z.union([
@@ -202,6 +209,20 @@ exports.cameraSettingsSchema = zod_1.z.object({
202
209
  pass: '',
203
210
  sourceKey: '',
204
211
  }),
212
+ milestone: exports.connectionSchema
213
+ .extend({
214
+ enabled: zod_1.z.boolean(),
215
+ cameraList: zod_1.z.string().array().default([]),
216
+ })
217
+ .default({
218
+ enabled: false,
219
+ protocol: 'https_insecure',
220
+ ip: '',
221
+ port: 443,
222
+ user: '',
223
+ pass: '',
224
+ cameraList: [],
225
+ }),
205
226
  camstreamerIntegration: zod_1.z
206
227
  .object({
207
228
  adPlacementEnabled: zod_1.z.boolean(),
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { blackListSchema, cameraSettingsSchema, domainListSchema, flightInfoSchema, getIcaoSchema, mapInfoSchema, priorityListSchema, serverSettingsSchema, trackingModeSchema, whiteListSchema, wsAliasResponseSchema, zonesSchema, } from './types/PlaneTrackerAPI';
2
+ import { blackListSchema, cameraSettingsSchema, domainListSchema, flightInfoSchema, getIcaoSchema, mapInfoSchema, milestoneCameraListSchema, priorityListSchema, serverSettingsSchema, trackingModeSchema, whiteListSchema, wsAliasResponseSchema, zonesSchema, } from './types/PlaneTrackerAPI';
3
3
  import { CannotSetCoordsInAutoModeError, ImportSettingsError, InvalidAltitudeError, InvalidLatLngError, ResetCalibrationError, ServerError, BadRequestError, } from './errors/errors';
4
4
  import { BasicAPI } from './internal/BasicAPI';
5
5
  const BASE_PATH = '/local/planetracker';
@@ -193,6 +193,19 @@ export class PlaneTrackerAPI extends BasicAPI {
193
193
  }
194
194
  }
195
195
  }
196
+ async checkMilestoneConnection(params, options) {
197
+ try {
198
+ await this._postUrlEncoded(`${BASE_PATH}/package/checkMilestoneConnection.cgi`, { ...params }, options);
199
+ return true;
200
+ }
201
+ catch {
202
+ return false;
203
+ }
204
+ }
205
+ async getMilestoneCameraList(params, options) {
206
+ const res = await this._postUrlEncoded(`${BASE_PATH}/package/getMilestoneCameraList.cgi`, { ...params }, options);
207
+ return milestoneCameraListSchema.parse(await res.json());
208
+ }
196
209
  downloadReport(options) {
197
210
  return this._getText(`${BASE_PATH}/report.cgi`, undefined, options);
198
211
  }
@@ -0,0 +1,120 @@
1
+ import { ErrorWithResponse } from '../../errors/errors';
2
+ import { HttpRequestSender } from '../HttpRequestSender';
3
+ import { camerasResponseSchema, tokenResponseSchema, } from '../../types/MilestoneAgent';
4
+ const CLIENT_ID = 'GrantValidatorClient';
5
+ const PAGE_SIZE = 100;
6
+ const TOKEN_EXPIRY_MARGIN_SEC = 60;
7
+ export class MilestoneAgent {
8
+ settings;
9
+ protocol;
10
+ sender;
11
+ token;
12
+ constructor(options = {}) {
13
+ this.settings = {
14
+ protocol: options.protocol ?? 'https_insecure',
15
+ ip: options.ip ?? '127.0.0.1',
16
+ port: options.port ?? 443,
17
+ user: options.user ?? '',
18
+ pass: options.pass ?? '',
19
+ timeout: options.timeout ?? 10000,
20
+ };
21
+ this.protocol = this.settings.protocol === 'http' ? 'http:' : 'https:';
22
+ const tlsInsecure = this.settings.protocol === 'https_insecure';
23
+ this.sender = new HttpRequestSender({ rejectUnaurhorized: !tlsInsecure });
24
+ }
25
+ async checkConnection() {
26
+ await this.getToken(true);
27
+ await this.getCamerasPage(1, 1);
28
+ }
29
+ async getAllCameras() {
30
+ const cameras = [];
31
+ let page = 1;
32
+ for (;;) {
33
+ const pageCameras = await this.getCamerasPage(page, PAGE_SIZE);
34
+ cameras.push(...pageCameras);
35
+ if (pageCameras.length < PAGE_SIZE) {
36
+ break;
37
+ }
38
+ page += 1;
39
+ }
40
+ return cameras;
41
+ }
42
+ async sendBookmark(cameraId, bookmark) {
43
+ const token = await this.getToken();
44
+ const body = JSON.stringify({
45
+ ...bookmark,
46
+ devicePath: { type: 'cameras', id: cameraId },
47
+ });
48
+ const res = await this.sender.sendRequest(this.getRequestOptions('POST', '/api/rest/v1/bookmarks', token, {
49
+ 'Content-Type': 'application/json',
50
+ }), body);
51
+ if (!res.ok) {
52
+ throw new ErrorWithResponse(res);
53
+ }
54
+ }
55
+ async getCamerasPage(page, itemsPerPage) {
56
+ const token = await this.getToken();
57
+ const res = await this.sender.sendRequest(this.getRequestOptions('GET', `/api/rest/v1/cameras?page=${page}&itemsPerPage=${itemsPerPage}`, token));
58
+ if (!res.ok) {
59
+ throw new ErrorWithResponse(res);
60
+ }
61
+ const responseBody = await res.text();
62
+ const result = await camerasResponseSchema.safeParseAsync(JSON.parse(responseBody));
63
+ if (!result.success) {
64
+ throw new Error('Milestone get cameras failed: ' + JSON.stringify(result.error.issues) + '\n' + responseBody);
65
+ }
66
+ return result.data.array;
67
+ }
68
+ async getToken(forceRefresh = false) {
69
+ const nowSec = Date.now() / 1000;
70
+ if (!forceRefresh && this.token !== undefined && this.token.expiresAt > nowSec) {
71
+ return this.token.value;
72
+ }
73
+ const body = new URLSearchParams({
74
+ grant_type: 'password',
75
+ username: this.settings.user,
76
+ password: this.settings.pass,
77
+ client_id: CLIENT_ID,
78
+ }).toString();
79
+ const res = await this.sender.sendRequest({
80
+ method: 'POST',
81
+ protocol: this.protocol,
82
+ host: this.settings.ip,
83
+ port: this.settings.port,
84
+ path: '/idp/connect/token',
85
+ timeout: this.settings.timeout,
86
+ headers: {
87
+ 'Content-Type': 'application/x-www-form-urlencoded',
88
+ 'Accept': 'application/json',
89
+ },
90
+ }, body);
91
+ if (!res.ok) {
92
+ throw new ErrorWithResponse(res);
93
+ }
94
+ const responseBody = await res.text();
95
+ const result = await tokenResponseSchema.safeParseAsync(JSON.parse(responseBody));
96
+ if (!result.success) {
97
+ throw new Error('Milestone authorization failed: ' + JSON.stringify(result.error.issues) + '\n' + responseBody);
98
+ }
99
+ this.token = {
100
+ value: result.data.access_token,
101
+ expiresAt: nowSec + result.data.expires_in - TOKEN_EXPIRY_MARGIN_SEC,
102
+ };
103
+ return this.token.value;
104
+ }
105
+ getRequestOptions(method, path, token, extraHeaders) {
106
+ return {
107
+ method,
108
+ protocol: this.protocol,
109
+ host: this.settings.ip,
110
+ port: this.settings.port,
111
+ path,
112
+ timeout: this.settings.timeout,
113
+ headers: {
114
+ Authorization: `Bearer ${token}`,
115
+ Accept: 'application/json',
116
+ ...extraHeaders,
117
+ },
118
+ };
119
+ }
120
+ }
package/esm/node/index.js CHANGED
@@ -6,6 +6,8 @@ export * from './events/AxisCameraStationEvents';
6
6
  export * from './TimeZoneDaemon';
7
7
  export * from './events/GenetecAgent';
8
8
  export * from '../types/GenetecAgent';
9
+ export * from './events/MilestoneAgent';
10
+ export * from '../types/MilestoneAgent';
9
11
  export { ResourceManager } from './CamOverlayPainter/ResourceManager';
10
12
  export { Painter } from './CamOverlayPainter/Painter';
11
13
  export { Frame } from './CamOverlayPainter/Frame';
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ export const tokenResponseSchema = z.object({
3
+ access_token: z.string(),
4
+ expires_in: z.number(),
5
+ token_type: z.string(),
6
+ });
7
+ export const milestoneCameraSchema = z.object({
8
+ id: z.string(),
9
+ name: z.string().optional(),
10
+ displayName: z.string().optional(),
11
+ enabled: z.boolean().optional(),
12
+ });
13
+ export const camerasResponseSchema = z.object({
14
+ array: z.array(milestoneCameraSchema),
15
+ });
@@ -11,6 +11,13 @@ export const connectionSchema = z.object({
11
11
  user: z.string(),
12
12
  pass: z.string(),
13
13
  });
14
+ export const milestoneCameraListSchema = z
15
+ .object({
16
+ index: z.number(),
17
+ value: z.string(),
18
+ label: z.string(),
19
+ })
20
+ .array();
14
21
  export const widgetSchema = z.object({
15
22
  enabled: z.boolean().default(true),
16
23
  coord: z.union([
@@ -199,6 +206,20 @@ export const cameraSettingsSchema = z.object({
199
206
  pass: '',
200
207
  sourceKey: '',
201
208
  }),
209
+ milestone: connectionSchema
210
+ .extend({
211
+ enabled: z.boolean(),
212
+ cameraList: z.string().array().default([]),
213
+ })
214
+ .default({
215
+ enabled: false,
216
+ protocol: 'https_insecure',
217
+ ip: '',
218
+ port: 443,
219
+ user: '',
220
+ pass: '',
221
+ cameraList: [],
222
+ }),
202
223
  camstreamerIntegration: z
203
224
  .object({
204
225
  adPlacementEnabled: z.boolean(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camstreamerlib",
3
- "version": "4.0.16",
3
+ "version": "4.0.17-dev-milestone.1",
4
4
  "description": "Helper library for CamStreamer ACAP applications.",
5
5
  "prettier": "@camstreamer/prettier-config",
6
6
  "engine": {
@@ -1,5 +1,5 @@
1
1
  import { IClient, TResponse } from './internal/types';
2
- import { ICAO, TBlackList, TCameraSettings, TExportDataType, TGetIcaoByOption, TImportDataType, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
2
+ import { ICAO, TBlackList, TCameraSettings, TConnection, TExportDataType, TGetIcaoByOption, TImportDataType, TMilestoneCameraOption, TPriorityList, TTrackingMode, TWhiteList, TZones } from './types/PlaneTrackerAPI';
3
3
  import { THttpRequestOptions } from './types/common';
4
4
  import { BasicAPI } from './internal/BasicAPI';
5
5
  import { TApiUser } from './types/ws/PlaneTrackerEvents';
@@ -107,6 +107,15 @@ export declare class PlaneTrackerAPI<Client extends IClient<TResponse, any>> ext
107
107
  protocol: "https" | "http" | "https_insecure";
108
108
  sourceKey: string;
109
109
  };
110
+ milestone: {
111
+ ip: string;
112
+ enabled: boolean;
113
+ port: number;
114
+ cameraList: string[];
115
+ pass: string;
116
+ user: string;
117
+ protocol: "https" | "http" | "https_insecure";
118
+ };
110
119
  camstreamerIntegration: {
111
120
  adPlacementEnabled: boolean;
112
121
  adMinIntervalSec: number;
@@ -250,5 +259,7 @@ export declare class PlaneTrackerAPI<Client extends IClient<TResponse, any>> ext
250
259
  }>;
251
260
  setZones(zones: TZones, options?: THttpRequestOptions): Promise<void>;
252
261
  goToCoordinates(lat: number, lon: number, alt?: number, options?: THttpRequestOptions): Promise<void>;
262
+ checkMilestoneConnection(params: TConnection, options?: THttpRequestOptions): Promise<boolean>;
263
+ getMilestoneCameraList(params: TConnection, options?: THttpRequestOptions): Promise<TMilestoneCameraOption[]>;
253
264
  downloadReport(options?: THttpRequestOptions): Promise<string>;
254
265
  }
@@ -0,0 +1,14 @@
1
+ import { MilestoneAgentOptions, TBookmark, TMilestoneCamera } from '../../types/MilestoneAgent';
2
+ export declare class MilestoneAgent {
3
+ private settings;
4
+ private protocol;
5
+ private sender;
6
+ private token?;
7
+ constructor(options?: MilestoneAgentOptions);
8
+ checkConnection(): Promise<void>;
9
+ getAllCameras(): Promise<TMilestoneCamera[]>;
10
+ sendBookmark(cameraId: string, bookmark: TBookmark): Promise<void>;
11
+ private getCamerasPage;
12
+ private getToken;
13
+ private getRequestOptions;
14
+ }
@@ -6,6 +6,8 @@ export * from './events/AxisCameraStationEvents';
6
6
  export * from './TimeZoneDaemon';
7
7
  export * from './events/GenetecAgent';
8
8
  export * from '../types/GenetecAgent';
9
+ export * from './events/MilestoneAgent';
10
+ export * from '../types/MilestoneAgent';
9
11
  export { ResourceManager } from './CamOverlayPainter/ResourceManager';
10
12
  export { Painter } from './CamOverlayPainter/Painter';
11
13
  export { Frame } from './CamOverlayPainter/Frame';
@@ -0,0 +1,81 @@
1
+ import { z } from 'zod';
2
+ export type MilestoneAgentOptions = {
3
+ protocol?: 'http' | 'https' | 'https_insecure';
4
+ ip?: string;
5
+ port?: number;
6
+ user?: string;
7
+ pass?: string;
8
+ timeout?: number;
9
+ };
10
+ export declare const tokenResponseSchema: z.ZodObject<{
11
+ access_token: z.ZodString;
12
+ expires_in: z.ZodNumber;
13
+ token_type: z.ZodString;
14
+ }, "strip", z.ZodTypeAny, {
15
+ access_token: string;
16
+ expires_in: number;
17
+ token_type: string;
18
+ }, {
19
+ access_token: string;
20
+ expires_in: number;
21
+ token_type: string;
22
+ }>;
23
+ export type TTokenResponse = z.infer<typeof tokenResponseSchema>;
24
+ export declare const milestoneCameraSchema: z.ZodObject<{
25
+ id: z.ZodString;
26
+ name: z.ZodOptional<z.ZodString>;
27
+ displayName: z.ZodOptional<z.ZodString>;
28
+ enabled: z.ZodOptional<z.ZodBoolean>;
29
+ }, "strip", z.ZodTypeAny, {
30
+ id: string;
31
+ name?: string | undefined;
32
+ enabled?: boolean | undefined;
33
+ displayName?: string | undefined;
34
+ }, {
35
+ id: string;
36
+ name?: string | undefined;
37
+ enabled?: boolean | undefined;
38
+ displayName?: string | undefined;
39
+ }>;
40
+ export type TMilestoneCamera = z.infer<typeof milestoneCameraSchema>;
41
+ export declare const camerasResponseSchema: z.ZodObject<{
42
+ array: z.ZodArray<z.ZodObject<{
43
+ id: z.ZodString;
44
+ name: z.ZodOptional<z.ZodString>;
45
+ displayName: z.ZodOptional<z.ZodString>;
46
+ enabled: z.ZodOptional<z.ZodBoolean>;
47
+ }, "strip", z.ZodTypeAny, {
48
+ id: string;
49
+ name?: string | undefined;
50
+ enabled?: boolean | undefined;
51
+ displayName?: string | undefined;
52
+ }, {
53
+ id: string;
54
+ name?: string | undefined;
55
+ enabled?: boolean | undefined;
56
+ displayName?: string | undefined;
57
+ }>, "many">;
58
+ }, "strip", z.ZodTypeAny, {
59
+ array: {
60
+ id: string;
61
+ name?: string | undefined;
62
+ enabled?: boolean | undefined;
63
+ displayName?: string | undefined;
64
+ }[];
65
+ }, {
66
+ array: {
67
+ id: string;
68
+ name?: string | undefined;
69
+ enabled?: boolean | undefined;
70
+ displayName?: string | undefined;
71
+ }[];
72
+ }>;
73
+ export type TCamerasResponse = z.infer<typeof camerasResponseSchema>;
74
+ export type TBookmark = {
75
+ header: string;
76
+ description: string;
77
+ timeBegin: string;
78
+ timeEnd: string;
79
+ timeTriggered: string;
80
+ reference: string;
81
+ };
@@ -33,6 +33,21 @@ export declare const connectionSchema: z.ZodObject<{
33
33
  user: string;
34
34
  protocol: "https" | "http" | "https_insecure";
35
35
  }>;
36
+ export type TConnection = z.infer<typeof connectionSchema>;
37
+ export declare const milestoneCameraListSchema: z.ZodArray<z.ZodObject<{
38
+ index: z.ZodNumber;
39
+ value: z.ZodString;
40
+ label: z.ZodString;
41
+ }, "strip", z.ZodTypeAny, {
42
+ value: string;
43
+ label: string;
44
+ index: number;
45
+ }, {
46
+ value: string;
47
+ label: string;
48
+ index: number;
49
+ }>, "many">;
50
+ export type TMilestoneCameraOption = z.infer<typeof milestoneCameraListSchema>[number];
36
51
  export declare const widgetSchema: z.ZodObject<{
37
52
  enabled: z.ZodDefault<z.ZodBoolean>;
38
53
  coord: z.ZodUnion<[z.ZodLiteral<"top_left">, z.ZodLiteral<"top_right">, z.ZodLiteral<"bottom_left">, z.ZodLiteral<"bottom_right">]>;
@@ -358,6 +373,32 @@ export declare const cameraSettingsSchema: z.ZodObject<{
358
373
  protocol: "https" | "http" | "https_insecure";
359
374
  sourceKey: string;
360
375
  }>>;
376
+ milestone: z.ZodDefault<z.ZodObject<{
377
+ protocol: z.ZodUnion<[z.ZodLiteral<"http">, z.ZodLiteral<"https">, z.ZodLiteral<"https_insecure">]>;
378
+ ip: z.ZodUnion<[z.ZodString, z.ZodLiteral<"">]>;
379
+ port: z.ZodNumber;
380
+ user: z.ZodString;
381
+ pass: z.ZodString;
382
+ } & {
383
+ enabled: z.ZodBoolean;
384
+ cameraList: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
385
+ }, "strip", z.ZodTypeAny, {
386
+ ip: string;
387
+ enabled: boolean;
388
+ port: number;
389
+ cameraList: string[];
390
+ pass: string;
391
+ user: string;
392
+ protocol: "https" | "http" | "https_insecure";
393
+ }, {
394
+ ip: string;
395
+ enabled: boolean;
396
+ port: number;
397
+ pass: string;
398
+ user: string;
399
+ protocol: "https" | "http" | "https_insecure";
400
+ cameraList?: string[] | undefined;
401
+ }>>;
361
402
  camstreamerIntegration: z.ZodDefault<z.ZodObject<{
362
403
  adPlacementEnabled: z.ZodBoolean;
363
404
  adMinIntervalSec: z.ZodNumber;
@@ -463,6 +504,15 @@ export declare const cameraSettingsSchema: z.ZodObject<{
463
504
  protocol: "https" | "http" | "https_insecure";
464
505
  sourceKey: string;
465
506
  };
507
+ milestone: {
508
+ ip: string;
509
+ enabled: boolean;
510
+ port: number;
511
+ cameraList: string[];
512
+ pass: string;
513
+ user: string;
514
+ protocol: "https" | "http" | "https_insecure";
515
+ };
466
516
  camstreamerIntegration: {
467
517
  adPlacementEnabled: boolean;
468
518
  adMinIntervalSec: number;
@@ -606,6 +656,15 @@ export declare const cameraSettingsSchema: z.ZodObject<{
606
656
  protocol: "https" | "http" | "https_insecure";
607
657
  sourceKey: string;
608
658
  } | undefined;
659
+ milestone?: {
660
+ ip: string;
661
+ enabled: boolean;
662
+ port: number;
663
+ pass: string;
664
+ user: string;
665
+ protocol: "https" | "http" | "https_insecure";
666
+ cameraList?: string[] | undefined;
667
+ } | undefined;
609
668
  camstreamerIntegration?: {
610
669
  adPlacementEnabled: boolean;
611
670
  adMinIntervalSec: number;