iobroker.zigbee 3.2.5 → 3.3.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -733,11 +733,17 @@
733
733
  <i class="material-icons large icon-blue">feedback</i></a>
734
734
  </li>
735
735
  <li>
736
- <a id="download_icons_btn"
736
+ <a id="download_icons_btn"
737
737
  class="btn-floating disabled waves-effect waves-light blue tooltipped center-align hoverable translateT"
738
738
  title="Download missing icons">
739
739
  <i class="material-icons large">cloud_download</i></a>
740
740
  </li>
741
+ <li>
742
+ <a id="rebuild_states_btn"
743
+ class="btn-floating disabled waves-effect waves-light blue tooltipped center-align hoverable translateT"
744
+ title="Rebuild states">
745
+ <i class="material-icons large">low_priority</i></a>
746
+ </li>
741
747
  <li>
742
748
  <a id="pairing"
743
749
  class="btn-floating disabled waves-effect waves-light green tooltipped center-align hoverable translateT"
@@ -1286,37 +1292,6 @@
1286
1292
  </nav>
1287
1293
  </div>
1288
1294
  <div class="row">
1289
- <!--
1290
- <div class="col s1 l1 m1"><a id="modelnamefilter" class="btn-large blue left" ><i class="material-icons icon-blue">filter_list</i></a></div>
1291
- <div class="col s5 l5 m5 input-field" style="line-height: 24px;"><input id="Filter" type="text" /><label class="translate">Search</div>
1292
- <div class="col s1 l1 m1"><a id="modelsetfilter" class="btn-large blue left" ><i class="material-icons icon-blue">reorder</i></a></div>
1293
- <div class="input-field suffix col s2 m2 l2">
1294
- <select id="channel" class="value">
1295
- <option value="function(a) { return true }" selected>All</option>
1296
- <option value="function(a) { return LocalDisplayDataValues[a].type == 'group' }">Groups</option>
1297
- <option value="function(a) { return LocalDisplayDataValues[a].type == 'Router' }">Routers</option>
1298
- <option value="function(a) { return LocalDisplayDataValues[a].type == 'Router' }">EndDevices</option>
1299
- <option value="function(a) { return LocalDisplayDataValues[a].setOptions?.length > 0 }">with Options</option>
1300
- <option value="function(a) { return !(LocalDisplayDataValues[a].setOptions?.length > 0) }">without Options</option>
1301
- <label class="translate">Filter</label>
1302
- </select>
1303
- </div>
1304
- <div class="col s1 l1 m1"><a id="modelnamefilter" class="btn-large blue left" ><i class="material-icons icon-blue">sort</i></a></div>
1305
- <div class="input-field suffix col s2 m2 l2">
1306
- <select id="channel" class="value">
1307
- <option value="function(a,b) { return 0 }" selected>noSort</option>
1308
- <option value="function(a,b) { return LocalDisplayDataValues[a].type > LocalDisplayDataValues[b].type }">by type</option>
1309
- <option value="function(a,b) { return LocalDisplayDataValues[a].devices?.length > LocalDisplayDataValues[b].devices?.length }">by device counttype</option>
1310
- <option value="function(a,b) { return LocalDisplayDataValues[a].setOptions?.length > LocalDisplayDataValues[b].setOptions?.length }">by option count</option>
1311
- <label class="translate">Sort</label>
1312
- </select>
1313
- </div></div>
1314
- <div class="fixed-action-btn" style="margin-bottom: 100px">
1315
- <a id="updateData"
1316
- class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT"
1317
- title="update Data"><i class="material-icons large">replay</i></a>
1318
- </div>
1319
- -->
1320
1295
  <div id="tab-overrides-content" row>
1321
1296
  Nothing to see yet.
1322
1297
  </div>
@@ -1490,6 +1465,20 @@
1490
1465
  <a href="#!" class="modal-action modal-close waves-effect waves-red btn-flat translate">Cancel</a>
1491
1466
  </div>
1492
1467
  </div>
1468
+ <div id="modalrebuild" class="modal">
1469
+ <div class="modal-content">
1470
+ <h3 class="translate">State rebuild confirmation</h3>
1471
+ <p>A bunch of text</p>
1472
+ </div>
1473
+ <div class="modal-footer">
1474
+ <div id="cforcediv" class="forcedelete">
1475
+ <input id="cforce_rebuild" type="checkbox" class="value"/>
1476
+ <label class="translate" for="cforce_rebuild">Force update all roles to adapter defined roles</label>
1477
+ </div>
1478
+ <a name="yes" href="#!" class="modal-action modal-close waves-effect waves-green btn green translate">Yes</a>
1479
+ <a href="#!" class="modal-action modal-close waves-effect waves-red btn-flat translate">Cancel</a>
1480
+ </div>
1481
+ </div>
1493
1482
  <div id="modalreconfigure" class="modal">
1494
1483
  <div class="modal-content">
1495
1484
  <h3 class="translate">Reconfigure device</h3>
package/admin/tab_m.html CHANGED
@@ -680,7 +680,7 @@
680
680
  </p></div>
681
681
  <ul id="nav-mobile" class="right">
682
682
  <li>
683
- <a id="adapterStopped_btn" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT hide" title="Adapter not running">
683
+ <a id="adapterStopped_btn" class="btn-floating waves-effect waves-light red icon-black tooltipped center-align hoverable translateT hide" title="Adapter not running">
684
684
  <i class="material-icons large">grid_off</i></a>
685
685
  </li>
686
686
  <li>
