UNPKG

iobroker.lovelace

Version:

With this adapter you can build visualization for ioBroker with Home Assistant Lovelace UI

325 lines (324 loc) 12.4 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var baseEntity_exports = {}; __export(baseEntity_exports, { BaseEntity: () => BaseEntity, processCommon: () => processCommon }); module.exports = __toCommonJS(baseEntity_exports); var import_friendly_name = require("./friendly_name"); var import_entity_id = require("./entity_id"); var import_utils = require("./utils"); var import_genericConverter = require("../converters/genericConverter"); const entityData = require("../../../lib/dataSingleton"); class BaseEntity { /** * entity_id of the entity, for example "light.living_room_light". Should be unique across all * entities and should not change after creation, since it is used for storing in entity registry * and so on. It should be based on the ioBroker id of the device or state and the type of entity * (like main state, battery, online/offline, error, maintenance, working), not on friendly name. */ entity_id; /** state of the entity. Needs to be a string and what the frontend expects it to be. */ state = "unknown"; /** when the state (and only the state) last changed. */ last_changed = 0; /** when the state or attributes last changed. */ last_updated = 0; /** attributes as the frontend expects them — an object, not an array. */ attributes = {}; /** ioBroker context information — internal bookkeeping not sent to the frontend. */ context; /** * Ids of ioBroker objects associated with this entity_id (for state subscription and lookup). */ iobIds = []; /** Marks an entity created from a manual user-configured object. */ isManual; /** * Generate a bare entity from common parameters. * * @param name - friendly name; if empty, taken from object or generated from room & func or id * @param room - room enum object (used for friendly-name generation) * @param func - function enum object (used for friendly-name generation) * @param obj - ioBroker object — used for id, name, icon, unit, lovelace-specific settings * @param entityType - lovelace domain of the entity (e.g. 'light', 'sensor') * @param entity_id - predefined entity id; if empty, generated from name * @param language - language for name extraction; defaults to 'en' */ constructor(name, room, func, obj, entityType, entity_id, language) { var _a, _b, _c, _d, _e, _f; const objId = (_a = obj == null ? void 0 : obj._id) != null ? _a : ""; const lang = language != null ? language : entityData.lang; const roomName = (0, import_utils.getEnumName)(room, lang); const funcName = (0, import_utils.getEnumName)(func, lang); this.entity_id = (0, import_entity_id.getEntityId)(entityType, entity_id, obj, roomName, funcName); this.attributes = { friendly_name: (0, import_friendly_name.getFriendlyName)(name, obj, roomName, funcName) }; this.context = { id: objId, type: (0, import_entity_id.getEntityType)(entityType, entity_id, obj), room: roomName, roomId: room ? room._id : null, func: funcName, funcId: func ? func._id : null, stateType: (_b = obj == null ? void 0 : obj.common) == null ? void 0 : _b.type, deviceId: objId, aliases: obj ? ((_c = (0, import_utils.getSmartName)(obj, objId, language != null ? language : entityData.lang)) == null ? void 0 : _c.split(",")) || [] : [], STATE: { getId: objId || null, attribute: "state" }, ATTRIBUTES: [], COMMANDS: [] }; if ((_d = obj == null ? void 0 : obj.common) == null ? void 0 : _d.unit) { this.attributes.unit_of_measurement = obj.common.unit; } if ((_e = obj == null ? void 0 : obj.common) == null ? void 0 : _e.icon) { this.attributes.entity_picture = (_f = (0, import_utils.getObjectIcon)(obj)) != null ? _f : void 0; } if (objId) { this.addID2entity(objId); } } /** * Register an ioBroker state id as used by this entity (for subscriptions and lookup). * * @param id - ioBroker state id */ addID2entity(id) { if (!this.iobIds.includes(id)) { this.iobIds.push(id); } } /** * Fill entity STATE/ATTRIBUTES from a `{state, stateRead, ...}` map. Replaces the old * standalone `fillEntityFromStates(states, entity, objects)` helper. * * @param states - ids of ioBroker states; "state" goes into entity-state, can also have stateRead. * Other keys become attributes named after the key. * @param objects - optional objects cache to determine writeability of attributes. */ fillFromStates(states, objects) { var _a, _b; this.context.STATE = { attribute: "state", setId: states.state || null, getId: states.stateRead || states.state || null }; this.context.ATTRIBUTES = (_a = this.context.ATTRIBUTES) != null ? _a : []; for (const key of Object.keys(states)) { const id = states[key]; const obj = objects ? objects[id] : null; if (id) { this.addID2entity(id); if (!key.endsWith("Read")) { if (key !== "state" && key !== "stateRead") { const attrs = this.context.ATTRIBUTES; const attr = attrs.find((a) => a.attribute === key); if (!attr) { attrs.push({ attribute: key, getId: states[`${key}Read`] || id, setId: ((_b = obj == null ? void 0 : obj.common) == null ? void 0 : _b.write) ? id : void 0 }); } else { attr.setId = id; } } } } } } /** * Register this entity in the dataSingleton caches (entities array, entityId2Entity, * iobID2entity). Replaces the old standalone `fillEntityIntoCaches(entity)` helper. */ registerInCaches() { const foundIndex = entityData.entities.findIndex((x) => x.entity_id === this.entity_id); if (foundIndex !== -1) { entityData.log.warn( `Got duplicate for entity ${this.entity_id}. Overwriting old value. Was for ${entityData.entities[foundIndex].context.id} and new one is for ${this.context.id}` ); entityData.entities[foundIndex] = this; } else { entityData.entities.push(this); } entityData.entityId2Entity[this.entity_id] = this; const ids = this.iobIds; for (const id of ids || []) { entityData.iobID2entity[id] = entityData.iobID2entity[id] || []; const foundIdx = entityData.iobID2entity[id].findIndex((e) => e.entity_id === this.entity_id); if (foundIdx === -1) { entityData.iobID2entity[id].push(this); } else { entityData.iobID2entity[id][foundIdx] = this; } } } /** * Remove this entity from the dataSingleton caches, or rename it to a new entity_id. * Replaces the old standalone `removeEntity(entity, newId?)` helper. * * @param newId - if set, the entity is re-keyed under this new id instead of being removed. */ unregister(newId) { if (newId) { delete entityData.entityId2Entity[this.entity_id]; entityData.entityId2Entity[newId] = this; } else { delete entityData.entityId2Entity[this.entity_id]; } if (!newId) { let foundIndex = entityData.entities.findIndex((x) => x.entity_id === this.entity_id); while (foundIndex !== -1) { entityData.entities.splice(foundIndex, 1); foundIndex = entityData.entities.findIndex((x) => x.entity_id === this.entity_id); } } if (!newId && this.attributes.entity_picture) { const urlIndex = entityData.entityIconUrls.findIndex((x) => x === this.attributes.entity_picture); if (urlIndex !== -1) { entityData.entityIconUrls.splice(urlIndex, 1); } } if (!newId) { for (const key of Object.keys(entityData.iobID2entity)) { const entities = entityData.iobID2entity[key]; let foundIndex = entities.findIndex((x) => x.entity_id === this.entity_id); while (foundIndex !== -1) { entities.splice(foundIndex, 1); foundIndex = entities.findIndex((x) => x.entity_id === this.entity_id); } } } } /** * Update timestamps from a state change. * * @param state - state to update from * @param isStateChange - true if entity.state was changed (rather than only an attribute) */ updateTimestamp(state, isStateChange) { if (!state) { if (isStateChange) { if (this.state !== "unknown") { this.last_changed = Date.now() / 1e3; this.last_updated = Date.now() / 1e3; } this.state = "unknown"; } return; } if (!state.ts || isNaN(new Date(state.ts).getTime())) { state.ts = Date.now(); } if (state.lc && isNaN(new Date(state.lc).getTime())) { state.lc = Date.now(); } const lu = (state.ts || Date.now()) / 1e3; const lc = (state.lc || state.ts || Date.now()) / 1e3; if (lu > this.last_updated) { this.last_updated = lu; } if (isStateChange && lc > this.last_changed) { this.last_changed = lc; } } /** * Process a state change from ioBroker state db. Routes to STATE.getParser / * ATTRIBUTES[*].getParser, then refreshes timestamps. * * @param id - ioBroker object id that changed * @param state - new state value (null when the state was deleted) */ processStateChange(id, state) { var _a; let isStateChange = false; let isChange = false; if (id === this.context.STATE.getId) { const isChanged = this.getParser(this.context.STATE, state); if (isChanged) { isStateChange = true; isChange = true; } } for (const attr of (_a = this.context.ATTRIBUTES) != null ? _a : []) { if (attr.getId === id) { isChange || (isChange = this.getParser(attr, state)); } } if (isChange) { this.updateTimestamp(state, isStateChange); } } /** * Default getParser — overridable by subclasses. * * @param attr - the attribute (or STATE) whose getId object changed. * @param state - new state of the getId object * @returns true when the value actually changed */ getParser(attr, state) { var _a; const oldVal = attr.attribute === "state" ? this.state : this.attributes[attr.attribute]; const newVal = (0, import_genericConverter.iobState2EntityState)(this, (_a = state == null ? void 0 : state.val) != null ? _a : null, attr.attribute); if (attr.attribute === "state") { this.state = newVal; } else { this.attributes[attr.attribute] = newVal; } return oldVal !== newVal; } /** Convert into the full entity representation expected by the HA frontend. */ getEntityRepresentationForFrontend() { return { entity_id: this.entity_id, state: this.state, last_updated: new Date(this.last_updated * 1e3).toISOString(), last_changed: new Date(this.last_changed * 1e3).toISOString(), attributes: this.attributes, context: { id: this.context.id, user_id: null, parent_id: null } }; } /** Convert into the short entity representation used for live state updates. */ getShortEntityForFrontend() { return { s: this.state, a: this.attributes, lc: this.last_changed, lu: this.last_updated }; } } function processCommon(name, room, func, obj, entityType, entity_id, language) { return new BaseEntity(name, room, func, obj, entityType, entity_id, language); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { BaseEntity, processCommon }); //# sourceMappingURL=baseEntity.js.map