iobroker.zigbee 1.10.14 → 2.0.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.
- package/README.md +27 -0
- package/admin/index_m.html +1 -1
- package/admin/tab_m.html +1 -1
- package/io-package.json +28 -41
- package/lib/binding.js +1 -1
- package/lib/commands.js +2 -2
- package/lib/exposes.js +21 -3
- package/lib/groups.js +4 -4
- package/lib/statescontroller.js +5 -5
- package/lib/zbDeviceAvailability.js +1 -1
- package/lib/zbDeviceEvent.js +13 -2
- package/lib/zigbeecontroller.js +188 -136
- package/main.js +34 -18
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -137,6 +137,9 @@ You can thank the authors by these links:
|
|
|
137
137
|
|
|
138
138
|
-----------------------------------------------------------------------------------------------------
|
|
139
139
|
## Changelog
|
|
140
|
+
### 2.0.0 (2025-02-22)
|
|
141
|
+
* (asgothian) new herdsman adaption
|
|
142
|
+
|
|
140
143
|
### 1.10.14 (2025-01-01)
|
|
141
144
|
* (arteck) Herdsman 2.1.9, Converters 20.58.0
|
|
142
145
|
* (asgothian) Fix: Aqara T1M (CL-L02D)
|
|
@@ -208,4 +211,28 @@ You can thank the authors by these links:
|
|
|
208
211
|
* Some design update
|
|
209
212
|
* Binding
|
|
210
213
|
|
|
214
|
+
|
|
211
215
|
------------------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
## License
|
|
218
|
+
The MIT License (MIT)
|
|
219
|
+
|
|
220
|
+
Copyright (c) 2018-2025 Kirov Ilya <kirovilya@gmail.com>
|
|
221
|
+
|
|
222
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
223
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
224
|
+
in the Software without restriction, including without limitation the rights
|
|
225
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
226
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
227
|
+
furnished to do so, subject to the following conditions:
|
|
228
|
+
|
|
229
|
+
The above copyright notice and this permission notice shall be included in
|
|
230
|
+
all copies or substantial portions of the Software.
|
|
231
|
+
|
|
232
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
233
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
234
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
235
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
236
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
237
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
238
|
+
THE SOFTWARE.
|
package/admin/index_m.html
CHANGED
|
@@ -654,7 +654,7 @@
|
|
|
654
654
|
<a id="state_cleanup_btn"
|
|
655
655
|
class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT"
|
|
656
656
|
title="State Cleanup">
|
|
657
|
-
<i class="material-icons large icon-blue">
|
|
657
|
+
<i class="material-icons large icon-blue">delete_sweep</i></a>
|
|
658
658
|
</li>
|
|
659
659
|
<li>
|
|
660
660
|
<a id="fw_check_btn"
|
package/admin/tab_m.html
CHANGED
|
@@ -660,7 +660,7 @@
|
|
|
660
660
|
<ul id="nav-mobile" class="right">
|
|
661
661
|
<li>
|
|
662
662
|
<a id="state_cleanup_btn" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT" title="State Cleanup">
|
|
663
|
-
<i class="material-icons large icon-blue">
|
|
663
|
+
<i class="material-icons large icon-blue">delete_sweep</i></a>
|
|
664
664
|
</li>
|
|
665
665
|
<li>
|
|
666
666
|
<a id="fw_check_btn" class="btn-floating waves-effect waves-light blue tooltipped center-align hoverable translateT" title="Check firmware updates">
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "zigbee",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"news": {
|
|
6
|
+
"2.0.0": {
|
|
7
|
+
"en": "new herdsman adaption",
|
|
8
|
+
"de": "neue herdsman adaption",
|
|
9
|
+
"ru": "адаптация нового пастуха",
|
|
10
|
+
"pt": "nova adaptação herdsman",
|
|
11
|
+
"nl": "nieuwe aanpassing van herders",
|
|
12
|
+
"fr": "nouvelle adaptation des éleveurs",
|
|
13
|
+
"it": "nuovo adattamento mandriano",
|
|
14
|
+
"es": "nueva adaptación del pastor",
|
|
15
|
+
"pl": "nowa adaptacja zioła",
|
|
16
|
+
"uk": "новий гердман адаптація",
|
|
17
|
+
"zh-cn": "新牧民适应"
|
|
18
|
+
},
|
|
19
|
+
"1.10.15": {
|
|
20
|
+
"en": "Work in progress",
|
|
21
|
+
"de": "Work in progress",
|
|
22
|
+
"ru": "Work in progress",
|
|
23
|
+
"pt": "Work in progress",
|
|
24
|
+
"nl": "Work in progress",
|
|
25
|
+
"fr": "Work in progress",
|
|
26
|
+
"it": "Work in progress",
|
|
27
|
+
"es": "Work in progress",
|
|
28
|
+
"pl": "Work in progress",
|
|
29
|
+
"uk": "Work in progress",
|
|
30
|
+
"zh-cn": "Work in progress"
|
|
31
|
+
},
|
|
6
32
|
"1.10.14": {
|
|
7
33
|
"en": "Herdsman 2.1.9, Converters 20.58.0\nFix: Aqara T1M (CL-L02D) \ndeleteDeviceStates change to deleteObj",
|
|
8
34
|
"de": "Herdsman 2.1.9, Konverter 20.58.0\nFix: Aqara T1M (CL-L02D)\nlöschen DeviceState Änderung zum Löschen Ob",
|
|
@@ -54,45 +80,6 @@
|
|
|
54
80
|
"pl": "ZMIANA ZBIORCZA\n\nbłędy: ChannelScan jest obecnie niedostępny\n\n\nnaprawić błędy lintera\nwyłączyć wyświetlacz mapy dla wyłączonych urządzeń\nnowa opcja na mapie: wyłączenie interakcji fizyki\nnowe konwertery zigbee- herdsman- 20.28.0\nnowy zigbee-herdsman 2.1.1\nZezwalaj na stosowanie konwerterów bezklawiszowych (używanych dla TuYa i kompatybilnych urządzeń w konwerterach zigbee- herdsman-\nzamiana z wniosku na aksjos\nusuń grupy działa ponownie",
|
|
55
81
|
"uk": "БРЕАКІНГ ЗМІН\n\nпомилки : CanalScan наразі немає\n\n\nвиправлено помилки linter\nвідключення відображення карти для деактивованих пристроїв\nновий варіант на карті: відключена фізика взаємодія\nнові zigbee-herdsman-converters 20.28.0\nновий zigbee-herdsman 2.1.1\nДозволити використання без ключів конвертерів (використовується для TuYa та сумісних пристроїв в zigbee-herdsman-converters\nковтання від запиту в осях\nвидалити групи знову",
|
|
56
82
|
"zh-cn": "破坏变化\n\n错误 : 频道扫描目前不可用\n\n\n修正线性错误\n禁用已停用设备的地图显示\n地图上的新选项: 禁用物理交互\n新齐格比-牧民-转换器 20.28.0\n新齐格比牧民 2.1.1\n允许使用无密钥转换器( 用于 TuYa 和 Zigbee- herdsman- 转换器中的兼容设备)\n从请求转换为轴\n再次删除组工作"
|
|
57
|
-
},
|
|
58
|
-
"1.10.10": {
|
|
59
|
-
"en": "core update\ndependency update",
|
|
60
|
-
"de": "kern-update\naktualisierung der abhängigkeit",
|
|
61
|
-
"ru": "обновление\nобновление",
|
|
62
|
-
"pt": "atualização do núcleo\natualização de dependência",
|
|
63
|
-
"nl": "kernupdate\nafhankelijkheidsupdate",
|
|
64
|
-
"fr": "mise à jour de base\nmise à jour de la dépendance",
|
|
65
|
-
"it": "aggiornamento del core\naggiornamento della dipendenza",
|
|
66
|
-
"es": "actualización básica\nactualización de la dependencia",
|
|
67
|
-
"pl": "podstawowa aktualizacja\naktualizacja zależności",
|
|
68
|
-
"uk": "оновлення ядра\nоновлення залежності",
|
|
69
|
-
"zh-cn": "核心更新\n依赖性更新"
|
|
70
|
-
},
|
|
71
|
-
"1.10.9": {
|
|
72
|
-
"en": "typo admin settings\neslint config",
|
|
73
|
-
"de": "typo admin einstellungen\neslint config",
|
|
74
|
-
"ru": "настройки admin\neslint config",
|
|
75
|
-
"pt": "configurações de administração do tipo\neslint config",
|
|
76
|
-
"nl": "typo admin instellingen\neslint config",
|
|
77
|
-
"fr": "paramètres d'administration typo\nconfig eslint",
|
|
78
|
-
"it": "impostazioni dell'amministratore\neslint config",
|
|
79
|
-
"es": "configuración de administración de tipo\neslint config",
|
|
80
|
-
"pl": "ustawienia admin typo\neslint config",
|
|
81
|
-
"uk": "параметри адміністратора\neslint config",
|
|
82
|
-
"zh-cn": "类型管理员设置\n埃斯林特配置"
|
|
83
|
-
},
|
|
84
|
-
"1.10.8": {
|
|
85
|
-
"en": "corr admin settings\nadd new eslint version\n",
|
|
86
|
-
"de": "korr admin einstellungen\nneue eslint-version hinzufügen\n",
|
|
87
|
-
"ru": "настройки администрирования\nдобавить новую версию eslint\n",
|
|
88
|
-
"pt": "configurações de administração de corrimento\nadicionar nova versão eslint\n",
|
|
89
|
-
"nl": "corr admin instellingen\nnieuwe eslint versie toevoegen\n",
|
|
90
|
-
"fr": "paramètres d'administration corr\najouter une nouvelle version eslint\n",
|
|
91
|
-
"it": "impostazioni dell'amministratore\naggiungere nuova versione eslint\n",
|
|
92
|
-
"es": "configuración de administración de corr\nañadir nueva versión eslint\n",
|
|
93
|
-
"pl": "ustawienia admin corr\ndodaj nową wersję eslint\n",
|
|
94
|
-
"uk": "корр налаштування адміністратора\nдодати нову версію eslint\n",
|
|
95
|
-
"zh-cn": "corr 管理员设置\n添加新的 eslint 版本\n"
|
|
96
83
|
}
|
|
97
84
|
},
|
|
98
85
|
"titleLang": {
|
|
@@ -192,7 +179,7 @@
|
|
|
192
179
|
],
|
|
193
180
|
"dependencies": [
|
|
194
181
|
{
|
|
195
|
-
"js-controller": ">=
|
|
182
|
+
"js-controller": ">=5.0.19"
|
|
196
183
|
}
|
|
197
184
|
],
|
|
198
185
|
"messages": [
|
package/lib/binding.js
CHANGED
|
@@ -238,7 +238,7 @@ class Binding {
|
|
|
238
238
|
await this.doBindUnbind(type, bind_source, bind_source_ep, 'coordinator', '1');
|
|
239
239
|
this.debug('Successfully ' + (type === 'bind' ? 'bound' : 'unbound') + ' Coordinator from ' + bind_source);
|
|
240
240
|
} catch (e) {
|
|
241
|
-
this.error(`Could not ${type} Coordinator from ${bind_source}: ${
|
|
241
|
+
this.error(`Could not ${type} Coordinator from ${bind_source}: ${(e && e.message ? e.message : 'no error message')} ${(e && e.stack ? e.stack : 'no call stack')}`);
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
} catch (error) {
|
package/lib/commands.js
CHANGED
|
@@ -150,8 +150,8 @@ class Commands {
|
|
|
150
150
|
return;
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
catch (
|
|
154
|
-
this.error(
|
|
153
|
+
catch (error) {
|
|
154
|
+
this.error(`Pairing with code failed with: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`);
|
|
155
155
|
this.adapter.sendTo(
|
|
156
156
|
from, command,
|
|
157
157
|
{error: 'Exception when trying to add QR code'},
|
package/lib/exposes.js
CHANGED
|
@@ -681,12 +681,15 @@ function createFromExposes(model, def) {
|
|
|
681
681
|
if (!Array.isArray(expose.values)) break;
|
|
682
682
|
const hasHold = expose.values.find((actionName) => actionName.includes('hold'));
|
|
683
683
|
const hasRelease = expose.values.find((actionName) => actionName.includes('release'));
|
|
684
|
+
const hasPress = expose.values.find((actionName) => actionName.includes('press'));
|
|
685
|
+
const hasPressRelease = expose.values.find((actionName) => actionName.includes('press_release'));
|
|
684
686
|
for (const actionName of expose.values) {
|
|
685
687
|
// is release state ? - skip
|
|
686
688
|
if (hasHold && hasRelease && actionName.includes('release')) continue;
|
|
687
689
|
// is hold state ?
|
|
688
690
|
if (hasHold && hasRelease && actionName.includes('hold')) {
|
|
689
691
|
const releaseActionName = actionName.replace('hold', 'release');
|
|
692
|
+
const releaseActionName2 = actionName.concat('_release');
|
|
690
693
|
state = {
|
|
691
694
|
id: actionName.replace(/\*/g, ''),
|
|
692
695
|
prop: 'action',
|
|
@@ -696,9 +699,11 @@ function createFromExposes(model, def) {
|
|
|
696
699
|
write: false,
|
|
697
700
|
read: true,
|
|
698
701
|
type: 'boolean',
|
|
699
|
-
getter: payload => payload.action === actionName ? true : (payload.action === releaseActionName ? false : undefined),
|
|
702
|
+
getter: payload => payload.action === actionName ? true : (payload.action === releaseActionName || payload.action === releaseActionName2 ? false : undefined),
|
|
700
703
|
};
|
|
701
|
-
} else {
|
|
704
|
+
} else if (hasPress && hasPressRelease && actionName.includes('press')) {
|
|
705
|
+
let getterKey = actionName.concat('_release');
|
|
706
|
+
if (expose.values.indexOf(getterKey) < 0) getterKey = actionName;
|
|
702
707
|
state = {
|
|
703
708
|
id: actionName.replace(/\*/g, ''),
|
|
704
709
|
prop: 'action',
|
|
@@ -708,10 +713,23 @@ function createFromExposes(model, def) {
|
|
|
708
713
|
write: false,
|
|
709
714
|
read: true,
|
|
710
715
|
type: 'boolean',
|
|
716
|
+
getter: payload => payload.action === getterKey ? true : undefined,
|
|
717
|
+
isEvent: true,
|
|
718
|
+
};
|
|
719
|
+
} else {
|
|
720
|
+
state = {
|
|
721
|
+
id: actionName.replace(/\*/g, ''),
|
|
722
|
+
prop: 'action',
|
|
723
|
+
name: actionName,
|
|
724
|
+
icon: undefined,
|
|
725
|
+
role: 'button',
|
|
726
|
+
write: false,
|
|
727
|
+
read: true,
|
|
728
|
+
type: 'boolean',
|
|
711
729
|
getter: payload => payload.action === actionName ? true : undefined,
|
|
712
730
|
isEvent: true,
|
|
713
731
|
};
|
|
714
|
-
}
|
|
732
|
+
};
|
|
715
733
|
pushToStates(state, expose.access);
|
|
716
734
|
}
|
|
717
735
|
state = null;
|
package/lib/groups.js
CHANGED
|
@@ -85,7 +85,7 @@ class Groups {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
} catch (error) {
|
|
88
|
-
if (error) this.error(`getGroupMembersFromController: error is ${
|
|
88
|
+
if (error) this.error(`getGroupMembersFromController: error is ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`);
|
|
89
89
|
else this.error('unidentifed error in getGroupMembersFromController');
|
|
90
90
|
}
|
|
91
91
|
return members;
|
|
@@ -138,7 +138,7 @@ class Groups {
|
|
|
138
138
|
for (const gpid of groups[epid]) {
|
|
139
139
|
const gpidn = parseInt(gpid);
|
|
140
140
|
if (gpidn < 0) {
|
|
141
|
-
this.
|
|
141
|
+
this.debug(`calling removeDevFromGroup with ${sysid}, ${-gpidn}, ${epid}` );
|
|
142
142
|
const response = await this.zbController.removeDevFromGroup(sysid, (-gpidn), epid);
|
|
143
143
|
if (response && response.error) {
|
|
144
144
|
errors.push(response.error);
|
|
@@ -146,7 +146,7 @@ class Groups {
|
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
} else if (gpidn > 0) {
|
|
149
|
-
this.
|
|
149
|
+
this.debug(`calling addDevToGroup with ${sysid}, ${gpidn}, ${epid}` );
|
|
150
150
|
const response = await this.zbController.addDevToGroup(sysid, (gpidn), epid);
|
|
151
151
|
if (response && response.error) {
|
|
152
152
|
errors.push(response.error);
|
|
@@ -158,7 +158,7 @@ class Groups {
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
} catch (e) {
|
|
161
|
-
this.warn('caught error ' +
|
|
161
|
+
this.warn('caught error ' + (e && e.message ? e.message : 'no error message') + ' in updateGroupMembership');
|
|
162
162
|
this.adapter.sendTo(from, command, {error: e}, callback);
|
|
163
163
|
return;
|
|
164
164
|
}
|
package/lib/statescontroller.js
CHANGED
|
@@ -54,9 +54,9 @@ class StatesController extends EventEmitter {
|
|
|
54
54
|
retainDeviceNames() {
|
|
55
55
|
clearTimeout(this.retTimeoutHandle);
|
|
56
56
|
this.retTimeoutHanlde = setTimeout(() => {
|
|
57
|
-
fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNamesDB, null, 2),
|
|
58
|
-
if (
|
|
59
|
-
this.error(`error saving device names: ${
|
|
57
|
+
fs.writeFile(this.dev_names_fn, JSON.stringify(savedDeviceNamesDB, null, 2), error => {
|
|
58
|
+
if (error) {
|
|
59
|
+
this.error(`error saving device names: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`);
|
|
60
60
|
} else {
|
|
61
61
|
this.debug('saved device names');
|
|
62
62
|
}
|
|
@@ -109,7 +109,7 @@ class StatesController extends EventEmitter {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
if (this.checkDebugDevice(id))
|
|
112
|
-
this.warn(`ELEVATED
|
|
112
|
+
this.warn(`ELEVATED O01: User state change of state ${id} with value ${state.val} (ack: ${state.ack}) from ${state.from}`);
|
|
113
113
|
|
|
114
114
|
this.debug(`User stateChange ${id} ${JSON.stringify(state)}`);
|
|
115
115
|
const devId = getAdId(this.adapter, id); // iobroker device id
|
|
@@ -211,7 +211,7 @@ class StatesController extends EventEmitter {
|
|
|
211
211
|
this.debug(`Change state '${stateKey}' at device ${deviceId} type '${model}'`);
|
|
212
212
|
const elevated = this.checkDebugDevice(deviceId);
|
|
213
213
|
|
|
214
|
-
if (elevated) this.warn(`ELEVATED
|
|
214
|
+
if (elevated) this.warn(`ELEVATED O02: Change state '${stateKey}' at device ${deviceId} type '${model}'`);
|
|
215
215
|
|
|
216
216
|
const devStates = await this.getDevStates(deviceId, model);
|
|
217
217
|
if (!devStates) {
|
|
@@ -181,7 +181,7 @@ class DeviceAvailability extends BaseExtension {
|
|
|
181
181
|
}
|
|
182
182
|
} catch (error) {
|
|
183
183
|
this.sendError(error);
|
|
184
|
-
this.debug(`Exception in readState of '${device.ieeeAddr}' - error : '${error}'`);
|
|
184
|
+
this.debug(`Exception in readState of '${device.ieeeAddr}' - error : '${(error && error.message ? error.message : 'no error message')}'`);
|
|
185
185
|
// intentionally empty: Just present to ensure we cause no harm
|
|
186
186
|
// when reading the state fails. => fall back on standard Ping function
|
|
187
187
|
}
|
package/lib/zbDeviceEvent.js
CHANGED
|
@@ -36,11 +36,22 @@ class DeviceEvent extends BaseExtension {
|
|
|
36
36
|
|
|
37
37
|
async callOnEvent(device, type, data, mappedDevice) {
|
|
38
38
|
if (!mappedDevice) {
|
|
39
|
-
|
|
39
|
+
try {
|
|
40
|
+
mappedDevice = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
this.log.error(`onEvent: unable to find mapped device for ${JSON.stringify(device)} `);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
if (mappedDevice && mappedDevice.onEvent) {
|
|
43
|
-
|
|
49
|
+
try {
|
|
50
|
+
mappedDevice.onEvent(type, data, device,mappedDevice.options,'{}');
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
this.log.error(`onEvent for ${JSON.stringify(device)} failed with error ${error.message}`);
|
|
54
|
+
}
|
|
44
55
|
}
|
|
45
56
|
}
|
|
46
57
|
}
|
package/lib/zigbeecontroller.js
CHANGED
|
@@ -148,9 +148,9 @@ class ZigbeeController extends EventEmitter {
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
this.debug(`Zigbee network parameters: panID=${debNetworkParam.panID} channel=${debNetworkParam.channel} extendedPanID=${extPanIDDebug}`);
|
|
151
|
-
} catch (
|
|
152
|
-
this.sendError(
|
|
153
|
-
this.error(`Starting zigbee-herdsman problem : ${
|
|
151
|
+
} catch (error) {
|
|
152
|
+
this.sendError(error);
|
|
153
|
+
this.error(`Starting zigbee-herdsman problem : ${(error && error.message ? error.message : 'no error message')}`);
|
|
154
154
|
throw 'Error herdsman start';
|
|
155
155
|
}
|
|
156
156
|
// Check if we have to turn off the LED
|
|
@@ -297,7 +297,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
297
297
|
}
|
|
298
298
|
} catch (error) {
|
|
299
299
|
this.sendError(error);
|
|
300
|
-
this.error(
|
|
300
|
+
this.error(`error in getGroups: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`);
|
|
301
301
|
return undefined;
|
|
302
302
|
}
|
|
303
303
|
}
|
|
@@ -308,7 +308,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
308
308
|
group && group.removeFromNetwork();
|
|
309
309
|
} catch (error) {
|
|
310
310
|
this.sendError(error);
|
|
311
|
-
this.error(`error in removeGroupById: ${error}`);
|
|
311
|
+
this.error(`error in removeGroupById: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`);
|
|
312
312
|
}
|
|
313
313
|
}
|
|
314
314
|
|
|
@@ -322,24 +322,34 @@ class ZigbeeController extends EventEmitter {
|
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
async verifyGroupExists(id) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
325
|
+
try {
|
|
326
|
+
const nid = typeof id === 'number' ? id : parseInt(id);
|
|
327
|
+
let group = await this.herdsman.getGroupByID(nid);
|
|
328
|
+
if (!group) {
|
|
329
|
+
group = await this.herdsman.createGroup(nid);
|
|
330
|
+
group.toZigbee = groupConverters;
|
|
331
|
+
group.model = 'group';
|
|
332
|
+
this.debug(`verifyGroupExists: created group ${nid}`);
|
|
333
|
+
} else {
|
|
334
|
+
this.debug(`verifyGroupExists: group ${nid} exists`);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
this.error(`verifyGroupExists: ${error && error.message ? error.message : 'unspecified error'}`);
|
|
334
339
|
}
|
|
335
340
|
}
|
|
336
341
|
|
|
337
342
|
async addPairingCode(code) {
|
|
338
343
|
this.debug(`calling addPairingCode with ${code}`);
|
|
339
344
|
if (code) {
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
345
|
+
try {
|
|
346
|
+
await this.herdsman.addInstallCode(code);
|
|
347
|
+
this.info(`added code ${code} for pairing`);
|
|
348
|
+
return true;
|
|
349
|
+
}
|
|
350
|
+
catch (error) {
|
|
351
|
+
this.error(`addPairingCode: ${error && error.message ? error.message : 'unspecified error'}`);
|
|
352
|
+
}
|
|
343
353
|
}
|
|
344
354
|
return false;
|
|
345
355
|
}
|
|
@@ -369,7 +379,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
369
379
|
} catch (error) {
|
|
370
380
|
this.sendError(error);
|
|
371
381
|
if (error) {
|
|
372
|
-
this.error(`getGroupMembersFromController:
|
|
382
|
+
this.error(`getGroupMembersFromController: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`);
|
|
373
383
|
} else {
|
|
374
384
|
this.error('unidentified error in getGroupMembersFromController');
|
|
375
385
|
}
|
|
@@ -378,100 +388,125 @@ class ZigbeeController extends EventEmitter {
|
|
|
378
388
|
}
|
|
379
389
|
|
|
380
390
|
getDevice(key) {
|
|
381
|
-
|
|
391
|
+
try {
|
|
392
|
+
return this.herdsman.getDeviceByIeeeAddr(key);
|
|
393
|
+
}
|
|
394
|
+
catch {
|
|
395
|
+
return undefined;
|
|
396
|
+
}
|
|
382
397
|
}
|
|
383
398
|
|
|
384
399
|
getDevicesByType(type) {
|
|
385
|
-
|
|
400
|
+
try {
|
|
401
|
+
return this.herdsman.getDevicesByType(type);
|
|
402
|
+
}
|
|
403
|
+
catch {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
386
406
|
}
|
|
387
407
|
|
|
388
408
|
getDeviceByNetworkAddress(networkAddress) {
|
|
389
|
-
|
|
409
|
+
try {
|
|
410
|
+
return this.herdsman.getDeviceByNetworkAddress(networkAddress);
|
|
411
|
+
}
|
|
412
|
+
catch {
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
390
415
|
}
|
|
391
416
|
|
|
392
417
|
async resolveEntity(key, ep) {
|
|
393
418
|
// assert(typeof key === 'string' || key.constructor.name === 'Device', `Wrong type '${typeof key}'`);
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
return {
|
|
399
|
-
type: 'device',
|
|
400
|
-
device: coordinator,
|
|
401
|
-
endpoint: coordinator.getEndpoint(1),
|
|
402
|
-
name: 'Coordinator',
|
|
403
|
-
};
|
|
404
|
-
} else {
|
|
405
|
-
const device = await this.herdsman.getDeviceByIeeeAddr(key);
|
|
406
|
-
if (device) {
|
|
407
|
-
const mapped = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
408
|
-
const endpoints = mapped && mapped.endpoint ? mapped.endpoint(device) : null;
|
|
409
|
-
let endpoint;
|
|
410
|
-
if (endpoints && ep != undefined && endpoints[ep]) {
|
|
411
|
-
endpoint = device.getEndpoint(endpoints[ep]);
|
|
412
|
-
} else if (endpoints && endpoints['default']) {
|
|
413
|
-
endpoint = device.getEndpoint(endpoints['default']);
|
|
414
|
-
} else {
|
|
415
|
-
const epNum = parseInt(ep);
|
|
416
|
-
if (!isNaN(epNum)) {
|
|
417
|
-
endpoint = device.getEndpoint(epNum);
|
|
418
|
-
} else {
|
|
419
|
-
endpoint = device.endpoints[0];
|
|
420
|
-
}
|
|
421
|
-
}
|
|
419
|
+
try {
|
|
420
|
+
if (typeof key === 'string') {
|
|
421
|
+
if (key === 'coordinator') {
|
|
422
|
+
const coordinator = this.herdsman.getDevicesByType('Coordinator')[0];
|
|
422
423
|
return {
|
|
423
424
|
type: 'device',
|
|
424
|
-
device,
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
endpoints: device.endpoints,
|
|
428
|
-
name: key,
|
|
425
|
+
device: coordinator,
|
|
426
|
+
endpoint: coordinator.getEndpoint(1),
|
|
427
|
+
name: 'Coordinator',
|
|
429
428
|
};
|
|
429
|
+
} else {
|
|
430
|
+
const device = await this.herdsman.getDeviceByIeeeAddr(key);
|
|
431
|
+
if (device) {
|
|
432
|
+
const mapped = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
433
|
+
const endpoints = mapped && mapped.endpoint ? mapped.endpoint(device) : null;
|
|
434
|
+
let endpoint;
|
|
435
|
+
if (endpoints && ep != undefined && endpoints[ep]) {
|
|
436
|
+
endpoint = device.getEndpoint(endpoints[ep]);
|
|
437
|
+
} else if (endpoints && endpoints['default']) {
|
|
438
|
+
endpoint = device.getEndpoint(endpoints['default']);
|
|
439
|
+
} else {
|
|
440
|
+
const epNum = parseInt(ep);
|
|
441
|
+
if (!isNaN(epNum)) {
|
|
442
|
+
endpoint = device.getEndpoint(epNum);
|
|
443
|
+
} else {
|
|
444
|
+
endpoint = device.endpoints[0];
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return {
|
|
448
|
+
type: 'device',
|
|
449
|
+
device,
|
|
450
|
+
mapped,
|
|
451
|
+
endpoint,
|
|
452
|
+
endpoints: device.endpoints,
|
|
453
|
+
name: key,
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
} else if (typeof key === 'number') {
|
|
458
|
+
let group = await this.herdsman.getGroupByID(key);
|
|
459
|
+
if (!group) group = await this.herdsman.createGroup(key);
|
|
460
|
+
group.toZigbee = groupConverters;
|
|
461
|
+
group.model = 'group';
|
|
462
|
+
return {
|
|
463
|
+
type: 'group',
|
|
464
|
+
mapped: group,
|
|
465
|
+
group,
|
|
466
|
+
name: `Group ${key}`,
|
|
467
|
+
};
|
|
468
|
+
} else {
|
|
469
|
+
let mapped;
|
|
470
|
+
try {
|
|
471
|
+
mapped = await zigbeeHerdsmanConverters.findByDevice(key);
|
|
472
|
+
} catch (err) {
|
|
473
|
+
this.error(`zigbeeHerdsmanConverters findByDevice ${key.ieeeAddr}`);
|
|
430
474
|
}
|
|
431
|
-
}
|
|
432
|
-
} else if (typeof key === 'number') {
|
|
433
|
-
let group = await this.herdsman.getGroupByID(key);
|
|
434
|
-
if (!group) group = await this.herdsman.createGroup(key);
|
|
435
|
-
group.toZigbee = groupConverters;
|
|
436
|
-
group.model = 'group';
|
|
437
|
-
return {
|
|
438
|
-
type: 'group',
|
|
439
|
-
mapped: group,
|
|
440
|
-
group,
|
|
441
|
-
name: `Group ${key}`,
|
|
442
|
-
};
|
|
443
|
-
} else {
|
|
444
|
-
let mapped;
|
|
445
|
-
try {
|
|
446
|
-
mapped = await zigbeeHerdsmanConverters.findByDevice(key);
|
|
447
|
-
} catch (err) {
|
|
448
|
-
this.error(`zigbeeHerdsmanConverters findByDevice ${key.ieeeAddr}`);
|
|
449
|
-
}
|
|
450
475
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
476
|
+
return {
|
|
477
|
+
type: 'device',
|
|
478
|
+
device: key,
|
|
479
|
+
mapped: mapped,
|
|
480
|
+
name: key.type === 'Coordinator' ? 'Coordinator' : key.ieeeAddr,
|
|
481
|
+
};
|
|
482
|
+
}
|
|
457
483
|
}
|
|
484
|
+
catch {
|
|
485
|
+
return undefined;
|
|
486
|
+
}
|
|
487
|
+
|
|
458
488
|
}
|
|
459
489
|
|
|
460
490
|
async incMsgHandler(message) {
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
491
|
+
try {
|
|
492
|
+
this.debug('incoming msg', message);
|
|
493
|
+
const device = await this.herdsman.getDeviceByIeeeAddr(message.srcaddr);
|
|
494
|
+
if (!device) {
|
|
495
|
+
this.debug('Message without device!');
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
// We can't handle devices without modelId.
|
|
499
|
+
if (!device.modelId) {
|
|
500
|
+
this.debug('Message without modelId!');
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
this.event('msg', device.ieeeAddr, message, {
|
|
504
|
+
modelId: device.modelId
|
|
505
|
+
});
|
|
466
506
|
}
|
|
467
|
-
|
|
468
|
-
if (!device.modelId) {
|
|
469
|
-
this.debug('Message without modelId!');
|
|
507
|
+
catch {
|
|
470
508
|
return;
|
|
471
509
|
}
|
|
472
|
-
this.event('msg', device.ieeeAddr, message, {
|
|
473
|
-
modelId: device.modelId
|
|
474
|
-
});
|
|
475
510
|
}
|
|
476
511
|
|
|
477
512
|
// Stop controller
|
|
@@ -814,39 +849,45 @@ class ZigbeeController extends EventEmitter {
|
|
|
814
849
|
if (cfg == null) {
|
|
815
850
|
cfg = {};
|
|
816
851
|
}
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
852
|
+
try {
|
|
853
|
+
if (type === 'foundation') {
|
|
854
|
+
cfg.disableDefaultResponse = true;
|
|
855
|
+
/*
|
|
856
|
+
if (cmd === 'read' && !Array.isArray(zclData)) {
|
|
857
|
+
// needs to be iterable (string[] | number [])
|
|
858
|
+
zclData[Symbol.iterator] = function* () {
|
|
859
|
+
let k;
|
|
860
|
+
for (k in this) {
|
|
861
|
+
yield k;
|
|
862
|
+
}
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
*/
|
|
866
|
+
let result;
|
|
867
|
+
if (cmd === 'configReport') {
|
|
868
|
+
result = await endpoint.configureReporting(cid, zclData, cfg);
|
|
869
|
+
} else {
|
|
870
|
+
if (cmd === 'read' && !Array.isArray(zclData))
|
|
871
|
+
result = await endpoint[cmd](cid, Object.keys(zclData), cfg);
|
|
872
|
+
else
|
|
873
|
+
result = await endpoint[cmd](cid, zclData, cfg);
|
|
874
|
+
}
|
|
875
|
+
callback && callback(undefined, result);
|
|
876
|
+
} else if (type === 'functionalResp') {
|
|
877
|
+
cfg.disableDefaultResponse = false;
|
|
878
|
+
const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
|
|
879
|
+
callback && callback(undefined, result);
|
|
834
880
|
} else {
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
result = await endpoint[cmd](cid, zclData, cfg);
|
|
881
|
+
cfg.disableDefaultResponse = false;
|
|
882
|
+
const result = await endpoint.command(cid, cmd, zclData, cfg);
|
|
883
|
+
callback && callback(undefined, result);
|
|
839
884
|
}
|
|
840
|
-
callback && callback(undefined, result);
|
|
841
|
-
} else if (type === 'functionalResp') {
|
|
842
|
-
cfg.disableDefaultResponse = false;
|
|
843
|
-
const result = await endpoint.commandResponse(cid, cmd, zclData, cfg, zclSeqNum);
|
|
844
|
-
callback && callback(undefined, result);
|
|
845
|
-
} else {
|
|
846
|
-
cfg.disableDefaultResponse = false;
|
|
847
|
-
const result = await endpoint.command(cid, cmd, zclData, cfg);
|
|
848
|
-
callback && callback(undefined, result);
|
|
849
885
|
}
|
|
886
|
+
catch (error)
|
|
887
|
+
{
|
|
888
|
+
this.log.error(`error sending ${type} ${cmd} to endpoint: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`)
|
|
889
|
+
}
|
|
890
|
+
|
|
850
891
|
}
|
|
851
892
|
|
|
852
893
|
async addDevToGroup(devId, groupId, epid) {
|
|
@@ -894,7 +935,7 @@ class ZigbeeController extends EventEmitter {
|
|
|
894
935
|
} catch (error) {
|
|
895
936
|
this.sendError(error);
|
|
896
937
|
this.error(`Exception when trying to Add ${devId} to group ${groupId}`, error);
|
|
897
|
-
return {error: `Failed to add ${devId} to group ${groupId}: ${
|
|
938
|
+
return {error: `Failed to add ${devId} to group ${groupId}: ${(error && error.message ? error.message : 'no error message')} ${(error && error.stack ? error.stack : 'no call stack')}`};
|
|
898
939
|
}
|
|
899
940
|
return {};
|
|
900
941
|
}
|
|
@@ -957,16 +998,21 @@ class ZigbeeController extends EventEmitter {
|
|
|
957
998
|
target = !target ? this.getCoordinator() : target;
|
|
958
999
|
|
|
959
1000
|
this.debug(`Binding ${log}`);
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
1001
|
+
try {
|
|
1002
|
+
ep.bind(cluster, target, error => {
|
|
1003
|
+
if (error) {
|
|
1004
|
+
this.sendError(error);
|
|
1005
|
+
this.error(`Failed to bind ${log} - (${error})`);
|
|
1006
|
+
} else {
|
|
1007
|
+
this.debug(`Successfully bound ${log}`);
|
|
1008
|
+
}
|
|
967
1009
|
|
|
1010
|
+
callback(error);
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1013
|
+
catch (error) {
|
|
968
1014
|
callback(error);
|
|
969
|
-
}
|
|
1015
|
+
}
|
|
970
1016
|
}
|
|
971
1017
|
|
|
972
1018
|
unbind(ep, cluster, target, callback) {
|
|
@@ -974,15 +1020,21 @@ class ZigbeeController extends EventEmitter {
|
|
|
974
1020
|
target = !target ? this.getCoordinator() : target;
|
|
975
1021
|
|
|
976
1022
|
this.debug(`Unbinding ${log}`);
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1023
|
+
try {
|
|
1024
|
+
ep.unbind(cluster, target, (error) => {
|
|
1025
|
+
if (error) {
|
|
1026
|
+
this.error(`Failed to unbind ${log} - (${error})`);
|
|
1027
|
+
} else {
|
|
1028
|
+
this.debug(`Successfully unbound ${log}`);
|
|
1029
|
+
}
|
|
983
1030
|
|
|
1031
|
+
callback(error);
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
catch (error)
|
|
1035
|
+
{
|
|
984
1036
|
callback(error);
|
|
985
|
-
}
|
|
1037
|
+
}
|
|
986
1038
|
}
|
|
987
1039
|
|
|
988
1040
|
reset(mode, callback) {
|
package/main.js
CHANGED
|
@@ -629,7 +629,14 @@ class Zigbee extends utils.Adapter {
|
|
|
629
629
|
let isGroup = false;
|
|
630
630
|
const has_elevated_debug = this.stController.checkDebugDevice(deviceId)
|
|
631
631
|
|
|
632
|
-
|
|
632
|
+
if (has_elevated_debug)
|
|
633
|
+
{
|
|
634
|
+
const stateNames = [];
|
|
635
|
+
stateList.forEach( state => stateNames.push(state.id));
|
|
636
|
+
this.log.warn(`ELEVATED O03: Publishing to ${deviceId} of model ${model} ${stateNames.join(', ')}`);
|
|
637
|
+
}
|
|
638
|
+
else
|
|
639
|
+
this.log.debug(`publishFromState : ${deviceId} ${model} ${safeJsonStringify(stateList)}`);
|
|
633
640
|
if (model === 'group') {
|
|
634
641
|
isGroup = true;
|
|
635
642
|
deviceId = parseInt(deviceId);
|
|
@@ -637,13 +644,11 @@ class Zigbee extends utils.Adapter {
|
|
|
637
644
|
try {
|
|
638
645
|
const entity = await this.zbController.resolveEntity(deviceId);
|
|
639
646
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
const mappedModel = entity.mapped;
|
|
647
|
+
const mappedModel = (entity ? entity.mapped : undefined);
|
|
643
648
|
|
|
644
649
|
if (!mappedModel) {
|
|
645
|
-
this.log.debug(`No mapped model for ${model}`);
|
|
646
|
-
if (has_elevated_debug) this.log.
|
|
650
|
+
this.log.debug(`No mapped model for ${deviceId} (model ${model})`);
|
|
651
|
+
if (has_elevated_debug) this.log.error(`ELEVATED OE01: No mapped model ${deviceId} (model ${model})`)
|
|
647
652
|
return;
|
|
648
653
|
}
|
|
649
654
|
|
|
@@ -682,25 +687,34 @@ class Zigbee extends utils.Adapter {
|
|
|
682
687
|
// on activation of the 'device_query' state trigger hardware query where possible
|
|
683
688
|
if (stateDesc.id === 'device_query') {
|
|
684
689
|
if (this.query_device_block.indexOf(deviceId) > -1) {
|
|
685
|
-
this.log.
|
|
690
|
+
this.log.info(`Device query for '${entity.device.ieeeAddr}' blocked`);
|
|
686
691
|
return;
|
|
687
692
|
}
|
|
688
693
|
if (mappedModel) {
|
|
689
694
|
this.query_device_block.push(deviceId);
|
|
690
|
-
|
|
695
|
+
if (has_elevated_debug)
|
|
696
|
+
this.log.warn(`ELEVATED O06: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' triggered`);
|
|
697
|
+
let t;
|
|
691
698
|
for (const converter of mappedModel.toZigbee) {
|
|
692
699
|
if (converter.hasOwnProperty('convertGet')) {
|
|
693
700
|
for (const ckey of converter.key) {
|
|
694
701
|
try {
|
|
695
|
-
await converter.convertGet(entity.device.endpoints[0], ckey, {});
|
|
702
|
+
await converter.convertGet(entity.device.endpoints[0], ckey, {endpoint_name:entity.device.endpoints[0].ID.toString()});
|
|
696
703
|
} catch (error) {
|
|
697
|
-
|
|
698
|
-
|
|
704
|
+
if (has_elevated_debug) {
|
|
705
|
+
this.log.warn(`ELEVATED OE02.1 Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' from query with '${error && error.message ? error.message : 'no error message'}`);
|
|
706
|
+
}
|
|
707
|
+
else
|
|
708
|
+
this.log.info(`failed to read state ${JSON.stringify(ckey)} of ${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID} after device query`);
|
|
699
709
|
}
|
|
700
710
|
}
|
|
701
711
|
}
|
|
702
712
|
}
|
|
703
|
-
|
|
713
|
+
if (has_elevated_debug)
|
|
714
|
+
this.log.warn(`ELEVATED O07: Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`);
|
|
715
|
+
else
|
|
716
|
+
this.log.info(`Device query for '${entity.device.ieeeAddr}/${entity.device.endpoints[0].ID}' complete`);
|
|
717
|
+
|
|
704
718
|
const idToRemove = deviceId;
|
|
705
719
|
setTimeout(() => {
|
|
706
720
|
const idx = this.query_device_block.indexOf(idToRemove);
|
|
@@ -715,6 +729,7 @@ class Zigbee extends utils.Adapter {
|
|
|
715
729
|
}
|
|
716
730
|
|
|
717
731
|
let converter = undefined;
|
|
732
|
+
let msgCnt = 1;
|
|
718
733
|
for (const c of mappedModel.toZigbee) {
|
|
719
734
|
|
|
720
735
|
if (!c.hasOwnProperty('convertSet')) continue;
|
|
@@ -724,13 +739,14 @@ class Zigbee extends utils.Adapter {
|
|
|
724
739
|
if (c.hasOwnProperty('convertSet') && converter === undefined)
|
|
725
740
|
{
|
|
726
741
|
converter = c;
|
|
727
|
-
if (has_elevated_debug)
|
|
728
|
-
this.log.warn(`ELEVATED
|
|
742
|
+
if (has_elevated_debug) {
|
|
743
|
+
this.log.warn(`ELEVATED O4.${msgCnt++}: Setting converter to keyless converter for ${deviceId} of type ${model}`)
|
|
744
|
+
}
|
|
729
745
|
this.log.debug('setting converter to keyless converter')
|
|
730
746
|
}
|
|
731
747
|
else
|
|
732
748
|
{
|
|
733
|
-
if (has_elevated_debug) this.log.warn(`ELEVATED
|
|
749
|
+
if (has_elevated_debug) this.log.warn(`ELEVATED O4.${msgCnt++}: ignoring keyless converter for ${deviceId} of type ${model}`)
|
|
734
750
|
this.log.debug('ignoring keyless converter')
|
|
735
751
|
}
|
|
736
752
|
continue;
|
|
@@ -738,7 +754,7 @@ class Zigbee extends utils.Adapter {
|
|
|
738
754
|
if (c.key.includes(stateDesc.prop) || c.key.includes(stateDesc.setattr) || c.key.includes(stateDesc.id))
|
|
739
755
|
{
|
|
740
756
|
this.log.debug(`${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`)
|
|
741
|
-
if (has_elevated_debug) this.log.warn(`ELEVATED
|
|
757
|
+
if (has_elevated_debug) this.log.warn(`ELEVATED O4.${msgCnt++}: ${(converter===undefined?'Setting':'Overriding')}' converter to converter with key(s)'${JSON.stringify(c.key)}}`)
|
|
742
758
|
converter = c;
|
|
743
759
|
}
|
|
744
760
|
}
|
|
@@ -804,7 +820,7 @@ class Zigbee extends utils.Adapter {
|
|
|
804
820
|
try {
|
|
805
821
|
const result = await converter.convertSet(target, key, preparedValue, meta);
|
|
806
822
|
this.log.debug(`convert result ${safeJsonStringify(result)}`);
|
|
807
|
-
if (has_elevated_debug) this.log.warn(`ELEVATED
|
|
823
|
+
if (has_elevated_debug) this.log.warn(`ELEVATED O05: convert result ${safeJsonStringify(result)} sent to device ${deviceId}`);
|
|
808
824
|
if (result !== undefined) {
|
|
809
825
|
if (stateModel && !isGroup) {
|
|
810
826
|
this.acknowledgeState(deviceId, model, stateDesc, value);
|
|
@@ -824,7 +840,7 @@ class Zigbee extends utils.Adapter {
|
|
|
824
840
|
}
|
|
825
841
|
});
|
|
826
842
|
} catch (err) {
|
|
827
|
-
this.log.error(`No entity for ${deviceId}`);
|
|
843
|
+
this.log.error(`No entity for ${deviceId} : ${err && err.message ? err.message : ''}`);
|
|
828
844
|
}
|
|
829
845
|
}
|
|
830
846
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.zigbee",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "Kirov Ilya",
|
|
6
6
|
"email": "kirovilya@gmail.com"
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@iobroker/adapter-core": "^3.2.2",
|
|
25
|
-
"@iobroker/dm-utils": "^0.
|
|
25
|
+
"@iobroker/dm-utils": "^1.0.9",
|
|
26
26
|
"humanize-duration": "^3.32.1",
|
|
27
27
|
"tar": "^7.4.3",
|
|
28
28
|
"ajv": "^8.17.1",
|
|
29
29
|
"uri-js": "^4.4.1",
|
|
30
|
-
"typescript": "^5.
|
|
30
|
+
"typescript": "^5.7.3",
|
|
31
31
|
"zigbee-herdsman": "2.1.9",
|
|
32
32
|
"zigbee-herdsman-converters": "20.58.0"
|
|
33
33
|
},
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
"@iobroker/testing": "^5.0.0",
|
|
41
41
|
"chai": "^5.1.2",
|
|
42
42
|
"chai-as-promised": "^7.1.1",
|
|
43
|
-
"eslint": "^9.
|
|
43
|
+
"eslint": "^9.19.0",
|
|
44
44
|
"eslint-config-prettier": "^9.1.0",
|
|
45
45
|
"eslint-plugin-prettier": "^5.2.1",
|
|
46
46
|
"gulp": "^4.0.2",
|
|
47
47
|
"gulp-jsdoc3": "^3.0.0",
|
|
48
48
|
"gulp-replace": "^1.1.4",
|
|
49
49
|
"mixin-deep": "^2.0.1",
|
|
50
|
-
"mocha": "^
|
|
50
|
+
"mocha": "^11.1.0"
|
|
51
51
|
},
|
|
52
52
|
"homepage": "https://github.com/ioBroker/ioBroker.zigbee",
|
|
53
53
|
"keywords": [
|