node-red-contrib-smartnora
Version:
Google Smart Home integration via Smart Nora https://smart-nora.eu/
89 lines (88 loc) • 4.25 kB
JavaScript
;
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();