iobroker.zigbee 3.0.5 → 3.1.4
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 +34 -0
- package/admin/admin.js +475 -230
- package/admin/i18n/de/translations.json +16 -16
- package/admin/index_m.html +84 -91
- package/admin/tab_m.html +38 -16
- package/docs/de/readme.md +1 -1
- package/docs/en/readme.md +4 -2
- package/io-package.json +35 -28
- package/lib/DeviceDebug.js +25 -2
- package/lib/binding.js +8 -8
- package/lib/commands.js +386 -326
- package/lib/developer.js +2 -2
- package/lib/devices.js +13 -9
- package/lib/exclude.js +1 -1
- package/lib/exposes.js +56 -24
- package/lib/groups.js +408 -73
- package/lib/localConfig.js +23 -12
- package/lib/networkmap.js +10 -2
- package/lib/states.js +32 -2
- package/lib/statescontroller.js +361 -209
- package/lib/utils.js +7 -5
- package/lib/zbDelayedAction.js +4 -4
- package/lib/zbDeviceAvailability.js +102 -46
- package/lib/zbDeviceConfigure.js +7 -0
- package/lib/zbDeviceEvent.js +40 -7
- package/lib/zigbeecontroller.js +552 -75
- package/main.js +168 -505
- package/package.json +8 -11
- package/lib/tools.js +0 -55
package/lib/utils.js
CHANGED
|
@@ -88,11 +88,13 @@ function decimalToHex(decimal, padding) {
|
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
function getZbId(adapterDevId) {
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
const pieces = adapterDevId.split('.');
|
|
92
|
+
const piece = pieces.length > 2 ? pieces[2] : adapterDevId;
|
|
93
|
+
const idx = piece.indexOf('group_');
|
|
94
|
+
if (idx > -1) {
|
|
95
|
+
return Number(piece.substr(idx + 6));
|
|
94
96
|
}
|
|
95
|
-
return `0x${
|
|
97
|
+
return `0x${piece}`;
|
|
96
98
|
}
|
|
97
99
|
|
|
98
100
|
function getAdId(adapter, id) {
|
|
@@ -197,4 +199,4 @@ exports.getDeviceIcon = getDeviceIcon;
|
|
|
197
199
|
exports.getEntityInfo = getEntityInfo;
|
|
198
200
|
exports.getNetAddress = getNetAddress;
|
|
199
201
|
exports.byteArrayToString = byteArrayToString;
|
|
200
|
-
exports.reverseByteString = reverseByteString;
|
|
202
|
+
exports.reverseByteString = reverseByteString;
|
package/lib/zbDelayedAction.js
CHANGED
|
@@ -45,10 +45,10 @@ class DelayedAction extends BaseExtension {
|
|
|
45
45
|
|
|
46
46
|
onZigbeeEvent(data) {
|
|
47
47
|
try {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
if (data && data.device) {
|
|
49
|
+
const device = data.device;
|
|
50
|
+
this.doActions(device);
|
|
51
|
+
}
|
|
52
52
|
} catch (error) {
|
|
53
53
|
this.sendError(error);
|
|
54
54
|
this.error(
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const BaseExtension = require('./zbBaseExtension');
|
|
4
|
-
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
|
5
4
|
const utils = require('./utils');
|
|
6
5
|
|
|
7
6
|
// Some EndDevices should be pinged
|
|
@@ -19,20 +18,23 @@ const Hours25 = 1000 * 60 * 60 * 25;
|
|
|
19
18
|
const MinAvailabilityTimeout = 300; // ping every 5 minutes with few devices
|
|
20
19
|
const MaxAvailabilityTimeout = 1800; // ping every 30 minutes with many devices;
|
|
21
20
|
const AverageTimeBetweenPings = 45; // on average, plan for 30 seconds between pings.
|
|
21
|
+
const pingClusters = {
|
|
22
|
+
c0a0: {id:'genBasic', attribute:'zclVersion'},
|
|
23
|
+
c0a5: {id:'genBasic', attribute:'modelId'},
|
|
24
|
+
c25a0: {id:'genOta', attribute:'upgradeServerId'},
|
|
25
|
+
};
|
|
22
26
|
|
|
23
27
|
/**
|
|
24
28
|
* This extensions pings devices to check if they are online.
|
|
25
29
|
*/
|
|
26
30
|
class DeviceAvailability extends BaseExtension {
|
|
27
|
-
constructor(zigbee, options) {
|
|
31
|
+
constructor(zigbee, options, config) {
|
|
28
32
|
super(zigbee, options);
|
|
29
33
|
this.availability_timeout = 300; // wait 5 min for live check
|
|
30
34
|
this.timers = {};
|
|
31
35
|
this.ping_counters = {};
|
|
32
36
|
this.max_ping = 3;
|
|
33
37
|
this.state = {};
|
|
34
|
-
this.active_ping = true;
|
|
35
|
-
this.forced_ping = true;
|
|
36
38
|
this.forcedNonPingable = {};
|
|
37
39
|
this.number_of_registered_devices = 0;
|
|
38
40
|
// force publish availability for new devices
|
|
@@ -44,28 +46,34 @@ class DeviceAvailability extends BaseExtension {
|
|
|
44
46
|
this.startDevicePingQueue = []; // simple fifo array for starting device pings
|
|
45
47
|
this.startDevicePingTimeout = null; // handle for the timeout which empties the queue
|
|
46
48
|
this.startDevicePingDelay = 500; // 200 ms delay between starting the ping timeout
|
|
49
|
+
this.startReadDelay = 0;
|
|
47
50
|
this.name = 'DeviceAvailability';
|
|
48
51
|
this.elevate_debug = false;
|
|
49
52
|
this.isStarted = false;
|
|
53
|
+
this.active_ping = config.pingCluster != 'off';
|
|
54
|
+
this.max_ping = 5;
|
|
55
|
+
this.availability_timeout = Math.max(60, typeof config.pingTimeout == 'number' ? config.pingTimeout : 300);
|
|
56
|
+
this.startReadDelay = config.readAllAtStart ? Math.max(500, Math.min(10000, config.startReadDelay * 1000)) : 0;
|
|
57
|
+
this.debugDevices = [];
|
|
58
|
+
this.pingCluster = pingClusters[config.pingCluster] ? pingClusters[config.pingCluster] : {};
|
|
50
59
|
}
|
|
51
60
|
|
|
52
|
-
|
|
53
|
-
if (typeof
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (typeof options.pingTimeout === 'number') {
|
|
63
|
-
this.availability_timeout = Math.min(60, options.pingTimeout);
|
|
64
|
-
}
|
|
65
|
-
if (typeof options.pingCount === 'number') {
|
|
66
|
-
this.max_ping = Math.min(2, options.pingCount);
|
|
61
|
+
checkDebugDevice(dev) {
|
|
62
|
+
if (typeof dev != 'string' || dev == '') return false;
|
|
63
|
+
if (this.debugDevices === undefined) return false;
|
|
64
|
+
else
|
|
65
|
+
{
|
|
66
|
+
for (const addressPart of this.debugDevices) {
|
|
67
|
+
if (typeof dev === 'string' && dev.includes(addressPart)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
|
-
return
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setLocalVariable(name, value) {
|
|
76
|
+
this[name] = value;
|
|
69
77
|
}
|
|
70
78
|
|
|
71
79
|
isPingable(device) {
|
|
@@ -89,7 +97,6 @@ class DeviceAvailability extends BaseExtension {
|
|
|
89
97
|
if (!this.isStarted) return;
|
|
90
98
|
this.debug(`register device Ping for ${JSON.stringify(device.ieeeAddr)}`);
|
|
91
99
|
this.forcedNonPingable[device.ieeeAddr] = false;
|
|
92
|
-
// this.warn(`Called registerDevicePing for '${device}' of '${entity}'`);
|
|
93
100
|
if (!this.isPingable(device)) {
|
|
94
101
|
return;
|
|
95
102
|
}
|
|
@@ -119,7 +126,6 @@ class DeviceAvailability extends BaseExtension {
|
|
|
119
126
|
}
|
|
120
127
|
|
|
121
128
|
async startDevicePing() {
|
|
122
|
-
// this.warn(JSON.stringify(this));
|
|
123
129
|
if (!this.isStarted) return;
|
|
124
130
|
this.startDevicePingTimeout = null;
|
|
125
131
|
const item = this.startDevicePingQueue.shift();
|
|
@@ -132,61 +138,104 @@ class DeviceAvailability extends BaseExtension {
|
|
|
132
138
|
}
|
|
133
139
|
}
|
|
134
140
|
|
|
141
|
+
async startNotPingable(device) {
|
|
142
|
+
this.publishAvailability(device, true);
|
|
143
|
+
this.timers[device.ieeeAddr] = setInterval(() =>
|
|
144
|
+
this.handleIntervalNotPingable(device), utils.secondsToMilliseconds(this.availability_timeout));
|
|
145
|
+
}
|
|
146
|
+
|
|
135
147
|
async onZigbeeStarted() {
|
|
136
148
|
// As some devices are not checked for availability (e.g. battery powered devices)
|
|
137
149
|
// we mark these device as online by default.
|
|
138
150
|
// NOTE: The start of active pings for pingable devices is done separately,
|
|
139
151
|
// triggered by the 'new device' event to ensure that they are handled
|
|
140
152
|
// identically on reconnect, disconnect and new pair (as)
|
|
141
|
-
const clients = await this.zigbee.
|
|
153
|
+
const clients = await this.zigbee.getClientIterator();
|
|
154
|
+
const readables = [];
|
|
155
|
+
|
|
142
156
|
this.isStarted = true;
|
|
143
|
-
|
|
157
|
+
this.debug('onZigbeeStarted called');
|
|
158
|
+
|
|
144
159
|
for (const device of clients) {
|
|
145
|
-
if (this.isPingable(device)) {
|
|
160
|
+
if (this.isPingable(device) && this.active_ping) {
|
|
161
|
+
readables.push(device);
|
|
146
162
|
// this.setTimerPingable(device);
|
|
147
163
|
} else {
|
|
148
|
-
|
|
164
|
+
this.debug(`Setting '${device.ieeeAddr}' as available - battery driven or no active availability check`);
|
|
149
165
|
this.publishAvailability(device, true);
|
|
150
166
|
this.timers[device.ieeeAddr] = setInterval(() =>
|
|
151
167
|
this.handleIntervalNotPingable(device), utils.secondsToMilliseconds(this.availability_timeout));
|
|
152
168
|
}
|
|
153
169
|
}
|
|
170
|
+
if (this.startReadDelay > 0 && readables.length > 0) {
|
|
171
|
+
this.info(`Triggering device_query on ${readables.length} devices in ${this.startReadDelay / 1000} seconds.`)
|
|
172
|
+
setTimeout(() => {
|
|
173
|
+
readables.forEach(device => this.zigbee.doDeviceQuery(device, Date().now, false));
|
|
174
|
+
}, this.startReadDelay)
|
|
175
|
+
}
|
|
154
176
|
}
|
|
155
177
|
|
|
156
178
|
async handleIntervalPingable(device, entity) {
|
|
157
179
|
if (!this.isStarted) return;
|
|
180
|
+
if (!this.active_ping) {
|
|
181
|
+
return await this.handleIntervalnonPingable();
|
|
182
|
+
}
|
|
183
|
+
const has_elevated_debug = this.checkDebugDevice(device.ieeeAddr)
|
|
184
|
+
|
|
158
185
|
const ieeeAddr = device.ieeeAddr;
|
|
159
186
|
const resolvedEntity = entity ? entity : await this.zigbee.resolveEntity(ieeeAddr);
|
|
160
187
|
if (!resolvedEntity) {
|
|
161
|
-
|
|
188
|
+
const msg = `Stop pinging '${ieeeAddr}' ${device.modelID}, device is not known anymore`
|
|
189
|
+
if (has_elevated_debug) this.warn(`ELEVADED: ${msg}`);
|
|
190
|
+
else this.info(msg);
|
|
162
191
|
return;
|
|
163
192
|
}
|
|
164
193
|
if (this.isPingable(device)) {
|
|
194
|
+
const pt = Date.now();
|
|
165
195
|
let pingCount = this.ping_counters[device.ieeeAddr];
|
|
166
196
|
if (pingCount === undefined) {
|
|
167
197
|
this.ping_counters[device.ieeeAddr] = {failed: 0, reported: 0};
|
|
168
198
|
pingCount = {failed: 0, reported: 0};
|
|
169
199
|
}
|
|
170
200
|
try {
|
|
171
|
-
|
|
172
|
-
|
|
201
|
+
if (!this.pingCluster || !this.pingCluster.hasOwnProperty('id')) {
|
|
202
|
+
this.debug(`Pinging '${ieeeAddr}' (${device.modelID}) via ZH Ping`)
|
|
203
|
+
await device.ping();
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
const zclData = {};
|
|
207
|
+
zclData[this.pingCluster.attribute] = {};
|
|
208
|
+
this.debug(`Pinging '${ieeeAddr}' (${device.modelID}) via ZCL Read with ${this.pingCluster.id}:${this.pingCluster.attribute}`)
|
|
209
|
+
await this.zigbee.publish(device, this.pingCluster.id, 'read', zclData, null, undefined, 'foundation');
|
|
210
|
+
}
|
|
173
211
|
this.publishAvailability(device, true);
|
|
174
|
-
|
|
212
|
+
if (has_elevated_debug) this.warn(`ELEVATED : Successfully pinged ${ieeeAddr} (${device.modelID}) in ${Date.now()-pt} ms`);
|
|
175
213
|
this.setTimerPingable(device, 1);
|
|
176
214
|
this.ping_counters[device.ieeeAddr].failed = 0;
|
|
177
215
|
} catch (error) {
|
|
216
|
+
if (error && error.message && error.message.includes('UNSUPPORTED_ATTRIBUTE')) {
|
|
217
|
+
// this error is acceptable, as it is raised off an answer of the device.
|
|
218
|
+
this.publishAvailability(device, true);
|
|
219
|
+
if (has_elevated_debug) this.warn(`ELEVATED : Successfully pinged ${ieeeAddr} (${device.modelID}) in ${Date.now()-pt} ms`);
|
|
220
|
+
this.setTimerPingable(device, 1);
|
|
221
|
+
this.ping_counters[device.ieeeAddr].failed = 0;
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (has_elevated_debug) this.warn(`ELEVATED : Failed to ping ${ieeeAddr} (${device.modelID}) after ${Date.now()-pt} ms${error && error.message ? ' - '+error.message : ''}`);
|
|
178
225
|
this.publishAvailability(device, false);
|
|
179
226
|
if (pingCount.failed++ <= this.max_ping) {
|
|
227
|
+
const msg = `Failed to ping ${ieeeAddr} ${device.modelID} for ${JSON.stringify(pingCount)} attempts`
|
|
180
228
|
if (pingCount.failed < 2 && pingCount.reported < this.max_ping) {
|
|
181
|
-
this.
|
|
229
|
+
if (has_elevated_debug) this.warn(`ELEVATED: ${msg}`); else this.info(msg);
|
|
182
230
|
pingCount.reported++;
|
|
183
231
|
} else {
|
|
184
|
-
this.debug(
|
|
232
|
+
this.debug(msg);
|
|
185
233
|
}
|
|
186
234
|
this.setTimerPingable(device, pingCount.failed);
|
|
187
235
|
this.ping_counters[device.ieeeAddr] = pingCount;
|
|
188
236
|
} else {
|
|
189
|
-
|
|
237
|
+
const msg = `Stopping to ping ${ieeeAddr} ${device.modelID} after ${pingCount.failed} ping attempts`;
|
|
238
|
+
if (has_elevated_debug) this.warn(`ELEVATED ${msg}`); else this.info(msg);
|
|
190
239
|
}
|
|
191
240
|
}
|
|
192
241
|
}
|
|
@@ -200,11 +249,15 @@ class DeviceAvailability extends BaseExtension {
|
|
|
200
249
|
}
|
|
201
250
|
|
|
202
251
|
const ago = Date.now() - entity.device.lastSeen;
|
|
203
|
-
this.debug(`Non-pingable device ${entity.device.ieeeAddr} ${entity.device.modelID} was last seen '${ago / 1000}' seconds ago.`);
|
|
204
252
|
|
|
205
253
|
if (ago > Hours25) {
|
|
206
254
|
this.publishAvailability(entity.device, false);
|
|
255
|
+
const msg = `Non-pingable device ${entity.device.ieeeAddr} ${entity.device.modelID} was last seen over 25 hrs ago - setting it offline.`
|
|
256
|
+
if (this.checkDebugDevice(device.ieeeAddr)) this.warn(`ELEVATED: ${msg}`); else this.debug(msg);
|
|
257
|
+
return;
|
|
207
258
|
}
|
|
259
|
+
const msg = `Non-pingable device ${entity.device.ieeeAddr} ${entity.device.modelID} was last seen '${ago / 1000}' seconds ago.`
|
|
260
|
+
if (this.checkDebugDevice(device.ieeeAddr)) this.warn(`ELEVATED: ${msg}`); else this.debug(msg);
|
|
208
261
|
}
|
|
209
262
|
|
|
210
263
|
setTimerPingable(device, factor) {
|
|
@@ -236,7 +289,7 @@ class DeviceAvailability extends BaseExtension {
|
|
|
236
289
|
for (const key of toZigbeeCandidates) {
|
|
237
290
|
const converter = entity.mapped.toZigbee.find((tz) => tz.key.includes(key));
|
|
238
291
|
if (converter && !used.includes(converter)) {
|
|
239
|
-
await converter.convertGet(device.endpoints[0], key, {});
|
|
292
|
+
await converter.convertGet(device.endpoints[0], key, {device:entity.device});
|
|
240
293
|
used.push(converter);
|
|
241
294
|
}
|
|
242
295
|
}
|
|
@@ -266,7 +319,7 @@ class DeviceAvailability extends BaseExtension {
|
|
|
266
319
|
}
|
|
267
320
|
}
|
|
268
321
|
|
|
269
|
-
onZigbeeEvent(data) {
|
|
322
|
+
async onZigbeeEvent(data) {
|
|
270
323
|
const device = data.device;
|
|
271
324
|
if (!device || this.forcedNonPingable[device.ieeeAddr]) {
|
|
272
325
|
return;
|
|
@@ -287,16 +340,19 @@ class DeviceAvailability extends BaseExtension {
|
|
|
287
340
|
|
|
288
341
|
const online = this.state.hasOwnProperty(device.ieeeAddr) && this.state[device.ieeeAddr];
|
|
289
342
|
if (online && data.type === 'deviceAnnounce' && !utils.isIkeaTradfriDevice(device)) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
343
|
+
const entity = await this.zigbee.resolveEntity(device);
|
|
344
|
+
if (entity && entity.mapped) {
|
|
345
|
+
/**
|
|
346
|
+
* In case the device is powered off AND on within the availability timeout,
|
|
347
|
+
* zigbee2qmtt does not detect the device as offline (device is still marked online).
|
|
348
|
+
* When a device is turned on again the state could be out of sync.
|
|
349
|
+
* https://github.com/Koenkk/zigbee2mqtt/issues/1383#issuecomment-489412168
|
|
350
|
+
* endDeviceAnnce is typically send when a device comes online.
|
|
351
|
+
*
|
|
352
|
+
* This isn't needed for TRADFRI devices as they already send the state themself.
|
|
353
|
+
*/
|
|
354
|
+
this.onReconnect(device);
|
|
355
|
+
}
|
|
300
356
|
}
|
|
301
357
|
}
|
|
302
358
|
}
|
package/lib/zbDeviceConfigure.js
CHANGED
|
@@ -90,6 +90,7 @@ class DeviceConfigure extends BaseExtension {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
onZigbeeEvent(data, mappedDevice) {
|
|
93
|
+
if (!mappedDevice || !data.device) return;
|
|
93
94
|
try {
|
|
94
95
|
const device = data.device;
|
|
95
96
|
const com = this.configureOnMessageAttempts[device.ieeeAddr];
|
|
@@ -100,7 +101,13 @@ class DeviceConfigure extends BaseExtension {
|
|
|
100
101
|
this.info('Configure on Message for ' + device.ieeeAddr);
|
|
101
102
|
this.doConfigure(device, mappedDevice);
|
|
102
103
|
}
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// check if the event is a 'deviceInterview successful' Event
|
|
107
|
+
if (data.type == 'deviceJoined' || data.type == 'deviceInterview' && data.status == 'successful') {
|
|
108
|
+
this.PushDeviceToQueue(device, mappedDevice);
|
|
103
109
|
}
|
|
110
|
+
|
|
104
111
|
} catch (error) {
|
|
105
112
|
this.sendError(error);
|
|
106
113
|
this.error(`Failed to DeviceConfigure.onZigbeeEvent (${error && error.message ? error.message : 'no error message'})`);
|
package/lib/zbDeviceEvent.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
const BaseExtension = require('./zbBaseExtension');
|
|
4
4
|
const zigbeeHerdsmanConverters = require('zigbee-herdsman-converters');
|
|
5
|
-
|
|
6
5
|
class DeviceEvent extends BaseExtension {
|
|
7
6
|
constructor(zigbee, options) {
|
|
8
7
|
super(zigbee, options);
|
|
@@ -10,8 +9,10 @@ class DeviceEvent extends BaseExtension {
|
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
async onZigbeeStarted() {
|
|
13
|
-
for (const device of await this.zigbee.
|
|
14
|
-
await this.
|
|
12
|
+
for (const device of await this.zigbee.getClientIterator()) {
|
|
13
|
+
const entity = await this.zigbee.resolveEntity(device);
|
|
14
|
+
|
|
15
|
+
await this.callOnEvent(device, 'start', {device, options:entity.options || {}});
|
|
15
16
|
}
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -21,7 +22,7 @@ class DeviceEvent extends BaseExtension {
|
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
async onZigbeeEvent(data, mappedDevice) {
|
|
24
|
-
if (data.device) {
|
|
25
|
+
if (data && data.device && data.type) {
|
|
25
26
|
this.callOnEvent(data.device, data.type, data, mappedDevice);
|
|
26
27
|
}
|
|
27
28
|
}
|
|
@@ -29,7 +30,7 @@ class DeviceEvent extends BaseExtension {
|
|
|
29
30
|
async stop() {
|
|
30
31
|
if (this.zigbee.getClients() > 0) {
|
|
31
32
|
for (const device of await this.zigbee.getClients()) {
|
|
32
|
-
await this.callOnEvent(device, 'stop', {});
|
|
33
|
+
await this.callOnEvent(device, 'stop', {ieeeAddr:device.ieeeAddr});
|
|
33
34
|
}
|
|
34
35
|
}
|
|
35
36
|
}
|
|
@@ -38,9 +39,41 @@ class DeviceEvent extends BaseExtension {
|
|
|
38
39
|
if (!mappedDevice) {
|
|
39
40
|
mappedDevice = await zigbeeHerdsmanConverters.findByDevice(device);
|
|
40
41
|
}
|
|
42
|
+
const baseData = {device, deviceExposeChanged: function() { return; }, options: data.options || {}, state: data.state || {}}
|
|
43
|
+
const eventData = {
|
|
44
|
+
type,
|
|
45
|
+
}
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
47
|
+
switch (type) {
|
|
48
|
+
case 'start':
|
|
49
|
+
case 'deviceNetworkAddressChanged':
|
|
50
|
+
case 'deviceAnnounce':
|
|
51
|
+
case `deviceJoined`:
|
|
52
|
+
{
|
|
53
|
+
eventData.data = baseData;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
case 'stop':
|
|
57
|
+
eventData.data = { ieeeAddr:device.ieeeAddr };
|
|
58
|
+
break;
|
|
59
|
+
case 'deviceInterview':
|
|
60
|
+
eventData.data = {...baseData,status: data.status};
|
|
61
|
+
break;
|
|
62
|
+
case 'deviceOptionsChanged':
|
|
63
|
+
// NOTE: This does not currently work. OptionsChange is not yet defined.
|
|
64
|
+
eventData.data = {...baseData, from:data.from || {}, to:data.to || {}};
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
if (mappedDevice && mappedDevice.onEvent && eventData.data) {
|
|
70
|
+
this.warn(`calling onEvent for ${eventData.type} on ${device.ieeeAddr}`);
|
|
71
|
+
try {
|
|
72
|
+
mappedDevice.onEvent(eventData);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
this.warn(`Error in onEvent: ${error && error.message ? error.message : 'no message'}`);
|
|
76
|
+
}
|
|
44
77
|
}
|
|
45
78
|
}
|
|
46
79
|
}
|