node-red-contrib-home-assistant-websocket
Version:
Node-RED integration with Home Assistant through websocket and REST API
244 lines (243 loc) • 14.7 kB
JavaScript
"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 _GetEntitiesController_instances, _GetEntitiesController_comparatorService, _GetEntitiesController_homeAssistant, _GetEntitiesController_currentDevice, _GetEntitiesController_currentArea, _GetEntitiesController_currentFloor, _GetEntitiesController_getEntities, _GetEntitiesController_checkConditions, _GetEntitiesController_checkLabelCondition, _GetEntitiesController_getPropertyValue, _GetEntitiesController_getDevice, _GetEntitiesController_getArea, _GetEntitiesController_getFloor, _GetEntitiesController_resetCurrent;
Object.defineProperty(exports, "__esModule", { value: true });
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 SendSplitMixin_1 = __importDefault(require("../../common/controllers/SendSplitMixin"));
const const_2 = require("../../const");
const const_3 = require("./const");
const helpers_1 = require("./helpers");
const operators_1 = require("./operators");
const SendSplitController = (0, SendSplitMixin_1.default)((InputOutputController_1.default));
class GetEntitiesController extends SendSplitController {
constructor(params) {
super(params);
_GetEntitiesController_instances.add(this);
_GetEntitiesController_comparatorService.set(this, void 0);
_GetEntitiesController_homeAssistant.set(this, void 0);
// Store the current device and area to avoid multiple lookups
_GetEntitiesController_currentDevice.set(this, void 0);
_GetEntitiesController_currentArea.set(this, void 0);
_GetEntitiesController_currentFloor.set(this, void 0);
__classPrivateFieldSet(this, _GetEntitiesController_comparatorService, params.comparatorService, "f");
__classPrivateFieldSet(this, _GetEntitiesController_homeAssistant, params.homeAssistant, "f");
}
async onInput({ message, parsedMessage, send, done, }) {
let noPayload = false;
const entities = await __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getEntities).call(this, parsedMessage.rules.value, message);
let statusText = [
'ha-get-entities.status.number_of_results',
{ count: entities.length },
];
let payload = [];
switch (parsedMessage.outputType.value) {
case const_3.OutputType.Count:
payload = entities.length;
break;
case const_3.OutputType.Split:
if (entities.length === 0) {
noPayload = true;
break;
}
this.status.setSuccess(statusText);
this.sendSplit(message, entities, send);
done();
return;
case const_3.OutputType.Random: {
if (entities.length === 0) {
noPayload = true;
break;
}
const maxReturned = Number(parsedMessage.outputResultsCount.value) || 1;
const max = entities.length <= maxReturned
? entities.length
: maxReturned;
const shuffledEntities = (0, lodash_1.shuffle)(entities);
payload = shuffledEntities.slice(0, max);
if (maxReturned === 1) {
payload = payload[0];
statusText = [
'ha-get-entities.status.number_of_random_resuls',
{ count: 1 },
];
}
else {
statusText = [
'ha-get-entities.status.number_of_random_resuls',
{ count: Array.isArray(payload) ? payload.length : 0 },
];
}
break;
}
case const_3.OutputType.Array:
default:
if (entities.length === 0 &&
!parsedMessage.outputEmptyResults.value) {
noPayload = true;
}
payload = entities;
break;
}
if (noPayload) {
this.status.setFailed('ha-get-entities.status.no_results');
done();
return;
}
this.status.setSuccess(statusText);
this.contextService.set(payload, parsedMessage.outputLocationType.value, parsedMessage.outputLocation.value, message);
send(message);
done();
}
}
_GetEntitiesController_comparatorService = new WeakMap(), _GetEntitiesController_homeAssistant = new WeakMap(), _GetEntitiesController_currentDevice = new WeakMap(), _GetEntitiesController_currentArea = new WeakMap(), _GetEntitiesController_currentFloor = new WeakMap(), _GetEntitiesController_instances = new WeakSet(), _GetEntitiesController_getEntities = async function _GetEntitiesController_getEntities(conditions, message) {
const currentTime = Date.now();
const filteredEntities = [];
const states = __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getStates();
const sortedConditions = (0, helpers_1.sortConditions)(conditions);
const stateKeys = Object.keys(states);
for (let i = 0; i < stateKeys.length; i++) {
const entityStateId = stateKeys[i];
const entityState = states[entityStateId];
__classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_resetCurrent).call(this);
// TODO: Remove for version 1.0
if (entityState === null || entityState === void 0 ? void 0 : entityState.last_changed) {
entityState.timeSinceChangedMs =
currentTime - new Date(entityState.last_changed).getTime();
}
const entity = __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getEntity(entityState.entity_id);
const ruleMatched = await __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_checkConditions).call(this, sortedConditions, entityState, entity, message);
if (ruleMatched && entityState) {
filteredEntities.push(entityState);
}
}
return filteredEntities;
}, _GetEntitiesController_checkConditions = async function _GetEntitiesController_checkConditions(conditions, entityState, entity, message) {
for (let i = 0; i < conditions.length; i++) {
const rule = conditions[i];
if (rule.condition === const_1.PropertySelectorType.State ||
// If the condition is not set, it is a state condition
rule.condition === undefined) {
const value = (0, selectn_1.default)(rule.property, entityState);
const result = await __classPrivateFieldGet(this, _GetEntitiesController_comparatorService, "f").getComparatorResult(rule.logic, rule.value, value, rule.valueType, {
message,
entity: entityState,
});
if ((rule.logic !== const_2.TypedInputTypes.JSONata &&
value === undefined) ||
!result) {
return false;
}
}
else if (rule.condition === const_1.PropertySelectorType.Label) {
if (!entity)
return false;
const labelCheck = await __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_checkLabelCondition).call(this, rule, entity, entityState, message);
if (!labelCheck) {
return false;
}
}
else {
const propertyValue = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getPropertyValue).call(this, rule.condition, rule.property, entity);
if (!propertyValue)
return false;
const result = (0, operators_1.simpleComparison)(rule.logic, propertyValue, await this.typedInputService.getValue(rule.value, rule.valueType, {
message,
entity: entityState,
}));
if (!result) {
return false;
}
}
}
return true;
}, _GetEntitiesController_checkLabelCondition = async function _GetEntitiesController_checkLabelCondition(rule, entity, entityState, message) {
const value = await this.typedInputService.getValue(rule.value, rule.valueType, { message, entity: entityState });
const hasMatchingLabel = (labelIds) => {
if (!labelIds)
return false;
for (const labelId of labelIds) {
const label = __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getLabel(labelId);
if (!label)
continue;
const result = (0, operators_1.simpleComparison)(rule.logic, label[rule.property], value);
if (result)
return true;
}
return false;
};
// Check entity labels
if (hasMatchingLabel(entity.labels))
return true;
// Check device labels
const device = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getDevice).call(this, entity);
if (hasMatchingLabel(device === null || device === void 0 ? void 0 : device.labels))
return true;
// Check area labels
const area = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getArea).call(this, entity);
if (hasMatchingLabel(area === null || area === void 0 ? void 0 : area.labels))
return true;
return false;
}, _GetEntitiesController_getPropertyValue = function _GetEntitiesController_getPropertyValue(condition, property, entity) {
var _a, _b, _c;
if (!entity)
return undefined;
switch (condition) {
case const_1.PropertySelectorType.Device:
return (_a = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getDevice).call(this, entity)) === null || _a === void 0 ? void 0 : _a[property];
case const_1.PropertySelectorType.Area:
return (_b = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getArea).call(this, entity)) === null || _b === void 0 ? void 0 : _b[property];
case const_1.PropertySelectorType.Floor:
return (_c = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getFloor).call(this, entity)) === null || _c === void 0 ? void 0 : _c[property];
default:
return undefined;
}
}, _GetEntitiesController_getDevice = function _GetEntitiesController_getDevice(entity) {
if (!__classPrivateFieldGet(this, _GetEntitiesController_currentDevice, "f") && entity.device_id) {
__classPrivateFieldSet(this, _GetEntitiesController_currentDevice, __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getDevice(entity.device_id), "f");
}
return __classPrivateFieldGet(this, _GetEntitiesController_currentDevice, "f");
}, _GetEntitiesController_getArea = function _GetEntitiesController_getArea(entity) {
if (__classPrivateFieldGet(this, _GetEntitiesController_currentArea, "f")) {
return __classPrivateFieldGet(this, _GetEntitiesController_currentArea, "f");
}
if (entity.area_id) {
__classPrivateFieldSet(this, _GetEntitiesController_currentArea, __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getArea(entity.area_id), "f");
}
if (!__classPrivateFieldGet(this, _GetEntitiesController_currentArea, "f") && entity.device_id) {
const device = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getDevice).call(this, entity);
if (device === null || device === void 0 ? void 0 : device.area_id) {
__classPrivateFieldSet(this, _GetEntitiesController_currentArea, __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getArea(device.area_id), "f");
}
}
return __classPrivateFieldGet(this, _GetEntitiesController_currentArea, "f");
}, _GetEntitiesController_getFloor = function _GetEntitiesController_getFloor(entity) {
if (__classPrivateFieldGet(this, _GetEntitiesController_currentFloor, "f")) {
return __classPrivateFieldGet(this, _GetEntitiesController_currentFloor, "f");
}
const area = __classPrivateFieldGet(this, _GetEntitiesController_instances, "m", _GetEntitiesController_getArea).call(this, entity);
if (area === null || area === void 0 ? void 0 : area.floor_id) {
__classPrivateFieldSet(this, _GetEntitiesController_currentFloor, __classPrivateFieldGet(this, _GetEntitiesController_homeAssistant, "f").websocket.getFloor(area.floor_id), "f");
}
return __classPrivateFieldGet(this, _GetEntitiesController_currentFloor, "f");
}, _GetEntitiesController_resetCurrent = function _GetEntitiesController_resetCurrent() {
__classPrivateFieldSet(this, _GetEntitiesController_currentDevice, undefined, "f");
__classPrivateFieldSet(this, _GetEntitiesController_currentArea, undefined, "f");
__classPrivateFieldSet(this, _GetEntitiesController_currentFloor, undefined, "f");
};
exports.default = GetEntitiesController;