iobroker.zigbee 3.2.1 → 3.2.2

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 CHANGED
@@ -154,6 +154,12 @@ You can thank the authors by these links:
154
154
 
155
155
  -----------------------------------------------------------------------------------------------------
156
156
  ## Changelog
157
+ ### 3.2.2 (2025-10-27)
158
+ * (asgothian) Bugfix on delete object.
159
+ * (asgothian) improved device query.
160
+ * (asgothain) fixed delete device with local overrides.
161
+ *
162
+
157
163
  ### 3.2.1 (2025-10-26)
158
164
  * (asgothian) fix bug #2640
159
165
  *
package/admin/admin.js CHANGED
@@ -466,7 +466,8 @@ function showLocalData() {
466
466
  const keys = item.replace('d_delall_', '').split('-');
467
467
  const model = models[keys[0]];
468
468
  const device = model.devices.find( (d) => d.native.id === keys[1]);
469
- deleteConfirmation(keys[1], device.common.name, keys[1], models[keys[0]].devices.count <=1 ? models[keys[0]]?.model.model : undefined);
469
+ console.warn(`setting delete confirmation with ${keys[1]} ${models[keys[0]].devices?.length} ${models[keys[0]]?.model.model} `);
470
+ deleteConfirmation(keys[1], device.common.name, keys[1], models[keys[0]]?.devices?.length <=1 ? models[keys[0]]?.model?.model : undefined);
470
471
  });
471
472
  }
472
473
  }
@@ -497,6 +498,7 @@ function getCard(dev) {
497
498
  rooms.push(dev.rooms[r]);
498
499
  }
499
500
  }
501
+
500
502
  const NoInterviewIcon = dev.info?.device?.interviewstate != 'SUCCESSFUL' ? `<div class="col tool"><i class="material-icons icon-red">perm_device_information</i></div>` : ``;
501
503
  const paired = (dev.paired) ? '' : '<i class="material-icons right">leak_remove</i>';
502
504
  const rid = id.split('.').join('_');
