camstreamerlib
Version:
Helper library for CamStreamer ACAP applications.
120 lines (119 loc) • 4.64 kB
JavaScript
import { z } from 'zod';
import { responseStringify, pad } from '../internal/utils';
const ACTION = 'AddCameraBookmark';
const GET_CAMERAS_URL = 'report/EntityConfiguration?q=EntityTypes@Camera';
const GET_CAMERAS_DETAILS_URL = '/entity?q=';
const cameraGuidsResponseSchema = z.object({
Rsp: z.object({
Status: z.string(),
Result: z.array(z.object({ Guid: z.string() })),
}),
});
const connectionResponseSchema = z.object({
Rsp: z.object({
Status: z.string(),
}),
});
export const cameraDetailSchema = z.object({
Guid: z.string().optional(),
Name: z.string().optional(),
EntityType: z.string().optional(),
});
export const cameraDetailsResponseSchema = z.object({
Rsp: z.object({
Status: z.string(),
Result: z.union([z.array(cameraDetailSchema), cameraDetailSchema]),
}),
});
export class GenetecAgent {
settings;
baseUrl;
credentials;
constructor(options = {}) {
this.settings = {
protocol: options.protocol ?? 'http',
ip: options.ip ?? '127.0.0.1',
port: options.port ?? 80,
base_uri: options.base_uri ?? 'WebSdk',
user: options.user ?? 'root',
pass: options.pass ?? '',
app_id: options.app_id ?? '',
};
this.baseUrl = `${this.settings.protocol}://${this.settings.ip}:${this.settings.port}/${this.settings.base_uri}`;
this.credentials = btoa(`${this.settings.user};${this.settings.app_id}:${this.settings.pass}`);
}
async checkConnection() {
const requestOptions = this.getRequestOptions('GET');
const res = await fetch(`${this.baseUrl}/`, requestOptions);
if (!res.ok) {
throw new Error(await responseStringify(res));
}
return connectionResponseSchema.parse(await res.json());
}
async getAllCameraGuids() {
const requestOptions = this.getRequestOptions('GET');
const res = await fetch(`${this.baseUrl}/${GET_CAMERAS_URL}`, requestOptions);
if (!res.ok) {
throw new Error(await responseStringify(res));
}
return cameraGuidsResponseSchema.parse(await res.json());
}
async getCameraDetails(guids, parameters) {
const params = parameters.join(',');
let camerasGuids = [];
const requestOptions = this.getRequestOptions('GET');
const allCameras = [];
const chunkSize = 10;
while (guids.length > 0) {
const chunk = guids.slice(0, chunkSize);
guids.splice(0, chunkSize);
camerasGuids = chunk.map((item) => item.Guid);
const camerasDetailsUrl = [];
for (const guid of camerasGuids) {
camerasDetailsUrl.push(`entity=${guid},${params}`);
}
const res = await fetch(`${this.baseUrl}/${GET_CAMERAS_DETAILS_URL}${camerasDetailsUrl.join(',')}`, requestOptions);
if (!res.ok) {
throw new Error(await responseStringify(res));
}
const data = cameraDetailsResponseSchema.parse(await res.json());
const resultArray = Array.isArray(data.Rsp.Result) ? data.Rsp.Result : [data.Rsp.Result];
allCameras.push(...resultArray);
}
return allCameras;
}
async sendBookmark(guids, bookmarkText) {
const cameraEntitiesUrl = [];
const timeStamp = this.getTimeStamp();
const requestOptions = this.getRequestOptions('POST');
for (const guid of guids) {
cameraEntitiesUrl.push(`${ACTION}(${guid},${timeStamp},${bookmarkText})`);
}
const res = await fetch(`${this.baseUrl}/action?q=${cameraEntitiesUrl.join(',')}`, requestOptions);
if (!res.ok) {
throw new Error(await responseStringify(res));
}
return res;
}
getRequestOptions(method) {
return {
method,
headers: new Headers({
Authorization: `Basic ${this.credentials}`,
Accept: 'text/json',
}),
redirect: 'follow',
};
}
getTimeStamp() {
const date = new Date();
const year = date.getUTCFullYear();
const month = pad(date.getUTCMonth() + 1, 2);
const day = pad(date.getUTCDate(), 2);
const hours = pad(date.getUTCHours(), 2);
const minutes = pad(date.getUTCMinutes(), 2);
const seconds = pad(date.getUTCSeconds(), 2);
const miliSeconds = pad(date.getUTCMilliseconds(), 2);
return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}.${miliSeconds}Z`;
}
}