iobroker.zigbee 3.3.1 → 3.3.3

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2018-2025 Kirov Ilya <kirovilya@gmail.com>
3
+ Copyright (c) 2018-2026 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
@@ -141,10 +141,22 @@ You can thank the authors by these links:
141
141
 
142
142
  -----------------------------------------------------------------------------------------------------
143
143
  ## Changelog
144
+ ### 3.3.3 (2026-01-11)
145
+ * Fix crash bug
146
+ * getter for composite states V1
147
+ * zhc
148
+ *
149
+
150
+ ### 3.3.2 (2026-01-04)
151
+ * Fix sync brightness / state
152
+ * Fix bug in expose
153
+ * Fix rewrite state config
154
+ *
155
+
144
156
  ### 3.3.1 (2025-12-31)
145
157
  * Update documentation
146
158
  * Color Hue/Saturation in Groups
147
- * ZH8
159
+ * Zigbee-Herdsman v8.x.x
148
160
  * Sort by model in Admin
149
161
  * Object for complex exposes
150
162
  * POSSIBLY BREAKING: Complex exposes changed to 'channel / state' structure
@@ -411,7 +423,7 @@ You can thank the authors by these links:
411
423
  ## License
412
424
  The MIT License (MIT)
413
425
 
414
- Copyright (c) 2018-2025 Kirov Ilya <kirovilya@gmail.com>
426
+ Copyright (c) 2018-2026 Kirov Ilya <kirovilya@gmail.com>
415
427
 
416
428
  Permission is hereby granted, free of charge, to any person obtaining a copy
