UNPKG

node-red-contrib-smartnora

Version:

Google Smart Home integration via Smart Nora https://smart-nora.eu/

89 lines (88 loc) 4.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AsyncCommandsRegistry = void 0; const nora_firebase_common_1 = require("@andrei-tatar/nora-firebase-common"); const database_1 = require("firebase/database"); const rxjs_1 = require("rxjs"); const safe_update_1 = require("./safe-update"); class AsyncCommandsRegistry { static handle({ id, response: rsp, warn }) { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.trace(`[async-cmd] got response for ${id}`); const handler = this.handlers.get(id); if (!handler) { warn('No handled registered for command'); return; } const response = {}; if ('errorCode' in rsp && typeof rsp.errorCode === 'string') { if (!(0, nora_firebase_common_1.isErrorCode)(rsp.errorCode)) { warn(`Invalid error code: ${rsp.errorCode}`); return; } response.errorCode = rsp.errorCode; } else if ('result' in rsp && typeof rsp.result === 'object') { if ((0, nora_firebase_common_1.isCameraResult)(rsp.result)) { response.result = rsp.result; } } else if ('state' in rsp && typeof rsp.state === 'object') { const safeUpdate = {}; (0, safe_update_1.getSafeUpdate)({ update: rsp.state, currentState: handler.device.state, safeUpdateObject: safeUpdate, path: 'msg.payload.state.', isValid: () => (0, nora_firebase_common_1.validate)(handler.device.traits, 'state-update', safeUpdate).valid, warn: prop => warn(`Ignoring prop ${prop}`), }); response.state = safeUpdate; } if (Object.keys(response).length === 0) { response.timestamp = new Date().getTime(); } handler.observer.next(response); } static withLogger(logger) { var _a; (_a = this.logger) !== null && _a !== void 0 ? _a : (this.logger = logger); return this; } static getLocalResponse(id, device) { return new rxjs_1.Observable(observer => { this.handlers.set(id, { observer, device }); return () => this.handlers.delete(id); }).pipe((0, rxjs_1.first)(), (0, rxjs_1.timeout)(nora_firebase_common_1.ASYNC_CMD_TIMEOUT_MILLISECONDS), (0, rxjs_1.catchError)(_ => (0, rxjs_1.of)({ errorCode: nora_firebase_common_1.ASYNC_CMD_TIMEOUT_ERRORCODE, }))); } static getCloudAsyncCommandHandler(device) { const asyncCommands = (0, database_1.child)(device.noraSpecific, 'commands'); const asyncResponses = (0, database_1.child)(device.noraSpecific, 'responses'); return new rxjs_1.Observable(observer => (0, database_1.onChildAdded)(asyncCommands, d => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.trace(`[async-cmd] async command received ${d.key}`); if (d.key) { observer.next({ id: d.key, command: d.val(), }); } })).pipe((0, rxjs_1.mergeMap)(cmd => { const handler = new rxjs_1.Subject(); const writeResponse$ = handler.pipe((0, rxjs_1.first)(), (0, rxjs_1.switchMap)(response => (0, database_1.set)((0, database_1.child)(asyncResponses, cmd.id), response)), (0, rxjs_1.timeout)(1000), (0, rxjs_1.catchError)(_ => { var _a; (_a = this.logger) === null || _a === void 0 ? void 0 : _a.warn('[async-cmd] timeout waiting for response'); return rxjs_1.EMPTY; }), (0, rxjs_1.ignoreElements)()); const registerHandler$ = new rxjs_1.Observable(_ => { this.handlers.set(cmd.id, { observer: handler, device: device.device }); return () => this.handlers.delete(cmd.id); }); return (0, rxjs_1.merge)((0, rxjs_1.race)(writeResponse$, registerHandler$), (0, rxjs_1.of)(cmd)); })); } } exports.AsyncCommandsRegistry = AsyncCommandsRegistry; AsyncCommandsRegistry.handlers = new Map();