@@ -697,6 +697,16 @@
697
697
  <a id="show_errors_btn" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT hide" title="Show Errors">
698
698
  <i class="material-icons large">feedback</i></a>
699
699
  </li>
700
+ <li>
701
+ <a id="map_errors_btn" class="btn-floating waves-effect waves-light orange tooltipped center-align hoverable translateT hide" title="Show errors from map generation">
702
+ <i class="material-icons large">filter_none</i></a>
703
+ </li>
704
+ <li>
705
+ <li>
706
+ <a id="map_generating_btn" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT hide" title="Map generation in progress">
707
+ <i class="material-icons large">filter_none</i></a>
708
+ </li>
709
+ <li>
700
710
  <li>
701
711
  <a id="fw_check_btn" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT hide" title="Check firmware updates">
702
712
  <i class="material-icons large">system_update</i></a>
@@ -761,6 +771,8 @@
761
771
  <!--<li class="device-order-item" data-type="kind" tabindex="0"><a class="translate" data-lang="Kind">Kind</a></li>-->
762
772
  <!--<li class="device-order-item" data-type="status" tabindex="0"><a class="translate" data-lang="Status">Status</a></li>-->
763
773
  <li class="device-order-item" data-type="default" tabindex="0"><a class="translate" data-lang="Default">Default</a></li>
774
+ <li class="device-order-item" data-type="range" tabindex="0"><a class="translate" data-lang="Range">Range</a></li>
775
+ <li class="device-order-item" data-type="load" tabindex="0"><a class="translate" data-lang="Load">Load</a></li>
764
776
  </ul>
765
777
  </div>
766
778
  </li>
@@ -1218,7 +1230,7 @@
1218
1230
  </label>
1219
1231
  </div>
1220
1232
  <div class="input-field col s12 admin-tooltip-icon translateT" title="Regenerate Map">
1221
- <br><button id="regenerate" class="waves-effect center hoverable blue"><i class="material-icons medium border:0 icon-Black">map</i></button>
1233
+ <br><button id="regenerate" class="waves-effect center hoverable blue"><i class="material-icons medium border:0 icon-black">map</i></button>
1222
1234
  </div>
1223
1235
  </div>
