UNPKG

node-red-contrib-home-assistant-websocket

Version:
201 lines (200 loc) 12.8 kB
"use strict"; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _WaitUntil_instances, _WaitUntil_active, _WaitUntil_comparatorService, _WaitUntil_clientEvents, _WaitUntil_homeAssistant, _WaitUntil_jsonataService, _WaitUntil_savedConfig, _WaitUntil_savedMessage, _WaitUntil_timeoutId, _WaitUntil_hasDeprecatedWarned, _WaitUntil_onEntityChange, _WaitUntil_onResetInput, _WaitUntil_isSingleEntitySelected; Object.defineProperty(exports, "__esModule", { value: true }); const joi_1 = __importDefault(require("joi")); const lodash_1 = require("lodash"); const selectn_1 = __importDefault(require("selectn")); const const_1 = require("../../common/const"); const InputOutputController_1 = __importDefault(require("../../common/controllers/InputOutputController")); const InputError_1 = __importDefault(require("../../common/errors/InputError")); const inputErrorHandler_1 = require("../../common/errors/inputErrorHandler"); const InputService_1 = require("../../common/services/InputService"); const const_2 = require("../../const"); const globals_1 = require("../../globals"); const mustache_1 = require("../../helpers/mustache"); const utils_1 = require("../../helpers/utils"); const resetSchema = joi_1.default.object({ reset: joi_1.default.any().required(), }).unknown(true); class WaitUntil extends InputOutputController_1.default { constructor(params) { super(params); _WaitUntil_instances.add(this); _WaitUntil_active.set(this, false); _WaitUntil_comparatorService.set(this, void 0); _WaitUntil_clientEvents.set(this, void 0); _WaitUntil_homeAssistant.set(this, void 0); _WaitUntil_jsonataService.set(this, void 0); _WaitUntil_savedConfig.set(this, void 0); _WaitUntil_savedMessage.set(this, void 0); _WaitUntil_timeoutId.set(this, void 0); _WaitUntil_hasDeprecatedWarned.set(this, false); __classPrivateFieldSet(this, _WaitUntil_comparatorService, params.comparatorService, "f"); __classPrivateFieldSet(this, _WaitUntil_clientEvents, params.clientEvents, "f"); __classPrivateFieldSet(this, _WaitUntil_homeAssistant, params.homeAssistant, "f"); __classPrivateFieldSet(this, _WaitUntil_jsonataService, params.jsonataService, "f"); this.addOptionalInput('reset', resetSchema, __classPrivateFieldGet(this, _WaitUntil_instances, "m", _WaitUntil_onResetInput).bind(this)); } async onInput({ message, parsedMessage, send, done, }) { clearTimeout(__classPrivateFieldGet(this, _WaitUntil_timeoutId, "f")); const config = { entities: parsedMessage.entities.value, property: parsedMessage.property.value, comparator: parsedMessage.comparator.value, value: parsedMessage.value.value, valueType: parsedMessage.valueType.value, timeout: parsedMessage.timeout.value, timeoutUnits: parsedMessage.timeoutUnits.value, checkCurrentState: parsedMessage.checkCurrentState.value, send, done, }; // TODO: remove in v1.0 if (parsedMessage.entityId.source === InputService_1.DataSource.Message) { if (!__classPrivateFieldGet(this, _WaitUntil_hasDeprecatedWarned, "f")) { __classPrivateFieldSet(this, _WaitUntil_hasDeprecatedWarned, true, "f"); this.node.warn(globals_1.RED._('ha-wait-until.error.entity_id_deprecated')); } } if (parsedMessage.entities.source === InputService_1.DataSource.Config) { // Render mustache templates in the entity id field when it's from the config config.entities[const_1.IdSelectorType.Entity] = parsedMessage.entities.value[const_1.IdSelectorType.Entity].map((e) => (0, mustache_1.renderTemplate)(e, message, this.node.context(), __classPrivateFieldGet(this, _WaitUntil_homeAssistant, "f").websocket.getStates())); } // If the timeout field is jsonata type evaluate the expression and // it to timeout let timeout = Number(config.timeout); if (parsedMessage.timeout.source === InputService_1.DataSource.Config && this.node.config.timeoutType === const_2.TypedInputTypes.JSONata) { timeout = await __classPrivateFieldGet(this, _WaitUntil_jsonataService, "f").evaluate(parsedMessage.timeout.value, { message, }); config.timeout = timeout.toString(); } // Validate if timeout is a number >= 0 if (isNaN(timeout) || timeout < 0) { throw new InputError_1.default(['ha-wait-until.error.invalid_timeout', { timeout }], 'homassistant.error.error'); } __classPrivateFieldGet(this, _WaitUntil_clientEvents, "f").removeListeners(); if (parsedMessage.entities.value[const_1.IdSelectorType.Substring].length === 0 && parsedMessage.entities.value[const_1.IdSelectorType.Regex].length === 0) { for (const entity of parsedMessage.entities.value[const_1.IdSelectorType.Entity]) { const eventTopic = `ha_events:state_changed:${entity === null || entity === void 0 ? void 0 : entity.trim()}`; __classPrivateFieldGet(this, _WaitUntil_clientEvents, "f").addListener(eventTopic, __classPrivateFieldGet(this, _WaitUntil_instances, "m", _WaitUntil_onEntityChange).bind(this)); } } else { __classPrivateFieldGet(this, _WaitUntil_clientEvents, "f").addListener('ha_events:state_changed', __classPrivateFieldGet(this, _WaitUntil_instances, "m", _WaitUntil_onEntityChange).bind(this)); } __classPrivateFieldSet(this, _WaitUntil_savedMessage, message, "f"); __classPrivateFieldSet(this, _WaitUntil_active, true, "f"); let statusText = 'ha-wait-until.status.waiting'; if (timeout > 0) { statusText = (0, utils_1.getWaitStatusText)(timeout, config.timeoutUnits); timeout = (0, utils_1.getTimeInMilliseconds)(timeout, config.timeoutUnits); __classPrivateFieldSet(this, _WaitUntil_timeoutId, (0, inputErrorHandler_1.setTimeoutWithErrorHandling)(async () => { let state; if (__classPrivateFieldGet(this, _WaitUntil_instances, "m", _WaitUntil_isSingleEntitySelected).call(this)) { state = __classPrivateFieldGet(this, _WaitUntil_homeAssistant, "f").websocket.getState(config.entities[const_1.IdSelectorType.Entity][0]); if (state) { state.timeSinceChangedMs = Date.now() - new Date(state.last_changed).getTime(); } } await this.setCustomOutputs(this.node.config.outputProperties, message, { entity: state, config: this.node.config, }); __classPrivateFieldSet(this, _WaitUntil_active, false, "f"); this.status.setFailed('ha-wait-until.status.timed_out'); send([null, message]); done(); }, timeout, { done, status: this.status }), "f"); } this.status.setText(statusText); __classPrivateFieldSet(this, _WaitUntil_savedConfig, config, "f"); // Only check current state when filter type is exact if (config.checkCurrentState === true && __classPrivateFieldGet(this, _WaitUntil_instances, "m", _WaitUntil_isSingleEntitySelected).call(this)) { const entityId = config.entities[const_1.IdSelectorType.Entity][0]; const currentState = __classPrivateFieldGet(this, _WaitUntil_homeAssistant, "f").websocket.getState(entityId); if (!currentState) { throw new InputError_1.default(['ha-wait-until.error.entity_not_found', { entityId }], 'ha-wait-until.error.not_found'); } await __classPrivateFieldGet(this, _WaitUntil_instances, "m", _WaitUntil_onEntityChange).call(this, { event: { entity_id: entityId, new_state: currentState, }, }); } } onClose(removed, done) { __classPrivateFieldGet(this, _WaitUntil_clientEvents, "f").removeListeners(); clearTimeout(__classPrivateFieldGet(this, _WaitUntil_timeoutId, "f")); done === null || done === void 0 ? void 0 : done(); } } _WaitUntil_active = new WeakMap(), _WaitUntil_comparatorService = new WeakMap(), _WaitUntil_clientEvents = new WeakMap(), _WaitUntil_homeAssistant = new WeakMap(), _WaitUntil_jsonataService = new WeakMap(), _WaitUntil_savedConfig = new WeakMap(), _WaitUntil_savedMessage = new WeakMap(), _WaitUntil_timeoutId = new WeakMap(), _WaitUntil_hasDeprecatedWarned = new WeakMap(), _WaitUntil_instances = new WeakSet(), _WaitUntil_onEntityChange = async function _WaitUntil_onEntityChange(evt) { var _a; const { event } = (0, lodash_1.cloneDeep)(evt); if (!__classPrivateFieldGet(this, _WaitUntil_savedConfig, "f") || !__classPrivateFieldGet(this, _WaitUntil_active, "f") || !__classPrivateFieldGet(this, _WaitUntil_homeAssistant, "f").isConnected) { return; } // Check if the event should be included const valid = Object.entries(__classPrivateFieldGet(this, _WaitUntil_savedConfig, "f").entities).some(([type, ids]) => { return ids === null || ids === void 0 ? void 0 : ids.some((id) => (0, utils_1.shouldIncludeEvent)(event.entity_id, id, type)); }); if (!valid) { return; } const result = await __classPrivateFieldGet(this, _WaitUntil_comparatorService, "f").getComparatorResult(__classPrivateFieldGet(this, _WaitUntil_savedConfig, "f").comparator, __classPrivateFieldGet(this, _WaitUntil_savedConfig, "f").value, (0, selectn_1.default)(__classPrivateFieldGet(this, _WaitUntil_savedConfig, "f").property, event.new_state), __classPrivateFieldGet(this, _WaitUntil_savedConfig, "f").valueType, { message: __classPrivateFieldGet(this, _WaitUntil_savedMessage, "f"), entity: event.new_state, }); if (!result) { return; } const { send, done } = __classPrivateFieldGet(this, _WaitUntil_savedConfig, "f"); clearTimeout(__classPrivateFieldGet(this, _WaitUntil_timeoutId, "f")); __classPrivateFieldSet(this, _WaitUntil_active, false, "f"); this.status.setSuccess('ha-wait-until.status.true'); if (event.new_state) { event.new_state.timeSinceChangedMs = Date.now() - new Date(event.new_state.last_changed).getTime(); } await this.setCustomOutputs(this.node.config.outputProperties, (_a = __classPrivateFieldGet(this, _WaitUntil_savedMessage, "f")) !== null && _a !== void 0 ? _a : {}, { entity: event.new_state, config: this.node.config, }); send([__classPrivateFieldGet(this, _WaitUntil_savedMessage, "f"), null]); done(); }, _WaitUntil_onResetInput = function _WaitUntil_onResetInput() { clearTimeout(__classPrivateFieldGet(this, _WaitUntil_timeoutId, "f")); __classPrivateFieldSet(this, _WaitUntil_active, false, "f"); this.status.setText('reset'); return true; }, _WaitUntil_isSingleEntitySelected = function _WaitUntil_isSingleEntitySelected() { return (this.node.config.entities[const_1.IdSelectorType.Entity].length === 1 && this.node.config.entities[const_1.IdSelectorType.Substring].length === 0 && this.node.config.entities[const_1.IdSelectorType.Regex].length === 0); }; exports.default = WaitUntil;