iobroker.zigbee 3.0.0 → 3.0.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/lib/networkmap.js CHANGED
@@ -9,6 +9,7 @@ class NetworkMap {
9
9
  start(zbController, stController) {
10
10
  this.zbController = zbController;
11
11
  this.stController = stController;
12
+ return this.stop;
12
13
  }
13
14
 
14
15
  stop() {
@@ -53,4 +54,4 @@ class NetworkMap {
53
54
  }
54
55
  }
55
56
 
56
- module.exports = NetworkMap;
57
+ module.exports = NetworkMap;
@@ -57,23 +57,6 @@ class StatesController extends EventEmitter {
57
57
  this.adapter.sendError(error, message);
58
58
  }
59
59
 
60
- TriggerUpload(delay) {
61
- if (this.timeoutHandleUpload) return;
62
- this.warn('triggering upload')
63
- this.timeoutHandleUpload = this.adapter.setTimeout(() => {
64
- try {
65
- this.warn('executing upload')
66
- exec('iobroker upload zigbee', (error, stdout, stderr) => {
67
- if (error) this.error('exec error: ' + JSON.stringify(error));
68
- this.warn('upload done');
69
- });
70
- }
71
- catch (error) {
72
- this.error('error on upload exec');
73
- }
74
- }, delay);
75
- }
76
-
77
60
  getStashedErrors() {
78
61
  const rv = [];
79
62
  try {
@@ -99,19 +82,19 @@ class StatesController extends EventEmitter {
99
82
 
100
83
  async AddModelFromHerdsman(device, model) {
101
84
  // this.warn('addModelFromHerdsman ' + JSON.stringify(model) + ' ' + JSON.stringify(this.localConfig.getOverrideWithKey(model, 'legacy', true)));
102
- if (this.localConfig.getOverrideWithKey(model, 'legacy', true)) {
85
+ if (this.localConfig.getOverrideWithTargetAndKey(model, 'legacy', true)) {
103
86
  this.debug('Applying legacy definition for ' + model);
104
87
  await this.addLegacyDevice(model);
105
88
  }
106
89
  else {
107
90
  this.debug('Generating states from exposes for ' + model);
108
- const modelDesc = await statesMapping.addExposeToDevices(device, this, model);
109
- const srcIcon = modelDesc.icon;
110
91
  // download icon if it external and not undefined
111
92
  if (model === undefined) {
112
93
  const dev_name = this.verifyDeviceName(device.ieeeAddr.substr(2), model, device.modelID);
113
- this.warn(`download icon ${dev_name} for undefined Device not available. Check your devices.`);
94
+ this.warn(`icon ${dev_name} for undefined Device not available. Check your devices.`);
114
95
  } else {
96
+ const modelDesc = await statesMapping.addExposeToDevices(device, this, model);
97
+ const srcIcon = modelDesc.icon;
115
98
  const model_modif = model.replace(/\//g, '-');
116
99
  const pathToAdminIcon = `img/${model_modif}.png`;
117
100
 
@@ -134,15 +117,17 @@ class StatesController extends EventEmitter {
134
117
  }
135
118
  const base64Match = srcIcon.match(/data:image\/(.+);base64,/);
136
119
  if (base64Match) {
120
+ this.warn(`base 64 Icon matched, trying to save it to disk as ${pathToAdminIcon}`);
137
121
  modelDesc.icon = pathToAdminIcon;
138
122
  this.adapter.fileExists(namespace, pathToAdminIcon, async (err,result) => {
139
123
  if (result) {
140
- this.debug(`no need to save icon to ${pathToAdminIcon}`);
124
+ this.warn(`no need to save icon to ${pathToAdminIcon}`);
141
125
  return;
142
126
  }
143
- this.debug(`Saving base64 data to ${pathToAdminIcon}`)
127
+ this.warn(`Saving base64 data to ${pathToAdminIcon}`)
144
128
  const buffer = new Buffer(srcIcon.replace(base64Match[0],''), 'base64');
145
129
  this.adapter.writeFile(pathToAdminIcon, buffer);
130
+ this.warn('write file complete.');
146
131
  });
147
132
  return;
148
133
  }
@@ -296,48 +281,60 @@ class StatesController extends EventEmitter {
296
281
  }
297
282
 
298
283
  }
299
- this.collectOptions(id.split('.')[2], model, options =>
284
+ this.collectOptions(id.split('.')[2], model, true, options =>
300
285
  this.publishFromState(deviceId, model, stateKey, state, options, debugId));
301
286
  }
302
287
  });
303
288
  }
304
289
  }
305
290
 
306
- async collectOptions(devId, model, callback) {
307
- const result = {};
308
- // find model states for options and get it values. No options for groups !!!
309
- const devStates = await this.getDevStates('0x' + devId, model);
310
- if (devStates == null || devStates == undefined || devStates.states == null || devStates.states == undefined) {
311
- callback(result);
312
- return;
313
- }
314
-
315
- const states = devStates.states.filter(statedesc => statedesc.isOption || statedesc.inOptions);
316
- if (states == null || states == undefined) {
317
- callback(result);
318
- return;
319
- }
320
- let cnt = 0;
291
+ async collectOptions(devId, model, getOptionStates, callback) {
321
292
  try {
322
- const len = states.length;
323
- states.forEach(statedesc => {
324
- const id = `${this.adapter.namespace}.${devId}.${statedesc.id}`;
325
- this.adapter.getState(id, (err, state) => {
326
- cnt = cnt + 1;
327
- if (!err && state) {
328
- result[statedesc.id] = state.val;
329
- }
330
- if (cnt === len) {
331
- callback(result);
332
- }
333
- });
334
- });
335
- if (!len) {
293
+ const result = this.localConfig.getOptions(devId);
294
+ if (!getOptionStates) {
336
295
  callback(result);
296
+ return;
297
+ }
298
+ // find model states for options and get it values. No options for groups !!!
299
+ const devStates = await this.getDevStates('0x' + devId, model);
300
+ if (devStates == null || devStates == undefined || devStates.states == null || devStates.states == undefined) {
301
+ callback(result);
302
+ return;
303
+ }
304
+
305
+ const states = devStates.states.filter(statedesc => statedesc.isOption || statedesc.inOptions);
306
+ if (states == null || states == undefined) {
307
+ callback(result);
308
+ return;
309
+ }
310
+ let cnt = 0;
311
+ try {
312
+ const len = states.length;
313
+ states.forEach(statedesc => {
314
+ const id = `${this.adapter.namespace}.${devId}.${statedesc.id}`;
315
+ this.adapter.getState(id, (err, state) => {
316
+ cnt = cnt + 1;
317
+ if (!err && state) {
318
+ this.debug(`collect options for ${devId}: ${JSON.stringify(result)}`);
319
+ result[statedesc.id] = state.val;
320
+ }
321
+ if (cnt === len) {
322
+ callback(result);
323
+ }
324
+ });
325
+ });
326
+ if (!len) {
327
+ callback(result);
328
+ }
329
+ } catch (error) {
330
+ this.sendError(error);
331
+ this.error(`Error collectOptions for ${devId}. Error: ${error.stack}`);
337
332
  }
338
- } catch (error) {
339
- this.sendError(error);
340
- this.error(`Error collectOptions for ${devId}. Error: ${error.stack}`);
333
+ }
334
+ catch (error) {
335
+ this.error(`Error in collectOptions for ${devId} , ${model} : ${error && error.message ? error.message : 'no message given'}`);
336
+ callback({});
337
+
341
338
  }
342
339
  }
343
340
 
@@ -1047,7 +1044,7 @@ class StatesController extends EventEmitter {
1047
1044
 
1048
1045
  } else {
1049
1046
  if (statedesc.prepublish) {
1050
- this.collectOptions(devId, model, options =>
1047
+ this.collectOptions(devId, model, false, options =>
1051
1048
  statedesc.prepublish(devId, value, newvalue => {
1052
1049
  this.updateState(devId, stateID, newvalue, common) }, options)
1053
1050
  );
@@ -1088,7 +1085,7 @@ class StatesController extends EventEmitter {
1088
1085
  };
1089
1086
 
1090
1087
  const options = await new Promise((resolve, reject) => {
1091
- this.collectOptions(devId, model, (options) => {
1088
+ this.collectOptions(devId, model, false, (options) => {
1092
1089
  resolve(options);
1093
1090
  });
1094
1091
  });
@@ -1220,10 +1217,15 @@ class StatesController extends EventEmitter {
1220
1217
  if (cluster !== '64529') {
1221
1218
  if (has_elevated_debug) this.emit('device_debug', { ID:debugId, data: { error:'EPROC', IO:true }});
1222
1219
  this.error(`Error while processing converters DEVICE_ID: '${devId}' cluster '${cluster}' type '${type}'`);
1220
+ this.error(`error message: ${error && error.message ? error.message : ''}`);
1223
1221
  }
1224
1222
  });
1225
1223
  }
1226
1224
 
1225
+ async stop() {
1226
+ this.localConfig.retainData();
1227
+ }
1228
+
1227
1229
 
1228
1230
 
1229
1231
  }
@@ -155,7 +155,7 @@ class DeviceConfigure extends BaseExtension {
155
155
  if (mappedDevice.configure === undefined) return `No configure available for ${device.ieeeAddr} ${mappedDevice.model}.`;
156
156
  this.info(`Configuring ${device.ieeeAddr} ${mappedDevice.model}`);
157
157
  this.configuring.add(device.ieeeAddr);
158
- if (typeof mappedDevice.configure === 'function') await mappedDevice.configure(device, coordinatorEndpoint, this);
158
+ if (typeof mappedDevice.configure === 'function') await mappedDevice.configure(device, coordinatorEndpoint, mappedDevice);
159
159
  else {
160
160
  const promises = [];
161
161
  promises.push(...mappedDevice.configure);
@@ -118,7 +118,7 @@ class ZigbeeController extends EventEmitter {
118
118
  this.powerText = powerLevels[this.transmitPower] || 'normal';
119
119
  }
120
120
 
121
- this.info(` --> transmitPower : ${this.powerText}`);
121
+ //this.info(` --> transmitPower : ${this.powerText}`);
122
122
 
123
123
  const herdsmanSettings = {
124
124
  network: {
@@ -185,6 +185,16 @@ class ZigbeeController extends EventEmitter {
185
185
  async start() {
186
186
  try {
187
187
  this.emit('pairing',`Starting zigbee-herdsman...`);
188
+ this.powerText = '';
189
+ if (this.transmitPower !== '0') {
190
+ const powerLevels = {
191
+ '-22': 'low',
192
+ '19': 'high',
193
+ '20': 'high+'
194
+ };
195
+ this.powerText = powerLevels[this.transmitPower] || 'normal';
196
+ }
197
+ this.info(`configured transmit power : ${this.powerText}`);
188
198
  if (this.debugActive) this.debug(`Starting zigbee-herdsman...`);
189
199
 
190
200
  // install event handlers before start
@@ -669,6 +679,7 @@ class ZigbeeController extends EventEmitter {
669
679
  if (this.HerdsmanStarted) await this.permitJoin(0);
670
680
  await this.herdsman.stop();
671
681
  this.HerdsmanStarted = false;
682
+ this.info('zigbecontroller stopped successfully');
672
683
  } catch (error) {
673
684
  this.sendError(error);
674
685
  if (this.herdsmanStarted) {
package/main.js CHANGED
@@ -232,7 +232,11 @@ class Zigbee extends utils.Adapter {
232
232
  this.deviceDebug.start(this.stController, this.zbController);
233
233
 
234
234
  this.reconnectCounter = 1;
235
- if (this.config.autostart) this.doConnect();
235
+ if (this.config.autostart) {
236
+ this.log.info('Autostart Zigbee subsystem');
237
+ this.doConnect();
238
+ }
239
+ else this.log.warn('Zigbee autostart option not set - omitting start of zigbee substystem!');
236
240
  }
237
241
  updateDebugLevel(state) {
238
242
  const dbActive = state === 'debug';
@@ -809,7 +813,7 @@ class Zigbee extends utils.Adapter {
809
813
  this.emit('device_debug', { ID:debugID, data: { error: 'NOCONV',states:[{id:stateDesc.id, value:value, payload:'no converter'}] , IO:false }, message:message});
810
814
  }
811
815
  else {
812
- this.log.warn(message);
816
+ this.log.info(message);
813
817
  }
814
818
  return;
815
819
  }
@@ -1079,17 +1083,19 @@ class Zigbee extends utils.Adapter {
1079
1083
  */
1080
1084
  async onUnload(callback) {
1081
1085
  try {
1086
+ this.log.info(`Halting zigbee adapter. Restart delay is at least ${this.ioPack.common.stopTimeout / 1000} seconds.`)
1082
1087
  if (this.config.debugHerdsman) {
1083
1088
  debug.disable();
1084
1089
  debug.log = originalLogMethod;
1085
1090
  }
1086
1091
 
1087
- this.log.info('cleaned everything up...');
1088
- if (this.reconnectTimer) clearTimeout(this.reconnectTimer);
1092
+ this.log.info('cleaning everything up...');
1089
1093
  await this.callPluginMethod('stop');
1094
+ await this.stController.stop();
1090
1095
  if (this.zbController) {
1091
1096
  await this.zbController.stop();
1092
1097
  }
1098
+ this.log.info('cleanup successful');
1093
1099
  callback();
1094
1100
  } catch (error) {
1095
1101
  if (error) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.zigbee",
3
- "version": "3.0.0",
3
+ "version": "3.0.2",
4
4
  "author": {
5
5
  "name": "Kirov Ilya",
6
6
  "email": "kirovilya@gmail.com"
@@ -22,14 +22,14 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@iobroker/adapter-core": "^3.2.3",
25
- "@iobroker/dm-utils": "^1.0.9",
26
- "humanize-duration": "^3.32.1",
25
+ "@iobroker/dm-utils": "^1.0.10",
26
+ "humanize-duration": "^3.33.0",
27
27
  "tar": "^7.4.3",
28
28
  "ajv": "^8.17.1",
29
29
  "uri-js": "^4.4.1",
30
- "typescript": "^5.6.3",
31
- "zigbee-herdsman": "^3.3.2",
32
- "zigbee-herdsman-converters": "^23.13.0"
30
+ "typescript": "^5.8.3",
31
+ "zigbee-herdsman": "4.0.0",
32
+ "zigbee-herdsman-converters": "23.35.0"
33
33
  },
34
34
  "description": "Zigbee devices",
35
35
  "devDependencies": {
@@ -40,9 +40,9 @@
40
40
  "@iobroker/testing": "^5.0.4",
41
41
  "chai": "^5.1.2",
42
42
  "chai-as-promised": "^7.1.1",
43
- "eslint": "^9.19.0",
43
+ "eslint": "^9.30.0",
44
44
  "eslint-config-prettier": "^9.1.0",
45
- "eslint-plugin-prettier": "^5.2.5",
45
+ "eslint-plugin-prettier": "^5.5.1",
46
46
  "gulp": "^4.0.2",
47
47
  "gulp-jsdoc3": "^3.0.0",
48
48
  "gulp-replace": "^1.1.4",