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/utils.js
CHANGED
|
@@ -24,7 +24,7 @@ function bulbLevelToAdapterLevel(bulbLevel) {
|
|
|
24
24
|
// - Bulb level range [2...254] is linearly mapped to adapter level range [1...100].
|
|
25
25
|
if (bulbLevel >= 2) {
|
|
26
26
|
// Perform linear mapping of range [2...254] to [1...100]
|
|
27
|
-
return
|
|
27
|
+
return Math.round((bulbLevel - 2) * 99 / 252) + 1;
|
|
28
28
|
} else {
|
|
29
29
|
// The bulb is considered off. Even a bulb level of "1" is considered as off.
|
|
30
30
|
return 0;
|
|
@@ -42,7 +42,7 @@ function adapterLevelToBulbLevel(adapterLevel) {
|
|
|
42
42
|
// Please read the comments there regarding the rules applied here for mapping the values.
|
|
43
43
|
if (adapterLevel) {
|
|
44
44
|
// Perform linear mapping of range [1...100] to [2...254]
|
|
45
|
-
return
|
|
45
|
+
return Math.round((adapterLevel - 1) * 252 / 99) + 2;
|
|
46
46
|
} else {
|
|
47
47
|
// Switch the bulb off. Some bulbs need "0" (IKEA), others "1" (HUE), and according to the
|
|
48
48
|
// ZigBee docs "1" is the "minimum possible level"... we choose "0" here which seems to work.
|
|
@@ -53,7 +53,7 @@ function adapterLevelToBulbLevel(adapterLevel) {
|
|
|
53
53
|
function bytesArrayToWordArray(ba) {
|
|
54
54
|
const wa = [];
|
|
55
55
|
for (let i = 0; i < ba.length; i++) {
|
|
56
|
-
wa[(i / 2) | 0] |= ba[i] << (8*(i % 2));
|
|
56
|
+
wa[(i / 2) | 0] |= ba[i] << (8 * (i % 2));
|
|
57
57
|
}
|
|
58
58
|
return wa;
|
|
59
59
|
}
|
|
@@ -91,24 +91,25 @@ function decimalToHex(decimal, padding) {
|
|
|
91
91
|
|
|
92
92
|
function getZbId(adapterDevId) {
|
|
93
93
|
const idx = adapterDevId.indexOf('group');
|
|
94
|
-
if (idx > 0)
|
|
95
|
-
|
|
94
|
+
if (idx > 0) {
|
|
95
|
+
return adapterDevId.substr(idx+6);
|
|
96
|
+
}
|
|
97
|
+
return `0x${adapterDevId.split('.')[2]}`;
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
function getAdId(adapter, id) {
|
|
99
|
-
return adapter.namespace
|
|
101
|
+
return `${adapter.namespace}.${id.split('.')[2]}`; // iobroker device id
|
|
100
102
|
}
|
|
101
103
|
|
|
102
104
|
function flatten(arr) {
|
|
103
|
-
return arr.reduce((flat, toFlatten) =>
|
|
104
|
-
|
|
105
|
-
}, []);
|
|
105
|
+
return arr.reduce((flat, toFlatten) =>
|
|
106
|
+
flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten), []);
|
|
106
107
|
}
|
|
107
108
|
|
|
108
109
|
const forceEndDevice = flatten(
|
|
109
110
|
['QBKG03LM', 'QBKG04LM', 'ZNMS13LM', 'ZNMS12LM']
|
|
110
|
-
.map(
|
|
111
|
-
.map(
|
|
111
|
+
.map(model => zigbeeHerdsmanConverters.devices.find((d) => d.model === model))
|
|
112
|
+
.map(mappedModel => mappedModel.zigbeeModel));
|
|
112
113
|
|
|
113
114
|
// Xiaomi uses 4151 and 4447 (lumi.plug) as manufacturer ID.
|
|
114
115
|
const xiaomiManufacturerID = [4151, 4447];
|
|
@@ -117,7 +118,7 @@ const ikeaTradfriManufacturerID = [4476];
|
|
|
117
118
|
function sanitizeImageParameter(parameter) {
|
|
118
119
|
const replaceByDash = [/\?/g, /&/g, /[^a-z\d\-_./:]/gi, /[/]/gi];
|
|
119
120
|
let sanitized = parameter;
|
|
120
|
-
replaceByDash.forEach(
|
|
121
|
+
replaceByDash.forEach(r => sanitized = sanitized.replace(r, '-'));
|
|
121
122
|
return sanitized;
|
|
122
123
|
}
|
|
123
124
|
|
|
@@ -132,7 +133,7 @@ function getDeviceIcon(definition) {
|
|
|
132
133
|
return icon;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
exports.secondsToMilliseconds =
|
|
136
|
+
exports.secondsToMilliseconds = seconds => seconds * 1000;
|
|
136
137
|
exports.bulbLevelToAdapterLevel = bulbLevelToAdapterLevel;
|
|
137
138
|
exports.adapterLevelToBulbLevel = adapterLevelToBulbLevel;
|
|
138
139
|
exports.bytesArrayToWordArray = bytesArrayToWordArray;
|
|
@@ -141,11 +142,11 @@ exports.miredKelvinConversion = miredKelvinConversion;
|
|
|
141
142
|
exports.decimalToHex = decimalToHex;
|
|
142
143
|
exports.getZbId = getZbId;
|
|
143
144
|
exports.getAdId = getAdId;
|
|
144
|
-
exports.isRouter =
|
|
145
|
-
exports.isBatteryPowered =
|
|
146
|
-
exports.isXiaomiDevice =
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
exports.isIkeaTradfriDevice =
|
|
151
|
-
exports.getDeviceIcon
|
|
145
|
+
exports.isRouter = device => device.type === 'Router' && !forceEndDevice.includes(device.modelID);
|
|
146
|
+
exports.isBatteryPowered = device => device.powerSource && device.powerSource === 'Battery';
|
|
147
|
+
exports.isXiaomiDevice = device =>
|
|
148
|
+
device.modelID !== 'lumi.router' &&
|
|
149
|
+
xiaomiManufacturerID.includes(device.manufacturerID) &&
|
|
150
|
+
(!device.manufacturerName || !device.manufacturerName.startsWith('Trust'));
|
|
151
|
+
exports.isIkeaTradfriDevice = device => ikeaTradfriManufacturerID.includes(device.manufacturerID);
|
|
152
|
+
exports.getDeviceIcon = getDeviceIcon;
|
package/lib/zbBaseExtension.js
CHANGED
|
@@ -14,18 +14,18 @@ class BaseExtension {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
error(message, data) {
|
|
17
|
-
this.zigbee.error(this.name
|
|
17
|
+
this.zigbee.error(`${this.name}:${message}`, data);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
warn(message, data) {
|
|
21
|
-
this.zigbee.warn(this.name
|
|
21
|
+
this.zigbee.warn(`${this.name}:${message}`, data);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
debug(message, data) {
|
|
25
25
|
if (this.elevate_debug)
|
|
26
|
-
this.zigbee.warn(
|
|
26
|
+
this.zigbee.warn(`DE ${this.name}:${message}`, data);
|
|
27
27
|
else
|
|
28
|
-
this.zigbee.debug(this.name
|
|
28
|
+
this.zigbee.debug(`${this.name}:${message}`, data);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
sendError(error, message) {
|
package/lib/zbDelayedAction.js
CHANGED
|
@@ -8,12 +8,11 @@ class DelayedAction extends BaseExtension {
|
|
|
8
8
|
|
|
9
9
|
this.actions = {};
|
|
10
10
|
this.zigbee.delayAction = this.delayAction.bind(this);
|
|
11
|
-
this.name =
|
|
11
|
+
this.name = 'DelayedAction';
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
setOptions(options) {
|
|
15
|
-
|
|
16
|
-
return true;
|
|
15
|
+
return typeof options === 'object';
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
|
|
@@ -30,11 +29,7 @@ class DelayedAction extends BaseExtension {
|
|
|
30
29
|
// return false;
|
|
31
30
|
// }
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return true;
|
|
32
|
+
return device.interviewing !== true;
|
|
38
33
|
}
|
|
39
34
|
|
|
40
35
|
async onZigbeeStarted() {
|
|
@@ -97,10 +92,7 @@ class DelayedAction extends BaseExtension {
|
|
|
97
92
|
}
|
|
98
93
|
const foundDev = await this.zigbee.getDevice(device.ieeeAddr);
|
|
99
94
|
if (!foundDev) {
|
|
100
|
-
this.debug(
|
|
101
|
-
`No found device ${device.ieeeAddr} ${device.modelID}, ` +
|
|
102
|
-
`for doAction`
|
|
103
|
-
);
|
|
95
|
+
this.debug(`No found device ${device.ieeeAddr} ${device.modelID}, for doAction`);
|
|
104
96
|
delete this.actions[device.ieeeAddr];
|
|
105
97
|
return;
|
|
106
98
|
}
|
|
@@ -120,7 +112,7 @@ class DelayedAction extends BaseExtension {
|
|
|
120
112
|
try {
|
|
121
113
|
// do action
|
|
122
114
|
await actionDef.action(device);
|
|
123
|
-
this.info(`Do action
|
|
115
|
+
this.info(`Do action successfully ${device.ieeeAddr} ${device.modelID}`);
|
|
124
116
|
toDelete.push(actionDef);
|
|
125
117
|
} catch (error) {
|
|
126
118
|
this.sendError(error);
|
|
@@ -44,65 +44,77 @@ class DeviceAvailability extends BaseExtension {
|
|
|
44
44
|
// force publish availability for new devices
|
|
45
45
|
this.zigbee.on('new', (entity) => {
|
|
46
46
|
// wait for 1s for creating device states
|
|
47
|
-
setTimeout(() =>
|
|
48
|
-
this.publishAvailability(entity.device, true, true);
|
|
49
|
-
}, 1000);
|
|
47
|
+
setTimeout(() =>
|
|
48
|
+
this.publishAvailability(entity.device, true, true), 1000);
|
|
50
49
|
});
|
|
51
50
|
this.startDevicePingQueue = []; // simple fifo array for starting device pings
|
|
52
51
|
this.startDevicePingTimeout = null; // handle for the timeout which empties the queue
|
|
53
52
|
this.startDevicePingDelay = 200; // 200 ms delay between starting the ping timeout
|
|
54
|
-
this.name =
|
|
53
|
+
this.name = 'DeviceAvailability';
|
|
55
54
|
this.elevate_debug = false;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
57
|
setOptions(options) {
|
|
59
|
-
if (typeof
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
58
|
+
if (typeof options !== 'object') {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (options.disableActivePing) {
|
|
62
|
+
this.active_ping = false;
|
|
63
|
+
}
|
|
64
|
+
if (options.disableForcedPing) {
|
|
65
|
+
this.forced_ping = false;
|
|
66
|
+
}
|
|
67
|
+
if (typeof options.pingTimeout === 'number') {
|
|
68
|
+
this.availability_timeout = Math.min(60,options.pingTimeout);
|
|
69
|
+
}
|
|
70
|
+
if (typeof options.pingCount === 'number') {
|
|
71
|
+
this.max_ping = Math.min(2, options.pingCount);
|
|
72
|
+
}
|
|
64
73
|
return true;
|
|
65
74
|
}
|
|
66
75
|
|
|
67
76
|
isPingable(device) {
|
|
68
77
|
if (this.active_ping)
|
|
69
78
|
{
|
|
70
|
-
if (this.forced_ping && forcedPingable.find(
|
|
79
|
+
if (this.forced_ping && forcedPingable.find(d => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
|
|
71
80
|
return true;
|
|
72
81
|
}
|
|
73
82
|
|
|
74
|
-
|
|
75
|
-
return result;
|
|
83
|
+
return utils.isRouter(device) && !utils.isBatteryPowered(device);
|
|
76
84
|
}
|
|
77
85
|
return false;
|
|
78
86
|
}
|
|
79
87
|
|
|
80
88
|
async getAllPingableDevices() {
|
|
81
89
|
const clients = await this.zigbee.getClients();
|
|
82
|
-
return clients.filter(
|
|
90
|
+
return clients.filter(d => this.isPingable(d));
|
|
83
91
|
}
|
|
84
92
|
|
|
85
93
|
async registerDevicePing(device, entity) {
|
|
86
|
-
this.debug(
|
|
94
|
+
this.debug(`register device Ping for ${JSON.stringify(device.ieeeAddr)}`);
|
|
87
95
|
this.forcedNonPingable[device.ieeeAddr] = false;
|
|
88
96
|
// this.warn(`Called registerDevicePing for '${device}' of '${entity}'`);
|
|
89
|
-
if (!this.isPingable(device))
|
|
97
|
+
if (!this.isPingable(device)) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
90
100
|
// ensure we do not already have this device in the queue
|
|
101
|
+
// TODO: Following does not work, may be `if (this.startDevicePingQueue.find(item => item && item.device === device)) { return; }`
|
|
91
102
|
this.startDevicePingQueue.forEach(item => {
|
|
92
|
-
if (item && item.device == device)
|
|
103
|
+
if (item && item.device == device) {
|
|
93
104
|
return;
|
|
105
|
+
}
|
|
94
106
|
});
|
|
95
107
|
this.number_of_registered_devices++;
|
|
96
108
|
this.availability_timeout = Math.max(Math.min(this.number_of_registered_devices * AverageTimeBetweenPings,MaxAvailabilityTimeout ),MinAvailabilityTimeout);
|
|
97
|
-
this.startDevicePingQueue.push({device
|
|
98
|
-
if (this.startDevicePingTimeout == null)
|
|
99
|
-
this.startDevicePingTimeout = setTimeout(async() =>
|
|
100
|
-
await this.startDevicePing();
|
|
101
|
-
|
|
109
|
+
this.startDevicePingQueue.push({device, entity});
|
|
110
|
+
if (this.startDevicePingTimeout == null) {
|
|
111
|
+
this.startDevicePingTimeout = setTimeout(async() =>
|
|
112
|
+
await this.startDevicePing(), this.startDevicePingDelay);
|
|
113
|
+
}
|
|
102
114
|
}
|
|
103
115
|
|
|
104
116
|
async deregisterDevicePing(device) {
|
|
105
|
-
this.info(
|
|
117
|
+
this.info(`deregister device Ping for deactivated device ${JSON.stringify(device.ieeeAddr)}`);
|
|
106
118
|
this.forcedNonPingable[device.ieeeAddr] = true;
|
|
107
119
|
if (this.timers[device.ieeeAddr]) {
|
|
108
120
|
clearTimeout(this.timers[device.ieeeAddr]);
|
|
@@ -114,9 +126,8 @@ class DeviceAvailability extends BaseExtension {
|
|
|
114
126
|
this.startDevicePingTimeout = null;
|
|
115
127
|
const item = this.startDevicePingQueue.shift();
|
|
116
128
|
if (this.startDevicePingQueue.length >0) {
|
|
117
|
-
this.startDevicePingTimeout = setTimeout(async() =>
|
|
118
|
-
await this.startDevicePing();
|
|
119
|
-
}, this.startDevicePingDelay);
|
|
129
|
+
this.startDevicePingTimeout = setTimeout(async() =>
|
|
130
|
+
await this.startDevicePing(), this.startDevicePingDelay);
|
|
120
131
|
}
|
|
121
132
|
if (item && item.hasOwnProperty('device')) {
|
|
122
133
|
this.handleIntervalPingable(item.device, item.entity);
|
|
@@ -131,15 +142,13 @@ class DeviceAvailability extends BaseExtension {
|
|
|
131
142
|
const clients = await this.zigbee.getClients();
|
|
132
143
|
// this.warn('onZigbeeStarted called');
|
|
133
144
|
for (const device of clients) {
|
|
134
|
-
|
|
135
145
|
if (this.isPingable(device)) {
|
|
136
146
|
// this.setTimerPingable(device);
|
|
137
147
|
} else {
|
|
138
148
|
// this.warn(`Setting '${device.ieeeAddr}' as available - battery driven`);
|
|
139
149
|
this.publishAvailability(device, true);
|
|
140
|
-
this.timers[device.ieeeAddr] = setInterval(() =>
|
|
141
|
-
this.handleIntervalNotPingable(device);
|
|
142
|
-
},utils.secondsToMilliseconds(this.availability_timeout));
|
|
150
|
+
this.timers[device.ieeeAddr] = setInterval(() =>
|
|
151
|
+
this.handleIntervalNotPingable(device), utils.secondsToMilliseconds(this.availability_timeout));
|
|
143
152
|
}
|
|
144
153
|
}
|
|
145
154
|
}
|
|
@@ -154,8 +163,8 @@ class DeviceAvailability extends BaseExtension {
|
|
|
154
163
|
if (this.isPingable(device)) {
|
|
155
164
|
let pingCount = this.ping_counters[device.ieeeAddr];
|
|
156
165
|
if (pingCount === undefined) {
|
|
157
|
-
this.ping_counters[device.ieeeAddr] = {
|
|
158
|
-
pingCount = {
|
|
166
|
+
this.ping_counters[device.ieeeAddr] = {failed: 0, reported: 0};
|
|
167
|
+
pingCount = {failed: 0, reported: 0};
|
|
159
168
|
}
|
|
160
169
|
|
|
161
170
|
// first see if we can "ping" the device by reading a Status
|
|
@@ -185,26 +194,22 @@ class DeviceAvailability extends BaseExtension {
|
|
|
185
194
|
this.ping_counters[device.ieeeAddr].failed = 0;
|
|
186
195
|
} catch (error) {
|
|
187
196
|
this.publishAvailability(device, false);
|
|
188
|
-
if (pingCount.failed++ <= this.max_ping)
|
|
189
|
-
{
|
|
197
|
+
if (pingCount.failed++ <= this.max_ping) {
|
|
190
198
|
if (pingCount.failed < 2 && pingCount.reported < this.max_ping) {
|
|
191
199
|
this.warn(`Failed to ping ${ieeeAddr} ${device.modelID}`);
|
|
192
200
|
pingCount.reported++;
|
|
193
|
-
}
|
|
194
|
-
else {
|
|
201
|
+
} else {
|
|
195
202
|
this.debug(`Failed to ping ${ieeeAddr} ${device.modelID} on ${pingCount} consecutive attempts`);
|
|
196
203
|
}
|
|
197
204
|
this.setTimerPingable(device, pingCount.failed);
|
|
198
205
|
this.ping_counters[device.ieeeAddr]= pingCount;
|
|
199
|
-
}
|
|
200
|
-
else {
|
|
206
|
+
} else {
|
|
201
207
|
this.warn(`Stopping to ping ${ieeeAddr} ${device.modelID} after ${pingCount.failed} ping attempts`);
|
|
202
208
|
}
|
|
203
209
|
}
|
|
204
210
|
}
|
|
205
211
|
}
|
|
206
212
|
|
|
207
|
-
|
|
208
213
|
async handleIntervalNotPingable(device) {
|
|
209
214
|
const entity = await this.zigbee.resolveEntity(device.ieeeAddr);
|
|
210
215
|
if (!entity || !device.lastSeen) {
|
|
@@ -224,9 +229,8 @@ class DeviceAvailability extends BaseExtension {
|
|
|
224
229
|
if (this.timers[device.ieeeAddr]) {
|
|
225
230
|
clearTimeout(this.timers[device.ieeeAddr]);
|
|
226
231
|
}
|
|
227
|
-
this.timers[device.ieeeAddr] = setTimeout(async() =>
|
|
228
|
-
await this.handleIntervalPingable(device);
|
|
229
|
-
}, utils.secondsToMilliseconds(this.availability_timeout * factor));
|
|
232
|
+
this.timers[device.ieeeAddr] = setTimeout(async() =>
|
|
233
|
+
await this.handleIntervalPingable(device), utils.secondsToMilliseconds(this.availability_timeout * factor));
|
|
230
234
|
}
|
|
231
235
|
|
|
232
236
|
async stop() {
|
|
@@ -234,7 +238,7 @@ class DeviceAvailability extends BaseExtension {
|
|
|
234
238
|
clearTimeout(timer);
|
|
235
239
|
}
|
|
236
240
|
const clients = await this.zigbee.getClients();
|
|
237
|
-
clients.forEach(
|
|
241
|
+
clients.forEach(device => this.publishAvailability(device, false));
|
|
238
242
|
}
|
|
239
243
|
|
|
240
244
|
async onReconnect(device) {
|
|
@@ -290,8 +294,7 @@ class DeviceAvailability extends BaseExtension {
|
|
|
290
294
|
const pc = this.ping_counters[device.ieeeAddr];
|
|
291
295
|
if (pc == undefined) {
|
|
292
296
|
this.ping_counters[device.ieeeAddr] = { failed:0, reported:0 };
|
|
293
|
-
}
|
|
294
|
-
else {
|
|
297
|
+
} else {
|
|
295
298
|
this.ping_counters[device.ieeeAddr].failed++;
|
|
296
299
|
}
|
|
297
300
|
|
package/lib/zbDeviceConfigure.js
CHANGED
|
@@ -10,20 +10,17 @@ const forcedConfigureOnEachStart = [
|
|
|
10
10
|
zigbeeHerdsmanConverters.devices.find((d) => d.model === 'ZK03840')
|
|
11
11
|
];
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
13
|
class DeviceConfigure extends BaseExtension {
|
|
16
14
|
constructor(zigbee, options) {
|
|
17
15
|
super(zigbee, options);
|
|
18
16
|
|
|
19
17
|
this.configuring = new Set();
|
|
20
18
|
this.attempts = {};
|
|
21
|
-
this.name =
|
|
19
|
+
this.name = 'DeviceConfigure';
|
|
22
20
|
}
|
|
23
21
|
|
|
24
22
|
setOptions(options) {
|
|
25
|
-
|
|
26
|
-
return true;
|
|
23
|
+
return typeof options === 'object';
|
|
27
24
|
}
|
|
28
25
|
|
|
29
26
|
shouldConfigure(device, mappedDevice) {
|
|
@@ -37,11 +34,8 @@ class DeviceConfigure extends BaseExtension {
|
|
|
37
34
|
zigbeeHerdsmanConverters.getConfigureKey(mappedDevice)) {
|
|
38
35
|
return false;
|
|
39
36
|
}
|
|
40
|
-
if (device.interviewing === true) {
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
37
|
|
|
44
|
-
return true;
|
|
38
|
+
return device.interviewing !== true;
|
|
45
39
|
}
|
|
46
40
|
|
|
47
41
|
async onZigbeeStarted() {
|
|
@@ -53,7 +47,7 @@ class DeviceConfigure extends BaseExtension {
|
|
|
53
47
|
|
|
54
48
|
if (forcedConfigureOnEachStart.find((d) => d && d.hasOwnProperty('zigbeeModel') && d.zigbeeModel.includes(device.modelID))) {
|
|
55
49
|
this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} forced by adapter config`);
|
|
56
|
-
device.meta.configured = -1; // Force a
|
|
50
|
+
device.meta.configured = -1; // Force a reconfiguration for this device
|
|
57
51
|
}
|
|
58
52
|
if (this.shouldConfigure(device, mappedDevice)) {
|
|
59
53
|
this.debug(`DeviceConfigure ${device.ieeeAddr} ${device.modelID} needed`);
|
|
@@ -64,9 +58,7 @@ class DeviceConfigure extends BaseExtension {
|
|
|
64
58
|
}
|
|
65
59
|
} catch (error) {
|
|
66
60
|
this.sendError(error);
|
|
67
|
-
this.error(
|
|
68
|
-
`Failed to DeviceConfigure.onZigbeeStarted (${error.stack})`,
|
|
69
|
-
);
|
|
61
|
+
this.error(`Failed to DeviceConfigure.onZigbeeStarted (${error.stack})`);
|
|
70
62
|
}
|
|
71
63
|
}
|
|
72
64
|
|
|
@@ -78,9 +70,7 @@ class DeviceConfigure extends BaseExtension {
|
|
|
78
70
|
}
|
|
79
71
|
} catch (error) {
|
|
80
72
|
this.sendError(error);
|
|
81
|
-
this.error(
|
|
82
|
-
`Failed to DeviceConfigure.onZigbeeEvent (${error.stack})`,
|
|
83
|
-
);
|
|
73
|
+
this.error(`Failed to DeviceConfigure.onZigbeeEvent (${error.stack})`);
|
|
84
74
|
}
|
|
85
75
|
}
|
|
86
76
|
|
|
@@ -95,9 +85,7 @@ class DeviceConfigure extends BaseExtension {
|
|
|
95
85
|
}
|
|
96
86
|
} catch (error) {
|
|
97
87
|
this.sendError(error);
|
|
98
|
-
this.error(
|
|
99
|
-
`Failed to DeviceConfigure.onDeviceRemove (${error.stack})`,
|
|
100
|
-
);
|
|
88
|
+
this.error(`Failed to DeviceConfigure.onDeviceRemove (${error.stack})`);
|
|
101
89
|
}
|
|
102
90
|
}
|
|
103
91
|
|
|
@@ -142,10 +130,17 @@ class DeviceConfigure extends BaseExtension {
|
|
|
142
130
|
async doConfigure(device, mappedDevice) {
|
|
143
131
|
this.info(`Configuring ${device.ieeeAddr} ${device.modelID}`);
|
|
144
132
|
const coordinatorEndpoint = await this.zigbee.getDevicesByType('Coordinator')[0].endpoints[0];
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
133
|
+
try {
|
|
134
|
+
await mappedDevice.configure(device, coordinatorEndpoint);
|
|
135
|
+
device.meta.configured = zigbeeHerdsmanConverters.getConfigureKey(mappedDevice);
|
|
136
|
+
device.save();
|
|
137
|
+
this.info(`DeviceConfigure successful ${device.ieeeAddr} ${device.modelID}`);
|
|
138
|
+
} catch (error) {
|
|
139
|
+
this.sendError(error);
|
|
140
|
+
this.error(
|
|
141
|
+
`Failed to DeviceConfigure.configure ${device.ieeeAddr} ${device.modelID} (${error.stack})`,
|
|
142
|
+
);
|
|
143
|
+
}
|
|
149
144
|
}
|
|
150
145
|
}
|
|
151
146
|
|
package/lib/zbDeviceEvent.js
CHANGED
|
@@ -6,10 +6,9 @@ const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
|
|
6
6
|
class DeviceEvent extends BaseExtension {
|
|
7
7
|
constructor(zigbee, options) {
|
|
8
8
|
super(zigbee, options);
|
|
9
|
-
this.name =
|
|
9
|
+
this.name = 'DeviceEvent';
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
|
|
13
12
|
async onZigbeeStarted() {
|
|
14
13
|
for (const device of await this.zigbee.getClients()) {
|
|
15
14
|
this.callOnEvent(device, 'start', {});
|
|
@@ -17,8 +16,8 @@ class DeviceEvent extends BaseExtension {
|
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
setOptions(options) {
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
return typeof options === 'object';
|
|
20
|
+
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
onZigbeeEvent(data, mappedDevice) {
|