UNPKG

security-camera-sdk

Version:

Universal SDK for interfacing with various security camera vendors including Hikvision, Dahua, Uniview and others

465 lines (405 loc) 13.6 kB
/** * 海康威视 OpenAPI 常用接口封装 * 基于海康威视 Artemis 开放平台 */ const { ParameterError } = require("../../utils/errors/cameraErrors"); const { Logger } = require("../../utils/logger"); /** * API接口常量 */ const API_PATHS = { // OAuth相关 OAUTH_TOKEN: "/artemis/api/v1/oauth/token", // 资源管理 CAMERAS: "/artemis/api/resource/v1/cameras", CAMERA_STATUS: '/artemis/api/nms/v1/online/camera/get', CAMERA_PREVIEW_URLS: "/artemis/api/video/v1/cameras/previewURLs", REGIONS: "/artemis/api/resource/v1/regions", ORGANIZATIONS: "/artemis/api/resource/v1/org/orgList", // 事件管理 EVENTS: "/artemis/api/event/v1/events", EVENTS_SUBSCRIPTION: "/artemis/api/event/v1/eventSubscriptionByEventTypes", // 设备管理 DEVICES: "/artemis/api/resource/v1/devices", DEVICE_V2: "/artemis/api/resource/v2/encodeDevice/search", DEVICE_STATUS: "/artemis/api/nms/v1/online/encode_device/get", DEVICE_INFO: '/artemis/api/resource/v1/resource/indexCodes/search', // 人员管理 PERSONS: "/artemis/api/resource/v1/person", FACE_PICTURES: "/artemis/api/resource/v1/face/picture", // 车辆管理 VEHICLES: "/artemis/api/resource/v1/vehicle", VEHICLE_PICTURES: "/artemis/api/resource/v1/vehicle/picture", // 门禁管理 ACCESS_CONTROL_POINTS: "/artemis/api/acs/v1/accessControlPoint", CARD_READERS: "/artemis/api/acs/v1/cardReader", DOORS: "/artemis/api/acs/v1/door", // 报警管理 ALARM_INPUTS: "/artemis/api/resource/v1/alarmInputs", ALARM_OUTPUTS: "/artemis/api/resource/v1/alarmOutputs", }; /** * API方法封装类 */ class HikvisionAPI { constructor(client) { this.client = client; } // =================== OAuth相关 =================== /** * 获取OAuth Token * @returns {Promise<Object>} Token信息 */ async getOAuthToken() { const response = await this.client.post(API_PATHS.OAUTH_TOKEN); return response.data; } // =================== 摄像头管理 =================== /** * 获取摄像头列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @param {string} options.cameraName 摄像头名称(模糊查询) * @param {string} options.regionIndexCode 区域编码 * @returns {Promise<Object>} 摄像头列表 */ async getCameras(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.CAMERAS, params); return response.data; } /** * 获取摄像头预览地址 * @param {Object} options 选项 * @param {string} options.cameraIndexCode 摄像头编码 * @param {number} options.streamType 码流类型:0-主码流,1-子码流,2-第三码流 * @param {string} options.protocol 协议类型:rtsp,rtmp,hls等 * @param {number} options.transmode 传输模式:0-UDP,1-TCP * @returns {Promise<Object>} 预览地址信息 */ async getCameraPreviewUrl(options) { if (!options.cameraIndexCode) { throw new ParameterError( "摄像头编码不能为空", "cameraIndexCode", options.cameraIndexCode ); } const params = { cameraIndexCode: options.cameraIndexCode, streamType: options.streamType || 0, protocol: options.protocol || "rtsp", transmode: options.transmode || 0, }; const response = await this.client.post(API_PATHS.CAMERA_PREVIEW_URLS, params); return response.data; } /** * 获取摄像头在线状态 * @param {Object} options 查询选项 * @param {Array} options.indexCodes 设备编码列表 * @returns {Promise<Object>} 设备状态列表 */ async getCameraStatus(options) { if (!options.indexCodes || !Array.isArray(options.indexCodes)) { throw new ParameterError( "设备编码列表不能为空", "indexCodes", options.indexCodes ); } const response = await this.client.post(API_PATHS.CAMERA_STATUS, options); return response.data; } // =================== 区域管理 =================== /** * 获取区域列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @param {string} options.treeCode 树节点编码 * @returns {Promise<Object>} 区域列表 */ async getRegions(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, treeCode: options.treeCode || "0", ...options, }; const response = await this.client.post(API_PATHS.REGIONS, params); return response.data; } // =================== 组织管理 =================== /** * 获取组织列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 组织列表 */ async getOrganizations(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.ORGANIZATIONS, params); return response.data; } // =================== 事件管理 =================== /** * 获取事件列表 * @param {Object} options 查询选项 * @param {string} options.startTime 开始时间(ISO格式) * @param {string} options.endTime 结束时间(ISO格式) * @param {Array} options.eventTypes 事件类型列表 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 事件列表 */ async getEvents(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.EVENTS, params); return response.data; } /** * 订阅事件 * @param {Object} options 订阅选项 * @param {Array} options.eventTypes 事件类型列表 * @param {string} options.eventDest 事件推送地址 * @returns {Promise<Object>} 订阅结果 */ async subscribeEvents(options) { if (!options.eventTypes || !Array.isArray(options.eventTypes)) { throw new ParameterError( "事件类型列表不能为空", "eventTypes", options.eventTypes ); } const response = await this.client.post( API_PATHS.EVENTS_SUBSCRIPTION, options ); return response.data; } // =================== 设备管理 =================== /** * 获取设备列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 设备列表 */ async getDevices(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.DEVICES, params); return response.data; } /** * 获取设备列表v2 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 设备列表 */ async getDeviceV2(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.DEVICE_V2, params); return response.data; } /** * 获取设备在线状态 * @param {Object} options 查询选项 * @param {Array} options.indexCodes 设备编码列表(getCameras方法中返回值encodeDevIndexCode的值) * @returns {Promise<Object>} 设备状态列表 */ async getDeviceStatus(options) { if (!options.indexCodes || !Array.isArray(options.indexCodes)) { throw new ParameterError( "设备编码列表不能为空", "indexCodes", options.indexCodes ); } const response = await this.client.post(API_PATHS.DEVICE_STATUS, options); return response.data; } /** * 获取设备在线状态 * @param {Object} options 查询选项 * @param {Array} options.indexCodes 设备编码列表 * @returns {Promise<Object>} 设备状态列表 */ async getDeviceInfo(options) { if (!options.resourceType || !Array.isArray(options.resourceIndexCodes)) { throw new ParameterError( "设备类型或设备编码列表[数组]不能为空", "options", options); } const response = await this.client.post(API_PATHS.DEVICE_INFO, options); return response.data; } // =================== 人员管理 =================== /** * 获取人员列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 人员列表 */ async getPersons(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.PERSONS, params); return response.data; } /** * 添加人员 * @param {Object} personData 人员数据 * @param {string} personData.personName 人员姓名 * @param {string} personData.orgIndexCode 组织编码 * @returns {Promise<Object>} 添加结果 */ async addPerson(personData) { if (!personData.personName) { throw new ParameterError( "人员姓名不能为空", "personName", personData.personName ); } const response = await this.client.post(API_PATHS.PERSONS, personData); return response.data; } // =================== 车辆管理 =================== /** * 获取车辆列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 车辆列表 */ async getVehicles(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.VEHICLES, params); return response.data; } // =================== 门禁管理 =================== /** * 获取门禁点列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 门禁点列表 */ async getAccessControlPoints(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post( API_PATHS.ACCESS_CONTROL_POINTS, params ); return response.data; } /** * 获取读卡器列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 读卡器列表 */ async getCardReaders(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.CARD_READERS, params); return response.data; } /** * 获取门列表 * @param {Object} options 查询选项 * @param {number} options.pageNo 页码,默认1 * @param {number} options.pageSize 每页大小,默认1000 * @returns {Promise<Object>} 门列表 */ async getDoors(options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(API_PATHS.DOORS, params); return response.data; } // =================== 通用方法 =================== /** * 通用分页查询方法 * @param {string} apiPath API路径 * @param {Object} options 查询选项 * @returns {Promise<Object>} 查询结果 */ async paginatedQuery(apiPath, options = {}) { const params = { pageNo: options.pageNo || 1, pageSize: options.pageSize || 1000, ...options, }; const response = await this.client.post(apiPath, params); return response.data; } /** * 批量处理数据 * @param {Function} apiMethod API方法 * @param {Array} dataList 数据列表 * @param {number} batchSize 批次大小 * @returns {Promise<Array>} 处理结果列表 */ async batchProcess(apiMethod, dataList, batchSize = 10) { const results = []; for (let i = 0; i < dataList.length; i += batchSize) { const batch = dataList.slice(i, i + batchSize); const batchPromises = batch.map((data) => apiMethod.call(this, data)); try { const batchResults = await Promise.all(batchPromises); results.push(...batchResults); } catch (error) { throw new Error( `批量处理失败,批次: ${Math.floor(i / batchSize) + 1}, 错误: ${error.message }` ); } } return results; } } module.exports = { HikvisionAPI, API_PATHS };