417
429
  of this software and associated documentation files (the "Software"), to deal
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zigbee",
4
- "version": "3.3.1",
4
+ "version": "3.3.3",
5
5
  "news": {
6
+ "3.3.3": {
7
+ "en": "Fix crash bug\ngetter for composite states V1\nzhc\n",
8
+ "de": "Fehler behoben\ngetter für zusammengesetzte Zustände V1\nzh\n",
9
+ "ru": "Исправить ошибку crash bug\nгеттер для композитных состояний V1\nджк\n",
10
+ "pt": "Corrigir erro de falha\ngetter para estados compostos V1\nzhc\n",
11
+ "nl": "Fix crash bug\ngetter voor samengestelde toestanden V1\nzhc\n",
12
+ "fr": "Correction d'un bug de plantage\ngetter pour les états composites V1\nzhc\n",
13
+ "it": "Correre bug crash\ngetter per stati compositi V1\nzhc\n",
14
+ "es": "Corrección de fallo\ngetter para estados compuestos V1\nzhc\n",
15
+ "pl": "Napraw błąd awarii\ngetter for composite states V1\nzhc\n",
16
+ "uk": "Виправлення помилки збою\nоберт для композитних станів V1\nжк\n",
17
+ "zh-cn": "修复崩溃错误\nv1 复合状态获取器\n日语\n"
18
+ },
19
+ "3.3.2": {
20
+ "en": "Fix sync brightness / state\nFix bug in expose\nFix rewrite state config\n",
21
+ "de": "Synchronisierhelligkeit / Zustand\nFehler behoben in exponieren\nRewriting State config\n",
22
+ "ru": "Исправление яркости синхронизации / состояние\nУстранение ошибки в разоблачении\nRewrite state config (переписать конфигурацию состояния)\n",
23
+ "pt": "Corrigir o brilho / estado da sincronização\nCorrigir erro na exposição\nCorrigir a configuração do estado de reescrita\n",
24
+ "nl": "Synchronische helderheid / status herstellen\nFix bug in expos\nHerschrijf statusconfiguratie\n",
25
+ "fr": "Correction de la luminosité de synchronisation / état\nCorrection du bogue dans l'exposition\nCorrection de la configuration de l'état de réécriture\n",
26
+ "it": "Fissare la luminosità di sincronizzazione / stato\nFissare bug in esposizione\nRiparare la configurazione dello stato di riscrittura\n",
27
+ "es": "Fijar el brillo de sincronización / estado\nFijar fallo en exponer\nReescribir el config del estado\n",
28
+ "pl": "Napraw jasność / stan synchronizacji\nPopraw błąd w odsłonięciu\nPopraw stan konfiguracji\n",
29
+ "uk": "Виправлення сипучих яскравості / стану\nВиправлення помилок у вигнанні\nВиправлення перезапису державного налаштування\n",
30
+ "zh-cn": "修正同步亮度/ 状态\n在曝光中修复错误\n修改状态配置\n"
31
+ },
6
32
  "3.3.1": {
7
33
  "en": "Update documentation\nColor Hue/Saturation in Groups\nZH8\nSort by model in Admin\nObject for complex exposes\nPOSSIBLY BREAKING: Complex exposes changed to 'channel / state' structure\nBugfixes\n",
8
34
  "de": "Dokumentation zur Aktualisierung\nFarbe Hue/Sättigung in Gruppen\nZH8\nSortieren nach Modell in Admin\nObjekt für komplexe Exponate\nPOSSIBLY BREAKING: Komplex enthüllt geändert in 'Kanal / Zustand' Struktur\nBugfixes\n",
@@ -67,32 +93,6 @@
67
93
  "pl": "Ulepszenia dotyczące debugowania interfejsu użytkownika\nOpcja \"resend _ states\" do publikowania wartości stanu dla urządzenia przy ponownym połączeniu\nUlepszona karta grupowa\nUlepszone informacje grupowe\nZmodyfikowana karta koordynatora (2 strony)\nponowna próba błędu 25\njasne komunikaty błędów ukryte\nZHC 25.50.0 lub nowsze",
68
94
  "uk": "Удосконалення на дебурзі UI\nВаріант 'resend_states' для публікації державних значень для пристрою на відключенні\nПокращена групова карта\nПокращена інформація групи\nЗмінена карта координатора (2 сторони)\nптиця по помилки 25\nчіткі повідомлення про помилку\nZHC 25.50.0 або новачок",
69
95
  "zh-cn": "调试 UI 的改进\n选项“ resend_ states ” 以在重新连接时发布状态值以设备\n改进组卡\n改进组信息\n修改的协调员卡(2面)\n重试错误 25\n清除隐藏的错误消息\nZHC 25.50.0或更新"
70
- },
71
- "3.2.2": {
72
- "en": "Bugfix on delete object.\nimproved device query.\nfixed delete device with local overrides.\n",
73
- "de": "Bugfix auf Löschobjekt.\nverbesserte geräteabfrage.\nfeste löschvorrichtung mit lokalen overrides.\n",
74
- "ru": "Bugfix для удаления объекта.\nулучшенный запрос устройства.\nфиксированное устройство удаления с локальными переопределениями.\n",
75
- "pt": "Correcção de erros ao apagar o objecto.\npesquisa de dispositivos melhorada.\ndispositivo de exclusão fixo com substituições locais.\n",
76
- "nl": "Bugfix bij verwijderen van object.\nverbeterde apparaatquery.\nvast delete apparaat met lokale overrides.\n",
77
- "fr": "Correction sur objet de suppression.\nrequête de périphérique améliorée.\ndispositif de suppression fixe avec redéfinitions locales.\n",
78
- "it": "Bugfix su delete object.\nmigliore query del dispositivo.\ndispositivo di cancellazione fisso con override locali.\n",
79
- "es": "Bugfix en el objeto borrado.\nmejorada consulta de dispositivos.\ndispositivo de eliminación fijo con anulas locales.\n",
80
- "pl": "Bugfix na usunąć obiekt.\nulepszone zapytanie urządzenia.\nnaprawione urządzenie usuwające z lokalnymi przekroczeniami.\n",
81
- "uk": "Виправлення помилок при видаленні об'єкта.\nпокращений пристрій запиту.\nфіксований пристрій видалення з локальними перенаряддями.\n",
82
- "zh-cn": "删除对象上的错误修正 .\n改进设备查询 .\n有本地覆盖的固定删除设备 .\n"
83
- },
84
- "3.2.1": {
85
- "en": "fix bug #2640\n",
86
- "de": "fehler beheben #2640\n",
87
- "ru": "исправить ошибку #2640\n",
88
- "pt": "corrigir o erro # 2640\n",
89
- "nl": "fix bug #2640\n",
90
- "fr": "correction du bug #2640\n",
91
- "it": "fix bug #2640\n",
92
- "es": "corrección de error #2640\n",
93
- "pl": "fix bug # 2640\n",
94
- "uk": "виправлення помилки #2640\n",
95
- "zh-cn": "修复错误 # 2640\n"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/lib/exposes.js CHANGED
@@ -180,15 +180,32 @@ function genState(expose, overrides) {
180
180
 
181
181
  function generateCompositeStates(expose, _channelID, options)
182
182
  {
183
- const states = [];
184
183
  const stname = `${_channelID}${expose.property}`;
185
184
  const stateId = stname.replace(/\*/g, '');
186
185
  const stateName = (expose.description || expose.name);
187
186
  const channelID = options.newCompositeMethod ? `c_${stateId}.` : '';
187
+ const stateData = {
188
+ states: [],
189
+ keys:[]
190
+ };
191
+ if (expose?.features?.[Symbol.iterator]) for (const prop of expose.features) {
192
+ if (prop.type === 'composite' || prop.type === 'list') {
193
+ const subStateData = generateCompositeStates(prop, channelID, options);
194
+ if (options.newCompositeMethod)
195
+ stateData.keys.push(prop.property);
196
+ else
197
+ stateData.keys.push(...subStateData.keys);
198
+ stateData.states.push(...subStateData.states);
199
+ }
200
+ else {
201
+ stateData.states.push(genState(prop, options.newCompositeMethod ? { fromComposite: true, name: `${channelID}${prop.property}` , channelID: stateId }: { fromComposite: true }))
202
+ stateData.keys.push(prop.property)
203
+ }
204
+ }
188
205
  if (options.newCompositeMethod) {
189
-
190
206
  if (typeof stname !== 'string') return undefined;;
191
- states.push({
207
+ const KeysToUpdate = stateData.keys;
208
+ stateData.states.push({
192
209
  id: stateId,
193
210
  name: stateName,
194
211
  icon: undefined,
@@ -196,7 +213,17 @@ function generateCompositeStates(expose, _channelID, options)
196
213
  write: Boolean (expose.access & ea.SET),
197
214
  read: Boolean(expose.access & ea.GET),
198
215
  type: 'string',
199
- getter: (value) => { return (typeof value === 'object' ? JSON.stringify(value) : value) },
216
+ subkeys : stateData.keys,
217
+ getter: (value) => {
218
+ const myval = value[stateId];
219
+ if (myval != undefined && typeof myval === 'object') return JSON.stringify(myval);
220
+ return myval;
221
+ },
222
+ compositeGetter: (value) => {
223
+ const myval = value[stateId];
224
+ if (typeof myval === 'object') return myval;
225
+ return undefined;
226
+ },
200
227
  setter: (value) => {
201
228
  try {
202
229
  return JSON.parse(value);
@@ -208,103 +235,8 @@ function generateCompositeStates(expose, _channelID, options)
208
235
  })
209
236
 
210
237
  }
211
- for (const prop of expose.features) {
212
- if (prop.type === 'composite' || prop.type === 'list') {
213
- states.push(...generateCompositeStates(prop, channelID, options))
214
- }
215
- else
216
- states.push(genState(prop, options.newCompositeMethod ? { fromComposite: true, name: `${channelID}${prop.name}` , channelID: stateId }: { fromComposite: true }))
217
- /*
218
- switch (prop.type) {
219
- case 'numeric':
220
- case 'text':
221
- case 'binary':
222
- {
223
- const st = genState(prop, 'state', `${channelID}${prop.name}`);
224
- st.prop = expose.property;
225
- st.inOptions = !LocalData.options.newCompositeMethod;
226
- if (LocalData.options.newCompositeMethod) {
227
- st.compositeKey = stateId;
228
- st.compositeTimeout = 250;
229
- st.compositeState = stateId;
230
- } else
231
- {
232
- // if we have a composite expose, the value have to be an object {expose.property : {prop.property: value}}
233
- // I'm not fully sure, as it really needed, but
234
- st.setterOpt = (value, options) => {
235
- const result = {};
236
- options[prop.property] = value;
237
- result[expose.property] = options;
238
- return result;
239
- };
240
- if (prop.access & ea.SET) {
241
- st.setter = (value, options) => {
242
- const result = {};
243
- options[prop.property] = value;
244
- result[expose.property] = options;
245
- return result;
246
- };
247
- st.setattr = expose.property;
248
- }
249
- // if we have a composite expose, the payload will be an object {expose.property : {prop.property: value}}
250
- if (prop.access & ea.STATE) {
251
- st.getter = payload => {
252
- if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(prop.property)) {
253
- return !isNaN(payload[expose.property][prop.property]) ? payload[expose.property][prop.property] : undefined;
254
- } else {
255
- return undefined;
256
- }
257
- };
258
- } else {
259
- st.getter = payload => undefined;
260
- }
261
- }
262
- pushToStates(st, prop.access);
263
- break;
264
- }
265
- case 'list': {
266
- for (const propList of prop.item_type.features) {
267
- const st = genState(propList);
268
- st.prop = expose.property;
269
- st.inOptions = true;
270
- st.setterOpt = (value, options) => {
271
- const result = {};
272
- options[propList.property] = value;
273
- result[expose.property] = options;
274
- return result;
275
- };
276
- if (propList.access & ea.SET) {
277
- st.setter = (value, options) => {
278
- const result = {};
279
- options[propList.property] = value;
280
- result[expose.property] = options;
281
- return result;
282
- };
283
- st.setattr = expose.property;
284
- }
285
- if (propList.access & ea.STATE) {
286
- st.getter = payload => {
287
- if ((payload.hasOwnProperty(expose.property)) && (payload[expose.property] !== null) && payload[expose.property].hasOwnProperty(propList.property)) {
288
- return !isNaN(payload[expose.property][propList.property]) ? payload[expose.property][propList.property] : undefined;
289
- } else {
290
- return undefined;
291
- }
292
- };
293
- } else {
294
- st.getter = payload => undefined;
295
- }
296
-
297
- st.id = st.prop + '_' + st.id;
298
- pushToStates(st, propList.access);
299
- break;
300
- }
301
- }
302
-
303
- }
304
- */
305
- }
306
238
 
307
- return states;
239
+ return stateData;
308
240
 
309
241
  }
310
242
  function createFromExposes(model, def, device, options, log) {
@@ -484,7 +416,7 @@ function createFromExposes(model, def, device, options, log) {
484
416
  let colorXYprop = undefined;
485
417
  let colorHSprop = undefined;
486
418
 
487
- for (const prop of expose.features) {
419
+ if (expose?.features?.[Symbol.iterator]) for (const prop of expose.features) {
488
420
  switch (prop.name) {
489
421
  case 'state': {
490
422
  const stateNameS = expose.endpoint ? `state_${expose.endpoint}` : 'state';
@@ -837,7 +769,7 @@ function createFromExposes(model, def, device, options, log) {
837
769
  break;
838
770
  }
839
771
  case 'switch':
840
- for (const prop of expose.features) {
772
+ if (expose?.features?.[Symbol.iterator]) for (const prop of expose.features) {
841
773
  switch (prop.name) {
842
774
  case 'state':
843
775
  pushToStates(genState(prop, { role:'switch' }), prop.access);
@@ -1045,7 +977,7 @@ function createFromExposes(model, def, device, options, log) {
1045
977
  case 'lock':
1046
978
  case 'fan':
1047
979
  case 'cover':
1048
- for (const prop of expose.features) {
980
+ if (expose?.features?.[Symbol.iterator]) for (const prop of expose.features) {
1049
981
  switch (prop.name) {
1050
982
  case 'state':
1051
983
  pushToStates(genState(prop, {role:'switch'}), prop.access);
@@ -1058,7 +990,7 @@ function createFromExposes(model, def, device, options, log) {
1058
990
  break;
1059
991
 
1060
992
  case 'climate':
1061
- for (const prop of expose.features) {
993
+ if (expose?.features?.[Symbol.iterator]) for (const prop of expose.features) {
1062
994
  pushToStates(genState(prop), prop.access);
1063
995
  }
1064
996
  break;
@@ -1066,8 +998,11 @@ function createFromExposes(model, def, device, options, log) {
1066
998
  case 'composite':
1067
999
  {
1068
1000
  const cStates = generateCompositeStates(expose, '', options);
1069
- for (const state of cStates)
1070
- pushToStates(state, expose.access);
1001
+ for (const state of cStates.states)
1002
+ if (options.newCompositeMethod)
1003
+ pushToStates(state, expose.access);
1004
+ else
1005
+ pushToStates(modifyState(state, { pairedkeys: cStates.keys } , false), expose.access);
1071
1006
  break;
1072
1007
  }
1073
1008
  case 'list':
package/lib/models.js CHANGED
@@ -668,8 +668,9 @@ async function clearModelDefinitions() {
668
668
 
669
669
  function getStateDefinition(name, type, prop) {
670
670
  if (typeof name != 'string') return getStateDefinition('ilstate', type, prop);
671
+ if (states.hasOwnProperty(name)) return states[name];
671
672
  if (legacyStates.hasOwnProperty(name)) return legacyStates[name];
672
- return states[name] || {
673
+ return {
673
674
  id: name,
674
675
  prop: prop || name,
675
676
  name: name.replace('_',' '),
@@ -751,6 +751,26 @@ class StatesController extends EventEmitter {
751
751
  setTimeout(() => this.updateState(dev_id, name, outValue, common), timeout);
752
752
  }
753
753
 
754
+ deepCompare(item1, item2) {
755
+ if (typeof item1 != typeof item2) return false; // different object, definitely different.
756
+ switch (typeof item1) {
757
+ case 'boolean':
758
+ case 'number':
759
+ case 'string': return item1 === item2;
760
+ case 'object':
761
+ if (!item1 || !item2) {
762
+ if (!item1 && !item2) return true;
763
+ return false;
764
+ }
765
+ for (const key of Object.keys(item1)) {
766
+ if (!this.deepCompare(item1[key],item2[key])) return false;
767
+ }
768
+ return true;
769
+ case 'function':
770
+ return true; // functions are always considere equal
771
+ }
772
+ }
773
+
754
774
  async updateState(devId, name, value, common) {
755
775
  const new_common = {name: name, color:null};
756
776
  const stateId = devId + '.' + name;
@@ -790,7 +810,7 @@ class StatesController extends EventEmitter {
790
810
  if (stobj.common) {
791
811
  for (const property in new_common) {
792
812
  if (stobj.common[property] != undefined) {
793
- if (stobj.common[property] === new_common[property]) {
813
+ if (this.deepCompare(stobj.common[property],new_common[property])) {
794
814
  delete new_common[property];
795
815
  }
796
816
  }
@@ -810,7 +830,7 @@ class StatesController extends EventEmitter {
810
830
  }
811
831
  }
812
832
 
813
- //
833
+ if (new_common.color=== null && (stobj?.common?.color === undefined || stobj?.common.color === null)) delete new_common.color;
814
834
  // only change object when any common property has changed
815
835
  if (Object.keys(new_common).length) {
816
836
  this.adapter.extendObject(stateId, {type: 'state', common: new_common, native: {}}, () =>
@@ -1153,6 +1173,11 @@ class StatesController extends EventEmitter {
1153
1173
 
1154
1174
  let stateID = statedesc.id;
1155
1175
 
1176
+ if (statedesc.compositeGetter) {
1177
+ const compositePayload = statedesc.compositeGetter(payload);
1178
+ if (compositePayload) await this.publishToState(devId, model, compositePayload, debugId);
1179
+ }
1180
+
1156
1181
  // checking value
1157
1182
  if (value === undefined || value === null) {
1158
1183
  const message = `value '${JSON.stringify(value)}' from device ${devId} via ${mode} for '${statedesc.name} (ID ${statedesc.id} ${statedesc.prop ? 'with property '+statedesc.prop : ''})`;
@@ -1218,6 +1243,7 @@ class StatesController extends EventEmitter {
1218
1243
  const has_elevated_debug = (this.checkDebugDevice(devId) && !payload.hasOwnProperty('msg_from_zigbee'));
1219
1244
 
1220
1245
  const message = `message received '${JSON.stringify(payload)}' from device ${devId} type '${model}'`;
1246
+
1221
1247
  if (has_elevated_debug)
1222
1248
  this.emit('device_debug', { ID:debugId, data: { deviceID: devId, flag:'03', IO:true }, message:message});
1223
1249
  else
@@ -1232,7 +1258,7 @@ class StatesController extends EventEmitter {
1232
1258
  let has_published = false;
1233
1259
  if (devStates.states !== undefined) {
1234
1260
  try {
1235
- const states = devStates.states.filter(statedesc => payload.hasOwnProperty(statedesc.prop || statedesc.id)
1261
+ const states = devStates.states.filter(statedesc => payload.hasOwnProperty(statedesc.prop ? statedesc.prop: statedesc.id)
1236
1262
  );
1237
1263
 
1238
1264
  for (const stateInd in states) {
@@ -1298,6 +1298,12 @@ class ZigbeeController extends EventEmitter {
1298
1298
 
1299
1299
  return;
1300
1300
  }
1301
+ // force read for brightness
1302
+ const skey = stateDesc.setattr || stateDesc.prop || stateDesc.id;
1303
+ const readKey = { key: undefined, converter: undefined };
1304
+ if (skey === 'brightness') readKey.key = 'state';
1305
+ if (skey === 'state') readKey.key = 'brightness';
1306
+
1301
1307
  for (const c of mappedModel.toZigbee) {
1302
1308
 
1303
1309
  if (!c.hasOwnProperty('convertSet')) continue;
@@ -1306,6 +1312,8 @@ class ZigbeeController extends EventEmitter {
1306
1312
  {
1307
1313
  if (converter === undefined)
1308
1314
  {
1315
+ if (readKey.key && readKey.converter === undefined && c.hasOwnProperty('convertGet'))
1316
+ readKey.converter = c;
1309
1317
  converter = c;
1310
1318
  if (has_elevated_debug) {
1311
1319
  const message = `Setting converter to keyless converter for ${deviceId} of type ${model}`;
@@ -1340,6 +1348,8 @@ class ZigbeeController extends EventEmitter {
1340
1348
  converter = c;
1341
1349
  msg_counter++;
1342
1350
  }
1351
+ if (readKey.key && c.key.includes(readKey.key) && c.hasOwnProperty('convertGet'))
1352
+ readKey.converter = c;
1343
1353
  }
1344
1354
  if (converter === undefined) {
1345
1355
  if (stateDesc.isInternalState) {
@@ -1455,6 +1465,17 @@ class ZigbeeController extends EventEmitter {
1455
1465
  }
1456
1466
  }
1457
1467
  retry = 0;
1468
+ if (readKey.converter) {
1469
+ const tt = preparedOptions.transition || preparedOptions.transition_time;
1470
+ const did = deviceId;
1471
+ setTimeout(async () => {
1472
+ try {
1473
+ await readKey.converter.convertGet(target, readKey.key, {device:entity.device}) }
1474
+ catch (error) {
1475
+ this.warn(`error reading ${readKey.key} from ${deviceId} : ${error?.message}`);
1476
+ }
1477
+ }, tt ? tt * 1000 : 100);
1478
+ }
1458
1479
  } catch (error) {
1459
1480
  if (has_elevated_debug) {
1460
1481
  const message = `caught error ${error?.message? error.message : 'no reason given'} when setting value for device ${deviceId}.`;
@@ -1471,7 +1492,9 @@ class ZigbeeController extends EventEmitter {
1471
1492
  ` Error: ${error.message}`, `Send command to ${deviceId} failed with`, error);
1472
1493
  }
1473
1494
  }
1474
- } while (retry > 0)
1495
+ } while (retry > 0);
1496
+
1497
+
1475
1498
  });
1476
1499
  } catch (err) {
1477
1500
  const message = `No entity for ${deviceId} : ${err && err.message ? err.message : 'no error message'}`;
package/main.js CHANGED
@@ -706,7 +706,7 @@ class Zigbee extends utils.Adapter {
706
706
  const model = (entity.mapped) ? entity.mapped.model : entity.device.modelID;
707
707
  if (this.debugActive) this.log.debug(`new device ${device.ieeeAddr} ${device.networkAddress} ${model} `);
708
708
 
709
- this.logToPairing(`New device joined '${device.ieeeAddr}' model ${model}`, true);
709
+ if (!obj) this.logToPairing(`New device joined '${device.ieeeAddr}' model ${model}`, true);
710
710
  this.stController.updateDev(zbIdorIeeetoAdId(this, device.ieeeAddr, false), model, model, () =>
711
711
  this.stController.syncDevStates(device, model));
712
712
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee",
3
- "version": "3.3.1",
3
+ "version": "3.3.3",
4
4
  "author": {
5
5
  "name": "Kirov Ilya",
6
6
  "email": "kirovilya@gmail.com"
@@ -28,8 +28,8 @@
28
28
  "ajv": "^8.17.1",
29
29
  "uri-js": "^4.4.1",
30
30
  "typescript": "^5.9.3",
31
- "zigbee-herdsman": "^8.0.0",
32
- "zigbee-herdsman-converters": "^25.85.0"
31
+ "zigbee-herdsman": "8.0.2",
32
+ "zigbee-herdsman-converters": "25.104.0"
33
33
  },
34
34
  "description": "Zigbee devices",
35
35
  "devDependencies": {