iobroker.zigbee 1.7.5 → 1.8.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/LICENSE +1 -1
- package/README.md +22 -29
- package/admin/admin.js +494 -469
- package/admin/i18n/de/translations.json +108 -0
- package/admin/i18n/en/translations.json +108 -0
- package/admin/i18n/es/translations.json +102 -0
- package/admin/i18n/fr/translations.json +108 -0
- package/admin/i18n/it/translations.json +102 -0
- package/admin/i18n/nl/translations.json +108 -0
- package/admin/i18n/pl/translations.json +108 -0
- package/admin/i18n/pt/translations.json +102 -0
- package/admin/i18n/ru/translations.json +108 -0
- package/admin/i18n/uk/translations.json +108 -0
- package/admin/i18n/zh-cn/translations.json +102 -0
- package/admin/index_m.html +1 -1
- package/admin/tab_m.html +44 -3
- package/admin/words.js +107 -108
- package/io-package.json +326 -357
- package/lib/backup.js +2 -2
- package/lib/binding.js +23 -24
- package/lib/colors.js +16 -14
- package/lib/commands.js +89 -82
- package/lib/developer.js +6 -7
- package/lib/devices.js +145 -154
- package/lib/exclude.js +30 -36
- package/lib/exposes.js +106 -111
- package/lib/groups.js +53 -54
- package/lib/json.js +3 -4
- package/lib/networkmap.js +2 -2
- package/lib/ota.js +23 -15
- package/lib/rgb.js +47 -44
- package/lib/seriallist.js +21 -10
- package/lib/states.js +488 -498
- package/lib/statescontroller.js +170 -164
- package/lib/utils.js +22 -21
- package/lib/zbBaseExtension.js +4 -4
- package/lib/zbDelayedAction.js +5 -13
- package/lib/zbDeviceAvailability.js +47 -44
- package/lib/zbDeviceConfigure.js +18 -23
- package/lib/zbDeviceEvent.js +3 -4
- package/lib/zigbeecontroller.js +97 -100
- package/main.js +149 -133
- package/package.json +33 -19
- package/.eslintignore +0 -2
- package/.eslintrc.json +0 -37
- package/.github/FUNDING.yml +0 -3
- package/.github/stale.yml +0 -13
- package/.github/workflows/test-and-release.yml +0 -151
- package/.travis/wiki.sh +0 -28
- package/admin/adapter-settings.js +0 -244
package/lib/backup.js
CHANGED
|
@@ -49,7 +49,7 @@ class Backup {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
async configure
|
|
52
|
+
async configure(zigbeeOptions) {
|
|
53
53
|
this.zigbeeOptions = zigbeeOptions;
|
|
54
54
|
this.backup(zigbeeOptions);
|
|
55
55
|
const allBackupFiles = this.listBackupsFiles(zigbeeOptions);
|
|
@@ -121,7 +121,7 @@ class Backup {
|
|
|
121
121
|
delBackupsFiles(options, files) {
|
|
122
122
|
const arr = files.length;
|
|
123
123
|
if (arr > 10) {
|
|
124
|
-
this.info('delete old Backup files. keep only last 10')
|
|
124
|
+
this.info('delete old Backup files. keep only last 10');
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
for (let i = 10; i < files.length; i++) {
|
package/lib/binding.js
CHANGED
|
@@ -34,7 +34,7 @@ class Binding {
|
|
|
34
34
|
debug(msg) {
|
|
35
35
|
this.adapter.log.debug(msg);
|
|
36
36
|
}
|
|
37
|
-
|
|
37
|
+
|
|
38
38
|
warn(msg) {
|
|
39
39
|
this.adapter.log.warn(msg);
|
|
40
40
|
}
|
|
@@ -86,21 +86,23 @@ class Binding {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
extractDeviceId(stateId) {
|
|
89
|
-
if (stateId)
|
|
89
|
+
if (stateId) {
|
|
90
90
|
return stateId.replace(`${this.adapter.namespace}.`, '');
|
|
91
|
+
}
|
|
91
92
|
return '';
|
|
92
93
|
}
|
|
93
94
|
|
|
94
95
|
getBindEp(ep) {
|
|
95
|
-
if (ep)
|
|
96
|
+
if (ep) {
|
|
96
97
|
return parseInt(ep.split('_')[0]);
|
|
98
|
+
}
|
|
97
99
|
|
|
98
100
|
this.warn(`getBindEp called with illegal ep: ${safeJsonStringify(ep)}`);
|
|
99
101
|
return 0;
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
getBindCl(ep) {
|
|
103
|
-
return
|
|
105
|
+
return ep.indexOf('_') > 0 ? ep.split('_')[1] : null;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
async doBindUnbind(type, bind_source, bind_source_ep, bind_target, bind_target_ep, callback) {
|
|
@@ -123,8 +125,7 @@ class Binding {
|
|
|
123
125
|
|
|
124
126
|
if (!source || !target) {
|
|
125
127
|
this.error('Devices not found');
|
|
126
|
-
|
|
127
|
-
return;
|
|
128
|
+
return callback && callback('Devices not found');
|
|
128
129
|
}
|
|
129
130
|
const sourceName = source.name;
|
|
130
131
|
const targetName = target.name;
|
|
@@ -144,8 +145,7 @@ class Binding {
|
|
|
144
145
|
}
|
|
145
146
|
if (!found) {
|
|
146
147
|
this.debug(`No bind clusters`);
|
|
147
|
-
|
|
148
|
-
return;
|
|
148
|
+
return callback && callback(`No bind clusters`);
|
|
149
149
|
} else {
|
|
150
150
|
let ok = true;
|
|
151
151
|
for (const clID of clusters) {
|
|
@@ -171,23 +171,23 @@ class Binding {
|
|
|
171
171
|
`Failed to ${type} cluster '${cluster}' from '${sourceName}' to ` +
|
|
172
172
|
`'${targetName}' (${error})`,
|
|
173
173
|
);
|
|
174
|
-
|
|
174
|
+
callback && callback(`Failed to ${type} cluster '${cluster}' from '${sourceName}' to '${targetName}' (${error})`);
|
|
175
175
|
ok = false;
|
|
176
176
|
break;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
}
|
|
180
|
-
|
|
180
|
+
ok && callback && callback(undefined, id);
|
|
181
181
|
}
|
|
182
182
|
} catch (error) {
|
|
183
183
|
this.error(`Failed to doBindUnbind ${error.stack}`);
|
|
184
|
-
|
|
184
|
+
callback && callback(`Failed to doBindUnbind ${error.stack}`);
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
|
|
188
188
|
async addBinding(from, command, params, callback) {
|
|
189
189
|
try {
|
|
190
|
-
this.debug(
|
|
190
|
+
this.debug(`addBinding message: ${JSON.stringify(params)}`);
|
|
191
191
|
const bind_source = params.bind_source,
|
|
192
192
|
bind_source_ep = params.bind_source_ep,
|
|
193
193
|
bind_target = params.bind_target,
|
|
@@ -207,9 +207,8 @@ class Binding {
|
|
|
207
207
|
type: 'state',
|
|
208
208
|
common: {name: id},
|
|
209
209
|
}, () => {
|
|
210
|
-
this.adapter.setState(stateId, JSON.stringify(params), true, () =>
|
|
211
|
-
callback();
|
|
212
|
-
});
|
|
210
|
+
this.adapter.setState(stateId, JSON.stringify(params), true, () =>
|
|
211
|
+
callback());
|
|
213
212
|
});
|
|
214
213
|
}
|
|
215
214
|
});
|
|
@@ -221,7 +220,7 @@ class Binding {
|
|
|
221
220
|
|
|
222
221
|
async editBinding(from, command, params, callback) {
|
|
223
222
|
try {
|
|
224
|
-
this.debug(
|
|
223
|
+
this.debug(`editBinding message: ${JSON.stringify(params)}`);
|
|
225
224
|
const old_id = params.id,
|
|
226
225
|
bind_source = params.bind_source,
|
|
227
226
|
bind_source_ep = params.bind_source_ep,
|
|
@@ -229,7 +228,7 @@ class Binding {
|
|
|
229
228
|
bind_target_ep = params.bind_target_ep,
|
|
230
229
|
id = this.getBindingId(bind_source, bind_source_ep, bind_target, bind_target_ep);
|
|
231
230
|
if (old_id !== id) {
|
|
232
|
-
await this.delBinding(from, command, old_id, async
|
|
231
|
+
await this.delBinding(from, command, old_id, async err => {
|
|
233
232
|
if (err) {
|
|
234
233
|
callback(err);
|
|
235
234
|
} else {
|
|
@@ -242,7 +241,7 @@ class Binding {
|
|
|
242
241
|
await this.doBindUnbind(type , bind_source, bind_source_ep, 'coordinator', '1');
|
|
243
242
|
this.debug('Successfully ' + (type === 'bind' ? 'bound' : 'unbound') + ' Coordinator from ' + bind_source);
|
|
244
243
|
} catch (e) {
|
|
245
|
-
this.error(
|
|
244
|
+
this.error(`Could not ${type} Coordinator from ${bind_source}: ${JSON.stringify(e)}`);
|
|
246
245
|
}
|
|
247
246
|
}
|
|
248
247
|
} catch (error) {
|
|
@@ -252,17 +251,17 @@ class Binding {
|
|
|
252
251
|
|
|
253
252
|
async delBinding(from, command, bind_id, callback) {
|
|
254
253
|
try {
|
|
255
|
-
this.debug(
|
|
254
|
+
this.debug(`delBinding message: ${JSON.stringify(bind_id)}`);
|
|
256
255
|
const stateId = `info.${bind_id}`;
|
|
257
256
|
this.adapter.getStateAsync(stateId)
|
|
258
|
-
.then(async
|
|
259
|
-
this.debug(
|
|
257
|
+
.then(async stateV => {
|
|
258
|
+
this.debug(`found state: ${JSON.stringify(stateV)}`);
|
|
260
259
|
const params = JSON.parse(stateV.val);
|
|
261
260
|
const bind_source = params.bind_source,
|
|
262
261
|
bind_source_ep = params.bind_source_ep,
|
|
263
262
|
bind_target = params.bind_target,
|
|
264
263
|
bind_target_ep = params.bind_target_ep;
|
|
265
|
-
await this.doBindUnbind('unbind', bind_source, bind_source_ep, bind_target, bind_target_ep, async
|
|
264
|
+
await this.doBindUnbind('unbind', bind_source, bind_source_ep, bind_target, bind_target_ep, async err => {
|
|
266
265
|
if (err) {
|
|
267
266
|
callback({error: err});
|
|
268
267
|
} else {
|
|
@@ -308,11 +307,11 @@ class Binding {
|
|
|
308
307
|
}
|
|
309
308
|
});
|
|
310
309
|
return Promise.all(chain).then(() => {
|
|
311
|
-
this.debug(
|
|
310
|
+
this.debug(`getBinding result: ${JSON.stringify(binding)}`);
|
|
312
311
|
callback(binding);
|
|
313
312
|
});
|
|
314
313
|
} else {
|
|
315
|
-
this.debug(
|
|
314
|
+
this.debug(`getBinding result: ${JSON.stringify(binding)}`);
|
|
316
315
|
callback(binding);
|
|
317
316
|
}
|
|
318
317
|
});
|
package/lib/colors.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
const namedColors = {
|
|
5
4
|
mediumvioletred: {
|
|
6
5
|
rgb: '#c71585',
|
|
@@ -424,15 +423,15 @@ const namedColors = {
|
|
|
424
423
|
},
|
|
425
424
|
};
|
|
426
425
|
|
|
427
|
-
function
|
|
428
|
-
{
|
|
426
|
+
function namedColorToRGBstring(name) {
|
|
429
427
|
const lowerName = name.toLowerCase();
|
|
430
|
-
if (namedColors.hasOwnProperty(lowerName))
|
|
428
|
+
if (namedColors.hasOwnProperty(lowerName)) {
|
|
429
|
+
return namedColors[lowerName].rgb;
|
|
430
|
+
}
|
|
431
431
|
return '#0088FF';
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
-
function
|
|
435
|
-
{
|
|
434
|
+
function parseColor(rgbstring) {
|
|
436
435
|
if (typeof(rgbstring) === 'string') {
|
|
437
436
|
const lowerName = rgbstring.toLowerCase();
|
|
438
437
|
if (namedColors.hasOwnProperty(lowerName))
|
|
@@ -446,15 +445,18 @@ function ParseColor(rgbstring)
|
|
|
446
445
|
oneColor.b = val % 256;
|
|
447
446
|
return oneColor;
|
|
448
447
|
}
|
|
449
|
-
|
|
448
|
+
|
|
449
|
+
return {r: 0,g: 128,b: 255};
|
|
450
450
|
}
|
|
451
451
|
|
|
452
|
-
function
|
|
453
|
-
{
|
|
454
|
-
|
|
455
|
-
|
|
452
|
+
function namedColorToRGB(name) {
|
|
453
|
+
if (namedColors.hasOwnProperty(name)) {
|
|
454
|
+
return parseColor(namedColors[name].rgb);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return {r: 0, g: 128, b: 255};
|
|
456
458
|
}
|
|
457
459
|
|
|
458
|
-
exports.NamedColorToRGB =
|
|
459
|
-
exports.NamedCOlorToRGBString =
|
|
460
|
-
exports.ParseColor =
|
|
460
|
+
exports.NamedColorToRGB = namedColorToRGB;
|
|
461
|
+
exports.NamedCOlorToRGBString = namedColorToRGBstring;
|
|
462
|
+
exports.ParseColor = parseColor;
|
package/lib/commands.js
CHANGED
|
@@ -112,7 +112,6 @@ class Commands {
|
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
|
|
116
115
|
letsPairing(from, command, message, callback) {
|
|
117
116
|
if (this.zbController) {
|
|
118
117
|
let devId = '';
|
|
@@ -123,11 +122,11 @@ class Commands {
|
|
|
123
122
|
this.adapter.logToPairing('Pairing started ' + devId, true);
|
|
124
123
|
|
|
125
124
|
let cTimer = Number(this.adapter.config.countDown);
|
|
126
|
-
if (!this.adapter.config.countDown || cTimer
|
|
125
|
+
if (!this.adapter.config.countDown || !cTimer) {
|
|
127
126
|
cTimer = 60;
|
|
128
127
|
}
|
|
129
128
|
|
|
130
|
-
this.zbController.permitJoin(cTimer, devId,
|
|
129
|
+
this.zbController.permitJoin(cTimer, devId, err => {
|
|
131
130
|
if (!err) {
|
|
132
131
|
// set pairing mode on
|
|
133
132
|
this.adapter.setState('info.pairingMode', true);
|
|
@@ -149,7 +148,7 @@ class Commands {
|
|
|
149
148
|
this.adapter.logToPairing('Touchlink reset started ', true);
|
|
150
149
|
|
|
151
150
|
let cTimer = Number(this.adapter.config.countDown);
|
|
152
|
-
if (!this.adapter.config.countDown || cTimer
|
|
151
|
+
if (!this.adapter.config.countDown || !cTimer) {
|
|
153
152
|
cTimer = 60;
|
|
154
153
|
}
|
|
155
154
|
|
|
@@ -170,20 +169,18 @@ class Commands {
|
|
|
170
169
|
const groups = {};
|
|
171
170
|
let rooms;
|
|
172
171
|
this.adapter.getEnumsAsync('enum.rooms')
|
|
173
|
-
.then(
|
|
172
|
+
.then(enums => {
|
|
174
173
|
// rooms
|
|
175
174
|
rooms = enums['enum.rooms'];
|
|
176
175
|
})
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
const allst = (id) ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
|
|
184
|
-
result = result.filter((item)=>!id || id == item._id);
|
|
176
|
+
// get all adapter devices
|
|
177
|
+
.then(() => this.adapter.getDevicesAsync())
|
|
178
|
+
.then(async result => {
|
|
179
|
+
const alls = id ? await this.adapter.getStatesAsync(id + '.*') : await this.adapter.getStatesAsync('*');
|
|
180
|
+
const allst = id ? await this.adapter.getStatesOfAsync(id) : await this.adapter.getStatesOfAsync();
|
|
181
|
+
result = result.filter(item => !id || id === item._id);
|
|
185
182
|
// get device states and groups
|
|
186
|
-
result.forEach(async
|
|
183
|
+
result.forEach(async devInfo => {
|
|
187
184
|
if (devInfo._id) {
|
|
188
185
|
// groups
|
|
189
186
|
// const grState = alls[`${devInfo._id}.groups`];
|
|
@@ -192,31 +189,31 @@ class Commands {
|
|
|
192
189
|
// }
|
|
193
190
|
// battery and link_quality
|
|
194
191
|
const lqState = alls[`${devInfo._id}.link_quality`];
|
|
195
|
-
devInfo.link_quality =
|
|
196
|
-
devInfo.link_quality_lc =
|
|
192
|
+
devInfo.link_quality = lqState ? lqState.val: undefined;
|
|
193
|
+
devInfo.link_quality_lc = lqState ? lqState.lc: undefined;
|
|
197
194
|
const batState = alls[`${devInfo._id}.battery`];
|
|
198
|
-
devInfo.battery =
|
|
195
|
+
devInfo.battery = batState ? batState.val: undefined;
|
|
199
196
|
// devInfo.states = states || {};
|
|
200
197
|
|
|
201
|
-
const states = allst.filter(
|
|
198
|
+
const states = allst.filter(item => item._id.startsWith(devInfo._id));
|
|
202
199
|
|
|
203
200
|
// put only allowed states
|
|
204
|
-
devInfo.statesDef = (states || []).filter(
|
|
201
|
+
devInfo.statesDef = (states || []).filter(stateDef => {
|
|
205
202
|
const sid = stateDef._id;
|
|
206
203
|
const name = sid.split('.').pop();
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
}).map(
|
|
204
|
+
return !disallowedDashStates.includes(name);
|
|
205
|
+
|
|
206
|
+
}).map(stateDef => {
|
|
210
207
|
const name = stateDef.common.name;
|
|
211
208
|
const devname = devInfo.common.name;
|
|
212
209
|
// replace state
|
|
213
210
|
return {
|
|
214
211
|
id: stateDef._id,
|
|
215
|
-
name:
|
|
212
|
+
name: typeof name === 'string' ? name.replace(devname, '') : name,
|
|
216
213
|
type: stateDef.common.type,
|
|
217
214
|
read: stateDef.common.read,
|
|
218
215
|
write: stateDef.common.write,
|
|
219
|
-
val:
|
|
216
|
+
val: alls[stateDef._id] ? alls[stateDef._id].val : undefined,
|
|
220
217
|
role: stateDef.common.role,
|
|
221
218
|
unit: stateDef.common.unit,
|
|
222
219
|
states: stateDef.common.states,
|
|
@@ -226,7 +223,7 @@ class Commands {
|
|
|
226
223
|
});
|
|
227
224
|
return result;
|
|
228
225
|
})
|
|
229
|
-
.then(async
|
|
226
|
+
.then(async result => {
|
|
230
227
|
// combine info
|
|
231
228
|
const devices = [];
|
|
232
229
|
for (const devInfo of result) {
|
|
@@ -237,40 +234,37 @@ class Commands {
|
|
|
237
234
|
const match = /zigbee.\d.group_([0-9]+)/.exec(devInfo._id);
|
|
238
235
|
if (match && match.length > 1) {
|
|
239
236
|
const groupmembers = await this.zbController.getGroupMembersFromController(match[1]);
|
|
240
|
-
this.debug(
|
|
237
|
+
this.debug(`group members: ${JSON.stringify(groupmembers)}`);
|
|
241
238
|
if (groupmembers && groupmembers.length > 0) {
|
|
242
239
|
const memberinfo = [];
|
|
243
240
|
for (const member of groupmembers) {
|
|
244
241
|
if (groups) {
|
|
245
242
|
const grouparray = groups[member.ieee];
|
|
246
|
-
if (grouparray)
|
|
247
|
-
{
|
|
243
|
+
if (grouparray) {
|
|
248
244
|
if (!grouparray.includes(match[1])) {
|
|
249
|
-
groups[member.ieee].push(match[1])
|
|
245
|
+
groups[member.ieee].push(match[1]);
|
|
250
246
|
}
|
|
251
247
|
}
|
|
252
248
|
else groups[member.ieee] = [match[1]];
|
|
253
249
|
}
|
|
254
|
-
const device = await this.adapter.getObjectAsync(this.adapter.namespace
|
|
250
|
+
const device = await this.adapter.getObjectAsync(`${this.adapter.namespace}.${member.ieee.substr(2)}`);
|
|
255
251
|
if (device) {
|
|
256
252
|
member.device = device.common.name;
|
|
257
|
-
}
|
|
258
|
-
else {
|
|
253
|
+
} else {
|
|
259
254
|
member.device = 'unknown';
|
|
260
255
|
}
|
|
261
256
|
memberinfo.push(member);
|
|
262
257
|
}
|
|
263
258
|
devInfo.memberinfo = memberinfo;
|
|
264
|
-
this.debug(
|
|
259
|
+
this.debug(`memberinfo: ${JSON.stringify(devInfo.memberinfo)}`);
|
|
265
260
|
}
|
|
266
261
|
}
|
|
267
|
-
}
|
|
268
|
-
else
|
|
269
|
-
{
|
|
262
|
+
} else {
|
|
270
263
|
const modelDesc = statesMapping.findModel(devInfo.common.type);
|
|
271
264
|
devInfo.icon = (modelDesc && modelDesc.icon) ? modelDesc.icon : 'img/unknown.png';
|
|
272
|
-
devInfo.vendor =
|
|
265
|
+
devInfo.vendor = modelDesc ? modelDesc.vendor : '';
|
|
273
266
|
}
|
|
267
|
+
|
|
274
268
|
const id = getZbId(devInfo._id);
|
|
275
269
|
devInfo.info = await this.zbController.resolveEntity(id);
|
|
276
270
|
|
|
@@ -279,10 +273,11 @@ class Commands {
|
|
|
279
273
|
if (!rooms.hasOwnProperty(room) ||
|
|
280
274
|
!rooms[room] ||
|
|
281
275
|
!rooms[room].common ||
|
|
282
|
-
!rooms[room].common.members
|
|
276
|
+
!rooms[room].common.members
|
|
277
|
+
) {
|
|
283
278
|
continue;
|
|
284
279
|
}
|
|
285
|
-
if (rooms[room].common.members.
|
|
280
|
+
if (rooms[room].common.members.includes(devInfo._id)) {
|
|
286
281
|
devInfo.rooms.push(rooms[room].common.name);
|
|
287
282
|
}
|
|
288
283
|
}
|
|
@@ -295,18 +290,20 @@ class Commands {
|
|
|
295
290
|
.then(async (devices) => {
|
|
296
291
|
// fill group info
|
|
297
292
|
for (const groupdev in groups) {
|
|
298
|
-
|
|
299
|
-
const device = devices.find((dev) =>( groupdev === getZbId(dev._id) ))
|
|
293
|
+
this.debug(`GetDevices scanning group ${groupdev} ${JSON.stringify(groups[groupdev])}`);
|
|
294
|
+
const device = devices.find((dev) =>( groupdev === getZbId(dev._id) ));
|
|
300
295
|
if (device) {
|
|
301
|
-
device.groups = groups[groupdev]
|
|
302
|
-
this.debug(
|
|
296
|
+
device.groups = groups[groupdev];
|
|
297
|
+
this.debug(`adding group info to device ${groupdev}`);
|
|
303
298
|
}
|
|
304
299
|
}
|
|
305
300
|
// append devices that paired but not created
|
|
306
301
|
if (!id) {
|
|
307
302
|
for (const d of pairedDevices) {
|
|
308
303
|
const device = await this.zbController.resolveEntity(d.ieeeAddr);
|
|
309
|
-
if (!device)
|
|
304
|
+
if (!device) {
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
310
307
|
const exists = devices.find((dev) => (dev._id && device.device.ieeeAddr === getZbId(dev._id)));
|
|
311
308
|
if (!exists) {
|
|
312
309
|
devices.push({
|
|
@@ -325,13 +322,11 @@ class Commands {
|
|
|
325
322
|
}
|
|
326
323
|
return devices;
|
|
327
324
|
})
|
|
328
|
-
.then(
|
|
329
|
-
this.debug(
|
|
325
|
+
.then(devices => {
|
|
326
|
+
this.debug(`getDevices result: ${JSON.stringify(devices)}`);
|
|
330
327
|
this.adapter.sendTo(from, command, devices, callback);
|
|
331
328
|
})
|
|
332
|
-
.catch(
|
|
333
|
-
this.error('getDevices error: ' + err.stack);
|
|
334
|
-
});
|
|
329
|
+
.catch(err => this.error(`getDevices error: ${err.stack}`));
|
|
335
330
|
} else {
|
|
336
331
|
this.adapter.sendTo(from, command, {error: 'You need save and run adapter before pairing!'}, callback);
|
|
337
332
|
}
|
|
@@ -352,17 +347,16 @@ class Commands {
|
|
|
352
347
|
|
|
353
348
|
const coordinatorVersion = await this.adapter.zbController.herdsman.getCoordinatorVersion();
|
|
354
349
|
|
|
355
|
-
await this.adapter.getForeignObject(
|
|
350
|
+
await this.adapter.getForeignObject(`system.adapter.${this.adapter.namespace}`, (err, obj) => {
|
|
356
351
|
if (!err && obj) {
|
|
357
352
|
if (obj.common.installedFrom && obj.common.installedFrom.includes('://')) {
|
|
358
353
|
const instFrom = obj.common.installedFrom;
|
|
359
|
-
coordinatorinfo.installSource = instFrom.replace('tarball','commit');
|
|
354
|
+
coordinatorinfo.installSource = instFrom.replace('tarball', 'commit');
|
|
360
355
|
} else {
|
|
361
356
|
coordinatorinfo.installSource = obj.common.installedFrom;
|
|
362
357
|
}
|
|
363
358
|
}
|
|
364
|
-
try
|
|
365
|
-
{
|
|
359
|
+
try {
|
|
366
360
|
coordinatorinfo.port = obj.native.port;
|
|
367
361
|
coordinatorinfo.channel = obj.native.channel;
|
|
368
362
|
coordinatorinfo.installedVersion = obj.native.version;
|
|
@@ -370,24 +364,40 @@ class Commands {
|
|
|
370
364
|
coordinatorinfo.type = coordinatorVersion.type;
|
|
371
365
|
const meta = coordinatorVersion.meta;
|
|
372
366
|
if (meta) {
|
|
373
|
-
if (meta.hasOwnProperty('revision'))
|
|
367
|
+
if (meta.hasOwnProperty('revision')) {
|
|
368
|
+
coordinatorinfo.revision = meta.revision;
|
|
369
|
+
}
|
|
374
370
|
let vt = 'x-';
|
|
375
|
-
if (meta.hasOwnProperty('transportrev'))
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
if (meta.hasOwnProperty('
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
371
|
+
if (meta.hasOwnProperty('transportrev')) {
|
|
372
|
+
vt = meta.transportrev + '-';
|
|
373
|
+
}
|
|
374
|
+
if (meta.hasOwnProperty('product')) {
|
|
375
|
+
vt = vt + meta.product + '.';
|
|
376
|
+
} else {
|
|
377
|
+
vt = vt + 'x.';
|
|
378
|
+
}
|
|
379
|
+
if (meta.hasOwnProperty('majorrel')) {
|
|
380
|
+
vt = vt + meta.majorrel + '.';
|
|
381
|
+
} else {
|
|
382
|
+
vt = vt + 'x.';
|
|
383
|
+
}
|
|
384
|
+
if (meta.hasOwnProperty('minorrel')) {
|
|
385
|
+
vt = vt + meta.minorrel + '.';
|
|
386
|
+
} else {
|
|
387
|
+
vt = vt + 'x.';
|
|
388
|
+
}
|
|
389
|
+
if (meta.hasOwnProperty('maintrel')) {
|
|
390
|
+
vt = vt + meta.maintrel + '.';
|
|
391
|
+
} else {
|
|
392
|
+
vt = vt + 'x.';
|
|
393
|
+
}
|
|
384
394
|
coordinatorinfo.version = vt;
|
|
385
395
|
}
|
|
386
396
|
}
|
|
387
397
|
}
|
|
388
398
|
catch { this.warn('exception raised in getCoordinatorInfo');}
|
|
389
399
|
|
|
390
|
-
this.debug(
|
|
400
|
+
this.debug(`getCoorinatorInfo result: ${JSON.stringify(coordinatorinfo)}`);
|
|
391
401
|
this.adapter.sendTo(from, command, coordinatorinfo, callback);
|
|
392
402
|
});
|
|
393
403
|
} else {
|
|
@@ -407,28 +417,26 @@ class Commands {
|
|
|
407
417
|
|
|
408
418
|
deleteDevice(from, command, msg, callback) {
|
|
409
419
|
if (this.zbController && this.stController) {
|
|
410
|
-
this.debug(
|
|
420
|
+
this.debug(`deleteDevice message: ${JSON.stringify(msg)}`);
|
|
411
421
|
const id = msg.id;
|
|
412
422
|
const force = msg.force;
|
|
413
423
|
const sysid = id.replace(this.adapter.namespace + '.', '0x');
|
|
414
424
|
const devId = id.replace(this.adapter.namespace + '.', '');
|
|
415
|
-
this.debug(
|
|
425
|
+
this.debug(`deleteDevice sysid: ${sysid}`);
|
|
416
426
|
const dev = this.zbController.getDevice(sysid);
|
|
417
427
|
if (!dev) {
|
|
418
428
|
this.debug('Not found!');
|
|
419
|
-
this.debug(
|
|
420
|
-
this.stController.deleteDeviceStates(devId, () =>
|
|
421
|
-
this.adapter.sendTo(from, command, {}, callback);
|
|
422
|
-
});
|
|
429
|
+
this.debug(`Try delete dev ${devId} from iobroker.`);
|
|
430
|
+
this.stController.deleteDeviceStates(devId, () =>
|
|
431
|
+
this.adapter.sendTo(from, command, {}, callback));
|
|
423
432
|
return;
|
|
424
433
|
}
|
|
425
|
-
this.zbController.remove(sysid, force,
|
|
434
|
+
this.zbController.remove(sysid, force, err => {
|
|
426
435
|
if (!err) {
|
|
427
|
-
this.stController.deleteDeviceStates(devId, () =>
|
|
428
|
-
this.adapter.sendTo(from, command, {}, callback);
|
|
429
|
-
});
|
|
436
|
+
this.stController.deleteDeviceStates(devId, () =>
|
|
437
|
+
this.adapter.sendTo(from, command, {}, callback));
|
|
430
438
|
} else {
|
|
431
|
-
this.debug(
|
|
439
|
+
this.debug(`Error on remove! ${err}`);
|
|
432
440
|
this.adapter.sendTo(from, command, {error: err}, callback);
|
|
433
441
|
}
|
|
434
442
|
});
|
|
@@ -453,7 +461,7 @@ class Commands {
|
|
|
453
461
|
async getChannels(from, command, message, callback) {
|
|
454
462
|
if (this.zbController) {
|
|
455
463
|
const result = await this.zbController.getChannelsEnergy();
|
|
456
|
-
this.debug(
|
|
464
|
+
this.debug(`getChannels result: ${JSON.stringify(result)}`);
|
|
457
465
|
this.adapter.sendTo(from, command, result, callback);
|
|
458
466
|
} else {
|
|
459
467
|
this.adapter.sendTo(
|
|
@@ -466,10 +474,10 @@ class Commands {
|
|
|
466
474
|
|
|
467
475
|
async setDeviceActivated(from, command, msg, callback) {
|
|
468
476
|
if (this.stController) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
477
|
+
const id = msg.id;
|
|
478
|
+
const targetstate = msg.deactivated;
|
|
479
|
+
this.stController.setDeviceActivated(id, targetstate);
|
|
480
|
+
this.adapter.sendTo(from, command, {}, callback);
|
|
473
481
|
}
|
|
474
482
|
}
|
|
475
483
|
|
|
@@ -486,8 +494,7 @@ class Commands {
|
|
|
486
494
|
);
|
|
487
495
|
this.adapter.sendTo(from, command, {}, callback);
|
|
488
496
|
} catch (error) {
|
|
489
|
-
const errmsg = `Reconfigure failed ${entity.device.ieeeAddr} ${entity.device.modelID},
|
|
490
|
-
`(${error.stack})`;
|
|
497
|
+
const errmsg = `Reconfigure failed ${entity.device.ieeeAddr} ${entity.device.modelID}, (${error.stack})`;
|
|
491
498
|
this.error(errmsg);
|
|
492
499
|
this.adapter.sendTo(from, command, {error: errmsg}, callback);
|
|
493
500
|
}
|
package/lib/developer.js
CHANGED
|
@@ -38,9 +38,8 @@ class Developer {
|
|
|
38
38
|
if (typeof obj === 'object' && obj.command) {
|
|
39
39
|
switch (obj.command) {
|
|
40
40
|
case 'reset':
|
|
41
|
-
this.zbController.reset(obj.message.mode,
|
|
42
|
-
this.adapter.sendTo(obj.from, obj.command, err, obj.callback);
|
|
43
|
-
}.bind(this));
|
|
41
|
+
this.zbController.reset(obj.message.mode, err =>
|
|
42
|
+
this.adapter.sendTo(obj.from, obj.command, err, obj.callback));
|
|
44
43
|
break;
|
|
45
44
|
case 'sendToZigbee':
|
|
46
45
|
this.sendToZigbee(obj);
|
|
@@ -94,7 +93,7 @@ class Developer {
|
|
|
94
93
|
cmd = zcl.Utils.getCluster(cid).getCommand(obj.message.cmd);
|
|
95
94
|
}
|
|
96
95
|
else if (cmdType === 'functionalResp') {
|
|
97
|
-
cmd = zcl.Utils.getCluster(cid).getCommandResponse(obj.message.cmd);
|
|
96
|
+
cmd = zcl.Utils.getCluster(cid).getCommandResponse(obj.message.cmd);
|
|
98
97
|
}
|
|
99
98
|
else if (cmdType === 'foundation') {
|
|
100
99
|
cmd = zcl.Utils.getGlobalCommand((obj.message.cmd));
|
|
@@ -106,7 +105,7 @@ class Developer {
|
|
|
106
105
|
|
|
107
106
|
const publishTarget = this.zbController.getDevice(devId) ? devId : this.zbController.getGroup(parseInt(devId));
|
|
108
107
|
if (!publishTarget) {
|
|
109
|
-
this.adapter.sendTo(obj.from, obj.command, {localErr:
|
|
108
|
+
this.adapter.sendTo(obj.from, obj.command, {localErr: `Device or group ${devId} not found!`}, obj.callback);
|
|
110
109
|
return;
|
|
111
110
|
}
|
|
112
111
|
if (!cid || !cmd) {
|
|
@@ -137,8 +136,8 @@ class Developer {
|
|
|
137
136
|
result.statusCode = exception.code;
|
|
138
137
|
this.adapter.sendTo(obj.from, obj.command, result, obj.callback);
|
|
139
138
|
} else {
|
|
140
|
-
this.error(
|
|
141
|
-
// exception (Error class) cannot be
|
|
139
|
+
this.error(`SendToZigbee failed! (${exception})`);
|
|
140
|
+
// exception (Error class) cannot be sent to adapter, send string message instead!
|
|
142
141
|
this.adapter.sendTo(obj.from, obj.command, {msg: exception.message}, obj.callback);
|
|
143
142
|
}
|
|
144
143
|
}
|