iobroker.zigbee 1.8.22 → 1.8.24

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
@@ -134,6 +134,12 @@ You can thank the authors by these links:
134
134
  -----------------------------------------------------------------------------------------------------
135
135
 
136
136
  ## Changelog
137
+ ### 1.8.24 (2023-09-05)
138
+ * (arteck) switch to exposes tab for some Aqara Devices
139
+
140
+ ### 1.8.23 (2023-08-10)
141
+ * (arteck) query from xiaomi is now better
142
+
137
143
  ### 1.8.22 (2023-08-05)
138
144
  * (arteck) crash when meta is empty
139
145
 
package/admin/admin.js CHANGED
@@ -31,7 +31,7 @@ const updateCardInterval = setInterval(updateCardTimer, 6000);
31
31
 
32
32
  const savedSettings = [
33
33
  'port', 'panID', 'channel', 'disableLed', 'countDown', 'groups', 'extPanID', 'precfgkey', 'transmitPower',
34
- 'adapterType', 'debugHerdsman', 'disableBackup', 'disablePing', 'external', 'startWithInconsistent',
34
+ 'adapterType', 'debugHerdsman', 'disableBackup', 'disablePing', 'external', 'startWithInconsistent', 'warnOnDeviceAnnouncement'
35
35
  ];
36
36
 
