UNPKG

node-red-contrib-home-assistant-websocket

Version:
187 lines (186 loc) 10.5 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 _EventsStateController_instances, _EventsStateController_comparatorService, _EventsStateController_topics, _EventsStateController_transformState, _EventsStateController_getTimerValue, _EventsStateController_isEventValid; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = require("lodash"); const ExposeAsMixin_1 = __importDefault(require("../../common/controllers/ExposeAsMixin")); const OutputController_1 = __importDefault(require("../../common/controllers/OutputController")); const ConfigError_1 = __importDefault(require("../../common/errors/ConfigError")); const TransformState_1 = require("../../common/TransformState"); const utils_1 = require("../../helpers/utils"); var State; (function (State) { State["Unknown"] = "unknown"; State["Unavailable"] = "unavailable"; })(State || (State = {})); const ExposeAsController = (0, ExposeAsMixin_1.default)((OutputController_1.default)); class EventsStateController extends ExposeAsController { constructor(props) { super(props); _EventsStateController_instances.add(this); _EventsStateController_comparatorService.set(this, void 0); _EventsStateController_topics.set(this, {}); _EventsStateController_transformState.set(this, void 0); __classPrivateFieldSet(this, _EventsStateController_comparatorService, props.comparatorService, "f"); __classPrivateFieldSet(this, _EventsStateController_transformState, props.transformState, "f"); } async onHaEventsStateChanged(evt, runAll = false) { if (this.isEnabled === false || !this.homeAssistant.isHomeAssistantRunning || !__classPrivateFieldGet(this, _EventsStateController_instances, "m", _EventsStateController_isEventValid).call(this, evt)) { return; } const config = this.node.config; const eventMessage = (0, lodash_1.cloneDeep)(evt); const entityId = eventMessage.entity_id; const oldEntity = eventMessage.event.old_state; const newEntity = eventMessage.event.new_state; // Convert and save original state if needed if (oldEntity && this.node.config.stateType !== TransformState_1.TransformType.String) { oldEntity.original_state = oldEntity.state; oldEntity.state = __classPrivateFieldGet(this, _EventsStateController_transformState, "f").transform(this.node.config.stateType, oldEntity.state); } if (newEntity && this.node.config.stateType !== TransformState_1.TransformType.String) { newEntity.original_state = newEntity.state; newEntity.state = __classPrivateFieldGet(this, _EventsStateController_transformState, "f").transform(this.node.config.stateType, newEntity.state); } const oldState = oldEntity ? oldEntity.state : undefined; const newState = newEntity ? newEntity.state : undefined; // Output only on state change if (runAll === false && config.outputOnlyOnStateChange === true && oldState === newState) { return; } // Get if state condition const isIfState = await __classPrivateFieldGet(this, _EventsStateController_comparatorService, "f").getComparatorResult(config.ifStateOperator, config.ifState, newState, config.ifStateType, { entity: newEntity !== null && newEntity !== void 0 ? newEntity : undefined, prevEntity: oldEntity !== null && oldEntity !== void 0 ? oldEntity : undefined, }); // Track multiple entity ids __classPrivateFieldGet(this, _EventsStateController_topics, "f")[entityId] = __classPrivateFieldGet(this, _EventsStateController_topics, "f")[entityId] || { active: false }; const timer = await __classPrivateFieldGet(this, _EventsStateController_instances, "m", _EventsStateController_getTimerValue).call(this); const validTimer = timer > 0; if (validTimer) { if ( // If the ifState is not used and prev and current state are the same return because timer should already be running oldState === newState || // Don't run timers for on connection updates runAll || // Timer already active and ifState is still true turn don't update (config.ifState && isIfState && __classPrivateFieldGet(this, _EventsStateController_topics, "f")[entityId].active)) { return; } if (config.ifState && !isIfState) { __classPrivateFieldGet(this, _EventsStateController_topics, "f")[entityId].active = false; } } if (!validTimer || (config.ifState && !isIfState)) { await this.output(eventMessage, isIfState); return; } const statusText = (0, utils_1.getWaitStatusText)(timer, this.node.config.forUnits); const timeout = (0, utils_1.getTimeInMilliseconds)(timer, this.node.config.forUnits); this.status.setText(statusText); clearTimeout(__classPrivateFieldGet(this, _EventsStateController_topics, "f")[entityId].timeoutId); __classPrivateFieldGet(this, _EventsStateController_topics, "f")[entityId] = { active: true, timeoutId: setTimeout(this.output.bind(this, eventMessage, isIfState), timeout), }; } async output(eventMessage, condition) { var _a, _b; const config = this.node.config; const message = {}; await this.setCustomOutputs(config.outputProperties, message, { config, entity: eventMessage.event.new_state, entityState: (_a = eventMessage.event.new_state) === null || _a === void 0 ? void 0 : _a.state, eventData: eventMessage.event, prevEntity: eventMessage.event.old_state, triggerId: eventMessage.entity_id, }); if (eventMessage.event.new_state) { eventMessage.event.new_state.timeSinceChangedMs = Date.now() - new Date(eventMessage.event.new_state.last_changed).getTime(); } const statusMessage = `${(_b = eventMessage.event.new_state) === null || _b === void 0 ? void 0 : _b.state}`; clearTimeout(__classPrivateFieldGet(this, _EventsStateController_topics, "f")[eventMessage.entity_id].timeoutId); if (config.ifState && !condition) { this.status.setFailed(statusMessage); this.node.send([null, message]); return; } this.status.setSuccess(statusMessage); this.node.send([message, null]); } onDeploy() { const entities = this.homeAssistant.websocket.getStates(); this.onStatesLoaded(entities); } onStatesLoaded(entities) { if (!this.isEnabled) return; for (const entityId in entities) { const eventMessage = { event_type: 'state_changed', entity_id: entityId, event: { entity_id: entityId, old_state: entities[entityId], new_state: entities[entityId], }, }; this.onHaEventsStateChanged(eventMessage, true); } } } _EventsStateController_comparatorService = new WeakMap(), _EventsStateController_topics = new WeakMap(), _EventsStateController_transformState = new WeakMap(), _EventsStateController_instances = new WeakSet(), _EventsStateController_getTimerValue = async function _EventsStateController_getTimerValue() { if (this.node.config.for === '') return 0; const timer = await this.typedInputService.getValue(this.node.config.for, this.node.config.forType); if (isNaN(timer) || timer < 0) { throw new ConfigError_1.default([ 'server-state-changed.error.invalid_for', { for: timer, type: this.node.config.forType }, ]); } return Number(timer); }, _EventsStateController_isEventValid = function _EventsStateController_isEventValid(evt) { var _a, _b, _c, _d; const oldState = (_b = (_a = evt.event) === null || _a === void 0 ? void 0 : _a.old_state) === null || _b === void 0 ? void 0 : _b.state; const newState = (_d = (_c = evt.event) === null || _c === void 0 ? void 0 : _c.new_state) === null || _d === void 0 ? void 0 : _d.state; const valid = Object.entries(this.node.config.entities).some(([type, ids]) => { return ids === null || ids === void 0 ? void 0 : ids.some((id) => (0, utils_1.shouldIncludeEvent)(evt.entity_id, id, type)); }); if (!valid) { return false; } if ((this.node.config.ignorePrevStateNull && !evt.event.old_state) || (this.node.config.ignorePrevStateUnknown && oldState === State.Unknown) || (this.node.config.ignorePrevStateUnavailable && oldState === State.Unavailable) || (this.node.config.ignoreCurrentStateUnknown && newState === State.Unknown) || (this.node.config.ignoreCurrentStateUnavailable && newState === State.Unavailable)) { return false; } return true; }; exports.default = EventsStateController;