UNPKG

node-red-contrib-ewelink-cube

Version:

Node-RED integration with eWeLink Cube

378 lines (374 loc) 13.2 kB
'use strict'; var __importDefault = (this && this.__importDefault) || function (mod) { return mod && mod.__esModule ? mod : { default: mod }; }; Object.defineProperty(exports, '__esModule', { value: true }); const axios_1 = __importDefault(require('axios')); const uuid_1 = require('uuid'); const eventsource_1 = __importDefault(require('eventsource')); const EMethod_1 = __importDefault(require('../ts/enum/EMethod')); const EPath_1 = __importDefault(require('../ts/enum/EPath')); class baseClass { ip = ''; at = ''; debug = false; interval = null; timeout = null; time = new Date().getTime(); event = null; constructor({ ip, at = '', debug = false }) { this.ip = ip; this.at = at; this.debug = debug; } setIp(ip) { this.ip = ip; } getIp() { return this.ip; } setAT(at) { this.at = at; } getAt() { return this.at; } /** * 获取网关访问凭证 */ async getBridgeAT({ timeout = 120000, interval = 2000 }) { return new Promise(async (resolve) => { // start interval // nspanelpro first request maybe get response const resp = await this.getBridgeATHandler(); resp && resolve(resp); this.interval = setInterval(async () => { const resp = await this.getBridgeATHandler(); if (resp) { this.interval && clearInterval(this.interval); this.timeout && clearTimeout(this.timeout); resolve(resp); } }, interval); this.timeout = setTimeout(() => { this.interval && clearInterval(this.interval); this.timeout && clearTimeout(this.timeout); resolve({ error: 1000, msg: 'timeout', data: {} }); }, timeout); }); } async getBridgeATHandler() { const params = { app_name: 'node-red-contrib-ewelink-cube' }; // console.log('----->', new Date().getTime() - this.time); const resp = await this.httpRequest({ path: EPath_1.default.BRIDGE_TOKEN, method: EMethod_1.default.GET, isNeedAT: false, params }); if (resp.error === 0) { this.interval && clearInterval(this.interval); // set at resp.data.token && this.setAT(resp.data.token); return resp; } } /** * 修改网关设置 */ async updateBridgeConfig(volume) { return await this.httpRequest({ path: EPath_1.default.BRIDGE_CONFIG, method: EMethod_1.default.PUT, params: { volume } }); } /** * 获取网关信息 */ async getBridgeInfo() { const resp = await this.httpRequest({ path: EPath_1.default.BRIDGE, method: EMethod_1.default.GET, isNeedAT: false }); // if (resp.error === 0 && resp.data.mac) { // // set mac // store.setMac(resp.data.mac) // } return resp; } /** * 重启网关 */ async rebootBridge() { return await this.httpRequest({ path: EPath_1.default.HARDWARE_REBOOT, method: EMethod_1.default.POST }); } /** * 扬声器控制 */ async controlSpeaker(params) { return await this.httpRequest({ path: EPath_1.default.HARDWARE_SPEAKER, method: EMethod_1.default.POST, params }); } /** * 搜索子设备 */ async discoverySubDevices(params) { return await this.httpRequest({ path: EPath_1.default.DEVICE_DISCOVERY, method: EMethod_1.default.PUT, params, }); } /** * 手动添加子设备 (目前仅支持添加RTSP摄像头和ESP32摄像头) */ async manualAddSubDevice(params) { return await this.httpRequest({ path: EPath_1.default.DEVICE, method: EMethod_1.default.POST, params }); } /** * 获取设备列表 */ async getDeviceList() { return await this.httpRequest({ path: EPath_1.default.DEVICE, method: EMethod_1.default.GET }); } /** * 更新指定设备信息或状态 */ async updateDeviceState(serial_number, updateParams) { return await this.httpRequest({ path: `${EPath_1.default.DEVICE}/${serial_number}`, method: EMethod_1.default.PUT, params: { ...updateParams }, }); } /** * 删除子设备 */ async deleteDevice(serial_number) { return await this.httpRequest({ path: `${EPath_1.default.DEVICE}/${serial_number}`, method: EMethod_1.default.DELETE, }); } /** * 同步新设备列表 */ async syncDevices({ devices, version = '2' }) { if (version !== '2') return { error: 1000, msg: 'version must be 2', data: {} }; const request = { event: { header: { name: 'DiscoveryRequest', message_id: (0, uuid_1.v4)(), version, }, payload: { endpoints: devices, }, }, }; return await this.httpRequest({ path: EPath_1.default.THIRD_PARTY, method: EMethod_1.default.POST, params: request }); } /** * 设备状态更新上报 */ async uploadDeviceState({ serial_number, third_serial_number, params, version = '2' }) { if (version !== '2') return { error: 1000, msg: 'version must be 2', data: {} }; const request = { event: { header: { name: 'DeviceStatesChangeReport', message_id: (0, uuid_1.v4)(), version, }, endpoint: { serial_number, third_serial_number, }, payload: params, }, }; return await this.httpRequest({ path: EPath_1.default.THIRD_PARTY, method: EMethod_1.default.POST, params: request }); } /** * 设备上下线状态上报 */ async updateDeviceOnline({ serial_number, third_serial_number, params, version = '2' }) { if (version !== '2') return { error: 1000, msg: 'version must be 2', data: {} }; const request = { event: { header: { name: 'DeviceOnlineChangeReport', message_id: (0, uuid_1.v4)(), version, }, endpoint: { serial_number, third_serial_number, }, payload: params, }, }; return await this.httpRequest({ path: EPath_1.default.THIRD_PARTY, method: EMethod_1.default.POST, params: request }); } /** * 获取调试日志接口 */ async getDebugLog({ serial_number, ...params }) { return await this.httpRequest({ path: `${EPath_1.default.DEBUG_LOG}/${serial_number}`, method: EMethod_1.default.GET, params }); } /** * 网关静音 */ async muteBridge() { return await this.httpRequest({ method: 'put', path: '/bridge/mute', }); } /** * 取消网关静音 */ async unmuteBridge() { return await this.httpRequest({ method: 'put', path: '/bridge/unmute', }); } /** * 取消网关报警 */ async cancelAlarm() { return await this.httpRequest({ method: 'put', path: '/bridge/cancel_alarm', }); } /** * 获取安防列表 */ async getSecurity() { return await this.httpRequest({ method: 'get', path: '/security', }); } /** * 启用指定安防模式 * @param sid security_id */ async enableSecurityById(sid) { return await this.httpRequest({ method: 'put', path: `/security/${sid}/enable`, }); } /** * 禁用指定安防模式 * @param sid security_id */ async disableSecurityById(sid) { return await this.httpRequest({ method: 'put', path: `/security/${sid}/disable`, }); } /** * 一键布防 */ async enableAllSecurity() { return await this.httpRequest({ method: 'put', path: '/security/enable', }); } /** * 一键撤防 */ async disableAllSecurity() { return await this.httpRequest({ method: 'put', path: '/security/disable', }); } /** * 获取网关信息 */ async getBridgeName() { return await this.httpRequest({ method: 'get', path: '/bridge', }); } async httpRequest(httpConfig) { const { path, method, isNeedAT = true, params = {} } = httpConfig; if (!this.ip) { return { error: 1000, msg: 'ip is needed', data: {} }; } if (!this.at && isNeedAT) { return { error: 1000, msg: 'at is needed', data: {} }; } const url = `http://${this.ip}${EPath_1.default.ROOT}${EPath_1.default.V1}${path}`; const headers = { 'Content-Type': 'application/json', }; if (isNeedAT) { Object.assign(headers, { Authorization: `Bearer ${this.at}`, }); } const config = { url, method, headers, timeout: 5000, }; if (Object.keys(params).length) { if (method === EMethod_1.default.GET || method === EMethod_1.default.DELETE) { config.params = params; } else { config.data = params; } } this.debug && console.log('http request body---->', JSON.stringify(config)); try { const resp = await (0, axios_1.default)(config); this.debug && console.log('http response body---->', JSON.stringify(resp.data)); return resp.data; } catch (error) { return { error: 1000, msg: 'http request catch error', data: error }; } // return { error: 1000, msg: 'http request catch error', data: '' } } /** * 初始化 sse 连接 */ async initSSE() { if (!this.ip) { return { error: 1000, msg: 'ip is needed', data: {} }; } if (!this.at) { return { error: 1000, msg: 'at is needed', data: {} }; } const url = `http://${this.ip}${EPath_1.default.ROOT}${EPath_1.default.SSE}?access_token=${this.at}`; console.log('🚀 ~ file: baseClass.ts:320 ~ baseClass ~ initSSE ~ url -- v2', url); try { this.event = new eventsource_1.default(url); } catch (error) { console.log('🚀 ~ file: baseClass.ts:323 ~ baseClass ~ initSSE ~ error', error); } } mountSseFunc(handler) { if (!this.event) return { error: 1000, msg: 'must be invoke initSSE first', data: {} }; handler.onopen && (this.event.onopen = handler.onopen); handler.onerror && (this.event.onerror = handler.onerror); handler.onAddDevice && this.event.addEventListener('device#v2#addDevice', handler.onAddDevice); handler.onUpdateDeviceState && this.event.addEventListener('device#v2#updateDeviceState', handler.onUpdateDeviceState); handler.onUpdateDeviceInfo && this.event.addEventListener('device#v2#updateDeviceInfo', handler.onUpdateDeviceInfo); handler.onUpdateDeviceOnline && this.event.addEventListener('device#v2#updateDeviceOnline', handler.onUpdateDeviceOnline); handler.onDeleteDevice && this.event.addEventListener('device#v2#deleteDevice', handler.onDeleteDevice); handler.onSecurityChange && this.event.addEventListener('security#v2#updateArmState', handler.onSecurityChange); handler.onAlarmChange && this.event.addEventListener('bridge#v2#updateAlarmState', handler.onAlarmChange); } unmountSseFunc() { this.event?.removeEventListener('device#v2#addDevice', () => {}); this.event?.removeEventListener('device#v2#updateDeviceState', () => {}); this.event?.removeEventListener('device#v2#updateDeviceInfo', () => {}); this.event?.removeEventListener('device#v2#updateDeviceOnline', () => {}); this.event?.removeEventListener('device#v2#deleteDevice', () => {}); this.event?.removeEventListener('security#v2#updateArmState', () => {}); this.event?.removeEventListener('bridge#v2#updateAlarmState', () => {}); this.event?.close(); } } exports.default = baseClass;