1224
1236
  <div class="input-field input-group col s12 m6 l6">
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zigbee",
4
- "version": "3.2.5",
4
+ "version": "3.3.1-alpha.0",
5
5
  "news": {
6
+ "3.3.1-alpha.0": {
7
+ "en": "\n",
8
+ "de": "\n",
9
+ "ru": "\n",
10
+ "pt": "\n",
11
+ "nl": "\n",
12
+ "fr": "\n",
13
+ "it": "\n",
14
+ "es": "\n",
15
+ "pl": "\n",
16
+ "uk": "\n",
17
+ "zh-cn": "\n"
18
+ },
19
+ "3.3.0": {
20
+ "en": "Fix: dynamic model assignment when exposes is function (PTVO, BuschJaeger)\nFix: Roles\nRefactor: Legacy code moved\nRefactor: Expose creation changed.\nRefactor: Exposes no longer use states from legacy code\nFeature: Offer state rebuild function in Settings\n: Additional filters for device display\nFix: Orphaned group states detected, marked and deletable\nUpdate: ZH 7.x\nUpdate: ZHC 25.84.0",
21
+ "de": "Fix: Dynamische Modellzuweisung bei Belichtungen ist Funktion (PTVO, BuschJaeger)\nFix: Roles\nRefactor: Legacy-Code bewegt\nHersteller: Expose Kreation geändert.\nRefactor: Exposes verwendet nicht mehr Staaten von Legacy-Code\nFeature: Offer state rebuild Funktion in Einstellungen\n: Zusätzliche Filter für Geräteanzeige\nFix: Verwaiste Gruppenzustände erkannt, markiert und verblendet\nAktualisierung: ZH 7.x\nAktualisierung: ZHC 25.84.0",
22
+ "ru": "Исправление: назначение динамической модели при раскрытии функции (PTVO, BuschJaeger)\nИсполнитель: Roles\nРефактор: код Legacy перемещен\nРефактор: Создание экспозиции изменилось.\nRefactor: EXPOES больше не используют устаревший код\nФункция: Предложите функцию восстановления состояния в настройках\nДополнительные фильтры для отображения устройства\nИсправление: обнаруженные, помеченные и удаляемые состояния орфанной группы\nОбновление: ZH 7.x\nОбновление: ZHC 25.84.0",
23
+ "pt": "Corrigir: atribuição dinâmica do modelo quando expõe é função (PTVO, BuschJaeger)\nCorrigir: Funções\nRefactor: Código de legado movido\nRefactor: Expor a criação mudou.\nRefator: Expos não usam mais estados do código legado\nCaracterística: Ofereça a função de reconstrução do estado em Configurações\n: Filtros adicionais para exibição do dispositivo\nCorrigir: estados de grupo órfão detectados, marcados e deletáveis\nActualização: ZH 7.x\nAtualização: ZHC 25.84.0",
24
+ "nl": "Fix: dynamische modeltoewijzing wanneer blootgesteld is functie (PTVO, BuschJaeger)\nFix: rollen\nRefactor: Legacy code verplaatst\nRefactor: Aanmaak gewijzigd tonen.\nRefactor: Exposes gebruikt geen staten meer van legacy code\nFunctie: Aanbieden status wederopbouw functie in Instellingen\n: Extra filters voor apparaatweergave\nFix: weesgroep staten gedetecteerd, gemarkeerd en deletable\nUpdate: ZH 7.x\nUpdate: ZHC 25.84.0",
25
+ "fr": "Correction : attribution de modèle dynamique lorsque l'exposition est fonction (PTVO, BuschJaeger)\nCorrection : Rôles\nRefactor: Legacy code déplacé\nRefacteur: La création d'exposition a changé.\nRefactor: Les expositions n'utilisent plus les états à partir du code ancien\nCaractéristique: Offre la fonction de reconstruction de l'état dans les paramètres\n: Filtres supplémentaires pour l'affichage des appareils\nCorrection : États de groupe orphelins détectés, marqués et délaissables\nMise à jour : ZH 7.x\nMise à jour: ZHC 25.84.0",
26
+ "it": "Fisso: l'assegnazione dinamica del modello quando espone è funzione (PTVO, BuschJaeger)\nFisso: Roles\nRefactor: Legacy code move\nRefactor: La creazione dell'esposizione è cambiata.\nRefactor: Exposes not use stati from legacy code\nCaratteristica: Offrire la funzione di ricostruzione dello stato in Impostazioni\n: Filtri aggiuntivi per display del dispositivo\nFisso: Stati del gruppo orfano rilevati, contrassegnati e cancellabili\nAggiornamento: ZH 7.x\nAggiornamento: ZHC 25.84.0",
27
+ "es": "Fijación: asignación de modelos dinámicos cuando se expone es función (PTVO, BuschJaeger)\nCorrección: Papeles\nRefactor: Se movió el código de Legacy\nRefactor: La creación de la exposición cambió.\nRefactor: Los Exposes ya no utilizan estados del código hereditario\nCaracterística: Oferta función de reconstrucción estatal en Ajustes\n: Filtros adicionales para la pantalla del dispositivo\nFijación: Estados del grupo huérfano detectados, marcados y eliminables\nActualización: ZH 7.x\nActualización: ZHC 25.84.0",
28
+ "pl": "Fix: przypisanie modelu dynamicznego, gdy funkcja eksponuje (PTVO, BuschJaeger)\nFix: Roles\nWspółczynnik: Przesunięty kod legacy\nWspółczynnik: Odkryj, że kreacja się zmieniła.\nRefaktor: Ekspozycje nie wykorzystują już stanów z dotychczasowego kodu\nCecha: Oferta funkcji odbudowy państwa w ustawieniach\n: Dodatkowe filtry do wyświetlania urządzeń\nFix: Osierocone państwa grupowe wykryte, oznaczone i usunięte\nAktualizacja: ZH 7.x\nAktualizacja: ZHC 25.84.0",
29
+ "uk": "Виправлення: динамічне завдання моделі при налаштуванні функції (PTVO, BuschJaeger)\nФіксація: Ролі\nРефактор: код Legacy переїхав\nРефактор: Змінено виставку.\nРефактор: Виставки більше не використовують стани з коду спадкування\nХарактеристика: Пропозиція функції державного відновлення в налаштуваннях\n: Додаткові фільтри для відображення пристрою\nВиправлення: Виявлені орфагенти групи, позначені та видалені\nОновлення: ZH 7.x\nОновлення: ZHC 25.84.0",
30
+ "zh-cn": "Fix: 曝光时的动态模型任务为函数( PTVO, Busch Jaeger)\n修补:角色\n内容: 遗留代码已移动\n重构 : 展览的创作改变了.\n内容: 展览不再使用遗留代码中的状态\n特性: 在设置中提供状态重建功能\n: 设备显示的额外过滤器\n修复:发现、标记和删除孤儿群体状态\n最新情况:ZH 7.x\n最新情况:ZHC 25.84.0"
31
+ },
6
32
  "3.2.5": {
7
33
  "en": "changed setState for lasterror",
8
34
  "de": "geändert setState für lasterror",
@@ -67,32 +93,6 @@
67
93
  "pl": "fix bug # 2640\n",
68
94
  "uk": "виправлення помилки #2640\n",
69
95
  "zh-cn": "修复错误 # 2640\n"
70
- },
71
- "3.2.0": {
72
- "en": "remove local overrides tab from config\nestablish local data tab in config to edit global and device level settings and options\nremove the local overrides tab\nremove the ability to set model level overrides from device tab.\nfix errors for 'polling' devices with changed poll times.\nwarning icon for devices which are not completely interviewed.\nimproved router detection for opening the network\nbugfix: open network on router\nZHC 25.x latest, ZH 6.1.3,\nrestore from in-adapter backup",
73
- "de": "entfernen sie lokale overrides tab von config\nlokale daten tab erstellen, um globale und geräteebene einstellungen und optionen zu bearbeiten\nentfernen der lokalen overrides tab\nentfernen sie die fähigkeit, modellebene überschrieben von der geräte-tab.\nfehler für \"polling\"-geräte mit veränderten abfragezeiten beheben.\nwarnsymbol für geräte, die nicht vollständig interviewt werden.\nverbesserte routererkennung zum öffnen des netzwerks\nbugfix: offenes netzwerk auf router\nZHC 25.x neueste, ZH 6.1.3,\nwiederherstellung von in-adapter-backup",
74
- "ru": "удалить локальную вкладку overrided из конфигураций\nустановить локальную вкладку данных в конфигурацию для редактирования глобальных настроек и параметров уровня устройства\nудалить вкладку local overrides\nудалить возможность установки переопределений уровня модели из вкладки устройства.\nисправление ошибок для «опросных» устройств с измененным временем опроса.\nиконка предупреждения для устройств, которые не были полностью опрошены.\nулучшенное обнаружение маршрутизатора для открытия сети\nbugfix: открытая сеть на маршрутизаторе\nZHC 25.x, ZH 6.1.3,\nвосстановление из in-adapter backup",
75
- "pt": "remover a página de substituições locais da configuração\nestabelecer a página de dados locais na configuração para editar as configurações e opções globais e de nível do dispositivo\nremover a página de sobreposições locais\nremover a capacidade de definir os comandos de nível do modelo da aba do dispositivo.\ncorrigir erros para dispositivos de 'polling' com tempos de votação alterados.\nícone de aviso para dispositivos que não são completamente entrevistados.\ndetecção de roteador melhorada para abrir a rede\ncorreção de erros: abrir rede no roteador\nZHC 25.x mais recente, ZH 6.1.3,\nrestaurar a partir de backup no adaptador",
76
- "nl": "tabblad overrides verwijderen uit config\nlokale datatabblad instellen in config om instellingen en opties voor het niveau van het apparaat en de globale instellingen te bewerken\nhet tabblad lokale overrides verwijderen\nverwijder de mogelijkheid om modelniveau overrides van apparaat tab.\nfouten te herstellen voor 'polling' apparaten met veranderde polltijden.\nwaarschuwingspictogram voor apparaten die niet volledig zijn geïnterviewd.\nverbeterde routerdetectie voor het openen van het netwerk\nbugfix: open netwerk op router\nZHC 25.x laatste, ZH 6.1.3,\nherstellen van in-adapter back-up",
77
- "fr": "supprimer l'onglet local de la configuration\ncréer un onglet local de données dans la configuration pour modifier les paramètres et les options de niveau global et périphérique\nsupprimer l'onglet local de remplacement\nsupprimer la possibilité de définir les dépassements de niveau du modèle de l'onglet périphérique.\ncorriger les erreurs pour les dispositifs 'polling' avec des temps de sondage modifiés.\nicône d'avertissement pour les appareils qui ne sont pas complètement interviewés.\namélioration de la détection du routeur pour l'ouverture du réseau\nbugfix: ouvrir le réseau sur le routeur\nZHC 25.x dernier, ZH 6.1.3,\nrestaurer à partir de la sauvegarde dans l'adaptateur",
78
- "it": "rimuovere la scheda override locale da config\nstabilire la scheda dati locale in configurazione per modificare le impostazioni e le opzioni del livello globale e del dispositivo\nrimuovere la scheda override locale\nrimuovere la capacità di impostare override di livello del modello dalla scheda del dispositivo.\ncorreggere gli errori per i dispositivi 'polling' con tempi di sondaggio modificati.\nicona di avviso per dispositivi che non sono completamente intervistati.\nmiglioramento del rilevamento del router per l'apertura della rete\nbugfix: aprire la rete sul router\nZHC 25.x ultimo, ZH 6.1.3,\nripristino da backup in-adapter",
79
- "es": "eliminar la pestaña de anulaciones locales de config\nestablecer la ficha de datos local en config para editar ajustes y opciones a nivel global y de dispositivos\neliminar la ficha de anulación local\neliminar la capacidad de establecer el nivel de modelo anula de la pestaña dispositivo.\ncorrige errores para dispositivos 'polling' con tiempos de votación cambiados.\nicono de advertencia para dispositivos que no son entrevistados por completo.\nmejor detección de router para abrir la red\nbugfix: red abierta en router\nZHC 25.x más reciente, ZH 6.1.3,\nrestaurar de la copia de seguridad en el equipo",
80
- "pl": "usuń lokalne nadjazdy z zakładki config\ntworzy lokalną kartę danych w konfigu, aby edytować globalne i na poziomie urządzenia ustawienia i opcje\nusuń kartę lokalnych nadwozi\nusuń możliwość ustawiania nadwyżek poziomu modelu z zakładki urządzenia.\nnaprawić błędy urządzeń 'sondażowych' ze zmienionymi okresami ankiety.\nikona ostrzegawcza dla urządzeń, które nie są w pełni przesłuchane.\nulepszone wykrywanie routerów w celu otwarcia sieci\nbugfix: otwarta sieć na routerze\nZHC 25.x najnowszy, ZH 6.1.3,\nprzywracanie z kopii zapasowej in- adaptera",
81
- "uk": "видалити локальну вкладку overrides з налаштування\nвстановити локальну вкладку даних в конфігурацію для редагування параметрів рівня глобального та пристрою та параметрів\nвидалити локальну вкладку\nприбрати можливість встановити рівень моделі перенаряддя з вкладки пристрою.\nфіксувати помилки для пристроїв «запилення» з змінними термінами опитування.\nзначок попередження для пристроїв, які не повністю опитуються.\nполіпшення виявлення маршрутизатора для відкриття мережі\nвиправлення помилок: відкрита мережа на маршрутизаторі\nZHC 25.x останнє, ZH 6.1.3,\nвідновлення з резервної копії",
82
- "zh-cn": "从配置中删除本地覆盖标签\n在配置中建立本地数据标签以编辑全局和设备级别设置和选项\n删除本地覆盖标签\n从设备标签中删除设置模型级别覆盖的能力 .\n修正“ 投票” 设备的错误, 并更改投票时间 .\n警告未完全访问设备的图标.\n为打开网络改进路由器检测\n错误修正: 在路由器上打开网络\nZHC 25.x最新版,ZH 6.1.3,\n从适应中备份恢复"
83
- },
84
- "3.1.6": {
85
- "en": "Bugfixes\n",
86
- "de": "Bugfixes\n",
87
- "ru": "Багфиксы\n",
88
- "pt": "Correcções de Erros\n",
89
- "nl": "Bugfixes\n",
90
- "fr": "Fixes de bogue\n",
91
- "it": "Bugfix\n",
92
- "es": "Bugfixes\n",
93
- "pl": "Korekty błędów\n",
94
- "uk": "Помилки\n",
95
- "zh-cn": "错误修正\n"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -159,7 +159,7 @@
159
159
  "tab": "materialize"
160
160
  },
161
161
  "messagebox": true,
162
- "stopTimeout": 5000,
162
+ "stopTimeout": 30000,
163
163
  "stopBeforeUpdate": true,
164
164
  "dataFolder": "zigbee_%INSTANCE%",
165
165
  "compact": true,
@@ -369,7 +369,7 @@
369
369
  "_id": "info.lasterror",
370
370
  "type": "state",
371
371
  "common": {
372
- "role": "indicator",
372
+ "role": "state",
373
373
  "name": "Last stashed error",
374
374
  "type": "string",
375
375
  "read": true,
@@ -382,7 +382,7 @@
382
382
  "_id": "info.pairingCountdown",
383
383
  "type": "state",
384
384
  "common": {
385
- "role": "indicator",
385
+ "role": "value",
386
386
  "name": "Pairing countdown",
387
387
  "type": "number",
388
388
  "read": true,
@@ -395,7 +395,7 @@
395
395
  "_id": "info.pairingMessage",
396
396
  "type": "state",
397
397
  "common": {
398
- "role": "indicator",
398
+ "role": "state",
399
399
  "name": "Pairing message",
400
400
  "type": "string",
401
401
  "read": true,
package/lib/commands.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { getZbId, getNetAddress, reverseByteString, zbIdorIeeetoAdId, adIdtoZbIdorIeee } = require('./utils');
4
4
  const fs = require('fs');
5
- const statesMapping = require('./devices');
5
+ const modelDefinitions = require('./models.js');
6
6
  const colors = require('./colors.js');
7
7
  /* currently not needed, kept for referencce
8
8
  const utils = require('@iobroker/adapter-core'); // Get common adapter utils
@@ -21,6 +21,7 @@ class Commands {
21
21
  constructor(adapter) {
22
22
  this.adapter = adapter;
23
23
  this.adapter.on('message', obj => this.onMessage(obj));
24
+ this.devicesDeleting = new Set();
24
25
  }
25
26
 
26
27
  start(zbController, stController) {
@@ -97,9 +98,12 @@ class Commands {
97
98
  this.getCoordinatorInfo(obj.from, obj.command, obj.callback);
98
99
  }
99
100
  break;
100
- case 'cleanDeviceStates':
101
+ case 'modifyDeviceStates':
101
102
  if (obj.message && typeof obj.message === 'object') {
102
- this.cleanDeviceStates(obj.from, obj.command, obj.message, obj.callback);
103
+ if (obj.message.action == 'clean')
104
+ return this.cleanDeviceStates(obj.from, obj.command, obj.message.force, obj.callback);
105
+ if (obj.message.action == 'rebuild')
106
+ return this.rebuildDeviceStates(obj.from, obj.command, obj.message.force, obj.callback);
103
107
  }
104
108
  break;
105
109
  case 'setState':
@@ -299,6 +303,9 @@ class Commands {
299
303
 
300
304
  if (await this.zbController.permitJoin(cTimer, devId)) {
301
305
  this.adapter.setState('info.pairingMode', cTimer > 0, true);
306
+ if (cTimer != 0 && this.stController) {
307
+ this.stController.resetKnownUnknownModels();
308
+ }
302
309
  //this.adapter.sendTo(from, command, cTimer ? 'Start pairing!':'Stop pairing!', callback);
303
310
  }
304
311
  else {
@@ -375,7 +382,7 @@ class Commands {
375
382
  }
376
383
  }
377
384
 
378
- async fillInfo(device, device_stateDefs, all_states, models) {
385
+ async fillInfo(device, entity, device_stateDefs, all_states, models) {
379
386
  device.statesDef = (device_stateDefs || []).filter(stateDef => {
380
387
  const sid = stateDef._id.replace(this.adapter.namespace + '.', '');
381
388
  const names = sid.split('.');
@@ -398,8 +405,6 @@ class Commands {
398
405
  };
399
406
  });
400
407
 
401
- const id = getZbId(device._id);
402
- const entity = await this.zbController.resolveEntity(id)
403
408
 
404
409
  device.info = this.buildDeviceInfo(entity);
405
410
 
@@ -413,7 +418,7 @@ class Commands {
413
418
  availableOptions : [...device.info?.mapped?.options || [], ...['use_legacy_model']],
414
419
  setOptions: this.adapter.stController.localConfig.getByModel(device.info?.mapped?.model || 'unknown') || [],
415
420
  devices: [device],
416
- }
421
+ };
417
422
  if (!models.byUID[UID].model.type)
418
423
  models.byUID[UID].model.type = 'Group';
419
424
  models.UIDbyModel[device.info?.mapped?.model || 'unknown'] = UID;
@@ -433,7 +438,7 @@ class Commands {
433
438
  }
434
439
  }
435
440
 
436
- buildDeviceInfo(device) {
441
+ buildDeviceInfo(entity) {
437
442
  function getKey(object, value) {
438
443
  try {
439
444
  for (const key of Object.keys(object)) {
@@ -459,34 +464,34 @@ class Commands {
459
464
  const rv = {};
460
465
  try {
461
466
  rv.device = {
462
- modelZigbee:device.device.modelID,
463
- type:device.device.type,
464
- ieee:device.device.ieeeAddr || device.device.groupID,
465
- nwk:device.device.networkAddress || 0,
466
- manuf_id:device.device.maufacturerID,
467
- manuf_name:device.device.manufacturerName,
468
- manufacturer:device.mapped?.vendor,
469
- power:device.device.powerSource,
470
- app_version:device.device.applicationVersion,
471
- hard_version:device.device.hardwareVersion,
472
- zcl_version:device.device.zclVersion,
473
- stack_version:device.device.stack_version,
474
- date_code:device.device.dateCode,
475
- build:device.device.softwareBuildID,
476
- interviewstate:device.device.interviewState || 'UNKNOWN',
467
+ modelZigbee:entity.device.modelID,
468
+ type:entity.device.type,
469
+ ieee:entity.device.ieeeAddr || entity.device.groupID,
470
+ nwk:entity.device.networkAddress || 0,
471
+ manuf_id:entity.device.maufacturerID,
472
+ manuf_name:entity.device.manufacturerName,
473
+ manufacturer:entity.mapped?.vendor,
474
+ power:entity.device.powerSource,
475
+ app_version:entity.device.applicationVersion,
476
+ hard_version:entity.device.hardwareVersion,
477
+ zcl_version:entity.device.zclVersion,
478
+ stack_version:entity.device.stack_version,
479
+ date_code:entity.device.dateCode,
480
+ build:entity.device.softwareBuildID,
481
+ interviewstate:entity.device.interviewState || 'UNKNOWN',
477
482
  BindSource: false,
478
483
  isGroupable: false,
479
484
  }
480
485
  rv.endpoints = [];
481
486
  let dBindSource = false;
482
487
  let disGroupable = false;
483
- for (const ep_idx in device.endpoints) {
484
- const ep = device.endpoints[ep_idx];
488
+ for (const ep_idx in entity.endpoints) {
489
+ const ep = entity.endpoints[ep_idx];
485
490
  const bindable = haveBindableClusters(ep.outputClusters);
486
491
  dBindSource |= bindable;
487
492
  rv.endpoints.push({
488
493
  ID:ep.ID,
489
- epName: device.mapped?.endpoint ? getKey(device.mapped?.endpoint(device), ep.ID) : ep.ID,
494
+ epName: entity.mapped?.endpoint ? getKey(entity.mapped?.endpoint(entity.device), ep.ID) : ep.ID,
490
495
  profile:ep.profileID,
491
496
  input_clusters:ep.inputClusters,
492
497
  output_clusters:ep.outputClusters,
@@ -496,23 +501,23 @@ class Commands {
496
501
  }
497
502
  rv.device.isGroupable = Boolean(disGroupable);
498
503
  rv.device.BindSource = Boolean(dBindSource);
499
- if (device.mapped) {
504
+ if (entity.mapped) {
500
505
  rv.mapped = {
501
- model:device.mapped.model,
502
- type:device.device.type,
503
- description:device.mapped.description,
504
- hasLegacyDef:statesMapping.hasLegacyDevice(device.mapped.model),
506
+ model:entity.mapped.model,
507
+ type:entity.device.type,
508
+ description:entity.mapped.description,
509
+ hasLegacyDef:modelDefinitions.hasLegacyDevice(entity.mapped.model),
505
510
  //fingerprint:JSON.stringify(device.mapped.fingerprint),
506
- vendor:device.mapped.vendor,
507
- hasOnEvent:device.mapped.onEvent != undefined,
508
- hasConfigure:device.mapped.configure != undefined,
509
- icon:`img/${device.mapped.model.replace(/\//g, '-')}.png`,
510
- legacyIcon: statesMapping.getIconforLegacyModel(device.mapped.model),
511
+ vendor:entity.mapped.vendor,
512
+ hasOnEvent:entity.mapped.onEvent != undefined,
513
+ hasConfigure:entity.mapped.configure != undefined,
514
+ icon:`img/${entity.mapped.model.replace(/\//g, '-')}.png`,
515
+ legacyIcon: modelDefinitions.getIconforLegacyModel(entity.mapped.model),
511
516
  options:[],
512
517
  }
513
- if (device.mapped.options && typeof (device.mapped.options == 'object')) {
514
- rv.mapped.optionExposes = device.mapped.options;
515
- for (const option of device.mapped.options) {
518
+ if (entity.mapped.options && typeof (entity.mapped.options == 'object')) {
519
+ rv.mapped.optionExposes = entity.mapped.options;
520
+ for (const option of entity.mapped.options) {
516
521
  if (option.name) {
517
522
  rv.mapped.options.push(option.name);
518
523
  }
@@ -521,9 +526,9 @@ class Commands {
521
526
  }
522
527
  else {
523
528
  rv.mapped = {
524
- model:device.name,
525
- type: device.device.type,
526
- description:device.name,
529
+ model:entity.name,
530
+ type: entity.device.type,
531
+ description:entity.name,
527
532
  vendor:'not set',
528
533
  hasOnEvent: false,
529
534
  hasConfigure: false,
@@ -532,34 +537,34 @@ class Commands {
532
537
  }
533
538
  }
534
539
  catch (error) {
535
- if (device && device.name === 'Coordinator') return rv;
536
- const dev = device ? device.device || {} : {}
537
- const msg = device ? `device ${device.name} (${dev.ieeeAddr}, NWK ${dev.networkAddres}, ID: ${dev.ID})` : 'undefined device';
540
+ if (entity && entity.name === 'Coordinator') return rv;
541
+ const dev = entity ? entity.device || {} : {}
542
+ const msg = entity ? `device ${entity.name} (${dev.ieeeAddr}, NWK ${dev.networkAddres}, ID: ${dev.ID})` : 'undefined device';
538
543
  this.warn(`Error ${error && error.message ? error.message + ' ' : ''}building device info for ${msg}`);
539
544
  }
540
545
  return rv;
541
546
  }
542
547
 
543
548
  async appendDevicesWithoutObjects(devices, client) {
544
- const device = await this.zbController.resolveEntity(client.ieeeAddr);
545
- if (!device || !device.device) {
549
+ const entity = await this.zbController.resolveEntity(client.ieeeAddr);
550
+ if (!entity || !entity.device) {
546
551
  return;
547
552
  }
548
- const exists = devices.find((dev) => (dev._id && device.device.ieeeAddr === getZbId(dev._id)));
553
+ const exists = devices.find((dev) => (dev._id && entity.device.ieeeAddr === getZbId(dev._id)));
549
554
  if (!exists) {
550
555
  const coordinatorData = {
551
- _id : `${this.adapter.namespace}.${device.device.ieeeAddr.substring(2)}`,
556
+ _id : `${this.adapter.namespace}.${entity.device.ieeeAddr.substring(2)}`,
552
557
  paired: true,
553
- info: this.buildDeviceInfo(device),
554
- native: { id: device.device.ieeeAddr.substring(2) },
558
+ info: this.buildDeviceInfo(entity),
559
+ native: { id: entity.device.ieeeAddr.substring(2) },
555
560
  mapped : { model: client.modelID || client.type || 'NotSet' },
556
561
  statesDev: [],
557
562
  }
558
- if (device.name === 'Coordinator') {
563
+ if (entity.name === 'Coordinator') {
559
564
  coordinatorData.icon = 'zigbee.png';
560
565
  coordinatorData.common = { name: 'Coordinator', type: 'Coordinator' };
561
566
  } else {
562
- coordinatorData.common = { name: device.mapped?.model || 'unknown', type: device.type };
567
+ coordinatorData.common = { name: entity.mapped?.model || 'unknown', type: entity.type };
563
568
  coordinatorData.icon= 'img/unknown.png';
564
569
  }
565
570
  devices.push(coordinatorData);
@@ -576,27 +581,30 @@ class Commands {
576
581
  const deviceObjects = (id ? [await this.adapter.getObjectAsync(id)] : await this.adapter.getDevicesAsync());
577
582
  const all_states = id ? await this.adapter.getStatesAsync(id + '.*') : await this.adapter.getStatesAsync('*');
578
583
  const all_stateDefs = id ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
584
+
579
585
  const illegalDevices = [];
580
586
  const groups = {};
581
587
  const PromiseChain = [];
582
588
  const models = { byUID : {}, UIDbyModel: {} };
583
- for (const devInfo of deviceObjects) {
584
- if (devInfo._id.indexOf('group') > -1) {
585
- PromiseChain.push(this.handleGroupforInfo(devInfo, groups));
589
+ for (const deviceObject of deviceObjects) {
590
+ const id = getZbId(deviceObject._id);
591
+ const entity = await this.zbController.resolveEntity(id);
592
+ if (deviceObject._id.indexOf('group') > -1) {
593
+ PromiseChain.push(this.handleGroupforInfo(deviceObject, groups));
586
594
  }
587
595
  else {
588
- const modelDesc = statesMapping.findModel(devInfo.common.type);
589
- devInfo.icon = (modelDesc && modelDesc.icon) ? modelDesc.icon : 'img/unknown.png';
590
- devInfo.vendor = modelDesc ? modelDesc.vendor : '';
591
- devInfo.legacyIcon = statesMapping.getIconforLegacyModel(devInfo.common.type);
592
- const lq_state = all_states[`${devInfo._id}.link_quality`];
593
- devInfo.link_quality = lq_state ? lq_state.val : -1;
594
- devInfo.link_quality_lc = lq_state ? lq_state.lc : undefined;
595
- const battery_state = all_states[`${devInfo._id}.battery`];
596
- devInfo.battery = battery_state ? battery_state.val : undefined;
596
+ const modelDesc = await modelDefinitions.findModel(deviceObject.common.type, entity?.device, deviceObject.common.UUID, entity?.mapped?.legacy);
597
+ deviceObject.icon = (modelDesc?.icon) ? modelDesc.icon : 'img/unknown.png';
598
+ if (modelDesc?.vendor) deviceObject.vendor = modelDesc.vendor;
599
+ deviceObject.legacyIcon = modelDefinitions.getIconforLegacyModel(deviceObject.common.type);
600
+ const lq_state = all_states[`${deviceObject._id}.link_quality`];
601
+ deviceObject.link_quality = lq_state ? lq_state.val : -1;
602
+ deviceObject.link_quality_lc = lq_state ? lq_state.lc : undefined;
603
+ const battery_state = all_states[`${deviceObject._id}.battery`];
604
+ deviceObject.battery = battery_state ? battery_state.val : undefined;
597
605
 
598
606
  }
599
- devInfo.rooms = [];
607
+ deviceObject.rooms = [];
600
608
  const rooms = roomsEnum['enum.rooms'] || {};
601
609
  for (const room of Object.keys(rooms)) {
602
610
  if (!rooms.hasOwnProperty(room) ||
@@ -606,11 +614,11 @@ class Commands {
606
614
  ) {
607
615
  continue;
608
616
  }
609
- if (rooms[room].common.members.includes(devInfo._id)) {
610
- devInfo.rooms.push(rooms[room].common.name);
617
+ if (rooms[room].common.members.includes(deviceObject._id)) {
618
+ deviceObject.rooms.push(rooms[room].common.name);
611
619
  }
612
620
  }
613
- PromiseChain.push(this.fillInfo(devInfo, all_stateDefs.filter(item => item._id.startsWith(devInfo._id)),all_states, models));
621
+ PromiseChain.push(this.fillInfo(deviceObject, entity, all_stateDefs.filter(item => item._id.startsWith(deviceObject._id)),all_states, models));
614
622
  }
615
623
  if (!id) {
616
624
  for (const client of this.zbController.getClientIterator(true)) {
@@ -756,6 +764,28 @@ class Commands {
756
764
  return;
757
765
  }
758
766
  this.info(`${force ? 'Force removing' : 'Gracefully removing '} device ${devId} from the network.`);
767
+ /*
768
+
769
+ // if with force, remove device and object in parallel;
770
+ const PromiseArr = [ this.zbController.remove(sysid, force) ]
771
+ if (force) PromiseArr.push( this.stController.deleteObj(devId));
772
+
773
+ const results = await Promise.all(PromiseArr);
774
+ const msgs = [];
775
+ for (const result of results) {
776
+ if (!result.status) msgs.push(result.message ? result.message : 'failed without message');
777
+ }
778
+ if (msgs.length == 0 && !force) {
779
+ const result = await this.stController.deleteObj(devId);
780
+ if (!result.status) msgs.push(result.message ? result.message : 'failed without message');
781
+ }
782
+
783
+ const removeResult = this.zbController.remove(sysid, force);
784
+ if (removeResult.status || force) {
785
+ this.info('Device removed from the network, deleting objects.')
786
+
787
+ }
788
+ */
759
789
  this.zbController.remove(sysid, force, async (err) => {
760
790
  if (!err) {
761
791
  this.info('Device removed from the network, deleting objects.')
@@ -780,9 +810,10 @@ class Commands {
780
810
  }
781
811
  }
782
812
 
783
- async cleanDeviceStates(from, command, msg, callback) {
784
- this.info(`State cleanup with ${JSON.stringify(msg)}`);
785
- const devicesFromDB = await this.zbController.getClients(false);
813
+ async cleanDeviceStates(from, command, force, callback) {
814
+ this.info(`State cleanup ${force ? 'including' : 'omitting'} states with custom configuration`);
815
+ const devicesFromDB = await this.zbController.getClientIterator(false);
816
+ const groupsFromDb = await this.zbController.getGroups();
786
817
  const messages = [];
787
818
  this.stController.CleanupRequired(false);
788
819
 
@@ -791,14 +822,26 @@ class Commands {
791
822
 
792
823
  if (entity) {
793
824
  const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID;
794
- this.stController.deleteOrphanedDeviceStates(device.ieeeAddr, model, msg.force, (msg)=> { messages.push(msg)});
825
+ this.stController.deleteOrphanedDeviceStates(device.ieeeAddr, model, force, (msg)=> { messages.push(msg)});
826
+ }
827
+ }
828
+ try {
829
+ for (const group of groupsFromDb) {
830
+ this.stController.deleteOrphanedDeviceStates(group.id, 'group', force, (msg)=> { messages.push(msg)});
795
831
  }
796
832
  }
797
- // rebuild retainDeviceNamesDB
798
- //this.stController.rebuildRetainDeviceNames();
833
+ catch (error) {
834
+ this.error(`error checking groups for deletable states: ${error?.message}`);
835
+ }
799
836
  this.adapter.sendTo(from, command, {stateList: messages}, callback);
800
837
  }
801
838
 
839
+ async rebuildDeviceStates(from, command, force, callback) {
840
+ this.info(`State cleanup ${force ? 'with' : 'without'} overriding changed roles`);
841
+ await this.adapter.syncAllDeviceStates(force);
842
+ this.adapter.sendTo(from, command, {}, callback);
843
+ }
844
+
802
845
  async getChannels(from, command, message, callback) {
803
846
  if (this.zbController && this.zbController.herdsmanStarted) {
804
847
  const result = await this.zbController.getChannelsEnergy();
@@ -818,6 +861,7 @@ class Commands {
818
861
  const id = msg.id;
819
862
  const targetstate = msg.deactivated;
820
863
  this.stController.setDeviceActivated(id, targetstate);
864
+ this.zbController.setDeviceEnable(id, targetstate);
821
865
  this.adapter.sendTo(from, command, {}, callback);
822
866
  }
823
867
  }
@@ -901,7 +945,7 @@ class Commands {
901
945
  [{'device': entity.device, 'type': 'deviceOptionsChanged', from: entity.options, to:newOptions || {}, }, entity.mapped]);
902
946
  }
903
947
  }
904
- this.warn(`enumerating data: ${JSON.stringify(prop)}`);
948
+ this.debug(`enumerating data: ${JSON.stringify(prop)}`);
905
949
  let val = msg.data[prop];
906
950
  if (typeof val === 'string') {
907
951
  val = val.trim();
package/lib/exclude.js CHANGED
@@ -1,5 +1,5 @@
1
1
  'use strict';
2
- const devicedefinitions = require('./devices');
2
+ //const modelDefinitions = require('./models');
3
3
  const utils = require('./utils');
4
4
 
5
5
  class Exclude {