@@ -1835,7 +1837,7 @@ function displayDebugMessages(msg) {
1835
1837
  const modelUrl = (type_url === 'unknown') ? 'unknown' : `<a href="https://www.zigbee2mqtt.io/devices/${type_url}.html" target="_blank" rel="noopener noreferrer">${image}</a>`;
1836
1838
  const devName = (dev && dev.common && dev.common.name) ? dev.common.name : 'unnamed';
1837
1839
  const button = `<a id="e_${devID}" class="btn-floating waves-effect waves-light green tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons large">sync_problem</i></a>`
1838
- const dbutton = `<a id="d_${devID}" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT" title="Update debug messages"><i class="material-icons icon-yellow large">delete_forever</i></a>`;
1840
+ const dbutton = `<a id="d_${devID}" class="btn-floating waves-effect waves-light red tooltipped center-align hoverable translateT" title="Delete debug messages"><i class="material-icons icon-yellow large">delete_forever</i></a>`;
1839
1841
  buttonNames.push(devID);
1840
1842
  Html.push(`<li><table><thead id="dbgtable"><tr><td colspan="4">${devName} (ID: ${devID} Model: ${dev && dev.common ? dev.common.name : 'unknown'})</td><td>${modelUrl}</td><td>${button}</td><td>${dbutton}</td></tr></thead><tbody>`);
1841
1843
  if (dbgData[devID].IN.length > 0) {
package/io-package.json CHANGED
@@ -1,8 +1,21 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zigbee",
4
- "version": "3.2.1",
4
+ "version": "3.2.2",
5
5
  "news": {
6
+ "3.2.2": {
7
+ "en": "Bugfix on delete object.\nimproved device query.\nfixed delete device with local overrides.\n",
8
+ "de": "Bugfix auf Löschobjekt.\nverbesserte geräteabfrage.\nfeste löschvorrichtung mit lokalen overrides.\n",
9
+ "ru": "Bugfix для удаления объекта.\nулучшенный запрос устройства.\nфиксированное устройство удаления с локальными переопределениями.\n",
10
+ "pt": "Correcção de erros ao apagar o objecto.\npesquisa de dispositivos melhorada.\ndispositivo de exclusão fixo com substituições locais.\n",
11
+ "nl": "Bugfix bij verwijderen van object.\nverbeterde apparaatquery.\nvast delete apparaat met lokale overrides.\n",
12
+ "fr": "Correction sur objet de suppression.\nrequête de périphérique améliorée.\ndispositif de suppression fixe avec redéfinitions locales.\n",
13
+ "it": "Bugfix su delete object.\nmigliore query del dispositivo.\ndispositivo di cancellazione fisso con override locali.\n",
14
+ "es": "Bugfix en el objeto borrado.\nmejorada consulta de dispositivos.\ndispositivo de eliminación fijo con anulas locales.\n",
15
+ "pl": "Bugfix na usunąć obiekt.\nulepszone zapytanie urządzenia.\nnaprawione urządzenie usuwające z lokalnymi przekroczeniami.\n",
16
+ "uk": "Виправлення помилок при видаленні об'єкта.\nпокращений пристрій запиту.\nфіксований пристрій видалення з локальними перенаряддями.\n",
17
+ "zh-cn": "删除对象上的错误修正 .\n改进设备查询 .\n有本地覆盖的固定删除设备 .\n"
18
+ },
6
19
  "3.2.1": {
7
20
  "en": "fix bug #2640\n",
8
21
  "de": "fehler beheben #2640\n",
@@ -80,19 +93,6 @@
80
93
  "pl": "ZHC 25.x\nZH 6.x\nNapraw błąd parowania\nDodaj wiadomości ping do debugowania urządzenia, aby zweryfikować przyczyny niepowodzenia pingu\n",
81
94
  "uk": "ЗХК 25.x\nЗХ 6.х\nВиправлено помилку з'єднання\nдодано повідомлення ping до відлагодження пристрою для перевірки причин невдачі ping\n",
82
95
  "zh-cn": "ZHC 25.x\nZH 6.x (英语)\n修复配对问题\n将ping消息添加到设备调试中,以验证ping失败的原因\n"
83
- },
84
- "3.0.5": {
85
- "en": "fix random error where devices are not shown due to illegal groups\ndrop support for node 18\nRequired node Versions Node 20.19.0 or 22.11.0 or newer (courtesy of ZH 4.4.1 / ZHC 24.8.0)",
86
- "de": "fehler beheben, bei denen geräte wegen illegaler gruppen nicht angezeigt werden\ndrop-unterstützung für knoten 183\nErforderliche Knotenversionen Nr. 20.19.0 oder 22.11.0 oder neuer (courtesy of ZH 4.4.1 / ZHC 24.8.0)",
87
- "ru": "исправить случайную ошибку, когда устройства не отображаются из-за незаконных групп\nподдержка drop для node 18\nТребуемый узел Версии Узел 20.19.0 или 22.11.0 или новее (документ ZH 4.4.1 / ZHC 24.8.0)",
88
- "pt": "corrigir erro aleatório onde os dispositivos não são mostrados devido a grupos ilegais\nsuporte de gota para o nó 18\nNó necessário Versões Node 20.19.0 ou 22.11.0 ou mais recente (cortesia de ZH 4.4.1 / ZHC 24.8.0)",
89
- "nl": "fix willekeurige fout wanneer apparaten niet worden getoond als gevolg van illegale groepen\ndrop ondersteuning voor knooppunt 18\nVereiste node Versies Node 20.19.0 of 22.11.0 of nieuwer (met dank aan ZH 4.4.1 / ZHC 24.8.0)",
90
- "fr": "corriger une erreur aléatoire lorsque les appareils ne sont pas montrés en raison de groupes illégaux\nsupport de chute pour noeud 18\nVersion requise Node 20.19.0 ou 22.11.0 ou plus récent (avec la permission de ZH 4.4.1 / ZHC 248.0)",
91
- "it": "correggere errore casuale in cui i dispositivi non vengono visualizzati a causa di gruppi illegali\nsupporto a goccia per nodo 18\nNodo richiesto Versioni Nodo 20.19.0 o 22.11.0 o più recente (cortesia di ZH 4.4.1 / ZHC 24.8.0)",
92
- "es": "corregir errores aleatorios donde no se muestran dispositivos debido a grupos ilegales\napoyo a los nodos 18\nNodo requerido Versiones Nodo 20.19.0 o 22.11.0 o nuevo (cortesía de ZH 4.4.1 / ZHC 24.8.0)",
93
- "pl": "naprawić błąd losowy w przypadku gdy urządzenia nie są wyświetlane z powodu nielegalnych grup\nobsługa zrzutu dla węzła 18\nWymagany węzeł Wersje Węzeł 20.19.0 lub 22.11.0 lub nowszy (uprzejmość ZH 4.4.1 / ZHC 24.8.0)",
94
- "uk": "виправити випадкові помилки, де пристрої не відображаються через незаконні групи\nпідтримка крапель для вузла 18 років\nПотрібні версії вузла Node 20.19.0 або 22.11.0 або новачка (кількість ЗЗ 4.4.1 / ЗЖК 24.8.0)",
95
- "zh-cn": "在设备因非法组而未显示时修复随机错误\n放弃节点支持 第 18 条\n要求的节点版本为20.19.0或22.11.0或更新(礼仪为ZH 4.4.1 / ZHC 24.8.0)"
96
96
  }
97
97
  },
98
98
  "titleLang": {
package/lib/commands.js CHANGED
@@ -445,6 +445,14 @@ class Commands {
445
445
  return undefined;
446
446
 
447
447
  }
448
+
449
+ function haveBindableClusters(clusters) {
450
+ const nonBindableClusters = [25,33, 4096]
451
+ if (Array.isArray(clusters)) {
452
+ return (clusters.filter((candidate) => !nonBindableClusters.includes(candidate)).length > 0);
453
+ }
454
+ return false;
455
+ }
448
456
  const rv = {};
449
457
  try {
450
458
  rv.device = {
@@ -463,19 +471,28 @@ class Commands {
463
471
  date_code:device.device.dateCode,
464
472
  build:device.device.softwareBuildID,
465
473
  interviewstate:device.device.interviewState || 'UNKNOWN',
474
+ BindSource: false,
475
+ isGroupable: false,
466
476
  }
467
477
  rv.endpoints = [];
478
+ let dBindSource = false;
479
+ let disGroupable = false;
468
480
  for (const ep_idx in device.endpoints) {
469
481
  const ep = device.endpoints[ep_idx];
482
+ const bindable = haveBindableClusters(ep.outputClusters);
483
+ dBindSource |= bindable;
470
484
  rv.endpoints.push({
471
485
  ID:ep.ID,
472
486
  epName: device.mapped?.endpoint ? getKey(device.mapped?.endpoint(device), ep.ID) : ep.ID,
473
487
  profile:ep.profileID,
474
488
  input_clusters:ep.inputClusters,
475
489
  output_clusters:ep.outputClusters,
490
+ BindSource: Boolean(bindable),
476
491
  })
477
- if (ep.inputClusters.includes(4)) rv.device.isGroupable = true;
492
+ disGroupable |= ep.inputClusters.includes(4);
478
493
  }
494
+ rv.device.isGroupable = Boolean(disGroupable);
495
+ rv.device.BindSource = Boolean(dBindSource);
479
496
  if (device.mapped) {
480
497
  rv.mapped = {
481
498
  model:device.mapped.model,
@@ -745,7 +762,7 @@ class Commands {
745
762
  else this.adapter.sendTo(from, command, {error:err}, callback);
746
763
  }
747
764
  this.adapter.sendTo(from, command, {}, callback);
748
- this.adapter.stController.localConfig.removeLocalData()
765
+ if (msg.dev) this.adapter.stController.localConfig.removeLocalData(devId, msg.model);
749
766
  } else {
750
767
  this.adapter.sendTo(from, command, {error: err}, callback);
751
768
  }
@@ -142,6 +142,12 @@ class localConfig extends EventEmitter {
142
142
  return defaultName;
143
143
  }
144
144
 
145
+ removeLocalData(dev, model) {
146
+ delete this.localData.by_id[dev];
147
+ if (model) delete this.localData.by_model[model];
148
+ this.retainData();
149
+ }
150
+
145
151
  IconForId(id, model, defaultIcon) {
146
152
  let modeloverride = {};
147
153
  this.debug('Icon for id with ' + id + ', ' + model + ' and ' + defaultIcon);
@@ -303,7 +309,6 @@ class localConfig extends EventEmitter {
303
309
  }
304
310
 
305
311
  writeData() {
306
- this.info('retaining local config: ' + JSON.stringify(this.localData));
307
312
  try {
308
313
  fs.writeFileSync(this.filename, JSON.stringify(this.localData, null, 2))
309
314
  this.info('Saved local configuration data');
@@ -657,7 +657,7 @@ class ZigbeeController extends EventEmitter {
657
657
  mapped = await zigbeeHerdsmanConverters.findByDevice(device, false);
658
658
  }
659
659
  catch (error) {
660
-
660
+ // intentionally empty
661
661
  }
662
662
  if (!mapped) {
663
663
  if (device.type === 'Coordinator')
@@ -812,7 +812,7 @@ class ZigbeeController extends EventEmitter {
812
812
  else if (this._permitJoinInterval) {
813
813
  const timestr = this._permitJoinTime > 0 ? ` with ${this._permitJoinTime} second${this._permitJoinTime > 1 ? 's':''} remaining.`: '.';
814
814
  this.info(`Closed Zigbee network${timestr}`)
815
- this.emit('pairing', `Closed network${timestr}`);
815
+ this.emit('pairing', `Closed network${timestr}`, 0);
816
816
  clearInterval(this._permitJoinInterval);
817
817
  this._permitJoinInterval = null;
818
818
  }
@@ -1517,18 +1517,25 @@ class ZigbeeController extends EventEmitter {
1517
1517
  }
1518
1518
  if (sources.length == 0) sources.push(entity.device.endpoints[0]);
1519
1519
  for (const source of sources) {
1520
- try {
1521
- await converter.convertGet(source, '', {device:entity.device});
1522
- this.debug(`read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${entity.device.ieeeAddr}/${source.ID}' after device query`);
1523
- } catch (error) {
1524
- if (elevated) {
1525
- const message = `Failed to read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${source.ID}' from query with '${error && error.message ? error.message : 'no error message'}`;
1526
- this.warn(`ELEVATED OE02.1 ${message}`);
1527
- this.emit('device_debug', { ID:debugID, data: { error: 'NOTREAD' , IO:false }, message:message });
1520
+ for (const k of converter.key)
1521
+ try {
1522
+ await converter.convertGet(source, k, {device:entity.device});
1523
+ if (elevated) {
1524
+ const message = `read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${entity.device.ieeeAddr}/${source.ID}' after device query`;
1525
+ this.warn(`ELEVATED O02.1 ${message}`);
1526
+ this.emit('device_debug', { ID:debugID, data: { flag: k, IO:false }, message:message });
1527
+ }
1528
+ else
1529
+ this.debug(`read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${entity.device.ieeeAddr}/${source.ID}' after device query`);
1530
+ } catch (error) {
1531
+ if (elevated) {
1532
+ const message = `Failed to read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${source.ID}' from query with '${error && error.message ? error.message : 'no error message'}`;
1533
+ this.warn(`ELEVATED OE02.1 ${message}`);
1534
+ this.emit('device_debug', { ID:debugID, data: { error: 'NOTREAD' , IO:false }, message:message });
1535
+ }
1536
+ else
1537
+ this.debug(`failed to read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${source.ID}'after device query`);
1528
1538
  }
1529
- else
1530
- this.debug(`failed to read for state${converter.key.length ? '' : 's'} '${converter.key.join(',')}' of '${source.ID}'after device query`);
1531
- }
1532
1539
  }
1533
1540
  }
1534
1541
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "author": {
5
5
  "name": "Kirov Ilya",
6
6
  "email": "kirovilya@gmail.com"