iobroker.zigbee 1.8.7 → 1.8.10
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.
- package/LICENSE +1 -1
- package/README.md +21 -3
- package/admin/admin.js +26 -6
- package/admin/index_m.html +25 -0
- package/admin/tab_m.html +25 -2
- package/admin/words.js +1 -1
- package/docs/de/basedocu.md +19 -0
- package/io-package.json +22 -31
- package/lib/binding.js +0 -1
- package/lib/commands.js +30 -6
- package/lib/groups.js +5 -0
- package/lib/utils.js +6 -0
- package/lib/zigbeecontroller.js +44 -11
- package/main.js +69 -4
- package/package.json +5 -5
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The MIT License (MIT)
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2018-
|
|
3
|
+
Copyright (c) 2018-2023 Kirov Ilya <kirovilya@gmail.com>
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
package/README.md
CHANGED
|
@@ -133,6 +133,24 @@ You can thank the authors by these links:
|
|
|
133
133
|
|
|
134
134
|
|
|
135
135
|
## Changelog
|
|
136
|
+
### 1.8.10 (2023-01-04) (2022-12-12)
|
|
137
|
+
* (asgothian) fix group access
|
|
138
|
+
* (asgothian) add option for pairing code:
|
|
139
|
+
A new icon allows to open the networ after first entering a pairing code
|
|
140
|
+
listed on the device
|
|
141
|
+
* (asgothian) easier use of external converters
|
|
142
|
+
- external converters can now be placed in the zigbee adapter data folder
|
|
143
|
+
- no absolite path is required to access them
|
|
144
|
+
- external converters posted on the github for zigbee-herdsman-converters
|
|
145
|
+
should work as they are - folders for libraries are rewritten to match
|
|
146
|
+
the expected location when 'required' from within the zigbee adapter
|
|
147
|
+
- Log entries will identify which files are entered as converters. Errors
|
|
148
|
+
in these files should not cause the adapter to crash - instead, use of
|
|
149
|
+
external converters may be unavailable.
|
|
150
|
+
|
|
151
|
+
### 1.8.9 (2022-12-10)
|
|
152
|
+
* (arteck) fix lidl plug
|
|
153
|
+
|
|
136
154
|
### 1.8.7 (2022-12-01)
|
|
137
155
|
* (arteck) fix exposes
|
|
138
156
|
|
|
@@ -156,7 +174,7 @@ You can thank the authors by these links:
|
|
|
156
174
|
### 1.7.5 (2022-06-01)
|
|
157
175
|
* (arteck) error message for undefined devices or icons
|
|
158
176
|
|
|
159
|
-
### 1.7.4 (2022-05-30)
|
|
177
|
+
### 1.7.4 (2022-05-30)
|
|
160
178
|
* (arteck) missing icons with multiple description
|
|
161
179
|
|
|
162
180
|
### 1.7.2 (2022-05-28)
|
|
@@ -165,7 +183,7 @@ You can thank the authors by these links:
|
|
|
165
183
|
### 1.7.1 (2022-05-28)
|
|
166
184
|
* (arteck) available status in admin is colored
|
|
167
185
|
* (arteck) disable Backups checkbox in settings
|
|
168
|
-
* (arteck) we keep last 10 backup files
|
|
186
|
+
* (arteck) we keep last 10 backup files
|
|
169
187
|
* (arteck) download missing icons automatically (manual upload needed)
|
|
170
188
|
|
|
171
189
|
### 1.6.18 (2022-04-21)
|
|
@@ -445,7 +463,7 @@ new Zigbee-herdsman features:
|
|
|
445
463
|
## License
|
|
446
464
|
The MIT License (MIT)
|
|
447
465
|
|
|
448
|
-
Copyright (c) 2018-
|
|
466
|
+
Copyright (c) 2018-2023 Kirov Ilya <kirovilya@gmail.com>
|
|
449
467
|
|
|
450
468
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
451
469
|
of this software and associated documentation files (the "Software"), to deal
|
package/admin/admin.js
CHANGED
|
@@ -683,6 +683,18 @@ function checkFwUpdate() {
|
|
|
683
683
|
}
|
|
684
684
|
}
|
|
685
685
|
|
|
686
|
+
function letsPairingWithCode(code) {
|
|
687
|
+
messages = [];
|
|
688
|
+
sendTo(namespace, 'letsPairing', {code: code}, function (msg) {
|
|
689
|
+
if (msg && msg.error) {
|
|
690
|
+
showMessage(msg.error, _('Error'));
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
showPairingProcess();
|
|
694
|
+
}
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
|
|
686
698
|
function letsPairing() {
|
|
687
699
|
messages = [];
|
|
688
700
|
sendTo(namespace, 'letsPairing', {}, function (msg) {
|
|
@@ -777,7 +789,7 @@ function load(settings, onChange) {
|
|
|
777
789
|
if (settings.extPanID === 'DDDDDDDDDDDDDDD') {
|
|
778
790
|
settings.extPanID = 'DDDDDDDDDDDDDDDD';
|
|
779
791
|
}
|
|
780
|
-
|
|
792
|
+
|
|
781
793
|
if (settings.precfgkey === undefined) {
|
|
782
794
|
settings.precfgkey = '01030507090B0D0F00020406080A0C0D';
|
|
783
795
|
}
|
|
@@ -787,7 +799,7 @@ function load(settings, onChange) {
|
|
|
787
799
|
if (settings.disablePing === undefined) {
|
|
788
800
|
settings.disablePing = false;
|
|
789
801
|
}
|
|
790
|
-
|
|
802
|
+
|
|
791
803
|
// example: select elements with id=key and class=value and insert value
|
|
792
804
|
for (const key in settings) {
|
|
793
805
|
if (savedSettings.indexOf(key) === -1) {
|
|
@@ -857,16 +869,25 @@ function load(settings, onChange) {
|
|
|
857
869
|
});
|
|
858
870
|
|
|
859
871
|
$('#add_group').click(function () {
|
|
860
|
-
// showGroupList(true);
|
|
861
872
|
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
862
873
|
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
863
874
|
});
|
|
875
|
+
|
|
864
876
|
$('#add_grp_btn').click(function () {
|
|
865
|
-
// showGroupList(true);
|
|
866
877
|
const maxind = parseInt(Object.getOwnPropertyNames(groups).reduce((a, b) => a > b ? a : b, 0));
|
|
867
878
|
editGroupName(maxind + 1, 'Group ' + maxind + 1, true);
|
|
868
879
|
});
|
|
869
880
|
|
|
881
|
+
$('#code_pairing').click(function () {
|
|
882
|
+
if (!$('#pairing').hasClass('pulse')) {
|
|
883
|
+
$('#codeentry a.btn[name=\'pair\']').click(() => {
|
|
884
|
+
const code = $('#codeentry').find('input[id=\'qr_code\']').val();
|
|
885
|
+
letsPairingWithCode(code)
|
|
886
|
+
});
|
|
887
|
+
$('#codeentry').modal('open');
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
|
|
870
891
|
$(document).ready(function () {
|
|
871
892
|
$('.modal').modal({
|
|
872
893
|
startingTop: '30%',
|
|
@@ -1920,9 +1941,8 @@ function updateDev(id, newName, newGroups) {
|
|
|
1920
1941
|
showMessage(msg.error, _('Error'));
|
|
1921
1942
|
} else {
|
|
1922
1943
|
// save dev-groups on success
|
|
1923
|
-
|
|
1944
|
+
getDevices();
|
|
1924
1945
|
}
|
|
1925
|
-
showDevices();
|
|
1926
1946
|
});
|
|
1927
1947
|
showWaitingDialog('Updating group memberships', 10);
|
|
1928
1948
|
|
package/admin/index_m.html
CHANGED
|
@@ -478,6 +478,12 @@
|
|
|
478
478
|
title="Touchlink reset and pairing">
|
|
479
479
|
<i class="material-icons large">wifi_tethering</i></a>
|
|
480
480
|
</li>
|
|
481
|
+
<li>
|
|
482
|
+
<a id="code_pairing"
|
|
483
|
+
class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT"
|
|
484
|
+
title="Pairing with QR Code">
|
|
485
|
+
<i class="material-icons large">select_all</i></a>
|
|
486
|
+
</li>
|
|
481
487
|
<li>
|
|
482
488
|
<a id="pairing"
|
|
483
489
|
class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT"
|
|
@@ -1079,6 +1085,25 @@
|
|
|
1079
1085
|
</div>
|
|
1080
1086
|
</div>
|
|
1081
1087
|
|
|
1088
|
+
<div id="codeentry" class="modal">
|
|
1089
|
+
<div class="modal-content">
|
|
1090
|
+
<div class="addgroup">
|
|
1091
|
+
<h3 class="translate">Enter Pairing Code</h3>
|
|
1092
|
+
</div>
|
|
1093
|
+
<div class="row">
|
|
1094
|
+
<div class="input-field">
|
|
1095
|
+
<input id="qr_code" type="text" class="value validate">
|
|
1096
|
+
<label for="qr_code" class="translate">QR Code</label>
|
|
1097
|
+
</div>
|
|
1098
|
+
</div>
|
|
1099
|
+
</div>
|
|
1100
|
+
<div class="modal-footer">
|
|
1101
|
+
<a name="pair" href="#!"
|
|
1102
|
+
class="modal-action modal-close waves-effect waves-green btn green translate">Start Pairing</a>
|
|
1103
|
+
<a href="#!" class="modal-action modal-close waves-effect waves-red btn-flat translate">Cancel</a>
|
|
1104
|
+
</div>
|
|
1105
|
+
</div>
|
|
1106
|
+
|
|
1082
1107
|
<div id="modaldelete" class="modal">
|
|
1083
1108
|
<div class="modal-content">
|
|
1084
1109
|
<h3 class="translate">Delete confirmation</h3>
|
package/admin/tab_m.html
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<script type="text/javascript" src="../../lib/js/materialize.js"></script>
|
|
17
17
|
<script type="text/javascript" >var noConfigDialog = true;</script><!-- Deactivate buttons -->
|
|
18
18
|
<script type="text/javascript" src="adapter-settings.js"></script>
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
<script>
|
|
21
21
|
// overload showMessage
|
|
22
22
|
function showMessage(message, title, icon) {
|
|
@@ -437,6 +437,12 @@
|
|
|
437
437
|
<a id="touchlink_btn" class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT" title="Touchlink reset and pairing">
|
|
438
438
|
<i class="material-icons large">wifi_tethering</i></a>
|
|
439
439
|
</li>
|
|
440
|
+
<li>
|
|
441
|
+
<a id="code_pairing"
|
|
442
|
+
class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT"
|
|
443
|
+
title="Pairing with QR Code">
|
|
444
|
+
<i class="material-icons large">select_all</i></a>
|
|
445
|
+
</li>
|
|
440
446
|
<li>
|
|
441
447
|
<a id="pairing" class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT" title="Let's pairing!">
|
|
442
448
|
<i class="material-icons large">leak_add</i></a>
|
|
@@ -729,7 +735,24 @@
|
|
|
729
735
|
<a href="#!" class="modal-action modal-close waves-effect waves-red btn-flat translate">Cancel</a>
|
|
730
736
|
</div>
|
|
731
737
|
</div>
|
|
732
|
-
|
|
738
|
+
<div id="codeentry" class="modal">
|
|
739
|
+
<div class="modal-content">
|
|
740
|
+
<div class="addgroup">
|
|
741
|
+
<h3 class="translate">Enter Pairing Code</h3>
|
|
742
|
+
</div>
|
|
743
|
+
<div class="row">
|
|
744
|
+
<div class="input-field">
|
|
745
|
+
<input id="qr_code" type="text" class="value validate">
|
|
746
|
+
<label for="qr_code" class="translate">QR Code</label>
|
|
747
|
+
</div>
|
|
748
|
+
</div>
|
|
749
|
+
</div>
|
|
750
|
+
<div class="modal-footer">
|
|
751
|
+
<a name="pair" href="#!"
|
|
752
|
+
class="modal-action modal-close waves-effect waves-green btn green translate">Start Pairing</a>
|
|
753
|
+
<a href="#!" class="modal-action modal-close waves-effect waves-red btn-flat translate">Cancel</a>
|
|
754
|
+
</div>
|
|
755
|
+
</div>
|
|
733
756
|
<div id="groupedit" class="modal">
|
|
734
757
|
<div class="modal-content">
|
|
735
758
|
<div class = "addgroup">
|
package/admin/words.js
CHANGED
|
@@ -97,7 +97,7 @@ systemDictionary = {
|
|
|
97
97
|
"№": { "uk": "№", "en": "№", "de": "Nr.", "ru": "№", "pt": "№", "nl": "№", "fr": "№", "it": "№", "es": "№", "pl": "Nr", "zh-cn": "№"},
|
|
98
98
|
"Excludes": { "uk": "виключити", "en": "to exclude", "de": "ausschließen", "ru": "Исключить", "nl": "uitsluiten", "fr": "d'exclure", "pl": "wyklucz"},
|
|
99
99
|
"ExcludeTextTranslation": { "uk": "Тут ви можете додати деякі пристрої, які слід виключити з нашого опису. Вони використовують лише \"викриття (exposes)\" від zigbee-herdsman-converter. Після додавання перезапустіть адаптер.", "en": "Here you can add some devices that should be excluded from our description. They only use \"exposes\" from zigbee-herdsman-converter. After adding, please restart the adapter.", "de": "Sie können hier einige Geräte hinzufügen, die von unserer Verarbeitung ausgeschlossen werden sollten. Sie verwenden dann nur exposes vom ZigBee-Herdsman-Converter. Nach dem Hinzufügen starten Sie bitte den Adapter neu.", "ru": "Здесь вы можете добавить устройства, для которых надо исключить представление заданное адаптером (iobroker.zigbee). В этом случае они будут использовать \"exposes\" из zigbee-herdsman-converter. После добавления перезапустите адаптер.", "nl": "Hier kunt u enkele apparaten toevoegen die moeten worden uitgesloten van onze beschrijving. Ze gebruiken alleen \"exposes\" van zigbee-herdsman-converter. Na het toevoegen moet u de adapter opnieuw opstarten.", "fr": "Ici, vous pouvez ajouter certains dispositifs qui doivent être exclus de notre description. Ils utilisent uniquement les \"exposes\" de zigbee-herdsman-converter. Après l'ajout, veuillez redémarrer l'adaptateur.", "pl": "Możesz dodać tutaj kilka urządzeń, które powinny zostać wyłączone z naszego opisu. Używasz tylko ekspozycji z zigbee-herdsman-converter. Po dodaniu zrestartuj adapter"},
|
|
100
|
-
"SettingsExclude": { "uk": "Примусовий запуск адаптера з не цілісною конфігурацією (не рекомендується). Оновіть адаптер до сумісної версії мікропрограми та перестворіть свою мережу якомога швидше.", "en": "Force start adapter with inconsistent configuration (not recommended). Please update the adapter to compatible firmware and recreate your network as soon as possible.", "de": "Den Start des Adapters mit inkonsistenter Konfiguration erzwingen
|
|
100
|
+
"SettingsExclude": { "uk": "Примусовий запуск адаптера з не цілісною конфігурацією (не рекомендується). Оновіть адаптер до сумісної версії мікропрограми та перестворіть свою мережу якомога швидше.", "en": "Force start adapter with inconsistent configuration (not recommended). Please update the adapter to compatible firmware and recreate your network as soon as possible.", "de": "Den Start des Adapters mit inkonsistenter Konfiguration erzwingen(nicht empfohlen). Bitte aktualisieren Sie den Adapter auf kompatible Firmware und erstellen Sie Ihr Netzwerk so schnell wie möglich neu.", "ru": "Принудительный запуск адаптера с несовместимой конфигурацией (не рекомендуется). Пожалуйста, обновите адаптер до совместимой прошивки и воссоздайте сеть как можно скорее.", "nl": "Forceer de adapter met een inconsistente configuratie (niet aanbevolen). Update de adapter naar compatibele firmware en maak uw netwerk zo snel mogelijk opnieuw aan.", "fr": "Démarrage forcé de l'adaptateur avec une configuration incohérente (non recommandé). Veuillez mettre à jour l'adaptateur avec un micrologiciel compatible et recréer votre réseau dès que possible.", "pl": "Wystaruj Adapter bez zgodnej konfiguracji (uwaga). Zaktualizuj adapter i jak najszybciej odtwórz sieć."},
|
|
101
101
|
"Others": { "uk": "інші налаштування", "en": "other settings", "de": "andere Einstellungen", "ru": "другие настройки", "nl": "andere instellingen", "fr": "autres réglages", "pl": "inne ustawienia"},
|
|
102
102
|
"disable internal Backup": { "uk": "вимкнути внутрішнє резервне копіювання", "en": "disable internal Backup", "de": "Deaktiviere die interne Sicherung", "ru": "отключить внутреннее резервное копирование", "nl": "interne back-up uitschakelen", "fr": "désactiver la sauvegarde interne", "pl": "wyłącz wewnętrzną kopię"},
|
|
103
103
|
"Disable active availability check": { "uk": "Вимкнути активну перевірку доступності", "en": "Disable active availability check", "de": "Aktive Verfügbarkeitsprüfung deaktivieren", "ru": "Отключить активную проверку доступности", "nl": "Actieve beschikbaarheidscontrole uitschakelen", "fr": "Désactiver le contrôle de disponibilité actif", "pl": "Wyłącz aktywne sprawdzanie dostępności"},
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+

|
|
2
|
+
# ioBroker.zigbee
|
|
3
|
+
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
[](https://www.npmjs.com/package/iobroker.zigbee)
|
|
7
|
+
|
|
8
|
+
[](https://weblate.iobroker.net/engage/adapters/?utm_source=widget)
|
|
9
|
+
[](https://www.npmjs.com/package/iobroker.zigbee)
|
|
10
|
+
|
|
11
|
+
Der Zigbee Adapter dient zur Ansteuerung eines Zigbee Netzes unter zu Hilfe nahme eines direkt am ioBroker angeschlossenen Koordinators. Der Koordinator kann dabei über USB, Seriell oder über TCP/IP angeschlossen werden.
|
|
12
|
+
|
|
13
|
+
Vor dem ersten Start des Adpaters sollten auf der Konfigurationsseite einige Einstellungen vorgenommen werden:
|
|
14
|
+
- Com Anschlussnahme
|
|
15
|
+
- Koordinator Typ
|
|
16
|
+
- Netzwerk verschlüsselung über PanID und extPanID
|
|
17
|
+
- Zigbee Kanal
|
|
18
|
+
|
|
19
|
+
Nachdem diese Parameter eingestellt wurden kann der Adapter gestartet werden.
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zigbee",
|
|
4
|
-
"version": "1.8.
|
|
4
|
+
"version": "1.8.10",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.8.10": {
|
|
7
|
+
"en": "fix group access and any new functions",
|
|
8
|
+
"de": "fix group access and any new functions"
|
|
9
|
+
},
|
|
10
|
+
"1.8.9": {
|
|
11
|
+
"en": "fix lidl plug",
|
|
12
|
+
"de": "deckelstecker",
|
|
13
|
+
"ru": "исправить lidl plug",
|
|
14
|
+
"pt": "fixar tampa",
|
|
15
|
+
"nl": "los deksel",
|
|
16
|
+
"fr": "fixer le couvercle",
|
|
17
|
+
"it": "correzione della spina del coperchio",
|
|
18
|
+
"es": "enchufe de tapa fija",
|
|
19
|
+
"pl": "naprawiony plug",
|
|
20
|
+
"uk": "фіксувати роз'єм",
|
|
21
|
+
"zh-cn": "fix 滑坡"
|
|
22
|
+
},
|
|
23
|
+
"1.8.8": {
|
|
24
|
+
"en": "fix lidl plug",
|
|
25
|
+
"de": "fix lidl plug"
|
|
26
|
+
},
|
|
6
27
|
"1.8.7": {
|
|
7
28
|
"en": "fix exposes",
|
|
8
29
|
"de": "belichtet fix",
|
|
@@ -35,36 +56,6 @@
|
|
|
35
56
|
},
|
|
36
57
|
"1.8.4": {
|
|
37
58
|
"en": "fix for new code"
|
|
38
|
-
},
|
|
39
|
-
"1.8.3": {
|
|
40
|
-
"en": "back to old source",
|
|
41
|
-
"de": "zurück zur alten quelle",
|
|
42
|
-
"ru": "назад к старому источнику",
|
|
43
|
-
"pt": "voltar para a velha fonte",
|
|
44
|
-
"nl": "terug naar de oude bron",
|
|
45
|
-
"fr": "retour à la vieille source",
|
|
46
|
-
"it": "torna alla vecchia fonte",
|
|
47
|
-
"es": "volver a la vieja fuente",
|
|
48
|
-
"pl": "tył",
|
|
49
|
-
"uk": "назад до старого джерела",
|
|
50
|
-
"zh-cn": "背 景"
|
|
51
|
-
},
|
|
52
|
-
"1.8.2": {
|
|
53
|
-
"en": "back to old source",
|
|
54
|
-
"de": "back to old source"
|
|
55
|
-
},
|
|
56
|
-
"1.8.1": {
|
|
57
|
-
"en": "Packages updated\nAdded names of serial ports in configuration dialog",
|
|
58
|
-
"de": "Pakete aktualisiert\nNamen der seriellen Ports im Konfigurationsdialog hinzugefügt",
|
|
59
|
-
"ru": "Пакеты обновлены\nДобавлены имена серийных портов в диалоге конфигурации",
|
|
60
|
-
"pt": "Pacotes atualizados\nNomes adicionados de portas seriais na caixa de diálogo de configuração",
|
|
61
|
-
"nl": "Verpakking geüpload\nNamen van serie havens in configuration dialog",
|
|
62
|
-
"fr": "Packages updated\nAjout de noms de ports série dans le dialogue de configuration",
|
|
63
|
-
"it": "Pacchetti aggiornati\nAggiunto i nomi delle porte seriali nella finestra di dialogo di configurazione",
|
|
64
|
-
"es": "Paquetes actualizados\nNombres añadidos de los puertos serie en el diálogo de configuración",
|
|
65
|
-
"pl": "Pakiet\nDodane nazwy portów seryjnych w dialogach konfiguracyjnych",
|
|
66
|
-
"uk": "Пакети оновлені\nДодано імена серійних портів у діалоговому вікні конфігурації",
|
|
67
|
-
"zh-cn": "更新的包装\n加 口号港口"
|
|
68
59
|
}
|
|
69
60
|
},
|
|
70
61
|
"title": "Zigbee",
|
package/lib/binding.js
CHANGED
|
@@ -104,7 +104,6 @@ class Binding {
|
|
|
104
104
|
async doBindUnbind(type, bind_source, bind_source_ep, bind_target, bind_target_ep, callback) {
|
|
105
105
|
try {
|
|
106
106
|
const id = this.getBindingId(bind_source, bind_source_ep, bind_target, bind_target_ep);
|
|
107
|
-
|
|
108
107
|
const source = await this.zbController.resolveEntity(`0x${this.extractDeviceId(bind_source)}`, this.getBindEp(bind_source_ep));
|
|
109
108
|
this.debug(`source: ${safeJsonStringify(source)}`);
|
|
110
109
|
let target = await this.zbController.resolveEntity(`0x${this.extractDeviceId(bind_target)}`, this.getBindEp(bind_target_ep));
|
package/lib/commands.js
CHANGED
|
@@ -112,11 +112,35 @@ class Commands {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
letsPairing(from, command, message, callback) {
|
|
115
|
+
async letsPairing(from, command, message, callback) {
|
|
116
116
|
if (this.zbController) {
|
|
117
117
|
let devId = '';
|
|
118
|
-
if (message
|
|
119
|
-
|
|
118
|
+
if (message) {
|
|
119
|
+
if (message.id) devId = getZbId(message.id);
|
|
120
|
+
if (message.code) {
|
|
121
|
+
try {
|
|
122
|
+
this.debug(`letsPairing called with code ${message.code}`);
|
|
123
|
+
const success = await this.zbController.addPairingCode(message.code)
|
|
124
|
+
if (!success) {
|
|
125
|
+
this.adapter.sendTo(
|
|
126
|
+
from, command,
|
|
127
|
+
{error: 'Pairing code rejected by Coordinator!'},
|
|
128
|
+
callback
|
|
129
|
+
);
|
|
130
|
+
return;
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (e) {
|
|
134
|
+
this.error(JSON.stringify(e))
|
|
135
|
+
this.adapter.sendTo(
|
|
136
|
+
from, command,
|
|
137
|
+
{error: 'Exception when trying to add QR code'},
|
|
138
|
+
callback
|
|
139
|
+
);
|
|
140
|
+
return;
|
|
141
|
+
|
|
142
|
+
}
|
|
143
|
+
}
|
|
120
144
|
}
|
|
121
145
|
// allow devices to join the network within 60 secs
|
|
122
146
|
this.adapter.logToPairing('Pairing started ' + devId, true);
|
|
@@ -257,7 +281,7 @@ class Commands {
|
|
|
257
281
|
memberinfo.push(member);
|
|
258
282
|
}
|
|
259
283
|
devInfo.memberinfo = memberinfo;
|
|
260
|
-
this.debug(`memberinfo: ${JSON.stringify(devInfo.memberinfo)}`);
|
|
284
|
+
this.debug(`memberinfo for ${match[1]}: ${JSON.stringify(devInfo.memberinfo)}`);
|
|
261
285
|
}
|
|
262
286
|
}
|
|
263
287
|
} else {
|
|
@@ -291,11 +315,11 @@ class Commands {
|
|
|
291
315
|
.then(async (devices) => {
|
|
292
316
|
// fill group info
|
|
293
317
|
for (const groupdev in groups) {
|
|
294
|
-
this.debug(`GetDevices scanning group ${groupdev} ${JSON.stringify(groups[groupdev])}`);
|
|
318
|
+
//this.debug(`GetDevices scanning group ${groupdev} ${JSON.stringify(groups[groupdev])}`);
|
|
295
319
|
const device = devices.find(dev => (groupdev === getZbId(dev._id)));
|
|
296
320
|
if (device) {
|
|
297
321
|
device.groups = groups[groupdev];
|
|
298
|
-
this.debug(`adding group info to device ${groupdev}`);
|
|
322
|
+
//this.debug(`adding group info to device ${groupdev}`);
|
|
299
323
|
}
|
|
300
324
|
}
|
|
301
325
|
// append devices that paired but not created
|
package/lib/groups.js
CHANGED
|
@@ -123,6 +123,7 @@ class Groups {
|
|
|
123
123
|
try {
|
|
124
124
|
const groups = message && message.groups ? message.groups : {};
|
|
125
125
|
const devId = message && message.id ? message.id : undefined;
|
|
126
|
+
this.warn('updateGroupMembership called with ' + JSON.stringify(devId))
|
|
126
127
|
if (devId === undefined) {
|
|
127
128
|
this.adapter.sendTo(from, command, {error: 'No device specified'}, callback);
|
|
128
129
|
}
|
|
@@ -137,12 +138,15 @@ class Groups {
|
|
|
137
138
|
for (const gpid of groups[epid]) {
|
|
138
139
|
const gpidn = parseInt(gpid);
|
|
139
140
|
if (gpidn < 0) {
|
|
141
|
+
this.warn(`calling removeDevFromGroup with ${sysid}, ${-gpidn}, ${epid}` )
|
|
140
142
|
const response = await this.zbController.removeDevFromGroup(sysid, (-gpidn), epid);
|
|
141
143
|
if (response && response.error) {
|
|
142
144
|
errors.push(response.error);
|
|
143
145
|
this.error(`remove dev from group Error: ${JSON.stringify(response.error)}`);
|
|
144
146
|
}
|
|
147
|
+
|
|
145
148
|
} else if (gpidn > 0) {
|
|
149
|
+
this.warn(`calling addDevToGroup with ${sysid}, ${gpidn}, ${epid}` )
|
|
146
150
|
const response = await this.zbController.addDevToGroup(sysid, (gpidn), epid);
|
|
147
151
|
if (response && response.error) {
|
|
148
152
|
errors.push(response.error);
|
|
@@ -154,6 +158,7 @@ class Groups {
|
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
} catch (e) {
|
|
161
|
+
this.warn('caught error ' + JSON.stringify(e) + ' in updateGroupMembership')
|
|
157
162
|
this.adapter.sendTo(from, command, {error: e}, callback);
|
|
158
163
|
return;
|
|
159
164
|
}
|
package/lib/utils.js
CHANGED
|
@@ -137,6 +137,11 @@ function getModelRegEx( model) {
|
|
|
137
137
|
return stripModel;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
+
function getEntityInfo(entity) {
|
|
141
|
+
if (entity) return `Type: ${entity.type} Name: ${entity.name}`
|
|
142
|
+
return `getEntityInfo: Illegal Entity ${JSON.stringify(entity)}`
|
|
143
|
+
}
|
|
144
|
+
|
|
140
145
|
exports.secondsToMilliseconds = seconds => seconds * 1000;
|
|
141
146
|
exports.bulbLevelToAdapterLevel = bulbLevelToAdapterLevel;
|
|
142
147
|
exports.adapterLevelToBulbLevel = adapterLevelToBulbLevel;
|
|
@@ -155,3 +160,4 @@ exports.isXiaomiDevice = device =>
|
|
|
155
160
|
(!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
|
|
156
161
|
exports.isIkeaTradfriDevice = device => ikeaTradfriManufacturerID.includes(device.manufacturerID);
|
|
157
162
|
exports.getDeviceIcon = getDeviceIcon;
|
|
163
|
+
exports.getEntityInfo = getEntityInfo;
|
package/lib/zigbeecontroller.js
CHANGED
|
@@ -9,6 +9,7 @@ const DeviceAvailabilityExt = require('./zbDeviceAvailability');
|
|
|
9
9
|
const DeviceConfigureExt = require('./zbDeviceConfigure');
|
|
10
10
|
const DeviceEventExt = require('./zbDeviceEvent');
|
|
11
11
|
const DelayedActionExt = require('./zbDelayedAction');
|
|
12
|
+
const utils = require('./utils');
|
|
12
13
|
const groupConverters = [
|
|
13
14
|
zigbeeHerdsmanConverters.toZigbeeConverters.light_onoff_brightness,
|
|
14
15
|
zigbeeHerdsmanConverters.toZigbeeConverters.light_colortemp,
|
|
@@ -311,6 +312,16 @@ class ZigbeeController extends EventEmitter {
|
|
|
311
312
|
}
|
|
312
313
|
}
|
|
313
314
|
|
|
315
|
+
async addPairingCode(code) {
|
|
316
|
+
this.debug(`calling addPairingCode with ${code}`);
|
|
317
|
+
if (code) {
|
|
318
|
+
await this.herdsman.addInstallCode(code)
|
|
319
|
+
this.info(`added code ${code} for pairing`)
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
324
|
+
|
|
314
325
|
async getGroupMembersFromController(id) {
|
|
315
326
|
const members = [];
|
|
316
327
|
try {
|
|
@@ -795,26 +806,36 @@ class ZigbeeController extends EventEmitter {
|
|
|
795
806
|
|
|
796
807
|
async addDevToGroup(devId, groupId, epid) {
|
|
797
808
|
try {
|
|
809
|
+
this.debug(`called addDevToGroup with ${devId}, ${groupId}, ${epid}`)
|
|
798
810
|
const entity = await this.resolveEntity(devId);
|
|
799
811
|
const group = await this.resolveEntity(groupId);
|
|
800
|
-
this.debug(`addDevFromGroup - entity: ${
|
|
801
|
-
|
|
812
|
+
this.debug(`addDevFromGroup - entity: ${utils.getEntityInfo(entity)}`);
|
|
813
|
+
// generate group debug info and display it
|
|
814
|
+
const members = await this.getGroupMembersFromController(groupId)
|
|
815
|
+
let memberIDs = []
|
|
816
|
+
for (let member of members) {
|
|
817
|
+
memberIDs.push(member.ieee)
|
|
818
|
+
}
|
|
819
|
+
this.debug(`addDevToGroup ${groupId} with ${memberIDs.length} members ${safeJsonStringify(memberIDs)}`);
|
|
802
820
|
if (epid != undefined) {
|
|
803
821
|
for (const ep of entity.endpoints) {
|
|
804
|
-
|
|
822
|
+
this.debug(`checking ep ${ep.ID} of ${devId} (${epid})`)
|
|
823
|
+
if (ep.ID == epid) {
|
|
824
|
+
if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)) {
|
|
805
825
|
this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`);
|
|
806
826
|
await (ep.addToGroup(group.mapped));
|
|
827
|
+
}
|
|
828
|
+
else this.error(`cluster genGroups not supported for endpoint ${epid} of ${devId}`)
|
|
807
829
|
}
|
|
808
830
|
}
|
|
809
831
|
} else {
|
|
810
832
|
if (entity.endpoint.inputClusters.includes(4)) {
|
|
811
|
-
this.
|
|
833
|
+
this.info(`adding endpoint ${entity.endpoint.ID} of ${devId} to group`);
|
|
812
834
|
await entity.endpoint.addToGroup(group.mapped);
|
|
813
835
|
} else {
|
|
814
836
|
let added = false;
|
|
815
837
|
for (const ep of entity.endpoints) {
|
|
816
838
|
if (ep.inputClusters.includes(4)) {
|
|
817
|
-
this.debug(`adding endpoint ${ep.ID} to group`);
|
|
818
839
|
await ep.addToGroup(group.mapped);
|
|
819
840
|
added = true;
|
|
820
841
|
break;
|
|
@@ -834,20 +855,33 @@ class ZigbeeController extends EventEmitter {
|
|
|
834
855
|
}
|
|
835
856
|
|
|
836
857
|
async removeDevFromGroup(devId, groupId, epid) {
|
|
858
|
+
this.debug(`removeDevFromGroup with ${devId}, ${groupId}, ${epid}`)
|
|
837
859
|
let entity;
|
|
838
860
|
try {
|
|
839
861
|
entity = await this.resolveEntity(devId);
|
|
840
862
|
const group = await this.resolveEntity(groupId);
|
|
841
|
-
|
|
842
|
-
|
|
863
|
+
|
|
864
|
+
const members = await this.getGroupMembersFromController(groupId)
|
|
865
|
+
let memberIDs = []
|
|
866
|
+
for (let member of members) {
|
|
867
|
+
memberIDs.push(member.ieee)
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
this.debug(`removeDevFromGroup - entity: ${utils.getEntityInfo(entity)}`);
|
|
871
|
+
this.debug(`removeDevFromGroup ${groupId} with ${memberIDs.length} members ${safeJsonStringify(memberIDs)}`);
|
|
872
|
+
|
|
843
873
|
if (epid != undefined) {
|
|
844
874
|
for (const ep of entity.endpoints) {
|
|
845
|
-
|
|
846
|
-
|
|
875
|
+
this.debug(`checking ep ${ep.ID} of ${devId} (${epid})`)
|
|
876
|
+
if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))) {
|
|
847
877
|
await ep.removeFromGroup(group.mapped);
|
|
878
|
+
this.info(`removing endpoint ${ep.ID} of ${devId} from group ${groupId}`);
|
|
848
879
|
}
|
|
849
880
|
}
|
|
850
|
-
} else
|
|
881
|
+
} else {
|
|
882
|
+
await entity.endpoint.removeFromGroup(group.mapped);
|
|
883
|
+
this.info(`removing endpoint ${entity.endpoint.ID} of ${devId} from group ${groupId}`);
|
|
884
|
+
}
|
|
851
885
|
} catch (error) {
|
|
852
886
|
this.sendError(error);
|
|
853
887
|
this.error(`Exception when trying remove ${devId} (ep ${epid ? epid : (entity ? entity.endpoint.ID : '')}) from group ${devId}`, error);
|
|
@@ -865,7 +899,6 @@ class ZigbeeController extends EventEmitter {
|
|
|
865
899
|
await ep.removefromAllGroups();
|
|
866
900
|
}
|
|
867
901
|
}
|
|
868
|
-
// await entity.endpoint.removeFromAllGroups();
|
|
869
902
|
} catch (error) {
|
|
870
903
|
this.sendError(error);
|
|
871
904
|
this.error(`Exception when trying remove ${devId} from all groups`, error);
|
package/main.js
CHANGED
|
@@ -216,9 +216,64 @@ class Zigbee extends utils.Adapter {
|
|
|
216
216
|
}
|
|
217
217
|
const extfiles = this.config.external.split(';');
|
|
218
218
|
for (const moduleName of extfiles) {
|
|
219
|
-
if (!moduleName)
|
|
220
|
-
|
|
219
|
+
if (!moduleName) continue;
|
|
220
|
+
const sandbox = {
|
|
221
|
+
require,
|
|
222
|
+
module: {},
|
|
223
|
+
};
|
|
224
|
+
const mN = (fs.existsSync(moduleName) ? moduleName : this.expandFileName(moduleName).replace('.', '_'));
|
|
225
|
+
if (!fs.existsSync(mN)) {
|
|
226
|
+
this.log.warn(`External converter not loaded - neither ${moduleName} nor ${mN} exist.`)
|
|
227
|
+
|
|
221
228
|
}
|
|
229
|
+
else {
|
|
230
|
+
const converterCode = fs.readFileSync(mN, {encoding: 'utf8'}).toString();
|
|
231
|
+
let converterLoaded = true;
|
|
232
|
+
if (converterCode.match(/..\/lib\/legacy/gm)) {
|
|
233
|
+
this.log.warn(`External converter ${mN} contains an unsupported reference to '/lib/legacy' - external converter not loaded.`)
|
|
234
|
+
converterLoaded = false;
|
|
235
|
+
}
|
|
236
|
+
else
|
|
237
|
+
{
|
|
238
|
+
// remove the require statements and attempt to place them in the sandbox
|
|
239
|
+
const requiredLibraries = converterCode.matchAll(/(\w+) += +require\(['"](\S+)['"]\);/gm);
|
|
240
|
+
for (const line of requiredLibraries) {
|
|
241
|
+
const movedLine = line[2].replace('..', '../zigbee-herdsman-converters')
|
|
242
|
+
try {
|
|
243
|
+
sandbox[line[1]] = require(movedLine);
|
|
244
|
+
}
|
|
245
|
+
catch (e) {
|
|
246
|
+
this.log.warn(`error adding ${line[1]} (${movedLine}) to the sandbox: ${e}`);
|
|
247
|
+
converterLoaded = false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (converterLoaded) {
|
|
252
|
+
this.log.info(`Apply converter from module: ${mN}`);
|
|
253
|
+
//this.log.warn(converterCode.replace(/const (\w+) += +require\(['"](\S+)['"]\);/gm, ''));
|
|
254
|
+
try {
|
|
255
|
+
vm.runInNewContext(converterCode.replace(/const (\w+) += +require\(['"](\S+)['"]\);/gm, ''), sandbox);
|
|
256
|
+
const converter = sandbox.module.exports;
|
|
257
|
+
|
|
258
|
+
if (Array.isArray(converter)) for (const item of converter) yield item;
|
|
259
|
+
else yield converter;
|
|
260
|
+
}
|
|
261
|
+
catch (e) {
|
|
262
|
+
this.log.error(`Unable to apply converter from module: ${mN} - the code does not run: ${e}`)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
else
|
|
266
|
+
this.log.info(`Ignoring converter from module: ${mN} - see warn messages for reason`);
|
|
267
|
+
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/* if (this.config.external === undefined) {
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
const extfiles = this.config.external.split(';');
|
|
275
|
+
for (const moduleName of extfiles) {
|
|
276
|
+
if (!moduleName) continue;
|
|
222
277
|
this.log.info(`Apply converter from module: ${moduleName}`);
|
|
223
278
|
const sandbox = {
|
|
224
279
|
require,
|
|
@@ -235,14 +290,23 @@ class Zigbee extends utils.Adapter {
|
|
|
235
290
|
yield converter;
|
|
236
291
|
}
|
|
237
292
|
}
|
|
238
|
-
|
|
293
|
+
*/
|
|
294
|
+
}
|
|
239
295
|
|
|
240
296
|
applyExternalConverters() {
|
|
297
|
+
try {
|
|
241
298
|
for (const definition of this.getExternalDefinition()) {
|
|
242
299
|
const toAdd = {...definition};
|
|
243
300
|
delete toAdd['homeassistant'];
|
|
244
|
-
|
|
301
|
+
try {
|
|
302
|
+
zigbeeHerdsmanConverters.addDeviceDefinition(toAdd);
|
|
303
|
+
}
|
|
304
|
+
catch { this.log.error(`unable to apply external converter ${JSON.stringfy(toAdd)}`) }
|
|
245
305
|
}
|
|
306
|
+
}
|
|
307
|
+
catch(error) {
|
|
308
|
+
this.log.error('error applying external converters');
|
|
309
|
+
}
|
|
246
310
|
}
|
|
247
311
|
|
|
248
312
|
async doConnect() {
|
|
@@ -851,6 +915,7 @@ class Zigbee extends utils.Adapter {
|
|
|
851
915
|
|
|
852
916
|
onPairing(message, data) {
|
|
853
917
|
if (Number.isInteger(data)) {
|
|
918
|
+
_pairingMode = true;
|
|
854
919
|
this.setState('info.pairingCountdown', data, true);
|
|
855
920
|
_pairingMode = true;
|
|
856
921
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "1.8.
|
|
3
|
+
"version": "1.8.10",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"@iobroker/adapter-core": "^2.6.7",
|
|
25
25
|
"tar": "^6.1.12",
|
|
26
26
|
"typescript": "^4.9.3",
|
|
27
|
-
"zigbee-herdsman": "0.14.
|
|
28
|
-
"zigbee-herdsman-converters": "
|
|
27
|
+
"zigbee-herdsman": "0.14.83",
|
|
28
|
+
"zigbee-herdsman-converters": "15.0.15"
|
|
29
29
|
},
|
|
30
30
|
"description": "Zigbee devices",
|
|
31
31
|
"devDependencies": {
|
|
@@ -36,14 +36,14 @@
|
|
|
36
36
|
"axios": "^1.2.0",
|
|
37
37
|
"chai": "^4.3.7",
|
|
38
38
|
"chai-as-promised": "^7.1.1",
|
|
39
|
-
"eslint": "^8.
|
|
39
|
+
"eslint": "^8.31.0",
|
|
40
40
|
"eslint-config-prettier": "^8.5.0",
|
|
41
41
|
"eslint-plugin-prettier": "^4.2.1",
|
|
42
42
|
"gulp": "^4.0.2",
|
|
43
43
|
"gulp-jsdoc3": "^3.0.0",
|
|
44
44
|
"gulp-replace": "^1.1.3",
|
|
45
45
|
"mixin-deep": "^2.0.1",
|
|
46
|
-
"mocha": "^10.
|
|
46
|
+
"mocha": "^10.2.0"
|
|
47
47
|
},
|
|
48
48
|
"homepage": "https://github.com/ioBroker/ioBroker.zigbee",
|
|
49
49
|
"keywords": [
|