37
37
  function getDeviceByID(ID) {
@@ -799,6 +799,9 @@ function load(settings, onChange) {
799
799
  if (settings.disablePing === undefined) {
800
800
  settings.disablePing = false;
801
801
  }
802
+ if (settings.warnOnDeviceAnnouncement === undefined) {
803
+ settings.warnOnDeviceAnnouncement = true;
804
+ }
802
805
 
803
806
  // example: select elements with id=key and class=value and insert value
804
807
  for (const key in settings) {
package/admin/index.html CHANGED
@@ -109,6 +109,10 @@
109
109
  <input id="disableQueue" type="checkbox" class="value" />
110
110
  <label class="translate" for="disableQueue">Disable Queue</label>
111
111
  </div>
112
+ <div class="input-field col s2 m2 l2">
113
+ <input id="warnOnDeviceAnnouncement" type="checkbox" class="value" />
114
+ <label class="translate" for="warnOnDeviceAnnouncement">Log warning on Zigbee device announcement</label>
115
+ </div>
112
116
  </div>
113
117
  </div>
114
118
  </div>
@@ -689,6 +689,10 @@
689
689
  <input id="debugHerdsman" type="checkbox" class="value"/>
690
690
  <label class="translate" for="debugHerdsman">Zigbee-herdsman debug info</label>
691
691
  </div>
692
+ <div class="input-field col s12 m6 l4 col-warnOnDeviceAnnouncement">
693
+ <input id="warnOnDeviceAnnouncement" type="checkbox" class="value"/>
694
+ <label class="translate" for="warnOnDeviceAnnouncement">Log warning on Zigbee device announcement</label>
695
+ </div>
692
696
  <div class="input-field col s12 m6 l4">
693
697
  <a id="reset-btn" class="waves-effect waves-light white-text btn-large translate">Reset...</a>
694
698
  </div>
package/admin/tab_m.html CHANGED
@@ -605,6 +605,10 @@
605
605
  <input id="disablePing" type="checkbox" class="value" />
606
606
  <label class="translate" for="disablePing">Disable active availability check</label>
607
607
  </div>
608
+ <div class="input-field col s12 m6 l4 col-warnOnDeviceAnnouncement">
609
+ <input id="warnOnDeviceAnnouncement" type="checkbox" class="value" />
610
+ <label class="translate" for="warnOnDeviceAnnouncement">Log warning on Zigbee device announcement</label>
611
+ </div>
608
612
  <div class="input-field col s12 m6 l8 col-transmitPower">
609
613
  <select id="transmitPower" class="value" >
610
614
  <option value="" disabled selected class="translate">transmitPower</option>
package/io-package.json CHANGED
@@ -1,8 +1,34 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "zigbee",
4
- "version": "1.8.22",
4
+ "version": "1.8.24",
5
5
  "news": {
6
+ "1.8.24": {
7
+ "en": "switch to exposes tab for some Aqara Devices",
8
+ "de": "schalter, um die Registerkarte für einige Aqara-Geräte freizusetzen",
9
+ "ru": "перейти на вкладку exposes для некоторых устройств Aqara",
10
+ "pt": "mudar para expor guia para alguns dispositivos Aqara",
11
+ "nl": "vertaling:",
12
+ "fr": "commutation pour exposer l'onglet pour certains appareils Aqara",
13
+ "it": "interruttore per esporre la scheda per alcuni dispositivi Aqara",
14
+ "es": "interruptor para exponer ficha para algunos dispositivos Aqara",
15
+ "pl": "zamienił tablicę dla niektórych Aqara Devices",
16
+ "uk": "перемикач для установки для деяких пристроїв Aqara",
17
+ "zh-cn": "对某些Aqara Devic的表格的转换"
18
+ },
19
+ "1.8.23": {
20
+ "en": "query from xiaomi is now better",
21
+ "de": "anfrage von xiaomi ist jetzt besser",
22
+ "ru": "запрос от xiaomi теперь лучше",
23
+ "pt": "consulta de xiaomi é agora melhor",
24
+ "nl": "quee van xiaomi is nu beter",
25
+ "fr": "la question de xiaomi est maintenant mieux",
26
+ "it": "query da xiaomi è ora meglio",
27
+ "es": "la consulta de xiaomi ahora es mejor",
28
+ "pl": "wykorzystywanie z xiaomi jest obecnie lepsze",
29
+ "uk": "запиту від xiaomi тепер краще",
30
+ "zh-cn": "来自米亚米的询问现在更好。"
31
+ },
6
32
  "1.8.22": {
7
33
  "en": "crash when meta is empty",
8
34
  "de": "crash, wenn meta leer ist",
@@ -67,32 +93,6 @@
67
93
  "pl": "wadliwość i błąd\n",
68
94
  "uk": "маленька фіксація відправлень і журнал помилок\n",
69
95
  "zh-cn": "很少发送过材料和错误逻辑\n"
70
- },
71
- "1.8.17": {
72
- "en": "sentry corr",
73
- "de": "versand",
74
- "ru": "сендри корр",
75
- "pt": "corante de sentinela",
76
- "nl": "vertaling:",
77
- "fr": "corr",
78
- "it": "cor",
79
- "es": "centry corr",
80
- "pl": "kor",
81
- "uk": "кофрів",
82
- "zh-cn": "发信"
83
- },
84
- "1.8.16": {
85
- "en": "battery corr",
86
- "de": "batterie korrektor",
87
- "ru": "аккумулятор корр",
88
- "pt": "corante da bateria",
89
- "nl": "batterij corr",
90
- "fr": "batterie",
91
- "it": "batteria corpo",
92
- "es": "batería corrido",
93
- "pl": "baterie",
94
- "uk": "акумулятор",
95
- "zh-cn": "电池组"
96
96
  }
97
97
  },
98
98
  "titleLang": {
@@ -188,8 +188,8 @@
188
188
  "condition": {
189
189
  "operand": "and",
190
190
  "rules": [
191
- "oldVersion<=1.6.18",
192
- "newVersion>=1.7.0"
191
+ "oldVersion<=1.8.22",
192
+ "newVersion>=1.8.24"
193
193
  ]
194
194
  },
195
195
  "title": {
@@ -205,16 +205,16 @@
205
205
  "zh-cn": "重要通知!"
206
206
  },
207
207
  "text": {
208
- "en": "This new version cleans the file backup (under \\opt\\iobroker\\iobroker-data\\zigbee_0\\) of the adapter. Only the last 10 backups are kept.",
209
- "de": "Diese neue Version bereinigt das Datei backup (unter \\opt\\iobroker\\iobroker-data\\zigbee_0\\) des Adapter. Es werden nur die letzten 10 Sicherungen behalten.",
210
- "ru": "Эта новая версия очищает резервную копию файла папке \\opt\\iobroker\\iobroker-data\\zigbee_0\\) адаптера. Сохраняются только последние 10 резервных копий.",
211
- "pt": "Esta nova versão limpa o backup do arquivo (em \\opt\\iobroker\\iobroker-data\\zigbee_0\\) do adaptador. Apenas os últimos 10 backups são mantidos.",
212
- "nl": "Deze nieuwe versie maakt de bestandsback-up schoon (onder \\opt\\iobroker\\iobroker-data\\zigbee_0\\) van de adapter. Alleen de laatste 10 back-ups worden bewaard.",
213
- "fr": "Cette nouvelle version nettoie le fichier de sauvegarde (sous \\opt\\iobroker\\iobroker-data\\zigbee_0\\) de l'adaptateur. Seules les 10 dernières sauvegardes sont conservées.",
214
- "it": "Questa nuova versione pulisce il backup del file (in \\opt\\iobroker\\iobroker-data\\zigbee_0\\) dell'adattatore. Vengono mantenuti solo gli ultimi 10 backup.",
215
- "es": "Esta nueva versión limpia la copia de seguridad del archivo (en \\opt\\iobroker\\iobroker-data\\zigbee_0\\) del adaptador. Solo se conservan las últimas 10 copias de seguridad.",
216
- "pl": "Ta nowa wersja czyści kopię pliku (w \\opt\\iobroker\\iobroker-data\\zigbee_0\\) adaptera. Przechowywanych jest tylko 10 ostatnich kopii.",
217
- "zh-cn": "这个新版本清理了适配器的文件备份(在 \\opt\\iobroker\\iobroker-data\\zigbee_0\\ 下)。仅保留最后 10 个备份。"
208
+ "en": "This new version use exposes for Aqara Button WXKG01LM. Plz select this device into exposes/Auschliessen tab",
209
+ "ru": "Эта новая версия использует экспозиции для Aqara Button WXKG01LM. Пожалуйста, выберите это устройство в exposes/Auschliessen tab",
210
+ "pt": "Esta nova versão usa expões para Aqara Button WXKG01LM. Por favor, selecione este dispositivo no separador exposes/Auschliessen",
211
+ "nl": "Deze nieuwe versie gebruikt blootstellingen voor Aqara Button WXK01LM. Kies alsjeblieft dit apparaat uit in de openbare aanklagers",
212
+ "fr": "Cette nouvelle version utilise pour Aqara Button WXKG01LM. Veuillez sélectionner cet appareil dans l'onglet Affichage/Auschliessen",
213
+ "it": "Questa nuova versione utilizza per Aqara Button WXKG01LM. Si prega di selezionare questo dispositivo per exposes/Auschliessen scheda",
214
+ "es": "Este nuevo uso expone para Aqara Button WXKG01LM. Por favor, seleccione este dispositivo en la pestaña exposes/Auschliessen",
215
+ "pl": "Nowa wersja została udostępniona dla zmian Aqary Button WXKG01LM. Prosze dodać to do exposes/Auschliessen tabsena",
216
+ "uk": "Ця нова версія використовується для кнопки Aqara Button WXKG01LM. Будь ласка, оберіть цей пристрій у вкладці ",
217
+ "zh-cn": "这一新版本用于Aqara Button WXKG01LM。 请选择这一装置暴露/Auschliessen tab"
218
218
  },
219
219
  "link": "https://github.com/ioBroker/ioBroker.zigbee/blob/master/README.md",
220
220
  "level": "warn",
@@ -250,7 +250,8 @@
250
250
  "disablePing": false,
251
251
  "disableBackup": false,
252
252
  "external": "",
253
- "startWithInconsistent": false
253
+ "startWithInconsistent": false,
254
+ "warnOnDeviceAnnouncement": true
254
255
  },
255
256
  "instanceObjects": [
256
257
  {
package/lib/backup.js CHANGED
@@ -93,14 +93,14 @@ class Backup {
93
93
  if (fs.existsSync(dir)) {
94
94
  const directoryContent = fs.readdirSync(dir);
95
95
 
96
- let files = directoryContent.filter((filename) => {
96
+ const files = directoryContent.filter((filename) => {
97
97
  if (filename.indexOf('gz') > 0) {
98
98
  return fs.statSync(`${dir}/${filename}`).isFile();
99
99
  }
100
100
  });
101
101
 
102
- let sorted = files.sort((a, b) => {
103
- let aStat = fs.statSync(`${dir}/${a}`),
102
+ files.sort((a, b) => {
103
+ const aStat = fs.statSync(`${dir}/${a}`),
104
104
  bStat = fs.statSync(`${dir}/${b}`);
105
105
 
106
106
  return new Date(bStat.birthtime).getTime() - new Date(aStat.birthtime).getTime();
package/lib/commands.js CHANGED
@@ -116,31 +116,31 @@ class Commands {
116
116
  if (this.zbController) {
117
117
  let devId = '';
118
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;
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
141
 
142
+ }
142
143
  }
143
- }
144
144
  }
145
145
  // allow devices to join the network within 60 secs
146
146
  this.adapter.logToPairing('Pairing started ' + devId, true);
@@ -307,7 +307,7 @@ class Commands {
307
307
  }
308
308
  }
309
309
  devInfo.paired = !!devInfo.info;
310
- // devInfo.groups = groups[devInfo._id];
310
+ // devInfo.groups = groups[devInfo._id];
311
311
  devices.push(devInfo);
312
312
  }
313
313
  return devices;
package/lib/devices.js CHANGED
@@ -3092,7 +3092,7 @@ const groupStates = [states.brightness_step].concat(lightStatesWithColor);
3092
3092
  function getByModel() {
3093
3093
  const byModel = new Map();
3094
3094
  for (const device of devices) {
3095
- for (const model of device.models) {
3095
+ for (const model of device.models) {
3096
3096
  const stripModel = model.replace(/\0.*$/g, '').trim();
3097
3097
  byModel.set(stripModel, device);
3098
3098
  }
package/lib/exposes.js CHANGED
@@ -873,7 +873,7 @@ function applyExposes(mappedDevices, byModel, allExcludesObj) {
873
873
  // create or update device from exposes
874
874
  for (const deviceDef of zigbeeHerdsmanConverters.definitions) {
875
875
  applyDeviceDef(mappedDevices, byModel, allExcludesStr, deviceDef);
876
-
876
+
877
877
  if (deviceDef.hasOwnProperty('whiteLabel')) {
878
878
  for (const deviceWhiteLabel of deviceDef.whiteLabel) {
879
879
  applyDeviceDef(mappedDevices, byModel, allExcludesStr, {
@@ -881,7 +881,7 @@ function applyExposes(mappedDevices, byModel, allExcludesObj) {
881
881
  model: deviceWhiteLabel.model,
882
882
  vendor: deviceWhiteLabel.vendor,
883
883
  description: deviceWhiteLabel.description || deviceDef.description,
884
- });
884
+ });
885
885
  }
886
886
  }
887
887
  }
package/lib/groups.js CHANGED
@@ -123,7 +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
+ this.warn('updateGroupMembership called with ' + JSON.stringify(devId));
127
127
  if (devId === undefined) {
128
128
  this.adapter.sendTo(from, command, {error: 'No device specified'}, callback);
129
129
  }
@@ -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.warn(`calling removeDevFromGroup with ${sysid}, ${-gpidn}, ${epid}` )
141
+ this.warn(`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.warn(`calling addDevToGroup with ${sysid}, ${gpidn}, ${epid}` )
149
+ this.warn(`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 ' + JSON.stringify(e) + ' in updateGroupMembership')
161
+ this.warn('caught error ' + JSON.stringify(e) + ' in updateGroupMembership');
162
162
  this.adapter.sendTo(from, command, {error: e}, callback);
163
163
  return;
164
164
  }
package/lib/states.js CHANGED
@@ -5828,10 +5828,10 @@ const states = {
5828
5828
  },
5829
5829
  getter: (payload) => {
5830
5830
  if (payload && payload.effect && payload.effect.hasOwnProperty('effect')) return payload.effect.effect;
5831
- return "steady";
5831
+ return 'steady';
5832
5832
  }
5833
5833
 
5834
- },
5834
+ },
5835
5835
  effect_json: {
5836
5836
  id: 'effect_json',
5837
5837
  name: 'Effect',
@@ -5958,10 +5958,10 @@ const states = {
5958
5958
  getter: (payload) => {
5959
5959
  if (payload.color) {
5960
5960
  const c = payload.color;
5961
- if (c.hasOwnProperty("h") && c.hasOwnProperty("s") && c.hasOwnProperty("b"))
5962
- return rgb.hsvToRGBString(c.h, c.s, c.b * 100 / 255);
5963
- if (c.hasOwnProperty("h") && c.hasOwnProperty("s") && c.hasOwnProperty("v"))
5964
- return rgb.hsvToRGBString(c.h, c.s, c.v * 100);
5961
+ if (c.hasOwnProperty('h') && c.hasOwnProperty('s') && c.hasOwnProperty('b'))
5962
+ return rgb.hsvToRGBString(c.h, c.s, c.b * 100 / 255);
5963
+ if (c.hasOwnProperty('h') && c.hasOwnProperty('s') && c.hasOwnProperty('v'))
5964
+ return rgb.hsvToRGBString(c.h, c.s, c.v * 100);
5965
5965
  }
5966
5966
  },
5967
5967
  setterOpt: (value, options) => {
@@ -142,9 +142,9 @@ class StatesController extends EventEmitter {
142
142
  callback(result);
143
143
  return;
144
144
  }
145
-
146
- const states = devStates.states.filter(statedesc => statedesc.isOption || statedesc.inOptions);
147
- if (states == null || states == undefined) {
145
+
146
+ const states = devStates.states.filter(statedesc => statedesc.isOption || statedesc.inOptions);
147
+ if (states == null || states == undefined) {
148
148
  callback(result);
149
149
  return;
150
150
  }
package/lib/utils.js CHANGED
@@ -138,10 +138,10 @@ function getModelRegEx( model) {
138
138
  }
139
139
 
140
140
  function getEntityInfo(entity) {
141
- if (entity) {
142
- return `Type: ${entity.type} Name: ${entity.name}`;
143
- }
144
- return `getEntityInfo: Illegal Entity ${JSON.stringify(entity)}`;
141
+ if (entity) {
142
+ return `Type: ${entity.type} Name: ${entity.name}`;
143
+ }
144
+ return `getEntityInfo: Illegal Entity ${JSON.stringify(entity)}`;
145
145
  }
146
146
 
147
147
  exports.secondsToMilliseconds = seconds => seconds * 1000;
@@ -109,7 +109,9 @@ class DeviceConfigure extends BaseExtension {
109
109
  this.attempts[device.ieeeAddr] = 0;
110
110
  }
111
111
  try {
112
- await this.doConfigure(device, mappedDevice);
112
+ if (mappedDevice && device) {
113
+ await this.doConfigure(device, mappedDevice);
114
+ }
113
115
  } catch (error) {
114
116
  this.sendError(error);
115
117
  this.warn(
@@ -83,6 +83,7 @@ class ZigbeeController extends EventEmitter {
83
83
  this.transmitPower = options.transmitPower;
84
84
  }
85
85
  this.disableLed = options.disableLed;
86
+ this.warnOnDeviceAnnouncement = options.warnOnDeviceAnnouncement;
86
87
 
87
88
  this.debug(`Using zigbee-herdsman with settings: ${JSON.stringify(herdsmanSettings)}`);
88
89
  this.herdsman = new ZigbeeHerdsman.Controller(herdsmanSettings, this.adapter.log);
@@ -319,7 +320,7 @@ class ZigbeeController extends EventEmitter {
319
320
  this.info(`added code ${code} for pairing`);
320
321
  return true;
321
322
  }
322
- return false;
323
+ return false;
323
324
  }
324
325
 
325
326
  async getGroupMembersFromController(id) {
@@ -579,7 +580,11 @@ class ZigbeeController extends EventEmitter {
579
580
  this.debug('handleDeviceAnnounce', message);
580
581
  const entity = await this.resolveEntity(message.device || message.ieeeAddr);
581
582
  const friendlyName = entity.name;
582
- this.warn(`Device '${friendlyName}' announced itself`);
583
+ if (this.warnOnDeviceAnnouncement) {
584
+ this.warn(`Device '${friendlyName}' announced itself`);
585
+ } else {
586
+ this.info(`Device '${friendlyName}' announced itself`);
587
+ }
583
588
 
584
589
  try {
585
590
  if (entity && entity.mapped) {
@@ -784,7 +789,7 @@ class ZigbeeController extends EventEmitter {
784
789
  for (k in this) {
785
790
  yield k;
786
791
  }
787
- }
792
+ };
788
793
  }
789
794
  let result;
790
795
  if (cmd === 'configReport') {
@@ -812,20 +817,20 @@ class ZigbeeController extends EventEmitter {
812
817
  this.debug(`addDevFromGroup - entity: ${utils.getEntityInfo(entity)}`);
813
818
  // generate group debug info and display it
814
819
  const members = await this.getGroupMembersFromController(groupId);
815
- let memberIDs = []
816
- for (let member of members) {
817
- memberIDs.push(member.ieee);
820
+ let memberIDs = [];
821
+ for (const member of members) {
822
+ memberIDs.push(member.ieee);
818
823
  }
819
824
  this.debug(`addDevToGroup ${groupId} with ${memberIDs.length} members ${safeJsonStringify(memberIDs)}`);
820
825
  if (epid != undefined) {
821
826
  for (const ep of entity.endpoints) {
822
827
  this.debug(`checking ep ${ep.ID} of ${devId} (${epid})`);
823
828
  if (ep.ID == epid) {
824
- if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)) {
825
- this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`);
826
- await (ep.addToGroup(group.mapped));
827
- }
828
- else this.error(`cluster genGroups not supported for endpoint ${epid} of ${devId}`);
829
+ if (ep.inputClusters.includes(4) || ep.outputClusters.includes(4)) {
830
+ this.debug(`adding endpoint ${ep.ID} (${epid}) to group ${groupId}`);
831
+ await (ep.addToGroup(group.mapped));
832
+ }
833
+ else this.error(`cluster genGroups not supported for endpoint ${epid} of ${devId}`);
829
834
  }
830
835
  }
831
836
  } else {
@@ -862,9 +867,9 @@ class ZigbeeController extends EventEmitter {
862
867
  const group = await this.resolveEntity(groupId);
863
868
 
864
869
  const members = await this.getGroupMembersFromController(groupId);
865
- let memberIDs = []
866
- for (let member of members) {
867
- memberIDs.push(member.ieee)
870
+ let memberIDs = [];
871
+ for (const member of members) {
872
+ memberIDs.push(member.ieee);
868
873
  }
869
874
 
870
875
  this.debug(`removeDevFromGroup - entity: ${utils.getEntityInfo(entity)}`);
@@ -872,15 +877,15 @@ class ZigbeeController extends EventEmitter {
872
877
 
873
878
  if (epid != undefined) {
874
879
  for (const ep of entity.endpoints) {
875
- this.debug(`checking ep ${ep.ID} of ${devId} (${epid})`)
880
+ this.debug(`checking ep ${ep.ID} of ${devId} (${epid})`);
876
881
  if (ep.ID == epid && (ep.inputClusters.includes(4) || ep.outputClusters.includes(4))) {
877
882
  await ep.removeFromGroup(group.mapped);
878
883
  this.info(`removing endpoint ${ep.ID} of ${devId} from group ${groupId}`);
879
884
  }
880
885
  }
881
886
  } else {
882
- await entity.endpoint.removeFromGroup(group.mapped);
883
- this.info(`removing endpoint ${entity.endpoint.ID} of ${devId} from group ${groupId}`);
887
+ await entity.endpoint.removeFromGroup(group.mapped);
888
+ this.info(`removing endpoint ${entity.endpoint.ID} of ${devId} from group ${groupId}`);
884
889
  }
885
890
  } catch (error) {
886
891
  this.sendError(error);
package/main.js CHANGED
@@ -124,7 +124,7 @@ class Zigbee extends utils.Adapter {
124
124
  message
125
125
  }));
126
126
  }
127
-
127
+
128
128
  if (typeof error == 'string') {
129
129
  Sentry.captureException(new Error(error));
130
130
  } else {
@@ -134,7 +134,7 @@ class Zigbee extends utils.Adapter {
134
134
  }
135
135
  }
136
136
  } catch (err) {
137
- this.log.error(`SentryError : ${message} ${error} ${err} `);
137
+ this.log.error(`SentryError : ${message} ${error} ${err} `);
138
138
  }
139
139
  }
140
140
 
@@ -278,7 +278,7 @@ class Zigbee extends utils.Adapter {
278
278
  delete toAdd['homeassistant'];
279
279
  try {
280
280
  zigbeeHerdsmanConverters.addDeviceDefinition(toAdd);
281
- } catch {
281
+ } catch {
282
282
  this.log.error(`unable to apply external converter ${JSON.stringfy(toAdd)}`);
283
283
  }
284
284
  }
@@ -465,50 +465,57 @@ class Zigbee extends utils.Adapter {
465
465
  // this assigment give possibility to use iobroker logger in code of the converters, via meta.logger
466
466
  meta.logger = this.log;
467
467
 
468
- await this.checkIfModelUpdate(entity);
469
-
470
- let voltage = 0;
471
- let battKey = false;
472
-
473
- if (mappedModel !== null && mappedModel !== undefined) {
474
- if (mappedModel.meta !== undefined && mappedModel.meta !== null) {
475
- if (mappedModel.meta.battery !== undefined) {
476
- const isVoltage = entity.mapped.meta.battery.hasOwnProperty('voltageToPercentage');
477
-
478
- if (isVoltage) {
479
- const keys = Object.keys(message.data);
480
-
481
- for (const key of keys) {
482
- const value = message.data[key];
483
-
484
- this.log.debug(`--> BatteryValue ${safeJsonStringify(value)} from battery search`);
485
-
486
- if (value != undefined && value[1] != undefined) {
487
- if (key == 65282 && value[1][1] != undefined) {
488
- voltage = value[1][1].elmVal;
489
- battKey = true;
490
- break;
491
- }
492
- if (key == 65281) {
493
- voltage = value[1];
494
- battKey = true;
495
- break;
496
- }
497
- }
468
+ await this.checkIfModelUpdate(entity);
469
+
470
+ let _voltage = 0;
471
+ let _temperature = 0;
472
+ let _humidity = 0;
473
+
474
+ let isMessure = false;
475
+ let isBattKey = false;
476
+
477
+ if (mappedModel && mappedModel.meta && mappedModel.meta.battery) {
478
+ const isVoltage = mappedModel.meta.battery.hasOwnProperty('voltageToPercentage');
479
+
480
+ if (isVoltage) {
481
+ const keys = Object.keys(message.data);
482
+
483
+ for (const key of keys) {
484
+ const value = message.data[key];
485
+
486
+ if (value && value[1]) {
487
+ if (key == 65282 && value[1][1]) {
488
+ _voltage = value[1][1].elmVal;
489
+ isBattKey = true;
490
+ break;
491
+ }
492
+ if (key == 65281) {
493
+ _voltage = value[1];
494
+ isBattKey = true;
495
+ _temperature = value[100];
496
+ _temperature = _temperature /100;
497
+ _humidity = value[101];
498
+ _humidity = _humidity / 100;
499
+ isMessure = true;
500
+ break;
498
501
  }
499
502
  }
500
503
  }
501
504
  }
502
505
  }
503
-
506
+
504
507
  // always publish link_quality and battery
505
508
  if (message.linkquality) { // send battery with
506
509
  this.publishToState(devId, model, {linkquality: message.linkquality});
507
- if (battKey) {
508
- this.publishToState(devId, model, {voltage: voltage});
509
- const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(voltage,entity.mapped.meta.battery.voltageToPercentage);
510
+ if (isBattKey) {
511
+ this.publishToState(devId, model, {voltage: _voltage});
512
+ const battProz = zigbeeHerdsmanConvertersUtils.batteryVoltageToPercentage(_voltage,entity.mapped.meta.battery.voltageToPercentage);
510
513
  this.publishToState(devId, model, {battery: battProz});
511
514
  }
515
+ if (isMessure) {
516
+ this.publishToState(devId, model, {temperature: _temperature});
517
+ this.publishToState(devId, model, {humidity: _humidity});
518
+ }
512
519
  }
513
520
 
514
521
  // publish raw event to "from_zigbee"
@@ -540,31 +547,43 @@ class Zigbee extends utils.Adapter {
540
547
  return;
541
548
  }
542
549
 
543
- let payload = {};
544
-
545
- const publish = (_payload) => {
546
- if (_payload) {
547
- this.publishToState(devId, model, _payload);
548
- }
549
- };
550
+ this.processConverters(converters, devId, model, mappedModel, message, meta)
551
+ // .then(() => {
552
+ //
553
+ // })
554
+ .catch((error) => {
555
+ this.log.error(`Error while processing converters: '${error}'`);
556
+ });
557
+ }
550
558
 
559
+ async processConverters(converters, devId, model, mappedModel, message, meta) {
551
560
  for (const converter of converters) {
552
- this.stController.collectOptions(devId, model, (options) => {
553
- try {
554
- payload = converter.convert(mappedModel, message, publish, options, meta);
555
-
556
- if (payload) {
557
- if (Object.keys(payload).length) {
558
- publish(payload);
559
- }
560
- }
561
- } catch (err) {
562
- this.log.warn(`convert problem with '${model}' '${devId}' `);
561
+ const publish = (payload) => {
562
+ this.log.debug(`Publish ${safeJsonStringify(payload)} to ${safeJsonStringify(devId)}`);
563
+ if (payload) {
564
+ this.publishToState(devId, model, payload);
563
565
  }
566
+ };
567
+
568
+ const options = await new Promise((resolve, reject) => {
569
+ this.stController.collectOptions(devId, model, (options) => {
570
+ resolve(options);
571
+ });
564
572
  });
573
+
574
+ const payload = await new Promise((resolve, reject) => {
575
+ const payload = converter.convert(mappedModel, message, publish, options, meta);
576
+ if (payload) {
577
+ resolve(payload);
578
+ }
579
+ });
580
+
581
+ publish(payload);
565
582
  }
566
583
  }
567
584
 
585
+
586
+
568
587
  publishToState(devId, model, payload) {
569
588
  this.stController.publishToState(devId, model, payload);
570
589
  }
@@ -595,20 +614,20 @@ class Zigbee extends utils.Adapter {
595
614
  }
596
615
  try {
597
616
  const entity = await this.zbController.resolveEntity(deviceId);
598
-
617
+
599
618
  this.log.debug(`entity: ${deviceId} ${model} ${safeJsonStringify(entity)}`);
600
-
601
- const mappedModel = entity.mapped;
602
-
619
+
620
+ const mappedModel = entity.mapped;
621
+
603
622
  if (!mappedModel) {
604
623
  this.log.debug(`No mapped model for ${model}`);
605
624
  return;
606
625
  }
607
-
626
+
608
627
  stateList.forEach(async changedState => {
609
628
  const stateDesc = changedState.stateDesc;
610
629
  const value = changedState.value;
611
-
630
+
612
631
  if (stateDesc.id === 'send_payload') {
613
632
  try {
614
633
  const json_value = JSON.parse(value);
@@ -623,14 +642,14 @@ class Zigbee extends utils.Adapter {
623
642
  }
624
643
  return;
625
644
  }
626
-
645
+
627
646
  if (stateDesc.isOption) {
628
647
  // acknowledge state with given value
629
648
  this.acknowledgeState(deviceId, model, stateDesc, value);
630
649
  // process sync state list
631
650
  //this.processSyncStatesList(deviceId, modelId, syncStateList);
632
651
  // if this is the device query state => trigger the device query
633
-
652
+
634
653
  // on activation of the 'device_query' state trigger hardware query where possible
635
654
  if (stateDesc.id === 'device_query') {
636
655
  if (this.query_device_block.indexOf(deviceId) > -1) {
@@ -647,7 +666,7 @@ class Zigbee extends utils.Adapter {
647
666
  await converter.convertGet(entity.device.endpoints[0], ckey, {});
648
667
  } catch (error) {
649
668
  this.log.warn(`Failed to read state '${JSON.stringify(ckey)}'of '${entity.device.ieeeAddr}' after query with '${JSON.stringify(error)}'`);
650
-
669
+
651
670
  }
652
671
  }
653
672
  }
@@ -671,7 +690,7 @@ class Zigbee extends utils.Adapter {
671
690
  this.sendError(`No converter available for '${model}' with key '${stateDesc.id}' `);
672
691
  return;
673
692
  }
674
-
693
+
675
694
  const preparedValue = (stateDesc.setter) ? stateDesc.setter(value, options) : value;
676
695
  const preparedOptions = (stateDesc.setterOpt) ? stateDesc.setterOpt(value, options) : {};
677
696
  let syncStateList = [];
@@ -683,11 +702,11 @@ class Zigbee extends utils.Adapter {
683
702
  }
684
703
  });
685
704
  }
686
-
705
+
687
706
  const epName = stateDesc.epname !== undefined ? stateDesc.epname : (stateDesc.prop || stateDesc.id);
688
707
  const key = stateDesc.setattr || stateDesc.prop || stateDesc.id;
689
708
  this.log.debug(`convert ${key}, ${safeJsonStringify(preparedValue)}, ${safeJsonStringify(preparedOptions)}`);
690
-
709
+
691
710
  let target;
692
711
  if (model === 'group') {
693
712
  target = entity.mapped;
@@ -695,9 +714,9 @@ class Zigbee extends utils.Adapter {
695
714
  target = await this.zbController.resolveEntity(deviceId, epName);
696
715
  target = target.endpoint;
697
716
  }
698
-
717
+
699
718
  this.log.debug(`target: ${safeJsonStringify(target)}`);
700
-
719
+
701
720
  const meta = {
702
721
  endpoint_name: epName,
703
722
  options: preparedOptions,
@@ -707,11 +726,11 @@ class Zigbee extends utils.Adapter {
707
726
  logger: this.log,
708
727
  state: {},
709
728
  };
710
-
729
+
711
730
  if (preparedOptions.hasOwnProperty('state')) {
712
731
  meta.state = preparedOptions.state;
713
732
  }
714
-
733
+
715
734
  try {
716
735
  const result = await converter.convertSet(target, key, preparedValue, meta);
717
736
  this.log.debug(`convert result ${safeJsonStringify(result)}`);
@@ -721,20 +740,20 @@ class Zigbee extends utils.Adapter {
721
740
  }
722
741
  // process sync state list
723
742
  this.processSyncStatesList(deviceId, model, syncStateList);
724
-
743
+
725
744
  if (isGroup) {
726
745
  await this.callPluginMethod('queryGroupMemberState', [deviceId, stateDesc]);
727
746
  this.acknowledgeState(deviceId, model, stateDesc, value);
728
747
  }
729
748
  }
730
-
749
+
731
750
  } catch (error) {
732
751
  this.filterError(`Error ${error.code} on send command to ${deviceId}.` +
733
752
  ` Error: ${error.stack}`, `Send command to ${deviceId} failed with`, error);
734
753
  }
735
754
  });
736
755
  } catch (err) {
737
- this.log.error(`No entity for ${deviceId}`);
756
+ this.log.error(`No entity for ${deviceId}`);
738
757
  }
739
758
  }
740
759
 
@@ -950,7 +969,7 @@ class Zigbee extends utils.Adapter {
950
969
  }
951
970
 
952
971
  onPairing(message, data) {
953
- if (Number.isInteger(data)) {
972
+ if (Number.isInteger(data)) {
954
973
  this.setState('info.pairingCountdown', data, true);
955
974
  }
956
975
  if (data === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee",
3
- "version": "1.8.22",
3
+ "version": "1.8.24",
4
4
  "author": {
5
5
  "name": "Kirov Ilya",
6
6
  "email": "kirovilya@gmail.com"
@@ -15,7 +15,7 @@
15
15
  }
16
16
  ],
17
17
  "engines": {
18
- "node": ">=10"
18
+ "node": ">=16"
19
19
  },
20
20
  "optionalDependencies": {
21
21
  "serialport": "^11.0.1"
@@ -23,9 +23,9 @@
23
23
  "dependencies": {
24
24
  "@iobroker/adapter-core": "^3.0.3",
25
25
  "tar": "^6.1.15",
26
- "typescript": "^5.1.6",
27
- "zigbee-herdsman": "0.17.2",
28
- "zigbee-herdsman-converters": "15.54.0"
26
+ "typescript": "^5.2.2",
27
+ "zigbee-herdsman": "0.18.7",
28
+ "zigbee-herdsman-converters": "15.70.0"
29
29
  },
30
30
  "description": "Zigbee devices",
31
31
  "devDependencies": {
@@ -34,11 +34,11 @@
34
34
  "@alcalzone/release-script-plugin-license": "^3.5.9",
35
35
  "@alcalzone/release-script-plugin-manual-review": "^3.5.9",
36
36
  "@iobroker/testing": "^4.1.0",
37
- "axios": "^1.3.4",
38
- "chai": "^4.3.7",
37
+ "axios": "^1.5.0",
38
+ "chai": "^4.3.8",
39
39
  "chai-as-promised": "^7.1.1",
40
40
  "eslint": "^8.46.0",
41
- "eslint-config-prettier": "^8.9.0",
41
+ "eslint-config-prettier": "^9.0.0",
42
42
  "eslint-plugin-prettier": "^5.0.0",
43
43
  "gulp": "^4.0.2",
44
44
  "gulp-jsdoc3": "^3.0.0",
package/support/docgen.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * This script generates the supported devices page.
3
- *
3
+ *
4
4
  */
5
5
 
6
6
  let devices = [...require('zigbee-herdsman-converters').devices];
@@ -86,7 +86,7 @@ vendors.sort();
86
86
  text += '| Model | Description | Picture |\n';
87
87
  text += '| ------------- | ------------- | -------------------------- |\n';
88
88
  vendors.forEach((vendor) => {
89
- text += `| | **${vendor}** | |\n`;
89
+ text += `| | **${vendor}** | |\n`;
90
90
  text += logDevices([...iobDevices.keys()].map((m) => devices.get(m)).filter((d) => d && d.vendor === vendor).map((d) => d.model));
91
91
  });
92
92