UNPKG

node-red-contrib-home-assistant-websocket

Version:
255 lines (254 loc) 14.3 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 _TriggerStateController_instances, _TriggerStateController_comparatorService, _TriggerStateController_state, _TriggerStateController_transformState, _TriggerStateController_getConstraintComparatorResults, _TriggerStateController_getConstraintTargetData, _TriggerStateController_getCustomOutputsComparatorResults, _TriggerStateController_getDefaultMessageOutputs, _TriggerStateController_getOutputMessage; Object.defineProperty(exports, "__esModule", { value: true }); const lodash_1 = require("lodash"); const selectn_1 = __importDefault(require("selectn")); const ExposeAsMixin_1 = __importDefault(require("../../common/controllers/ExposeAsMixin")); const InputOutputController_1 = __importDefault(require("../../common/controllers/InputOutputController")); const ConfigError_1 = __importDefault(require("../../common/errors/ConfigError")); const TransformState_1 = require("../../common/TransformState"); const assert_1 = require("../../helpers/assert"); const mustache_1 = require("../../helpers/mustache"); const utils_1 = require("../../helpers/utils"); const homeAssistant_1 = require("../../homeAssistant"); const const_1 = require("./const"); const ExposeAsController = (0, ExposeAsMixin_1.default)((InputOutputController_1.default)); class TriggerStateController extends ExposeAsController { constructor(props) { super(props); _TriggerStateController_instances.add(this); _TriggerStateController_comparatorService.set(this, void 0); _TriggerStateController_state.set(this, void 0); _TriggerStateController_transformState.set(this, void 0); __classPrivateFieldSet(this, _TriggerStateController_comparatorService, props.comparatorService, "f"); __classPrivateFieldSet(this, _TriggerStateController_state, props.state, "f"); __classPrivateFieldSet(this, _TriggerStateController_transformState, props.transformState, "f"); } get isEnabled() { var _a, _b; if (this.exposeAsConfigNode) { return super.isEnabled; } return (_b = (_a = __classPrivateFieldGet(this, _TriggerStateController_state, "f")) === null || _a === void 0 ? void 0 : _a.isEnabled()) !== null && _b !== void 0 ? _b : true; } onInputEnabled(message) { var _a; const enable = message.payload === const_1.ENABLE; (_a = __classPrivateFieldGet(this, _TriggerStateController_state, "f")) === null || _a === void 0 ? void 0 : _a.setEnabled(enable); this.enableExposeAs(enable); return true; } onInputTesting(message) { const { entity_id: entityId, new_state: newState, old_state: oldState, } = message.payload; if (entityId && newState && oldState) { const evt = { event_type: homeAssistant_1.HaEvent.StateChanged, entity_id: entityId, event: message.payload, }; this.onEntityStateChanged(evt); } return true; } async onEntityStateChanged(evt) { if (this.isEnabled === false || !this.homeAssistant.isHomeAssistantRunning) { return; } const eventMessage = (0, lodash_1.cloneDeep)(evt); if (!eventMessage.event.new_state) { return; } // Check if the entity_id is in the list of entities to watch 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)(eventMessage.entity_id, id, type)); }); // If the entity_id is not in the list of entities to watch, return if (!valid) { return; } // Convert and save original state if needed if (eventMessage.event.old_state && this.node.config.stateType !== TransformState_1.TransformType.String) { eventMessage.event.old_state.original_state = eventMessage.event .old_state.state; eventMessage.event.old_state.state = __classPrivateFieldGet(this, _TriggerStateController_transformState, "f").transform(this.node.config.stateType, eventMessage.event.old_state.state); } if (eventMessage.event.new_state && this.node.config.stateType !== TransformState_1.TransformType.String) { eventMessage.event.new_state.original_state = eventMessage.event .new_state.state; eventMessage.event.new_state.state = __classPrivateFieldGet(this, _TriggerStateController_transformState, "f").transform(this.node.config.stateType, eventMessage.event.new_state.state); } if (eventMessage.event.new_state) { eventMessage.event.new_state.timeSinceChangedMs = Date.now() - new Date(eventMessage.event.new_state.last_changed).getTime(); } const constraintComparatorResults = await __classPrivateFieldGet(this, _TriggerStateController_instances, "m", _TriggerStateController_getConstraintComparatorResults).call(this, this.node.config.constraints, eventMessage); let outputs = __classPrivateFieldGet(this, _TriggerStateController_instances, "m", _TriggerStateController_getDefaultMessageOutputs).call(this, constraintComparatorResults, eventMessage); const stateString = eventMessage.event.new_state.state.toString(); // If a constraint comparator failed we're done, also if no custom outputs to look at if (constraintComparatorResults.failed.length || !this.node.config.customOutputs.length) { if (constraintComparatorResults.failed.length) { this.status.setFailed(stateString); } else { this.status.setSuccess(stateString); } this.debugToClient(`done processing sending messages:`); this.debugToClient(outputs); this.node.send(outputs); return; } const customOutputsComparatorResults = await __classPrivateFieldGet(this, _TriggerStateController_instances, "m", _TriggerStateController_getCustomOutputsComparatorResults).call(this, this.node.config.customOutputs, eventMessage); const customOutputMessages = customOutputsComparatorResults.map((r) => r.message); outputs = outputs.concat(customOutputMessages); this.debugToClient(`done processing sending messages: ${outputs}`); this.status.setSuccess(stateString); this.node.send(outputs); } } _TriggerStateController_comparatorService = new WeakMap(), _TriggerStateController_state = new WeakMap(), _TriggerStateController_transformState = new WeakMap(), _TriggerStateController_instances = new WeakSet(), _TriggerStateController_getConstraintComparatorResults = async function _TriggerStateController_getConstraintComparatorResults(constraints, eventMessage) { const comparatorResults = []; // Check constraints for (const constraint of constraints) { const { comparatorType, comparatorValue, comparatorValueDatatype, propertyValue, } = constraint; const constraintTarget = __classPrivateFieldGet(this, _TriggerStateController_instances, "m", _TriggerStateController_getConstraintTargetData).call(this, constraint, eventMessage.event); const actualValue = (0, selectn_1.default)(constraint.propertyValue, constraintTarget.state); const comparatorResult = await __classPrivateFieldGet(this, _TriggerStateController_comparatorService, "f").getComparatorResult(comparatorType, comparatorValue, actualValue, comparatorValueDatatype, { entity: eventMessage.event.new_state, prevEntity: eventMessage.event.old_state, }); if (comparatorResult === false) { this.debugToClient(`constraint comparator: failed entity "${constraintTarget.entityId}" property "${propertyValue}" with value ${actualValue} failed "${comparatorType}" check against (${comparatorValueDatatype}) ${comparatorValue}`); } comparatorResults.push({ constraint, constraintTarget, actualValue, comparatorResult, }); } const failedComparators = comparatorResults.filter((res) => !res.comparatorResult); return { all: comparatorResults, failed: failedComparators, }; }, _TriggerStateController_getConstraintTargetData = function _TriggerStateController_getConstraintTargetData(constraint, triggerEvent) { const isTargetThisEntity = constraint.targetType === const_1.TargetType.ThisEntity; const entityId = isTargetThisEntity ? triggerEvent.entity_id : constraint.targetValue; const entity = isTargetThisEntity ? triggerEvent : this.homeAssistant.websocket.getState(entityId); if (entity === null) { throw new ConfigError_1.default([ 'trigger-state.error.entity_id_not_found', { entity_id: entityId }, ]); } const targetData = { entityId, state: entity, }; if (!isTargetThisEntity && constraint.propertyType === const_1.PropertyType.CurrentState) { targetData.state = { entity_id: entityId, old_state: null, new_state: this.homeAssistant.websocket.getState(entityId), }; } return targetData; }, _TriggerStateController_getCustomOutputsComparatorResults = async function _TriggerStateController_getCustomOutputsComparatorResults(outputs, eventMessage) { return outputs.reduce(async (acc, output) => { const result = { output, comparatorMatched: true, actualValue: null, message: null, }; if (output.comparatorPropertyType !== const_1.ComparatorPropertyType.Always) { result.actualValue = (0, selectn_1.default)(output.comparatorPropertyValue, eventMessage.event); result.comparatorMatched = await __classPrivateFieldGet(this, _TriggerStateController_comparatorService, "f").getComparatorResult(output.comparatorType, output.comparatorValue, result.actualValue, output.comparatorValueDataType, { entity: eventMessage.event.new_state, prevEntity: eventMessage.event.old_state, }); } result.message = await __classPrivateFieldGet(this, _TriggerStateController_instances, "m", _TriggerStateController_getOutputMessage).call(this, result, eventMessage); return [...(await acc), result]; }, Promise.resolve([])); }, _TriggerStateController_getDefaultMessageOutputs = function _TriggerStateController_getDefaultMessageOutputs(comparatorResults, eventMessage) { var _a; const { entity_id: entityId, event } = eventMessage; const msg = { topic: entityId, payload: (_a = event.new_state) === null || _a === void 0 ? void 0 : _a.state, data: eventMessage, }; let outputs; if (comparatorResults.failed.length) { this.debugToClient('constraint comparator: one or more comparators failed to match constraints, message will send on the failed output'); msg.failedComparators = comparatorResults.failed; outputs = [null, msg]; } else { outputs = [msg, null]; } return outputs; }, _TriggerStateController_getOutputMessage = async function _TriggerStateController_getOutputMessage({ output, comparatorMatched, actualValue, }, eventMessage) { var _a; // If comparator did not match if (!comparatorMatched) { this.debugToClient(`output comparator failed: property "${output.comparatorPropertyValue}" with value ${actualValue} failed "${output.comparatorType}" check against (${output.comparatorValueDataType}) ${output.comparatorValue}`); return null; } let message = { topic: eventMessage.entity_id, payload: (_a = eventMessage.event.new_state) === null || _a === void 0 ? void 0 : _a.state, data: eventMessage, }; if (output.messageType === const_1.MessageType.Custom || output.messageType === const_1.MessageType.Payload) { let payload = output.messageValue; // Render Template Variables if ((0, utils_1.containsMustache)(output.messageValue)) { payload = (0, mustache_1.renderTemplate)(output.messageValue, eventMessage.event, this.node.context(), this.homeAssistant.websocket.getStates()); } payload = await this.typedInputService.getValue(payload, output.messageValueType, { eventData: eventMessage, }); if (output.messageType === const_1.MessageType.Custom) { if (!(0, assert_1.isRecord)(payload)) { throw new ConfigError_1.default('trigger-state.error.custom_output_message_needs_to_be_object'); } message = payload; } else { message = { payload, }; } } return message; }; exports.default = TriggerStateController;