UNPKG

node-red-contrib-home-assistant-websocket

Version:
261 lines (260 loc) 11.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); 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 _UnidirectionalIntegration_instances, _UnidirectionalIntegration_isValidVersionforDevices, _UnidirectionalIntegration_removeDevice; Object.defineProperty(exports, "__esModule", { value: true }); const compare_versions_1 = require("compare-versions"); const node_1 = require("../../helpers/node"); const Events_1 = require("../events/Events"); const helpers_1 = require("./helpers"); const Integration_1 = __importStar(require("./Integration")); class UnidirectionalIntegration extends Integration_1.default { constructor(props) { super(props); _UnidirectionalIntegration_instances.add(this); this.deviceConfigNode = props.deviceConfigNode; this.entityConfigNode = props.entityConfigNode; } async init() { var _a; this.entityConfigNode.on(Events_1.NodeEvent.Close, this.onEntityConfigNodeClose.bind(this)); (_a = this.deviceConfigNode) === null || _a === void 0 ? void 0 : _a.on(Events_1.NodeEvent.Close, this.onDeviceConfigNodeClose.bind(this)); super.init(); } async onEntityConfigNodeClose(removed, done) { if (this.registered && this.isIntegrationLoaded && removed) { try { await this.unregister(); } catch (err) { done(err); } } done(); } async onDeviceConfigNodeClose(removed, done) { if (this.registered && this.isIntegrationLoaded && removed) { try { await __classPrivateFieldGet(this, _UnidirectionalIntegration_instances, "m", _UnidirectionalIntegration_removeDevice).call(this); } catch (err) { done(err); } } done(); } getDeviceInfo() { if (!this.deviceConfigNode) { return undefined; } const config = this.deviceConfigNode.config; return { id: config.id, hw_version: config.hwVersion, name: config.name, manufacturer: config.manufacturer, model: config.model, sw_version: config.swVersion, }; } getStateData(state) { if (!state) { return {}; } let data = {}; if (this.entityConfigNode.config.resend && state) { const lastPayload = state.getLastPayload(); if (lastPayload) { data = { ...lastPayload }; } } return data; } getDiscoveryPayload({ config, remove, state, }) { const deviceInfo = this.getDeviceInfo(); const message = { ...this.getStateData(state), type: Integration_1.MessageType.Discovery, server_id: this.entityConfigNode.config.server, node_id: this.entityConfigNode.id, config, component: this.entityConfigNode.config.entityType, remove, device_info: deviceInfo, }; return message; } getEntityPayload(state, attributes) { return { type: Integration_1.MessageType.Entity, server_id: this.entityConfigNode.config.server, node_id: this.entityConfigNode.id, state, attributes, }; } async register() { if (!this.isIntegrationLoaded) { this.entityConfigNode.error(this.notInstalledMessage); this.status.forEach((status) => status.setFailed('home-assistant.status.error')); return; } if (this.isRegistered) return; const config = (0, helpers_1.createHaConfig)(this.entityConfigNode.config.haConfig); const payload = this.getDiscoveryPayload({ config, state: this.state, }); this.debugToClient('register', payload); this.entityConfigNode.debug(`Registering ${this.entityConfigNode.config.entityType} with HA`); try { await this.homeAssistant.websocket.send(payload); } catch (err) { this.status.forEach((status) => status.setFailed('home-assistant.status.error_registering')); const message = err instanceof Error ? err.message : err; this.entityConfigNode.error(`Error registering entity. Error Message: ${message}`); return; } this.saveHaConfigToContext(config); this.status.forEach((status) => status === null || status === void 0 ? void 0 : status.setSuccess('home-assistant.status.registered')); this.registered = true; } setStatus(status) { this.status.push(status); } async updateStateAndAttributes(state, attributes) { const payload = this.getEntityPayload(state, attributes); try { await this.homeAssistant.websocket.send(payload); } catch (err) { this.entityConfigNode.error(`Error updating entity. Error Message: ${err}`); } if (this.entityConfigNode.config.resend) { const lastPayload = { state, attributes, }; this.state.setLastPayload(lastPayload); } this.debugToClient('update state', payload); return payload; } async unregister() { var _a; this.entityConfigNode.debug(`Unregistering ${this.entityConfigNode.config.entityType} node from HA`); const payload = this.entityConfigNode.integration.getDiscoveryPayload({ remove: true, }); this.debugToClient('unregister', payload); try { await ((_a = this.homeAssistant) === null || _a === void 0 ? void 0 : _a.websocket.send(payload)); } catch (err) { this.entityConfigNode.error(`Error unregistering entity. Error Message: ${err}`); } } debugToClient(topic, message) { (0, node_1.debugToClient)(this.entityConfigNode, message, topic); } getEntityConfigNode() { return this.entityConfigNode; } /** * This method retrieves the value of a specific key from the Home Assistant configuration for the entity. * If the key does not exist in the configuration, it returns undefined. * * @param key - The key for which to retrieve the value. * @returns The value of the key from the Home Assistant configuration, or undefined if the key does not exist. */ getEntityHomeAssistantConfigValue(key) { var _a; // Get the Home Assistant configuration from the context or the entity's config const haConfig = (_a = this.getHaConfigFromContext()) !== null && _a !== void 0 ? _a : (0, helpers_1.createHaConfig)(this.entityConfigNode.config.haConfig); return haConfig[key]; } /** * This method saves the Home Assistant (HA) configuration to the context. * It first retrieves any existing HA configuration from the context. * Then it removes any properties from the new HA configuration that have undefined values. * Finally, it merges the existing and new HA configurations and saves the result back to the context. * * @param haConfig - The new HA configuration to save. Properties with undefined values will not be saved. */ saveHaConfigToContext(haConfig) { var _a; const existingHaConfig = (_a = this.getHaConfigFromContext()) !== null && _a !== void 0 ? _a : {}; // remove undefined values from haConfig Object.keys(haConfig).forEach((key) => haConfig[key] === undefined && delete haConfig[key]); const mergedHaConfig = { ...existingHaConfig, ...haConfig, }; this.entityConfigNode.context().set('haConfig', mergedHaConfig); } /** * This method retrieves the Home Assistant (HA) configuration from the context. * If the HA configuration does not exist in the context, it returns undefined. * * @returns The HA configuration from the context, or undefined if it does not exist. */ getHaConfigFromContext() { return this.entityConfigNode.context().get('haConfig'); } } _UnidirectionalIntegration_instances = new WeakSet(), _UnidirectionalIntegration_isValidVersionforDevices = function _UnidirectionalIntegration_isValidVersionforDevices() { return ((0, compare_versions_1.compareVersions)(`${this.homeAssistant.websocket.integrationVersion}`, '1.1') >= 0); }, _UnidirectionalIntegration_removeDevice = async function _UnidirectionalIntegration_removeDevice() { var _a; if (!this.deviceConfigNode || !__classPrivateFieldGet(this, _UnidirectionalIntegration_instances, "m", _UnidirectionalIntegration_isValidVersionforDevices).call(this)) return; this.deviceConfigNode.debug(`Removing device from Home Assistant: ${this.deviceConfigNode.config.name}`); try { await ((_a = this.homeAssistant) === null || _a === void 0 ? void 0 : _a.websocket.send({ type: Integration_1.MessageType.RemoveDevice, node_id: this.deviceConfigNode.id, })); } catch (err) { this.deviceConfigNode.error(`Error removing device. Error Message: ${err}`); } }; exports.default = UnidirectionalIntegration;