diff --git a/README.md b/README.md index cf24d503..9fc35d6f 100644 --- a/README.md +++ b/README.md @@ -134,6 +134,10 @@ You can thank the authors by these links: ----------------------------------------------------------------------------------------------------- ## Changelog +### 1.9.2 (2023-12-25) +* (arteck) gen states from exposes as function +* (arteck) rebuild dev_names.json with state cleanup button + ### 1.9.1 (2023-12-23) * (arteck) corr TypeError: Cannot read properties of undefined (reading 'state') diff --git a/io-package.json b/io-package.json index eb168dd5..f792d6ab 100644 --- a/io-package.json +++ b/io-package.json @@ -1,8 +1,21 @@ { "common": { "name": "zigbee", - "version": "1.9.1", + "version": "1.9.2", "news": { + "1.9.2": { + "en": "gen states from exposes as function\nrebuild dev_names.json with state cleanup button", + "de": "gen-staaten von exponiert als funktion\ndev_names neu aufbauen. json with state cleanup taste", + "ru": "гены из экспозиций как функция\nперестроить dev_names. json с государственной кнопкой очистки", + "pt": "gen estados de exposições como função\nreconstruir dev_names. json com botão de limpeza do estado", + "nl": "gen staten van blootstelling als functioneren\nherbouwde dev namen. json met staatsopruimknop", + "fr": "gen states from exposes as function\nreconstruire dev_names. json avec bouton de nettoyage de l'état", + "it": "gen stati da espone come funzione\nricostruire dev_names. json con il pulsante di pulizia dello stato", + "es": "gen estados de expone como función\nreconstruir dev_names. json con botón de limpieza del estado", + "pl": "państwa genowe zjawiają się jako funkcje\nodbudowa nazw. json z przyciskiem czystego przycisku", + "uk": "генні стани від вибухів як функції\nrebuild dev_names. json з державною кнопкою очищення", + "zh-cn": "根塔里斯·奥古尔(签名)\n页:1 j. 有国家清洁,但顿" + }, "1.9.1": { "en": "corr TypeError: Cannot read properties of undefined (reading 'state')", "de": "korpustyp Fehler: Kann Eigenschaften von undefinierten (Lesezustand) nicht lesen", @@ -80,19 +93,6 @@ "pl": "zamienił tablicę dla niektórych Aqara Devices", "uk": "перемикач для установки для деяких пристроїв Aqara", "zh-cn": "对某些Aqara Devic的表格的转换" - }, - "1.8.23": { - "en": "query from xiaomi is now better", - "de": "anfrage von xiaomi ist jetzt besser", - "ru": "запрос от xiaomi теперь лучше", - "pt": "consulta de xiaomi é agora melhor", - "nl": "quee van xiaomi is nu beter", - "fr": "la question de xiaomi est maintenant mieux", - "it": "query da xiaomi è ora meglio", - "es": "la consulta de xiaomi ahora es mejor", - "pl": "wykorzystywanie z xiaomi jest obecnie lepsze", - "uk": "запиту від xiaomi тепер краще", - "zh-cn": "来自米亚米的询问现在更好。" } }, "titleLang": { diff --git a/lib/commands.js b/lib/commands.js index fb712fca..9a6c25a0 100644 --- a/lib/commands.js +++ b/lib/commands.js @@ -88,7 +88,6 @@ class Commands { break; case 'setState': if (obj && obj.message && typeof obj.message === 'object' && obj.message.id) { - // this.adapter.setState(obj.message.id, obj.message.val, false, obj.callback); this.stController.setState_typed(obj.message.id, obj.message.val, false, undefined, obj.callback); } break; @@ -107,7 +106,6 @@ class Commands { this.setDeviceActivated(obj.from, obj.command, obj.message, obj.callback); } break; - } } } @@ -474,13 +472,17 @@ class Commands { async cleanDeviceStates(from, command, msg, callback) { this.info(`State cleanup with ${JSON.stringify(msg)}`); const devicesFromDB = await this.zbController.getClients(false); + for (const device of devicesFromDB) { const entity = await this.zbController.resolveEntity(device); + if (entity) { const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID; await this.stController.deleteOrphanedDeviceStates(device.ieeeAddr, model, msg.force); } } + // rebuild retainDeviceNamesDB + this.stController.rebuildRetainDeviceNames(); this.adapter.sendTo(from, command, {}, callback); } diff --git a/lib/devicemgmt.js b/lib/devicemgmt.js index c4c23303..071fe2c7 100644 --- a/lib/devicemgmt.js +++ b/lib/devicemgmt.js @@ -7,7 +7,7 @@ class dmZigbee extends dmUtils.DeviceManagement { const data = { ...super.getInstanceInfo(), apiVersion: 'v1', - actions: [ + actions: [ { id: 'newDevice', icon: 'fas fa-plus', diff --git a/lib/exposes.js b/lib/exposes.js index 3edfb3dd..8a06a7c5 100644 --- a/lib/exposes.js +++ b/lib/exposes.js @@ -248,9 +248,37 @@ function createFromExposes(model, def) { } const icon = utils.getDeviceIcon(def); - for (const expose of def.exposes) { - let state; + if (typeof def.exposes == 'object') { + for (const expose of def.exposes) { + genStateFromExpose(expose); + + + } + } + + // maybee here check manufacturerName for tuya devices + if (typeof def.exposes == 'function') { + const expFunction = def.exposes(def, {}); // maybee here check manufacturerName for tuya devices + + for (const expose of expFunction) { + genStateFromExpose(expose); + } + } + + const newDev = { + models: [model], + icon, + states, + exposed: true, + }; + + return newDev; + + + + function genStateFromExpose(expose) { + let state; switch (expose.type) { case 'light': for (const prop of expose.features) { @@ -362,7 +390,7 @@ function createFromExposes(model, def) { x: xy[0], y: xy[1] }; -*/ + */ let xy = [0, 0]; const rgbcolor = colors.ParseColor(value); @@ -851,22 +879,20 @@ function createFromExposes(model, def) { } } break; + case 'list': + // is not mapped + // for (const prop of expose) { + // let nam = prop.name; + + // } + break; default: console.log(`Unhandled expose type ${expose.type} for device ${model}`); + } } - const newDev = { - models: [model], - icon, - states, - exposed: true, - }; - // make the function code printable in log - //console.log(`Created mapping for device ${model}: ${JSON.stringify(newDev, function(key, value) { - // if (typeof value === 'function') {return value.toString() } else { return value } }, ' ')}`); - return newDev; -} +} function applyExposes(mappedDevices, byModel, allExcludesObj) { // for exclude search const allExcludesStr = JSON.stringify(allExcludesObj); @@ -890,6 +916,7 @@ function applyExposes(mappedDevices, byModel, allExcludesObj) { function applyDeviceDef(mappedDevices, byModel, allExcludesStr, deviceDef) { const stripModel = utils.getModelRegEx(deviceDef.model); // check if device is mapped + const existsMap = byModel.get(stripModel); if ((deviceDef.hasOwnProperty('exposes') && (!existsMap || !existsMap.hasOwnProperty('states'))) || allExcludesStr.indexOf(stripModel) > 0) { diff --git a/lib/statescontroller.js b/lib/statescontroller.js index 87938ad5..96464b84 100644 --- a/lib/statescontroller.js +++ b/lib/statescontroller.js @@ -7,7 +7,7 @@ const getZbId = require('./utils').getZbId; const fs = require('fs'); const request = require('request'); -let savedDeviceNames = {}; +let savedDeviceNamesDB = {}; const knownUndefinedDevices = {}; class StatesController extends EventEmitter { @@ -23,9 +23,9 @@ class StatesController extends EventEmitter { fs.readFile(this.dev_names_fn, (err, data) => { if (!err) { try { - savedDeviceNames = JSON.parse(data); + savedDeviceNamesDB = JSON.parse(data); } catch { - savedDeviceNames = {}; + savedDeviceNamesDB = {}; } } }); @@ -54,7 +54,7 @@ class StatesController extends EventEmitter { retainDeviceNames() { clearTimeout(this.retTimeoutHandle); this.retTimeoutHanlde = setTimeout(() => { - fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNames, null, 2), err => { + fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNamesDB, null, 2), err => { if (err) { this.error(`error saving device names: ${JSON.stringify(err)}`); } else { @@ -272,18 +272,30 @@ class StatesController extends EventEmitter { this.adapter.extendObject(id, {common: {deactivated: active}}); } + async rebuildRetainDeviceNames() { + savedDeviceNamesDB = {}; + const devList = await this.adapter.getAdapterObjectsAsync(); + + for (const key in devList) { + if (devList[key].type == 'device') { + savedDeviceNamesDB[devList[key]._id.replace(`${this.adapter.namespace}.`, '')] = devList[key].common.name; + } + } + this.retainDeviceNames(); + } + storeDeviceName(id, name) { - savedDeviceNames[id.replace(`${this.adapter.namespace}.`, '')] = name; + savedDeviceNamesDB[id.replace(`${this.adapter.namespace}.`, '')] = name; this.retainDeviceNames(); } verifyDeviceName(id, name) { const savedId = id.replace(`${this.adapter.namespace}.`, ''); - if (!savedDeviceNames.hasOwnProperty(savedId)) { - savedDeviceNames[savedId] = name; + if (!savedDeviceNamesDB.hasOwnProperty(savedId)) { + savedDeviceNamesDB[savedId] = name; this.retainDeviceNames(); } - return savedDeviceNames[savedId]; + return savedDeviceNamesDB[savedId]; } deleteDeviceStates(devId, callback) { diff --git a/package-lock.json b/package-lock.json index b85e1eda..9db26eea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "iobroker.zigbee", - "version": "1.9.1", + "version": "1.9.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "iobroker.zigbee", - "version": "1.9.1", + "version": "1.9.2", "license": "MIT", "dependencies": { "@iobroker/adapter-core": "^3.0.4", - "@jey-cee/dm-utils": "^0.0.5", + "@iobroker/dm-utils": "^0.1.8", "humanize-duration": "^3.31.0", "tar": "^6.2.0", "typescript": "^5.3.3", @@ -353,6 +353,14 @@ "@iobroker/types": "^5.0.11" } }, + "node_modules/@iobroker/dm-utils": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/@iobroker/dm-utils/-/dm-utils-0.1.8.tgz", + "integrity": "sha512-AvJLDQOkeXq2lrO8VKbsUwGs2c3xr7UpqTOt8ZX3bokCHQc63E+N3lfjyW5Xf8knIH+8zEmBE03aEhO2NSUMmQ==", + "dependencies": { + "@iobroker/adapter-core": "^3.0.4" + } + }, "node_modules/@iobroker/testing": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@iobroker/testing/-/testing-4.1.0.tgz", @@ -378,14 +386,6 @@ "node": ">=12.0.0" } }, - "node_modules/@jey-cee/dm-utils": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/@jey-cee/dm-utils/-/dm-utils-0.0.5.tgz", - "integrity": "sha512-gVqu3BAo+uDgpSZYYMQUwRfQoH/7aXJc6+GeuWJ5NSuR61J6d+Yz2oVw7T4mh14BqWPUzBqq1Ix3IhKFn1jI5w==", - "dependencies": { - "@iobroker/adapter-core": "^3.0.4" - } - }, "node_modules/@leichtgewicht/ip-codec": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", diff --git a/package.json b/package.json index fa203dc1..f88a69da 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iobroker.zigbee", - "version": "1.9.1", + "version": "1.9.2", "author": { "name": "Kirov Ilya", "email": "kirovilya@gmail.com"