zigbee-herdsman 1.0.0 → 1.1.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/.release-please-manifest.json +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/adapter/adapter.d.ts +6 -0
- package/dist/adapter/adapter.d.ts.map +1 -1
- package/dist/adapter/adapter.js.map +1 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts +5 -3
- package/dist/adapter/deconz/adapter/deconzAdapter.d.ts.map +1 -1
- package/dist/adapter/deconz/adapter/deconzAdapter.js +261 -558
- package/dist/adapter/deconz/adapter/deconzAdapter.js.map +1 -1
- package/dist/adapter/deconz/driver/constants.d.ts +102 -56
- package/dist/adapter/deconz/driver/constants.d.ts.map +1 -1
- package/dist/adapter/deconz/driver/constants.js +1 -2
- package/dist/adapter/deconz/driver/constants.js.map +1 -1
- package/dist/adapter/deconz/driver/driver.d.ts.map +1 -1
- package/dist/adapter/deconz/driver/driver.js +46 -41
- package/dist/adapter/deconz/driver/driver.js.map +1 -1
- package/dist/adapter/deconz/driver/frameParser.d.ts.map +1 -1
- package/dist/adapter/deconz/driver/frameParser.js +174 -107
- package/dist/adapter/deconz/driver/frameParser.js.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.d.ts +4 -12
- package/dist/adapter/ember/adapter/emberAdapter.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/emberAdapter.js +215 -249
- package/dist/adapter/ember/adapter/emberAdapter.js.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.d.ts +16 -12
- package/dist/adapter/ember/adapter/oneWaitress.d.ts.map +1 -1
- package/dist/adapter/ember/adapter/oneWaitress.js +16 -41
- package/dist/adapter/ember/adapter/oneWaitress.js.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts +10 -8
- package/dist/adapter/ezsp/adapter/ezspAdapter.d.ts.map +1 -1
- package/dist/adapter/ezsp/adapter/ezspAdapter.js +241 -238
- package/dist/adapter/ezsp/adapter/ezspAdapter.js.map +1 -1
- package/dist/adapter/ezsp/driver/driver.d.ts +6 -14
- package/dist/adapter/ezsp/driver/driver.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/driver.js +56 -37
- package/dist/adapter/ezsp/driver/driver.js.map +1 -1
- package/dist/adapter/ezsp/driver/ezsp.d.ts.map +1 -1
- package/dist/adapter/ezsp/driver/ezsp.js +3 -0
- package/dist/adapter/ezsp/driver/ezsp.js.map +1 -1
- package/dist/adapter/z-stack/adapter/manager.js +2 -2
- package/dist/adapter/z-stack/adapter/manager.js.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts +4 -3
- package/dist/adapter/z-stack/adapter/zStackAdapter.d.ts.map +1 -1
- package/dist/adapter/z-stack/adapter/zStackAdapter.js +258 -197
- package/dist/adapter/z-stack/adapter/zStackAdapter.js.map +1 -1
- package/dist/adapter/z-stack/znp/definition.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/definition.js +256 -302
- package/dist/adapter/z-stack/znp/definition.js.map +1 -1
- package/dist/adapter/z-stack/znp/tstype.d.ts +8 -8
- package/dist/adapter/z-stack/znp/tstype.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/utils.d.ts +3 -2
- package/dist/adapter/z-stack/znp/utils.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/utils.js +8 -7
- package/dist/adapter/z-stack/znp/utils.js.map +1 -1
- package/dist/adapter/z-stack/znp/znp.d.ts +3 -1
- package/dist/adapter/z-stack/znp/znp.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/znp.js +31 -14
- package/dist/adapter/z-stack/znp/znp.js.map +1 -1
- package/dist/adapter/z-stack/znp/zpiObject.d.ts +5 -6
- package/dist/adapter/z-stack/znp/zpiObject.d.ts.map +1 -1
- package/dist/adapter/z-stack/znp/zpiObject.js +28 -11
- package/dist/adapter/z-stack/znp/zpiObject.js.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts +7 -5
- package/dist/adapter/zboss/adapter/zbossAdapter.d.ts.map +1 -1
- package/dist/adapter/zboss/adapter/zbossAdapter.js +284 -138
- package/dist/adapter/zboss/adapter/zbossAdapter.js.map +1 -1
- package/dist/adapter/zboss/commands.d.ts +3 -0
- package/dist/adapter/zboss/commands.d.ts.map +1 -1
- package/dist/adapter/zboss/commands.js +248 -205
- package/dist/adapter/zboss/commands.js.map +1 -1
- package/dist/adapter/zboss/driver.d.ts +4 -14
- package/dist/adapter/zboss/driver.d.ts.map +1 -1
- package/dist/adapter/zboss/driver.js +63 -89
- package/dist/adapter/zboss/driver.js.map +1 -1
- package/dist/adapter/zboss/enums.d.ts +24 -2
- package/dist/adapter/zboss/enums.d.ts.map +1 -1
- package/dist/adapter/zboss/enums.js +35 -3
- package/dist/adapter/zboss/enums.js.map +1 -1
- package/dist/adapter/zboss/frame.d.ts +6 -1
- package/dist/adapter/zboss/frame.d.ts.map +1 -1
- package/dist/adapter/zboss/frame.js +56 -11
- package/dist/adapter/zboss/frame.js.map +1 -1
- package/dist/adapter/zboss/uart.d.ts +1 -0
- package/dist/adapter/zboss/uart.d.ts.map +1 -1
- package/dist/adapter/zboss/uart.js +4 -2
- package/dist/adapter/zboss/uart.js.map +1 -1
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts +5 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.d.ts.map +1 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js +44 -0
- package/dist/adapter/zigate/adapter/patchZdoBuffaloBE.js.map +1 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts +5 -0
- package/dist/adapter/zigate/adapter/zigateAdapter.d.ts.map +1 -1
- package/dist/adapter/zigate/adapter/zigateAdapter.js +247 -262
- package/dist/adapter/zigate/adapter/zigateAdapter.js.map +1 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/buffaloZiGate.js +2 -18
- package/dist/adapter/zigate/driver/buffaloZiGate.js.map +1 -1
- package/dist/adapter/zigate/driver/commandType.js +218 -218
- package/dist/adapter/zigate/driver/commandType.js.map +1 -1
- package/dist/adapter/zigate/driver/constants.d.ts +14 -8
- package/dist/adapter/zigate/driver/constants.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/constants.js +36 -9
- package/dist/adapter/zigate/driver/constants.js.map +1 -1
- package/dist/adapter/zigate/driver/messageType.js +42 -42
- package/dist/adapter/zigate/driver/messageType.js.map +1 -1
- package/dist/adapter/zigate/driver/zigate.d.ts +17 -13
- package/dist/adapter/zigate/driver/zigate.d.ts.map +1 -1
- package/dist/adapter/zigate/driver/zigate.js +83 -18
- package/dist/adapter/zigate/driver/zigate.js.map +1 -1
- package/dist/controller/controller.d.ts +1 -0
- package/dist/controller/controller.d.ts.map +1 -1
- package/dist/controller/controller.js +28 -0
- package/dist/controller/controller.js.map +1 -1
- package/dist/utils/patchBigIntSerialization.d.ts +2 -0
- package/dist/utils/patchBigIntSerialization.d.ts.map +1 -0
- package/dist/utils/patchBigIntSerialization.js +9 -0
- package/dist/utils/patchBigIntSerialization.js.map +1 -0
- package/dist/zspec/zcl/zclFrame.d.ts +1 -0
- package/dist/zspec/zcl/zclFrame.d.ts.map +1 -1
- package/dist/zspec/zcl/zclFrame.js +1 -0
- package/dist/zspec/zcl/zclFrame.js.map +1 -1
- package/dist/zspec/zdo/buffaloZdo.d.ts +1 -139
- package/dist/zspec/zdo/buffaloZdo.d.ts.map +1 -1
- package/dist/zspec/zdo/buffaloZdo.js.map +1 -1
- package/dist/zspec/zdo/definition/tstypes.d.ts +168 -1
- package/dist/zspec/zdo/definition/tstypes.d.ts.map +1 -1
- package/dist/zspec/zdo/definition/tstypes.js +1 -0
- package/dist/zspec/zdo/definition/tstypes.js.map +1 -1
- package/dist/zspec/zdo/utils.d.ts +2 -3
- package/dist/zspec/zdo/utils.d.ts.map +1 -1
- package/dist/zspec/zdo/utils.js +3 -4
- package/dist/zspec/zdo/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -27,16 +27,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
28
|
};
|
|
29
29
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
-
const buffalo_1 = require("../../../buffalo");
|
|
31
30
|
const utils_1 = require("../../../utils");
|
|
32
31
|
const logger_1 = require("../../../utils/logger");
|
|
32
|
+
const ZSpec = __importStar(require("../../../zspec"));
|
|
33
33
|
const Zcl = __importStar(require("../../../zspec/zcl"));
|
|
34
|
+
const Zdo = __importStar(require("../../../zspec/zdo"));
|
|
34
35
|
const adapter_1 = __importDefault(require("../../adapter"));
|
|
35
36
|
const constants_1 = require("../driver/constants");
|
|
36
37
|
const zigate_1 = __importDefault(require("../driver/zigate"));
|
|
38
|
+
const patchZdoBuffaloBE_1 = require("./patchZdoBuffaloBE");
|
|
37
39
|
const NS = 'zh:zigate';
|
|
38
40
|
const default_bind_group = 901; // https://github.com/Koenkk/zigbee-herdsman-converters/blob/master/lib/constants.js#L3
|
|
39
|
-
const channelsToMask = (channels) => channels.map((x) => 2 ** x).reduce((acc, x) => acc + x, 0);
|
|
40
41
|
class ZiGateAdapter extends adapter_1.default {
|
|
41
42
|
driver;
|
|
42
43
|
joinPermitted;
|
|
@@ -44,8 +45,9 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
44
45
|
closing;
|
|
45
46
|
queue;
|
|
46
47
|
constructor(networkOptions, serialPortOptions, backupPath, adapterOptions) {
|
|
48
|
+
(0, patchZdoBuffaloBE_1.patchZdoBuffaloBE)();
|
|
47
49
|
super(networkOptions, serialPortOptions, backupPath, adapterOptions);
|
|
48
|
-
this.hasZdoMessageOverhead = false;
|
|
50
|
+
this.hasZdoMessageOverhead = false; // false for requests, true for responses
|
|
49
51
|
this.joinPermitted = false;
|
|
50
52
|
this.closing = false;
|
|
51
53
|
const concurrent = this.adapterOptions && this.adapterOptions.concurrent ? this.adapterOptions.concurrent : 2;
|
|
@@ -57,6 +59,7 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
57
59
|
this.driver.on('LeaveIndication', this.leaveIndicationListener.bind(this));
|
|
58
60
|
this.driver.on('DeviceAnnounce', this.deviceAnnounceListener.bind(this));
|
|
59
61
|
this.driver.on('close', this.onZiGateClose.bind(this));
|
|
62
|
+
this.driver.on('zdoResponse', this.onZdoResponse.bind(this));
|
|
60
63
|
}
|
|
61
64
|
/**
|
|
62
65
|
* Adapter methods
|
|
@@ -81,9 +84,9 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
81
84
|
await this.initNetwork();
|
|
82
85
|
await this.driver.sendCommand(constants_1.ZiGateCommandCode.AddGroup, {
|
|
83
86
|
addressMode: constants_1.ADDRESS_MODE.short,
|
|
84
|
-
shortAddress:
|
|
85
|
-
sourceEndpoint:
|
|
86
|
-
destinationEndpoint:
|
|
87
|
+
shortAddress: ZSpec.COORDINATOR_ADDRESS,
|
|
88
|
+
sourceEndpoint: ZSpec.HA_ENDPOINT,
|
|
89
|
+
destinationEndpoint: ZSpec.HA_ENDPOINT,
|
|
87
90
|
groupAddress: default_bind_group,
|
|
88
91
|
});
|
|
89
92
|
}
|
|
@@ -101,7 +104,7 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
101
104
|
// @TODO deal hardcoded endpoints, made by analogy with deconz
|
|
102
105
|
// polling the coordinator on some firmware went into a memory leak, so we don't ask this info
|
|
103
106
|
const response = {
|
|
104
|
-
networkAddress:
|
|
107
|
+
networkAddress: ZSpec.COORDINATOR_ADDRESS,
|
|
105
108
|
manufacturerID: 0,
|
|
106
109
|
ieeeAddr: networkResponse.payload.extendedAddress,
|
|
107
110
|
endpoints: constants_1.coordinatorEndpoints.slice(), // copy
|
|
@@ -125,14 +128,25 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
125
128
|
};
|
|
126
129
|
}
|
|
127
130
|
async permitJoin(seconds, networkAddress) {
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST;
|
|
132
|
+
if (networkAddress !== undefined) {
|
|
133
|
+
// specific device that is not `Coordinator`
|
|
134
|
+
// `authentication`: TC significance always 1 (zb specs)
|
|
135
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
|
|
136
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
137
|
+
/* istanbul ignore next */
|
|
138
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
139
|
+
// TODO: will disappear once moved upstream
|
|
140
|
+
throw new Zdo.StatusError(result[0]);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// broadcast permit joining ZDO
|
|
145
|
+
// `authentication`: TC significance always 1 (zb specs)
|
|
146
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []);
|
|
147
|
+
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
|
|
148
|
+
}
|
|
149
|
+
this.joinPermitted = seconds !== 0;
|
|
136
150
|
}
|
|
137
151
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
138
152
|
async addInstallCode(ieeeAddress, key) {
|
|
@@ -169,9 +183,11 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
169
183
|
async backup() {
|
|
170
184
|
throw new Error('This adapter does not support backup');
|
|
171
185
|
}
|
|
172
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
173
186
|
async changeChannel(newChannel) {
|
|
174
|
-
|
|
187
|
+
const clusterId = Zdo.ClusterId.NWK_UPDATE_REQUEST;
|
|
188
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, [newChannel], 0xfe, undefined, undefined, undefined);
|
|
189
|
+
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.SLEEPY, clusterId, zdoPayload, true /* handled below */);
|
|
190
|
+
await (0, utils_1.Wait)(12000);
|
|
175
191
|
}
|
|
176
192
|
async setTransmitPower(value) {
|
|
177
193
|
try {
|
|
@@ -182,252 +198,215 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
182
198
|
}
|
|
183
199
|
}
|
|
184
200
|
async lqi(networkAddress) {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
201
|
+
const clusterId = Zdo.ClusterId.LQI_TABLE_REQUEST;
|
|
202
|
+
const neighbors = [];
|
|
203
|
+
const request = async (startIndex) => {
|
|
204
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, startIndex);
|
|
205
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
206
|
+
/* istanbul ignore else */
|
|
207
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
208
|
+
const payload = result[1];
|
|
209
|
+
for (const entry of payload.entryList) {
|
|
191
210
|
neighbors.push({
|
|
192
|
-
|
|
193
|
-
networkAddress: entry.
|
|
194
|
-
|
|
195
|
-
relationship:
|
|
196
|
-
depth: entry.
|
|
211
|
+
ieeeAddr: entry.eui64,
|
|
212
|
+
networkAddress: entry.nwkAddress,
|
|
213
|
+
linkquality: entry.lqi,
|
|
214
|
+
relationship: entry.relationship,
|
|
215
|
+
depth: entry.depth,
|
|
197
216
|
});
|
|
198
217
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
218
|
+
return [payload.neighborTableEntries, payload.entryList.length];
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
// TODO: will disappear once moved upstream
|
|
222
|
+
throw new Zdo.StatusError(result[0]);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
let [tableEntries, entryCount] = await request(0);
|
|
226
|
+
const size = tableEntries;
|
|
227
|
+
let nextStartIndex = entryCount;
|
|
228
|
+
while (neighbors.length < size) {
|
|
229
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
230
|
+
nextStartIndex += entryCount;
|
|
231
|
+
}
|
|
232
|
+
return { neighbors };
|
|
233
|
+
}
|
|
234
|
+
async routingTable(networkAddress) {
|
|
235
|
+
const clusterId = Zdo.ClusterId.ROUTING_TABLE_REQUEST;
|
|
236
|
+
const table = [];
|
|
237
|
+
const request = async (startIndex) => {
|
|
238
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, startIndex);
|
|
239
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
240
|
+
/* istanbul ignore else */
|
|
241
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
242
|
+
const payload = result[1];
|
|
243
|
+
for (const entry of payload.entryList) {
|
|
244
|
+
table.push({
|
|
245
|
+
destinationAddress: entry.destinationAddress,
|
|
246
|
+
status: entry.status,
|
|
247
|
+
nextHop: entry.nextHopAddress,
|
|
205
248
|
});
|
|
206
|
-
const data = resultPayload.payload.payload;
|
|
207
|
-
if (data[1] !== 0) {
|
|
208
|
-
// status
|
|
209
|
-
throw new Error(`LQI for '${networkAddress}' failed`);
|
|
210
|
-
}
|
|
211
|
-
const tableList = [];
|
|
212
|
-
const response = {
|
|
213
|
-
status: data[1],
|
|
214
|
-
tableEntrys: data[2],
|
|
215
|
-
startIndex: data[3],
|
|
216
|
-
tableListCount: data[4],
|
|
217
|
-
tableList: tableList,
|
|
218
|
-
};
|
|
219
|
-
let tableEntry = [];
|
|
220
|
-
let counter = 0;
|
|
221
|
-
for (let i = 5; i < response.tableListCount * 22 + 5; i++) {
|
|
222
|
-
// one tableentry = 22 bytes
|
|
223
|
-
tableEntry.push(data[i]);
|
|
224
|
-
counter++;
|
|
225
|
-
if (counter === 22) {
|
|
226
|
-
response.tableList.push(Buffer.from(tableEntry));
|
|
227
|
-
tableEntry = [];
|
|
228
|
-
counter = 0;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
logger_1.logger.debug('LQI RESPONSE - addr: ' +
|
|
232
|
-
networkAddress.toString(16) +
|
|
233
|
-
' status: ' +
|
|
234
|
-
response.status +
|
|
235
|
-
' read ' +
|
|
236
|
-
(response.tableListCount + response.startIndex) +
|
|
237
|
-
'/' +
|
|
238
|
-
response.tableEntrys +
|
|
239
|
-
' entrys', NS);
|
|
240
|
-
return response;
|
|
241
|
-
}
|
|
242
|
-
catch (error) {
|
|
243
|
-
const msg = 'LQI REQUEST FAILED - addr: 0x' + networkAddress.toString(16) + ' ' + error;
|
|
244
|
-
logger_1.logger.error(msg, NS);
|
|
245
|
-
throw new Error(msg);
|
|
246
249
|
}
|
|
247
|
-
|
|
248
|
-
let response = await request(0);
|
|
249
|
-
add(response.tableList);
|
|
250
|
-
let nextStartIndex = response.tableListCount;
|
|
251
|
-
while (neighbors.length < response.tableEntrys) {
|
|
252
|
-
response = await request(nextStartIndex);
|
|
253
|
-
add(response.tableList);
|
|
254
|
-
nextStartIndex += response.tableListCount;
|
|
250
|
+
return [payload.routingTableEntries, payload.entryList.length];
|
|
255
251
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
252
|
+
else {
|
|
253
|
+
// TODO: will disappear once moved upstream
|
|
254
|
+
throw new Zdo.StatusError(result[0]);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
let [tableEntries, entryCount] = await request(0);
|
|
258
|
+
const size = tableEntries;
|
|
259
|
+
let nextStartIndex = entryCount;
|
|
260
|
+
while (table.length < size) {
|
|
261
|
+
[tableEntries, entryCount] = await request(nextStartIndex);
|
|
262
|
+
nextStartIndex += entryCount;
|
|
263
|
+
}
|
|
264
|
+
return { table };
|
|
263
265
|
}
|
|
264
266
|
async nodeDescriptor(networkAddress) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
type = 'Coordinator';
|
|
283
|
-
break;
|
|
284
|
-
}
|
|
285
|
-
const manufacturer = buf.readUInt16LE(7);
|
|
286
|
-
logger_1.logger.debug('RECEIVING NODE_DESCRIPTOR - addr: 0x' +
|
|
287
|
-
networkAddress.toString(16) +
|
|
288
|
-
' type: ' +
|
|
289
|
-
type +
|
|
290
|
-
' manufacturer: 0x' +
|
|
291
|
-
manufacturer.toString(16), NS);
|
|
292
|
-
return { manufacturerCode: manufacturer, type };
|
|
267
|
+
const clusterId = Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST;
|
|
268
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress);
|
|
269
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
270
|
+
/* istanbul ignore else */
|
|
271
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
272
|
+
const payload = result[1];
|
|
273
|
+
let type = 'Unknown';
|
|
274
|
+
switch (payload.logicalType) {
|
|
275
|
+
case 0x0:
|
|
276
|
+
type = 'Coordinator';
|
|
277
|
+
break;
|
|
278
|
+
case 0x1:
|
|
279
|
+
type = 'Router';
|
|
280
|
+
break;
|
|
281
|
+
case 0x2:
|
|
282
|
+
type = 'EndDevice';
|
|
283
|
+
break;
|
|
293
284
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
}
|
|
285
|
+
return { type, manufacturerCode: payload.manufacturerCode };
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
// TODO: will disappear once moved upstream
|
|
289
|
+
throw new Zdo.StatusError(result[0]);
|
|
290
|
+
}
|
|
300
291
|
}
|
|
301
292
|
async activeEndpoints(networkAddress) {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
const payloadAE = {
|
|
315
|
-
endpoints: epList,
|
|
316
|
-
};
|
|
317
|
-
logger_1.logger.debug(() => `ActiveEndpoints response: ${JSON.stringify(payloadAE)}`, NS);
|
|
318
|
-
return payloadAE;
|
|
319
|
-
}
|
|
320
|
-
catch (error) {
|
|
321
|
-
logger_1.logger.error(`RECEIVING ActiveEndpoints FAILED, ${error}`, NS);
|
|
322
|
-
throw new Error('RECEIVING ActiveEndpoints FAILED ' + error);
|
|
323
|
-
}
|
|
324
|
-
}, networkAddress);
|
|
293
|
+
const clusterId = Zdo.ClusterId.ACTIVE_ENDPOINTS_REQUEST;
|
|
294
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress);
|
|
295
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
296
|
+
/* istanbul ignore else */
|
|
297
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
298
|
+
const payload = result[1];
|
|
299
|
+
return { endpoints: payload.endpointList };
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
// TODO: will disappear once moved upstream
|
|
303
|
+
throw new Zdo.StatusError(result[0]);
|
|
304
|
+
}
|
|
325
305
|
}
|
|
326
306
|
async simpleDescriptor(networkAddress, endpointID) {
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
cIndex = 13 + inCount * 2;
|
|
346
|
-
for (let l = 0; l < outCount; l++) {
|
|
347
|
-
outClusters[l] = buf.readUInt16LE(cIndex);
|
|
348
|
-
cIndex += 2;
|
|
349
|
-
}
|
|
350
|
-
const resultPayload = {
|
|
351
|
-
profileID: buf.readUInt16LE(6),
|
|
352
|
-
endpointID: buf.readUInt8(5),
|
|
353
|
-
deviceID: buf.readUInt16LE(8),
|
|
354
|
-
inputClusters: inClusters,
|
|
355
|
-
outputClusters: outClusters,
|
|
356
|
-
};
|
|
357
|
-
return resultPayload;
|
|
358
|
-
}
|
|
359
|
-
throw new Error(`Invalid buffer length ${buf.length}.`);
|
|
360
|
-
}
|
|
361
|
-
catch (error) {
|
|
362
|
-
const msg = 'RECEIVING SIMPLE_DESCRIPTOR FAILED - addr: 0x' + networkAddress.toString(16) + ' EP:' + endpointID + ' ' + error;
|
|
363
|
-
logger_1.logger.error(msg, NS);
|
|
364
|
-
throw new Error(msg);
|
|
365
|
-
}
|
|
366
|
-
}, networkAddress);
|
|
307
|
+
const clusterId = Zdo.ClusterId.SIMPLE_DESCRIPTOR_REQUEST;
|
|
308
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, networkAddress, endpointID);
|
|
309
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
310
|
+
/* istanbul ignore else */
|
|
311
|
+
if (Zdo.Buffalo.checkStatus(result)) {
|
|
312
|
+
const payload = result[1];
|
|
313
|
+
return {
|
|
314
|
+
profileID: payload.profileId,
|
|
315
|
+
endpointID: payload.endpoint,
|
|
316
|
+
deviceID: payload.deviceId,
|
|
317
|
+
inputClusters: payload.inClusterList,
|
|
318
|
+
outputClusters: payload.outClusterList,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// TODO: will disappear once moved upstream
|
|
323
|
+
throw new Zdo.StatusError(result[0]);
|
|
324
|
+
}
|
|
367
325
|
}
|
|
368
326
|
async bind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
const result = await this.driver.sendCommand(constants_1.ZiGateCommandCode.Bind, payload, undefined, { destinationNetworkAddress });
|
|
381
|
-
const data = result.payload.payload;
|
|
382
|
-
if (data[1] === 0) {
|
|
383
|
-
logger_1.logger.debug(`Bind ${sourceIeeeAddress} success`, NS);
|
|
384
|
-
}
|
|
385
|
-
else {
|
|
386
|
-
const msg = `Bind ${sourceIeeeAddress} failed`;
|
|
387
|
-
logger_1.logger.error(msg, NS);
|
|
388
|
-
throw new Error(msg);
|
|
389
|
-
}
|
|
390
|
-
}, destinationNetworkAddress);
|
|
327
|
+
const clusterId = Zdo.ClusterId.BIND_REQUEST;
|
|
328
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, sourceIeeeAddress, sourceEndpoint, clusterID, type === 'group' ? Zdo.MULTICAST_BINDING : Zdo.UNICAST_BINDING, destinationAddressOrGroup, // not used with MULTICAST_BINDING
|
|
329
|
+
destinationAddressOrGroup, // not used with UNICAST_BINDING
|
|
330
|
+
destinationEndpoint ?? 0);
|
|
331
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, destinationNetworkAddress, clusterId, zdoPayload, false);
|
|
332
|
+
/* istanbul ignore next */
|
|
333
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
334
|
+
// TODO: will disappear once moved upstream
|
|
335
|
+
throw new Zdo.StatusError(result[0]);
|
|
336
|
+
}
|
|
391
337
|
}
|
|
392
338
|
async unbind(destinationNetworkAddress, sourceIeeeAddress, sourceEndpoint, clusterID, destinationAddressOrGroup, type, destinationEndpoint) {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
const result = await this.driver.sendCommand(constants_1.ZiGateCommandCode.UnBind, payload, undefined, { destinationNetworkAddress });
|
|
405
|
-
const data = result.payload.payload;
|
|
406
|
-
if (data[1] === 0) {
|
|
407
|
-
logger_1.logger.debug(`Unbind ${sourceIeeeAddress} success`, NS);
|
|
408
|
-
}
|
|
409
|
-
else {
|
|
410
|
-
const msg = `Unbind ${sourceIeeeAddress} failed`;
|
|
411
|
-
logger_1.logger.error(msg, NS);
|
|
412
|
-
throw new Error(msg);
|
|
413
|
-
}
|
|
414
|
-
}, destinationNetworkAddress);
|
|
339
|
+
const clusterId = Zdo.ClusterId.UNBIND_REQUEST;
|
|
340
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, sourceIeeeAddress, sourceEndpoint, clusterID, type === 'group' ? Zdo.MULTICAST_BINDING : Zdo.UNICAST_BINDING, destinationAddressOrGroup, // not used with MULTICAST_BINDING
|
|
341
|
+
destinationAddressOrGroup, // not used with UNICAST_BINDING
|
|
342
|
+
destinationEndpoint ?? 0);
|
|
343
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, destinationNetworkAddress, clusterId, zdoPayload, false);
|
|
344
|
+
/* istanbul ignore next */
|
|
345
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
346
|
+
// TODO: will disappear once moved upstream
|
|
347
|
+
throw new Zdo.StatusError(result[0]);
|
|
348
|
+
}
|
|
415
349
|
}
|
|
416
350
|
async removeDevice(networkAddress, ieeeAddr) {
|
|
351
|
+
const clusterId = Zdo.ClusterId.LEAVE_REQUEST;
|
|
352
|
+
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, ieeeAddr, Zdo.LeaveRequestFlags.WITHOUT_REJOIN);
|
|
353
|
+
const result = await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, false);
|
|
354
|
+
/* istanbul ignore next */
|
|
355
|
+
if (!Zdo.Buffalo.checkStatus(result)) {
|
|
356
|
+
// TODO: will disappear once moved upstream
|
|
357
|
+
throw new Zdo.StatusError(result[0]);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
async sendZdo(ieeeAddress, networkAddress, clusterId, payload, disableResponse) {
|
|
417
361
|
return await this.queue.execute(async () => {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
362
|
+
// stack-specific requirements
|
|
363
|
+
// https://zigate.fr/documentation/commandes-zigate/
|
|
364
|
+
switch (clusterId) {
|
|
365
|
+
case Zdo.ClusterId.LEAVE_REQUEST: {
|
|
366
|
+
const prefixedPayload = Buffer.alloc(payload.length + 3); // extra zero for `removeChildren`
|
|
367
|
+
prefixedPayload.writeUInt16BE(networkAddress, 0);
|
|
368
|
+
prefixedPayload.set(payload, 2);
|
|
369
|
+
payload = prefixedPayload;
|
|
370
|
+
break;
|
|
371
|
+
}
|
|
372
|
+
case Zdo.ClusterId.BIND_REQUEST:
|
|
373
|
+
case Zdo.ClusterId.UNBIND_REQUEST: {
|
|
374
|
+
// extra zeroes for endpoint XXX: not needed?
|
|
375
|
+
const zeroes = 15 - payload.length;
|
|
376
|
+
const prefixedPayload = Buffer.alloc(payload.length + zeroes);
|
|
377
|
+
prefixedPayload.set(payload, 0);
|
|
378
|
+
payload = prefixedPayload;
|
|
379
|
+
break;
|
|
380
|
+
}
|
|
381
|
+
case Zdo.ClusterId.PERMIT_JOINING_REQUEST:
|
|
382
|
+
case Zdo.ClusterId.SYSTEM_SERVER_DISCOVERY_REQUEST:
|
|
383
|
+
case Zdo.ClusterId.LQI_TABLE_REQUEST:
|
|
384
|
+
case Zdo.ClusterId.ROUTING_TABLE_REQUEST:
|
|
385
|
+
case Zdo.ClusterId.BINDING_TABLE_REQUEST:
|
|
386
|
+
case Zdo.ClusterId.NWK_UPDATE_REQUEST: {
|
|
387
|
+
const prefixedPayload = Buffer.alloc(payload.length + 2);
|
|
388
|
+
prefixedPayload.writeUInt16BE(networkAddress, 0);
|
|
389
|
+
prefixedPayload.set(payload, 2);
|
|
390
|
+
payload = prefixedPayload;
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
426
393
|
}
|
|
427
|
-
|
|
428
|
-
|
|
394
|
+
let waiter;
|
|
395
|
+
if (!disableResponse) {
|
|
396
|
+
const responseClusterId = Zdo.Utils.getResponseClusterId(clusterId);
|
|
397
|
+
if (responseClusterId) {
|
|
398
|
+
waiter = this.driver.zdoWaitFor({
|
|
399
|
+
clusterId: responseClusterId,
|
|
400
|
+
target: responseClusterId === Zdo.ClusterId.NETWORK_ADDRESS_RESPONSE ? ieeeAddress : networkAddress,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
429
403
|
}
|
|
430
|
-
|
|
404
|
+
await this.driver.requestZdo(clusterId, payload);
|
|
405
|
+
if (waiter) {
|
|
406
|
+
const result = await waiter.start().promise;
|
|
407
|
+
return result.zdo;
|
|
408
|
+
}
|
|
409
|
+
}, networkAddress /* TODO: replace with ieeeAddress once zdo moved upstream */);
|
|
431
410
|
}
|
|
432
411
|
async sendZclFrameToEndpoint(ieeeAddr, networkAddress, endpoint, zclFrame, timeout, disableResponse, disableRecovery, sourceEndpoint) {
|
|
433
412
|
return await this.queue.execute(async () => {
|
|
@@ -442,9 +421,9 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
442
421
|
const payload = {
|
|
443
422
|
addressMode: constants_1.ADDRESS_MODE.short, //nwk
|
|
444
423
|
targetShortAddress: networkAddress,
|
|
445
|
-
sourceEndpoint: sourceEndpoint ||
|
|
424
|
+
sourceEndpoint: sourceEndpoint || ZSpec.HA_ENDPOINT,
|
|
446
425
|
destinationEndpoint: endpoint,
|
|
447
|
-
profileID:
|
|
426
|
+
profileID: ZSpec.HA_PROFILE_ID,
|
|
448
427
|
clusterID: zclFrame.cluster.ID,
|
|
449
428
|
securityMode: 0x02,
|
|
450
429
|
radius: 30,
|
|
@@ -497,7 +476,7 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
497
476
|
targetShortAddress: destination,
|
|
498
477
|
sourceEndpoint: sourceEndpoint,
|
|
499
478
|
destinationEndpoint: endpoint,
|
|
500
|
-
profileID: /*sourceEndpoint ===
|
|
479
|
+
profileID: /*sourceEndpoint === ZSpec.GP_ENDPOINT ? ZSpec.GP_PROFILE_ID :*/ ZSpec.HA_PROFILE_ID,
|
|
501
480
|
clusterID: zclFrame.cluster.ID,
|
|
502
481
|
securityMode: 0x02,
|
|
503
482
|
radius: 30,
|
|
@@ -515,9 +494,9 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
515
494
|
const payload = {
|
|
516
495
|
addressMode: constants_1.ADDRESS_MODE.group, //nwk
|
|
517
496
|
targetShortAddress: groupID,
|
|
518
|
-
sourceEndpoint: sourceEndpoint ||
|
|
497
|
+
sourceEndpoint: sourceEndpoint || ZSpec.HA_ENDPOINT,
|
|
519
498
|
destinationEndpoint: 0xff,
|
|
520
|
-
profileID:
|
|
499
|
+
profileID: ZSpec.HA_PROFILE_ID,
|
|
521
500
|
clusterID: zclFrame.cluster.ID,
|
|
522
501
|
securityMode: 0x02,
|
|
523
502
|
radius: 30,
|
|
@@ -533,7 +512,9 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
533
512
|
*/
|
|
534
513
|
async initNetwork() {
|
|
535
514
|
logger_1.logger.debug(`Set channel mask ${this.networkOptions.channelList} key`, NS);
|
|
536
|
-
await this.driver.sendCommand(constants_1.ZiGateCommandCode.SetChannelMask, {
|
|
515
|
+
await this.driver.sendCommand(constants_1.ZiGateCommandCode.SetChannelMask, {
|
|
516
|
+
channelMask: ZSpec.Utils.channelsToUInt32Mask(this.networkOptions.channelList),
|
|
517
|
+
});
|
|
537
518
|
logger_1.logger.debug(`Set security key`, NS);
|
|
538
519
|
await this.driver.sendCommand(constants_1.ZiGateCommandCode.SetSecurityStateKey, {
|
|
539
520
|
keyType: this.networkOptions.networkKeyDistribute
|
|
@@ -591,36 +572,40 @@ class ZiGateAdapter extends adapter_1.default {
|
|
|
591
572
|
restoreChannelInterPAN() {
|
|
592
573
|
throw new Error('Not supported');
|
|
593
574
|
}
|
|
594
|
-
deviceAnnounceListener(
|
|
575
|
+
deviceAnnounceListener(response) {
|
|
595
576
|
// @todo debounce
|
|
596
|
-
const payload = { networkAddress, ieeeAddr };
|
|
577
|
+
const payload = { networkAddress: response.nwkAddress, ieeeAddr: response.eui64 };
|
|
597
578
|
if (this.joinPermitted === true) {
|
|
598
579
|
this.emit('deviceJoined', payload);
|
|
599
580
|
}
|
|
600
581
|
else {
|
|
601
|
-
|
|
582
|
+
// convert to `zdoResponse` to avoid needing extra event upstream
|
|
583
|
+
this.emit('zdoResponse', Zdo.ClusterId.END_DEVICE_ANNOUNCE, [Zdo.Status.SUCCESS, response]);
|
|
602
584
|
}
|
|
603
585
|
}
|
|
604
|
-
|
|
586
|
+
onZdoResponse(clusterId, response) {
|
|
587
|
+
this.emit('zdoResponse', clusterId, response);
|
|
588
|
+
}
|
|
589
|
+
dataListener(ziGateObject) {
|
|
605
590
|
const payload = {
|
|
606
|
-
address:
|
|
607
|
-
clusterID:
|
|
608
|
-
data:
|
|
609
|
-
header: Zcl.Header.fromBuffer(
|
|
610
|
-
endpoint:
|
|
611
|
-
linkquality:
|
|
591
|
+
address: ziGateObject.payload.sourceAddress,
|
|
592
|
+
clusterID: ziGateObject.payload.clusterID,
|
|
593
|
+
data: ziGateObject.payload.payload,
|
|
594
|
+
header: Zcl.Header.fromBuffer(ziGateObject.payload.payload),
|
|
595
|
+
endpoint: ziGateObject.payload.sourceEndpoint,
|
|
596
|
+
linkquality: ziGateObject.frame.readRSSI(), // read: frame valid
|
|
612
597
|
groupID: 0, // @todo
|
|
613
598
|
wasBroadcast: false, // TODO
|
|
614
|
-
destinationEndpoint:
|
|
599
|
+
destinationEndpoint: ziGateObject.payload.destinationEndpoint,
|
|
615
600
|
};
|
|
616
601
|
this.waitress.resolve(payload);
|
|
617
602
|
this.emit('zclPayload', payload);
|
|
618
603
|
}
|
|
619
|
-
leaveIndicationListener(
|
|
620
|
-
logger_1.logger.debug(() => `LeaveIndication ${JSON.stringify(
|
|
604
|
+
leaveIndicationListener(ziGateObject) {
|
|
605
|
+
logger_1.logger.debug(() => `LeaveIndication ${JSON.stringify(ziGateObject)}`, NS);
|
|
621
606
|
const payload = {
|
|
622
|
-
networkAddress:
|
|
623
|
-
ieeeAddr:
|
|
607
|
+
networkAddress: ziGateObject.payload.extendedAddress,
|
|
608
|
+
ieeeAddr: ziGateObject.payload.extendedAddress,
|
|
624
609
|
};
|
|
625
610
|
this.emit('deviceLeave', payload);
|
|
626
611
|
}
|