zwave-js 10.0.2 → 10.0.3
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/build/lib/node/Node.js
CHANGED
|
@@ -1234,6 +1234,7 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1234
1234
|
const securityClass = this.getHighestSecurityClass();
|
|
1235
1235
|
if (securityClass == undefined ||
|
|
1236
1236
|
(0, core_1.securityClassIsS2)(securityClass)) {
|
|
1237
|
+
this.driver.controllerLog.logNode(this.nodeId, "Root device interview: Security S2", "silly");
|
|
1237
1238
|
if (!this.driver.securityManager2) {
|
|
1238
1239
|
if (!this._hasEmittedNoS2NetworkKeyError) {
|
|
1239
1240
|
// Cannot interview a secure device securely without a network key
|
|
@@ -1265,6 +1266,7 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1265
1266
|
this.addCC(core_1.CommandClasses.Security, { secure: true });
|
|
1266
1267
|
// Query supported CCs unless we know for sure that the node wasn't assigned the S0 security class
|
|
1267
1268
|
if (this.hasSecurityClass(core_1.SecurityClass.S0_Legacy) !== false) {
|
|
1269
|
+
this.driver.controllerLog.logNode(this.nodeId, "Root device interview: Security S0", "silly");
|
|
1268
1270
|
if (!this.driver.securityManager) {
|
|
1269
1271
|
if (!this._hasEmittedNoS0NetworkKeyError) {
|
|
1270
1272
|
// Cannot interview a secure device securely without a network key
|
|
@@ -1289,9 +1291,11 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1289
1291
|
// Manufacturer Specific and Version CC need to be handled before the other CCs because they are needed to
|
|
1290
1292
|
// identify the device and apply device configurations
|
|
1291
1293
|
if (this.supportsCC(core_1.CommandClasses["Manufacturer Specific"])) {
|
|
1294
|
+
this.driver.controllerLog.logNode(this.nodeId, "Root device interview: Manufacturer Specific", "silly");
|
|
1292
1295
|
await interviewEndpoint(this, core_1.CommandClasses["Manufacturer Specific"]);
|
|
1293
1296
|
}
|
|
1294
1297
|
if (this.supportsCC(core_1.CommandClasses.Version)) {
|
|
1298
|
+
this.driver.controllerLog.logNode(this.nodeId, "Root device interview: Version", "silly");
|
|
1295
1299
|
await interviewEndpoint(this, core_1.CommandClasses.Version);
|
|
1296
1300
|
// After the version CC interview of the root endpoint, we have enough info to load the correct device config file
|
|
1297
1301
|
await this.loadDeviceConfig();
|
|
@@ -1338,8 +1342,15 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1338
1342
|
// This interview cannot be done
|
|
1339
1343
|
throw new core_1.ZWaveError("The CC interview cannot be completed because there are circular dependencies between CCs!", core_1.ZWaveErrorCodes.CC_Invalid);
|
|
1340
1344
|
}
|
|
1345
|
+
this.driver.controllerLog.logNode(this.nodeId, `Root device interviews before endpoints: ${rootInterviewOrderBeforeEndpoints
|
|
1346
|
+
.map((cc) => `\n· ${(0, core_1.getCCName)(cc)}`)
|
|
1347
|
+
.join("")}`, "silly");
|
|
1348
|
+
this.driver.controllerLog.logNode(this.nodeId, `Root device interviews after endpoints: ${rootInterviewOrderAfterEndpoints
|
|
1349
|
+
.map((cc) => `\n· ${(0, core_1.getCCName)(cc)}`)
|
|
1350
|
+
.join("")}`, "silly");
|
|
1341
1351
|
// Now that we know the correct order, do the interview in sequence
|
|
1342
1352
|
for (const cc of rootInterviewOrderBeforeEndpoints) {
|
|
1353
|
+
this.driver.controllerLog.logNode(this.nodeId, `Root device interview: ${(0, core_1.getCCName)(cc)}`, "silly");
|
|
1343
1354
|
const action = await interviewEndpoint(this, cc);
|
|
1344
1355
|
if (action === "continue")
|
|
1345
1356
|
continue;
|
|
@@ -1361,9 +1372,13 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1361
1372
|
// Security S2 is always supported *securely*
|
|
1362
1373
|
endpoint.addCC(core_1.CommandClasses["Security 2"], { secure: true });
|
|
1363
1374
|
// If S2 is the highest security class, interview it for the endpoint
|
|
1364
|
-
if (securityClass
|
|
1365
|
-
(0, core_1.securityClassIsS2)(securityClass) &&
|
|
1375
|
+
if ((0, core_1.securityClassIsS2)(securityClass) &&
|
|
1366
1376
|
!!this.driver.securityManager2) {
|
|
1377
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1378
|
+
endpoint: endpoint.index,
|
|
1379
|
+
message: `Endpoint ${endpoint.index} interview: Security S2`,
|
|
1380
|
+
level: "silly",
|
|
1381
|
+
});
|
|
1367
1382
|
const action = await interviewEndpoint(endpoint, core_1.CommandClasses["Security 2"]);
|
|
1368
1383
|
if (typeof action === "boolean")
|
|
1369
1384
|
return action;
|
|
@@ -1375,19 +1390,92 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1375
1390
|
// If S0 is the highest security class, interview it for the endpoint
|
|
1376
1391
|
if (securityClass === core_1.SecurityClass.S0_Legacy &&
|
|
1377
1392
|
!!this.driver.securityManager) {
|
|
1393
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1394
|
+
endpoint: endpoint.index,
|
|
1395
|
+
message: `Endpoint ${endpoint.index} interview: Security S0`,
|
|
1396
|
+
level: "silly",
|
|
1397
|
+
});
|
|
1378
1398
|
const action = await interviewEndpoint(endpoint, core_1.CommandClasses.Security);
|
|
1379
1399
|
if (typeof action === "boolean")
|
|
1380
1400
|
return action;
|
|
1381
1401
|
}
|
|
1382
1402
|
}
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
endpoint.
|
|
1403
|
+
// It has been found that legacy nodes do not always advertise the S0 Command Class in their Multi
|
|
1404
|
+
// Channel Capability Report and still accept all their Command Class using S0 encapsulation.
|
|
1405
|
+
// A controlling node SHOULD try to control End Points with S0 encapsulation even if S0 is not
|
|
1406
|
+
// listed in the Multi Channel Capability Report.
|
|
1407
|
+
const endpointMissingS0 = securityClass === core_1.SecurityClass.S0_Legacy &&
|
|
1408
|
+
this.supportsCC(core_1.CommandClasses.Security) &&
|
|
1409
|
+
!endpoint.supportsCC(core_1.CommandClasses.Security);
|
|
1410
|
+
if (endpointMissingS0) {
|
|
1411
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1412
|
+
endpoint: endpoint.index,
|
|
1413
|
+
message: `is included using Security S0, but endpoint ${endpoint.index} does not list the CC. Testing if it accepts secure commands anyways.`,
|
|
1414
|
+
level: "silly",
|
|
1415
|
+
});
|
|
1416
|
+
// Define which CCs we can use to test this - and if supported, how
|
|
1417
|
+
const tests = [
|
|
1418
|
+
{
|
|
1419
|
+
ccId: core_1.CommandClasses["Z-Wave Plus Info"],
|
|
1420
|
+
test: () => endpoint.commandClasses["Z-Wave Plus Info"].get(),
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
ccId: core_1.CommandClasses["Binary Switch"],
|
|
1424
|
+
test: () => endpoint.commandClasses["Binary Switch"].get(),
|
|
1425
|
+
},
|
|
1426
|
+
{
|
|
1427
|
+
ccId: core_1.CommandClasses["Binary Sensor"],
|
|
1428
|
+
test: () => endpoint.commandClasses["Binary Sensor"].get(),
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
ccId: core_1.CommandClasses["Multilevel Switch"],
|
|
1432
|
+
test: () => endpoint.commandClasses["Multilevel Switch"].get(),
|
|
1433
|
+
},
|
|
1434
|
+
{
|
|
1435
|
+
ccId: core_1.CommandClasses["Multilevel Sensor"],
|
|
1436
|
+
test: () => endpoint.commandClasses["Multilevel Sensor"].get(),
|
|
1437
|
+
},
|
|
1438
|
+
// TODO: add other tests if necessary
|
|
1439
|
+
];
|
|
1440
|
+
for (const { ccId, test } of tests) {
|
|
1441
|
+
if (!endpoint.supportsCC(ccId))
|
|
1442
|
+
continue;
|
|
1443
|
+
// Temporarily mark the CC as secure so we can use it to test
|
|
1444
|
+
endpoint.addCC(ccId, { secure: true });
|
|
1445
|
+
// Perform the test and treat errors as negative results
|
|
1446
|
+
const success = !!(await test().catch(() => false));
|
|
1447
|
+
if (success) {
|
|
1448
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1449
|
+
endpoint: endpoint.index,
|
|
1450
|
+
message: `Endpoint ${endpoint.index} accepts/expects secure commands`,
|
|
1451
|
+
level: "silly",
|
|
1452
|
+
});
|
|
1453
|
+
// Mark all endpoint CCs as secure
|
|
1454
|
+
for (const [ccId] of endpoint.getCCs()) {
|
|
1455
|
+
endpoint.addCC(ccId, { secure: true });
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
else {
|
|
1459
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1460
|
+
endpoint: endpoint.index,
|
|
1461
|
+
message: `Endpoint ${endpoint.index} is actually not using S0`,
|
|
1462
|
+
level: "silly",
|
|
1463
|
+
});
|
|
1464
|
+
// Mark the CC as not secure again
|
|
1465
|
+
endpoint.addCC(ccId, { secure: false });
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1390
1468
|
}
|
|
1469
|
+
// if (
|
|
1470
|
+
// endpoint.supportsCC(CommandClasses.Security) &&
|
|
1471
|
+
// // The root endpoint has been interviewed, so we know if the device supports security
|
|
1472
|
+
// this.hasSecurityClass(SecurityClass.S0_Legacy) === true &&
|
|
1473
|
+
// // Only interview SecurityCC if the network key was set
|
|
1474
|
+
// this.driver.securityManager
|
|
1475
|
+
// ) {
|
|
1476
|
+
// // Security is always supported *securely*
|
|
1477
|
+
// endpoint.addCC(CommandClasses.Security, { secure: true });
|
|
1478
|
+
// }
|
|
1391
1479
|
// The Security S0/S2 CC adds new CCs to the endpoint, so we need to once more remove those
|
|
1392
1480
|
// that aren't actually properly supported by the device.
|
|
1393
1481
|
this.applyCommandClassesCompatFlag(endpoint.index);
|
|
@@ -1408,8 +1496,20 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1408
1496
|
// This interview cannot be done
|
|
1409
1497
|
throw new core_1.ZWaveError("The CC interview cannot be completed because there are circular dependencies between CCs!", core_1.ZWaveErrorCodes.CC_Invalid);
|
|
1410
1498
|
}
|
|
1499
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1500
|
+
endpoint: endpoint.index,
|
|
1501
|
+
message: `Endpoint ${endpoint.index} interview order: ${endpointInterviewOrder
|
|
1502
|
+
.map((cc) => `\n· ${(0, core_1.getCCName)(cc)}`)
|
|
1503
|
+
.join("")}`,
|
|
1504
|
+
level: "silly",
|
|
1505
|
+
});
|
|
1411
1506
|
// Now that we know the correct order, do the interview in sequence
|
|
1412
1507
|
for (const cc of endpointInterviewOrder) {
|
|
1508
|
+
this.driver.controllerLog.logNode(this.nodeId, {
|
|
1509
|
+
endpoint: endpoint.index,
|
|
1510
|
+
message: `Endpoint ${endpoint.index} interview: ${(0, core_1.getCCName)(cc)}`,
|
|
1511
|
+
level: "silly",
|
|
1512
|
+
});
|
|
1413
1513
|
const action = await interviewEndpoint(endpoint, cc);
|
|
1414
1514
|
if (action === "continue")
|
|
1415
1515
|
continue;
|
|
@@ -1419,6 +1519,7 @@ protocol version: ${this.protocolVersion}`;
|
|
|
1419
1519
|
}
|
|
1420
1520
|
// Continue with the application CCs for the root endpoint
|
|
1421
1521
|
for (const cc of rootInterviewOrderAfterEndpoints) {
|
|
1522
|
+
this.driver.controllerLog.logNode(this.nodeId, `Root device interview: ${(0, core_1.getCCName)(cc)}`, "silly");
|
|
1422
1523
|
const action = await interviewEndpoint(this, cc);
|
|
1423
1524
|
if (action === "continue")
|
|
1424
1525
|
continue;
|