iobroker.lovelace
Version:
With this adapter you can build visualization for ioBroker with Home Assistant Lovelace UI
192 lines (174 loc) • 7.06 kB
JavaScript
const pinyin = require('pinyin');
/**
* Replaces invalid characters from generated unique part of entity id, i.e. light.idPart
* @param idPart unique part of entity Id
* @returns {string} cleaned entity Id part.
*/
function replaceInvalidChars(idPart) {
idPart = idPart.replace(/Ü/g, 'UE');
idPart = idPart.replace(/Ä/g, 'AE');
idPart = idPart.replace(/Ö/g, 'OE');
idPart = idPart.replace(/ü/g, 'ue');
idPart = idPart.replace(/ä/g, 'ae');
idPart = idPart.replace(/ö/g, 'oe');
idPart = idPart.replace(/ß/g, 'ss');
idPart = idPart.replace(/[^a-zA-Z0-9А-Яа-я_]/g, '_');
return idPart;
}
function getObjectIcon(obj, prefix) {
prefix = prefix || '.';//http://localhost:8081';
if (!obj || !obj.common || !obj.common.icon) {
return null;
}
let icon;
if (!obj.common.icon.match(/^data:image\//)) {
if (obj.common.icon.startsWith('http')) {
//icon is full URL. Use that.
return obj.common.icon;
}
if (obj.common.icon.indexOf('.') !== -1) {
let instance;
if (obj.type === 'instance') {
icon = prefix + '/adapter/' + obj.common.name + '/' + obj.common.icon;
} else if (obj._id && obj._id.match(/^system\.adapter\./)) {
instance = obj._id.split('.', 3);
if (obj.common.icon[0] === '/') {
instance[2] += obj.common.icon;
} else {
instance[2] += '/' + obj.common.icon;
}
icon = prefix + '/adapter/' + instance[2];
} else {
instance = obj._id.split('.', 2);
if (obj.common.icon[0] === '/') {
instance[0] += obj.common.icon;
} else {
instance[0] += '/' + obj.common.icon;
}
icon = prefix + '/adapter/' + instance[0];
}
} else {
return null; // '<i class="material-icons iob-list-icon">' + obj.common.icon + '</i>';
}
} else {
// base 64 image
icon = obj.common.icon;
}
return icon;
}
/**
* ioBroker ID needs to be subscribed, if entity is used in vis in order to update.
* @param id of ioBroker object
* @param entity entity_id
*/
function _addID2entity(id, entity) {
this._ID2entity[id] = this._ID2entity[id] || [];
const found = this._ID2entity[id].find(e => e.entity_id === entity.entity_id);
if (!found) {
this._ID2entity[id].push(entity);
}
}
function _getObjectName(obj, _lang) {
//_lang = _lang || this.lang; can't do this. Make sure lang is set below.
if (obj && obj.common && obj.common.name) {
if (typeof obj.common.name === 'object') {
if (obj.common.name[_lang] || obj.common.name.en) {
return obj.common.name[_lang] || obj.common.name.en;
} else {
const lang = Object.keys(obj.common.name).find(lang => obj.common.name[lang]);
if (obj.common.name[lang]) {
return obj.common.name[lang];
} else {
return obj._id;
}
}
} else {
return obj.common.name;
}
} else {
return obj ? obj._id || '' : '';
}
}
function getObjectName(obj, __lang) {
const objName = _getObjectName(obj, __lang);
const pinyinObjNameObj = pinyin(objName, {style: pinyin.STYLE_TONE2});
if (typeof pinyinObjNameObj === 'object' && pinyinObjNameObj.length > 1) {
// Found Chinese word.
// "Chinese中文" => [ [ 'Chinese' ], [ 'zhong1' ], [ 'wen2' ] ]
let pinyinObjName = '';
for (let i = 0; i < pinyinObjNameObj.length; i++) {
if (typeof pinyinObjNameObj[i] === 'object') {
pinyinObjName += pinyinObjNameObj[i][0];
}
}
return pinyinObjName;
}
// No Chinese word found, return origin object name
return objName;
}
function generateName(obj, lang) {
return getObjectName(obj, lang).replace(/[^-._\w0-9А-Яа-яÄÜÖßäöü ]/g, '_');
}
/**
* generate a bare entity from parameters. Already adds the entity to a bunch of arrays. So be sure to use it!
* @param {string|null} name friendly name of entity, if empty, will be read from object or generated from room & func or id.
* @param {string|null} room room of device for name generation
* @param {string|null} func function of device for name generation
* @param {Object} obj ioBroker object, used to read id, name, icon, unit, lovelace specific settings.
* @param {string} entityType lovelace domain of entity, for example light, sensor, ...
* @param [entity_id] predefined entity id. If empty, will be generated from name
* @returns {{context: {id: string, type: string}, attributes: {friendly_name: string}, entity_id: string}}
*/
function _processCommon(name, room, func, obj, entityType, entity_id) {
if (!name) {
if (obj && obj.common && obj.common.name) {
name = generateName(obj, this.lang);
} else if (func && room) {
name = room + ' ' + func;
} else {
name = (obj && obj.common && obj.common.custom && obj.common.custom[this.adapter.namespace] && obj.common.custom[this.adapter.namespace].name) || generateName(obj, this.lang);
}
}
let idPart;
if (entity_id && /^.+\..+$/.test(entity_id)) {
/** @type{Array<String>} */
const parts = entity_id.split('.');
entityType = parts.shift();
idPart = replaceInvalidChars(parts.join('_'));
} else {
idPart = replaceInvalidChars(generateName(obj, 'en'));
}
const entity = {
entity_id: (entityType + '.' + idPart),
attributes: {
friendly_name: name
},
//last_changed: new Date(state.lc).toISOString(),
//last_updated: new Date(state.ts).toISOString(),
context: {
id: obj._id,
type: entityType,
}
};
if (obj.common.unit) {
entity.attributes.unit_of_measurement = obj.common.unit;
//entity.attributes.unit_of_measurement_dict = obj.common.unit;
}
if (obj.common.icon) {
entity.attributes.entity_picture = getObjectIcon(obj);
}
this._addID2entity(obj._id, entity);
this._entity2ID[entity.entity_id] = entity;
const foundIndex = this._entities.findIndex(x => x.entity_id === entity.entity_id);
if (foundIndex !== -1) {
this._entities[foundIndex] = entity;
} else {
this._entities.push(entity);
}
return entity;
}
//required to read user name
exports.getObjectName = getObjectName;
//required by other converters:
exports._processCommon = _processCommon;
exports._addID2entity = _addID2entity;