@zwave-js/cc 13.10.1 → 14.0.0-beta.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/build/cc/AlarmSensorCC.d.ts +31 -20
- package/build/cc/AlarmSensorCC.d.ts.map +1 -1
- package/build/cc/AlarmSensorCC.js +106 -87
- package/build/cc/AlarmSensorCC.js.map +1 -1
- package/build/cc/AssociationCC.d.ts +38 -32
- package/build/cc/AssociationCC.d.ts.map +1 -1
- package/build/cc/AssociationCC.js +193 -176
- package/build/cc/AssociationCC.js.map +1 -1
- package/build/cc/AssociationGroupInfoCC.d.ts +42 -36
- package/build/cc/AssociationGroupInfoCC.d.ts.map +1 -1
- package/build/cc/AssociationGroupInfoCC.js +218 -200
- package/build/cc/AssociationGroupInfoCC.js.map +1 -1
- package/build/cc/BarrierOperatorCC.d.ts +41 -24
- package/build/cc/BarrierOperatorCC.d.ts.map +1 -1
- package/build/cc/BarrierOperatorCC.js +143 -109
- package/build/cc/BarrierOperatorCC.js.map +1 -1
- package/build/cc/BasicCC.d.ts +22 -23
- package/build/cc/BasicCC.d.ts.map +1 -1
- package/build/cc/BasicCC.js +83 -77
- package/build/cc/BasicCC.js.map +1 -1
- package/build/cc/BatteryCC.d.ts +22 -14
- package/build/cc/BatteryCC.d.ts.map +1 -1
- package/build/cc/BatteryCC.js +116 -87
- package/build/cc/BatteryCC.js.map +1 -1
- package/build/cc/BinarySensorCC.d.ts +22 -19
- package/build/cc/BinarySensorCC.d.ts.map +1 -1
- package/build/cc/BinarySensorCC.js +103 -93
- package/build/cc/BinarySensorCC.js.map +1 -1
- package/build/cc/BinarySwitchCC.d.ts +20 -20
- package/build/cc/BinarySwitchCC.d.ts.map +1 -1
- package/build/cc/BinarySwitchCC.js +71 -59
- package/build/cc/BinarySwitchCC.js.map +1 -1
- package/build/cc/CRC16CC.d.ts +9 -9
- package/build/cc/CRC16CC.d.ts.map +1 -1
- package/build/cc/CRC16CC.js +36 -36
- package/build/cc/CRC16CC.js.map +1 -1
- package/build/cc/CentralSceneCC.d.ts +34 -16
- package/build/cc/CentralSceneCC.d.ts.map +1 -1
- package/build/cc/CentralSceneCC.js +116 -79
- package/build/cc/CentralSceneCC.js.map +1 -1
- package/build/cc/ClimateControlScheduleCC.d.ts +38 -21
- package/build/cc/ClimateControlScheduleCC.d.ts.map +1 -1
- package/build/cc/ClimateControlScheduleCC.js +113 -81
- package/build/cc/ClimateControlScheduleCC.js.map +1 -1
- package/build/cc/ClockCC.d.ts +18 -11
- package/build/cc/ClockCC.d.ts.map +1 -1
- package/build/cc/ClockCC.js +57 -43
- package/build/cc/ClockCC.js.map +1 -1
- package/build/cc/ColorSwitchCC.d.ts +37 -33
- package/build/cc/ColorSwitchCC.d.ts.map +1 -1
- package/build/cc/ColorSwitchCC.js +216 -189
- package/build/cc/ColorSwitchCC.js.map +1 -1
- package/build/cc/ConfigurationCC.d.ts +89 -74
- package/build/cc/ConfigurationCC.d.ts.map +1 -1
- package/build/cc/ConfigurationCC.js +541 -485
- package/build/cc/ConfigurationCC.js.map +1 -1
- package/build/cc/DeviceResetLocallyCC.d.ts +3 -3
- package/build/cc/DeviceResetLocallyCC.d.ts.map +1 -1
- package/build/cc/DeviceResetLocallyCC.js +14 -14
- package/build/cc/DeviceResetLocallyCC.js.map +1 -1
- package/build/cc/DoorLockCC.d.ts +66 -27
- package/build/cc/DoorLockCC.d.ts.map +1 -1
- package/build/cc/DoorLockCC.js +288 -197
- package/build/cc/DoorLockCC.js.map +1 -1
- package/build/cc/DoorLockLoggingCC.d.ts +23 -13
- package/build/cc/DoorLockLoggingCC.d.ts.map +1 -1
- package/build/cc/DoorLockLoggingCC.js +81 -63
- package/build/cc/DoorLockLoggingCC.js.map +1 -1
- package/build/cc/EnergyProductionCC.d.ts +16 -14
- package/build/cc/EnergyProductionCC.d.ts.map +1 -1
- package/build/cc/EnergyProductionCC.js +58 -52
- package/build/cc/EnergyProductionCC.js.map +1 -1
- package/build/cc/EntryControlCC.d.ts +44 -18
- package/build/cc/EntryControlCC.d.ts.map +1 -1
- package/build/cc/EntryControlCC.js +163 -112
- package/build/cc/EntryControlCC.js.map +1 -1
- package/build/cc/FirmwareUpdateMetaDataCC.d.ts +69 -34
- package/build/cc/FirmwareUpdateMetaDataCC.d.ts.map +1 -1
- package/build/cc/FirmwareUpdateMetaDataCC.js +311 -245
- package/build/cc/FirmwareUpdateMetaDataCC.js.map +1 -1
- package/build/cc/HumidityControlModeCC.d.ts +24 -16
- package/build/cc/HumidityControlModeCC.d.ts.map +1 -1
- package/build/cc/HumidityControlModeCC.js +80 -65
- package/build/cc/HumidityControlModeCC.js.map +1 -1
- package/build/cc/HumidityControlOperatingStateCC.d.ts +11 -7
- package/build/cc/HumidityControlOperatingStateCC.d.ts.map +1 -1
- package/build/cc/HumidityControlOperatingStateCC.js +31 -22
- package/build/cc/HumidityControlOperatingStateCC.js.map +1 -1
- package/build/cc/HumidityControlSetpointCC.d.ts +68 -49
- package/build/cc/HumidityControlSetpointCC.d.ts.map +1 -1
- package/build/cc/HumidityControlSetpointCC.js +203 -181
- package/build/cc/HumidityControlSetpointCC.js.map +1 -1
- package/build/cc/InclusionControllerCC.d.ts +13 -11
- package/build/cc/InclusionControllerCC.d.ts.map +1 -1
- package/build/cc/InclusionControllerCC.js +49 -42
- package/build/cc/InclusionControllerCC.js.map +1 -1
- package/build/cc/IndicatorCC.d.ts +46 -39
- package/build/cc/IndicatorCC.d.ts.map +1 -1
- package/build/cc/IndicatorCC.js +298 -277
- package/build/cc/IndicatorCC.js.map +1 -1
- package/build/cc/IrrigationCC.d.ts +127 -57
- package/build/cc/IrrigationCC.d.ts.map +1 -1
- package/build/cc/IrrigationCC.js +496 -352
- package/build/cc/IrrigationCC.js.map +1 -1
- package/build/cc/LanguageCC.d.ts +17 -11
- package/build/cc/LanguageCC.d.ts.map +1 -1
- package/build/cc/LanguageCC.js +54 -44
- package/build/cc/LanguageCC.js.map +1 -1
- package/build/cc/LockCC.d.ts +16 -11
- package/build/cc/LockCC.d.ts.map +1 -1
- package/build/cc/LockCC.js +48 -38
- package/build/cc/LockCC.js.map +1 -1
- package/build/cc/ManufacturerProprietaryCC.d.ts +12 -11
- package/build/cc/ManufacturerProprietaryCC.d.ts.map +1 -1
- package/build/cc/ManufacturerProprietaryCC.js +45 -50
- package/build/cc/ManufacturerProprietaryCC.js.map +1 -1
- package/build/cc/ManufacturerSpecificCC.d.ts +20 -13
- package/build/cc/ManufacturerSpecificCC.d.ts.map +1 -1
- package/build/cc/ManufacturerSpecificCC.js +79 -63
- package/build/cc/ManufacturerSpecificCC.js.map +1 -1
- package/build/cc/MeterCC.d.ts +30 -26
- package/build/cc/MeterCC.d.ts.map +1 -1
- package/build/cc/MeterCC.js +236 -204
- package/build/cc/MeterCC.js.map +1 -1
- package/build/cc/MultiChannelAssociationCC.d.ts +31 -26
- package/build/cc/MultiChannelAssociationCC.d.ts.map +1 -1
- package/build/cc/MultiChannelAssociationCC.js +177 -168
- package/build/cc/MultiChannelAssociationCC.js.map +1 -1
- package/build/cc/MultiChannelCC.d.ts +70 -49
- package/build/cc/MultiChannelCC.d.ts.map +1 -1
- package/build/cc/MultiChannelCC.js +377 -318
- package/build/cc/MultiChannelCC.js.map +1 -1
- package/build/cc/MultiCommandCC.d.ts +9 -9
- package/build/cc/MultiCommandCC.d.ts.map +1 -1
- package/build/cc/MultiCommandCC.js +35 -36
- package/build/cc/MultiCommandCC.js.map +1 -1
- package/build/cc/MultilevelSensorCC.d.ts +38 -33
- package/build/cc/MultilevelSensorCC.d.ts.map +1 -1
- package/build/cc/MultilevelSensorCC.js +172 -152
- package/build/cc/MultilevelSensorCC.js.map +1 -1
- package/build/cc/MultilevelSwitchCC.d.ts +29 -25
- package/build/cc/MultilevelSwitchCC.d.ts.map +1 -1
- package/build/cc/MultilevelSwitchCC.js +147 -127
- package/build/cc/MultilevelSwitchCC.js.map +1 -1
- package/build/cc/NoOperationCC.d.ts +0 -8
- package/build/cc/NoOperationCC.d.ts.map +1 -1
- package/build/cc/NoOperationCC.js +2 -11
- package/build/cc/NoOperationCC.js.map +1 -1
- package/build/cc/NodeNamingCC.d.ts +27 -17
- package/build/cc/NodeNamingCC.d.ts.map +1 -1
- package/build/cc/NodeNamingCC.js +86 -69
- package/build/cc/NodeNamingCC.js.map +1 -1
- package/build/cc/NotificationCC.d.ts +46 -43
- package/build/cc/NotificationCC.d.ts.map +1 -1
- package/build/cc/NotificationCC.js +317 -303
- package/build/cc/NotificationCC.js.map +1 -1
- package/build/cc/PowerlevelCC.d.ts +22 -18
- package/build/cc/PowerlevelCC.d.ts.map +1 -1
- package/build/cc/PowerlevelCC.js +125 -95
- package/build/cc/PowerlevelCC.js.map +1 -1
- package/build/cc/ProtectionCC.d.ts +49 -26
- package/build/cc/ProtectionCC.d.ts.map +1 -1
- package/build/cc/ProtectionCC.js +172 -126
- package/build/cc/ProtectionCC.js.map +1 -1
- package/build/cc/SceneActivationCC.d.ts +8 -7
- package/build/cc/SceneActivationCC.d.ts.map +1 -1
- package/build/cc/SceneActivationCC.js +28 -23
- package/build/cc/SceneActivationCC.js.map +1 -1
- package/build/cc/SceneActuatorConfigurationCC.d.ts +23 -15
- package/build/cc/SceneActuatorConfigurationCC.d.ts.map +1 -1
- package/build/cc/SceneActuatorConfigurationCC.js +79 -62
- package/build/cc/SceneActuatorConfigurationCC.js.map +1 -1
- package/build/cc/SceneControllerConfigurationCC.d.ts +25 -17
- package/build/cc/SceneControllerConfigurationCC.d.ts.map +1 -1
- package/build/cc/SceneControllerConfigurationCC.js +92 -78
- package/build/cc/SceneControllerConfigurationCC.js.map +1 -1
- package/build/cc/ScheduleEntryLockCC.d.ts +86 -72
- package/build/cc/ScheduleEntryLockCC.d.ts.map +1 -1
- package/build/cc/ScheduleEntryLockCC.js +607 -455
- package/build/cc/ScheduleEntryLockCC.js.map +1 -1
- package/build/cc/Security2CC.d.ts +78 -87
- package/build/cc/Security2CC.d.ts.map +1 -1
- package/build/cc/Security2CC.js +798 -765
- package/build/cc/Security2CC.js.map +1 -1
- package/build/cc/SecurityCC.d.ts +47 -42
- package/build/cc/SecurityCC.d.ts.map +1 -1
- package/build/cc/SecurityCC.js +240 -218
- package/build/cc/SecurityCC.js.map +1 -1
- package/build/cc/SoundSwitchCC.d.ts +36 -29
- package/build/cc/SoundSwitchCC.d.ts.map +1 -1
- package/build/cc/SoundSwitchCC.js +180 -157
- package/build/cc/SoundSwitchCC.js.map +1 -1
- package/build/cc/SupervisionCC.d.ts +17 -14
- package/build/cc/SupervisionCC.d.ts.map +1 -1
- package/build/cc/SupervisionCC.js +86 -66
- package/build/cc/SupervisionCC.js.map +1 -1
- package/build/cc/ThermostatFanModeCC.d.ts +25 -15
- package/build/cc/ThermostatFanModeCC.d.ts.map +1 -1
- package/build/cc/ThermostatFanModeCC.js +79 -60
- package/build/cc/ThermostatFanModeCC.js.map +1 -1
- package/build/cc/ThermostatFanStateCC.d.ts +11 -7
- package/build/cc/ThermostatFanStateCC.d.ts.map +1 -1
- package/build/cc/ThermostatFanStateCC.js +31 -22
- package/build/cc/ThermostatFanStateCC.js.map +1 -1
- package/build/cc/ThermostatModeCC.d.ts +24 -21
- package/build/cc/ThermostatModeCC.d.ts.map +1 -1
- package/build/cc/ThermostatModeCC.js +106 -90
- package/build/cc/ThermostatModeCC.js.map +1 -1
- package/build/cc/ThermostatOperatingStateCC.d.ts +11 -7
- package/build/cc/ThermostatOperatingStateCC.d.ts.map +1 -1
- package/build/cc/ThermostatOperatingStateCC.js +31 -22
- package/build/cc/ThermostatOperatingStateCC.js.map +1 -1
- package/build/cc/ThermostatSetbackCC.d.ts +14 -13
- package/build/cc/ThermostatSetbackCC.d.ts.map +1 -1
- package/build/cc/ThermostatSetbackCC.js +64 -57
- package/build/cc/ThermostatSetbackCC.js.map +1 -1
- package/build/cc/ThermostatSetpointCC.d.ts +38 -57
- package/build/cc/ThermostatSetpointCC.d.ts.map +1 -1
- package/build/cc/ThermostatSetpointCC.js +200 -264
- package/build/cc/ThermostatSetpointCC.js.map +1 -1
- package/build/cc/TimeCC.d.ts +24 -20
- package/build/cc/TimeCC.d.ts.map +1 -1
- package/build/cc/TimeCC.js +119 -108
- package/build/cc/TimeCC.js.map +1 -1
- package/build/cc/TimeParametersCC.d.ts +18 -14
- package/build/cc/TimeParametersCC.d.ts.map +1 -1
- package/build/cc/TimeParametersCC.js +77 -69
- package/build/cc/TimeParametersCC.js.map +1 -1
- package/build/cc/TransportServiceCC.d.ts +29 -32
- package/build/cc/TransportServiceCC.d.ts.map +1 -1
- package/build/cc/TransportServiceCC.js +159 -161
- package/build/cc/TransportServiceCC.js.map +1 -1
- package/build/cc/UserCodeCC.d.ts +83 -66
- package/build/cc/UserCodeCC.d.ts.map +1 -1
- package/build/cc/UserCodeCC.js +449 -402
- package/build/cc/UserCodeCC.js.map +1 -1
- package/build/cc/VersionCC.d.ts +36 -20
- package/build/cc/VersionCC.d.ts.map +1 -1
- package/build/cc/VersionCC.js +190 -149
- package/build/cc/VersionCC.js.map +1 -1
- package/build/cc/WakeUpCC.d.ts +27 -13
- package/build/cc/WakeUpCC.d.ts.map +1 -1
- package/build/cc/WakeUpCC.js +105 -77
- package/build/cc/WakeUpCC.js.map +1 -1
- package/build/cc/WindowCoveringCC.d.ts +39 -27
- package/build/cc/WindowCoveringCC.d.ts.map +1 -1
- package/build/cc/WindowCoveringCC.js +169 -137
- package/build/cc/WindowCoveringCC.js.map +1 -1
- package/build/cc/ZWavePlusCC.d.ts +8 -7
- package/build/cc/ZWavePlusCC.d.ts.map +1 -1
- package/build/cc/ZWavePlusCC.js +44 -37
- package/build/cc/ZWavePlusCC.js.map +1 -1
- package/build/cc/ZWaveProtocolCC.d.ts +111 -84
- package/build/cc/ZWaveProtocolCC.d.ts.map +1 -1
- package/build/cc/ZWaveProtocolCC.js +583 -508
- package/build/cc/ZWaveProtocolCC.js.map +1 -1
- package/build/cc/index.d.ts +37 -34
- package/build/cc/index.d.ts.map +1 -1
- package/build/cc/index.js +6 -7
- package/build/cc/index.js.map +1 -1
- package/build/cc/manufacturerProprietary/FibaroCC.d.ts +29 -24
- package/build/cc/manufacturerProprietary/FibaroCC.d.ts.map +1 -1
- package/build/cc/manufacturerProprietary/FibaroCC.js +109 -112
- package/build/cc/manufacturerProprietary/FibaroCC.js.map +1 -1
- package/build/index.d.ts +0 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +0 -1
- package/build/index.js.map +1 -1
- package/build/lib/API.d.ts +21 -18
- package/build/lib/API.d.ts.map +1 -1
- package/build/lib/API.js +25 -49
- package/build/lib/API.js.map +1 -1
- package/build/lib/CommandClass.d.ts +51 -89
- package/build/lib/CommandClass.d.ts.map +1 -1
- package/build/lib/CommandClass.js +177 -249
- package/build/lib/CommandClass.js.map +1 -1
- package/build/lib/EncapsulatingCommandClass.d.ts +1 -15
- package/build/lib/EncapsulatingCommandClass.d.ts.map +1 -1
- package/build/lib/EncapsulatingCommandClass.js.map +1 -1
- package/build/lib/ICommandClassContainer.d.ts +1 -8
- package/build/lib/ICommandClassContainer.d.ts.map +1 -1
- package/build/lib/ICommandClassContainer.js +0 -8
- package/build/lib/ICommandClassContainer.js.map +1 -1
- package/build/lib/Values.d.ts +3 -3
- package/build/lib/Values.d.ts.map +1 -1
- package/build/lib/_Types.d.ts.map +1 -1
- package/build/lib/_Types.js +1 -0
- package/build/lib/_Types.js.map +1 -1
- package/build/lib/utils.d.ts +14 -13
- package/build/lib/utils.d.ts.map +1 -1
- package/build/lib/utils.js +94 -92
- package/build/lib/utils.js.map +1 -1
- package/package.json +4 -5
package/build/lib/utils.js
CHANGED
|
@@ -19,10 +19,10 @@ const AssociationGroupInfoCC_1 = require("../cc/AssociationGroupInfoCC");
|
|
|
19
19
|
const MultiChannelAssociationCC_1 = require("../cc/MultiChannelAssociationCC");
|
|
20
20
|
const API_1 = require("./API");
|
|
21
21
|
const _Types_1 = require("./_Types");
|
|
22
|
-
function getAssociations(
|
|
22
|
+
function getAssociations(ctx, endpoint) {
|
|
23
23
|
const ret = new Map();
|
|
24
24
|
if (endpoint.supportsCC(safe_1.CommandClasses.Association)) {
|
|
25
|
-
const destinations = AssociationCC_1.AssociationCC.getAllDestinationsCached(
|
|
25
|
+
const destinations = AssociationCC_1.AssociationCC.getAllDestinationsCached(ctx, endpoint);
|
|
26
26
|
for (const [groupId, assocs] of destinations) {
|
|
27
27
|
ret.set(groupId, assocs);
|
|
28
28
|
}
|
|
@@ -32,7 +32,7 @@ function getAssociations(applHost, endpoint) {
|
|
|
32
32
|
}
|
|
33
33
|
// Merge the "normal" destinations with multi channel destinations
|
|
34
34
|
if (endpoint.supportsCC(safe_1.CommandClasses["Multi Channel Association"])) {
|
|
35
|
-
const destinations = MultiChannelAssociationCC_1.MultiChannelAssociationCC.getAllDestinationsCached(
|
|
35
|
+
const destinations = MultiChannelAssociationCC_1.MultiChannelAssociationCC.getAllDestinationsCached(ctx, endpoint);
|
|
36
36
|
for (const [groupId, assocs] of destinations) {
|
|
37
37
|
if (ret.has(groupId)) {
|
|
38
38
|
const normalAssociations = ret.get(groupId);
|
|
@@ -50,7 +50,7 @@ function getAssociations(applHost, endpoint) {
|
|
|
50
50
|
}
|
|
51
51
|
return ret;
|
|
52
52
|
}
|
|
53
|
-
function getAllAssociations(
|
|
53
|
+
function getAllAssociations(ctx, node) {
|
|
54
54
|
const ret = new safe_2.ObjectKeyMap();
|
|
55
55
|
for (const endpoint of node.getAllEndpoints()) {
|
|
56
56
|
const address = {
|
|
@@ -58,15 +58,15 @@ function getAllAssociations(applHost, node) {
|
|
|
58
58
|
endpoint: endpoint.index,
|
|
59
59
|
};
|
|
60
60
|
if (endpoint.supportsCC(safe_1.CommandClasses.Association)) {
|
|
61
|
-
ret.set(address, getAssociations(
|
|
61
|
+
ret.set(address, getAssociations(ctx, endpoint));
|
|
62
62
|
}
|
|
63
63
|
}
|
|
64
64
|
return ret;
|
|
65
65
|
}
|
|
66
|
-
function checkAssociation(
|
|
66
|
+
function checkAssociation(ctx, endpoint, group, destination) {
|
|
67
67
|
// Check that the target endpoint exists except when adding an association to the controller
|
|
68
|
-
const targetNode =
|
|
69
|
-
const targetEndpoint = destination.nodeId ===
|
|
68
|
+
const targetNode = ctx.getNodeOrThrow(destination.nodeId);
|
|
69
|
+
const targetEndpoint = destination.nodeId === ctx.ownNodeId
|
|
70
70
|
? targetNode
|
|
71
71
|
: targetNode.getEndpointOrThrow(destination.endpoint ?? 0);
|
|
72
72
|
if (!endpoint.supportsCC(safe_1.CommandClasses.Association)
|
|
@@ -79,12 +79,12 @@ function checkAssociation(applHost, endpoint, group, destination) {
|
|
|
79
79
|
}
|
|
80
80
|
else if ((0, safe_1.isLongRangeNodeId)(endpoint.nodeId)) {
|
|
81
81
|
// Except the lifeline back to the host
|
|
82
|
-
if (group !== 1 || destination.nodeId !==
|
|
82
|
+
if (group !== 1 || destination.nodeId !== ctx.ownNodeId) {
|
|
83
83
|
return _Types_1.AssociationCheckResult.Forbidden_SourceIsLongRange;
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
// The following checks don't apply to Lifeline associations
|
|
87
|
-
if (destination.nodeId ===
|
|
87
|
+
if (destination.nodeId === ctx.ownNodeId) {
|
|
88
88
|
return _Types_1.AssociationCheckResult.OK;
|
|
89
89
|
}
|
|
90
90
|
// Disallow self-associations
|
|
@@ -97,7 +97,7 @@ function checkAssociation(applHost, endpoint, group, destination) {
|
|
|
97
97
|
// For Association version 3 / MCA version 4:
|
|
98
98
|
// A controlling node MUST NOT associate Node A to a Node B destination
|
|
99
99
|
// if Node A was not granted Node B’s highest Security Class.
|
|
100
|
-
const sourceNode = endpoint.
|
|
100
|
+
const sourceNode = ctx.getNode(endpoint.nodeId);
|
|
101
101
|
let securityClassMustMatch;
|
|
102
102
|
if (destination.endpoint == undefined) {
|
|
103
103
|
// "normal" association
|
|
@@ -136,7 +136,7 @@ function checkAssociation(applHost, endpoint, group, destination) {
|
|
|
136
136
|
if (!endpoint.supportsCC(safe_1.CommandClasses["Association Group Information"])) {
|
|
137
137
|
return _Types_1.AssociationCheckResult.OK;
|
|
138
138
|
}
|
|
139
|
-
const groupCommandList = AssociationGroupInfoCC_1.AssociationGroupInfoCC.getIssuedCommandsCached(
|
|
139
|
+
const groupCommandList = AssociationGroupInfoCC_1.AssociationGroupInfoCC.getIssuedCommandsCached(ctx, endpoint, group);
|
|
140
140
|
if (!groupCommandList || !groupCommandList.size) {
|
|
141
141
|
// We don't know which CCs this group controls, just allow it
|
|
142
142
|
return _Types_1.AssociationCheckResult.OK;
|
|
@@ -156,7 +156,7 @@ function checkAssociation(applHost, endpoint, group, destination) {
|
|
|
156
156
|
return _Types_1.AssociationCheckResult.Forbidden_NoSupportedCCs;
|
|
157
157
|
}
|
|
158
158
|
}
|
|
159
|
-
function getAssociationGroups(
|
|
159
|
+
function getAssociationGroups(ctx, endpoint) {
|
|
160
160
|
// Check whether we have multi channel support or not
|
|
161
161
|
let assocInstance;
|
|
162
162
|
let mcInstance;
|
|
@@ -169,11 +169,12 @@ function getAssociationGroups(applHost, endpoint) {
|
|
|
169
169
|
if (endpoint.supportsCC(safe_1.CommandClasses["Multi Channel Association"])) {
|
|
170
170
|
mcInstance = MultiChannelAssociationCC_1.MultiChannelAssociationCC;
|
|
171
171
|
}
|
|
172
|
-
const assocGroupCount = assocInstance.getGroupCountCached(
|
|
173
|
-
|
|
172
|
+
const assocGroupCount = assocInstance.getGroupCountCached(ctx, endpoint)
|
|
173
|
+
?? 0;
|
|
174
|
+
const mcGroupCount = mcInstance?.getGroupCountCached(ctx, endpoint)
|
|
174
175
|
?? 0;
|
|
175
176
|
const groupCount = Math.max(assocGroupCount, mcGroupCount);
|
|
176
|
-
const deviceConfig =
|
|
177
|
+
const deviceConfig = ctx.getDeviceConfig?.(endpoint.nodeId);
|
|
177
178
|
const ret = new Map();
|
|
178
179
|
if (endpoint.supportsCC(safe_1.CommandClasses["Association Group Information"])) {
|
|
179
180
|
// We can read all information we need from the AGI CC
|
|
@@ -184,19 +185,19 @@ function getAssociationGroups(applHost, endpoint) {
|
|
|
184
185
|
ret.set(group, {
|
|
185
186
|
maxNodes: (multiChannel
|
|
186
187
|
? mcInstance
|
|
187
|
-
: assocInstance).getMaxNodesCached(
|
|
188
|
+
: assocInstance).getMaxNodesCached(ctx, endpoint, group) || 1,
|
|
188
189
|
// AGI implies Z-Wave+ where group 1 is the lifeline
|
|
189
190
|
isLifeline: group === 1,
|
|
190
191
|
label:
|
|
191
192
|
// prefer the configured label if we have one
|
|
192
193
|
assocConfig?.label
|
|
193
194
|
// the ones reported by AGI are sometimes pretty bad
|
|
194
|
-
?? agiInstance.getGroupNameCached(
|
|
195
|
+
?? agiInstance.getGroupNameCached(ctx, endpoint, group)
|
|
195
196
|
// but still better than "unnamed"
|
|
196
197
|
?? `Unnamed group ${group}`,
|
|
197
198
|
multiChannel,
|
|
198
|
-
profile: agiInstance.getGroupProfileCached(
|
|
199
|
-
issuedCommands: agiInstance.getIssuedCommandsCached(
|
|
199
|
+
profile: agiInstance.getGroupProfileCached(ctx, endpoint, group),
|
|
200
|
+
issuedCommands: agiInstance.getIssuedCommandsCached(ctx, endpoint, group),
|
|
200
201
|
});
|
|
201
202
|
}
|
|
202
203
|
}
|
|
@@ -208,7 +209,7 @@ function getAssociationGroups(applHost, endpoint) {
|
|
|
208
209
|
ret.set(group, {
|
|
209
210
|
maxNodes: (multiChannel
|
|
210
211
|
? mcInstance
|
|
211
|
-
: assocInstance).getMaxNodesCached(
|
|
212
|
+
: assocInstance).getMaxNodesCached(ctx, endpoint, group)
|
|
212
213
|
|| assocConfig?.maxNodes
|
|
213
214
|
|| 1,
|
|
214
215
|
isLifeline: assocConfig?.isLifeline ?? group === 1,
|
|
@@ -219,16 +220,16 @@ function getAssociationGroups(applHost, endpoint) {
|
|
|
219
220
|
}
|
|
220
221
|
return ret;
|
|
221
222
|
}
|
|
222
|
-
function getAllAssociationGroups(
|
|
223
|
+
function getAllAssociationGroups(ctx, node) {
|
|
223
224
|
const ret = new Map();
|
|
224
225
|
for (const endpoint of node.getAllEndpoints()) {
|
|
225
226
|
if (endpoint.supportsCC(safe_1.CommandClasses.Association)) {
|
|
226
|
-
ret.set(endpoint.index, getAssociationGroups(
|
|
227
|
+
ret.set(endpoint.index, getAssociationGroups(ctx, endpoint));
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
return ret;
|
|
230
231
|
}
|
|
231
|
-
async function addAssociations(
|
|
232
|
+
async function addAssociations(ctx, endpoint, group, destinations) {
|
|
232
233
|
const nodeAndEndpointString = `${endpoint.nodeId}${endpoint.index > 0 ? `, endpoint ${endpoint.index}` : ""}`;
|
|
233
234
|
// Check whether we should add any associations the device does not have support for
|
|
234
235
|
let assocInstance;
|
|
@@ -259,14 +260,15 @@ async function addAssociations(applHost, endpoint, group, destinations) {
|
|
|
259
260
|
checkResult: _Types_1.AssociationCheckResult.Forbidden_SelfAssociation,
|
|
260
261
|
})));
|
|
261
262
|
}
|
|
262
|
-
const assocGroupCount = assocInstance?.getGroupCountCached(
|
|
263
|
-
|
|
263
|
+
const assocGroupCount = assocInstance?.getGroupCountCached(ctx, endpoint)
|
|
264
|
+
?? 0;
|
|
265
|
+
const mcGroupCount = mcInstance?.getGroupCountCached(ctx, endpoint)
|
|
264
266
|
?? 0;
|
|
265
267
|
const groupCount = Math.max(assocGroupCount, mcGroupCount);
|
|
266
268
|
if (group > groupCount) {
|
|
267
269
|
throw new safe_1.ZWaveError(`Group ${group} does not exist on node ${nodeAndEndpointString}`, safe_1.ZWaveErrorCodes.AssociationCC_InvalidGroup);
|
|
268
270
|
}
|
|
269
|
-
const deviceConfig =
|
|
271
|
+
const deviceConfig = ctx.getDeviceConfig?.(endpoint.nodeId);
|
|
270
272
|
const groupIsMultiChannel = !!mcInstance
|
|
271
273
|
&& group <= mcGroupCount
|
|
272
274
|
&& deviceConfig?.associations?.get(group)?.multiChannel !== false;
|
|
@@ -274,7 +276,7 @@ async function addAssociations(applHost, endpoint, group, destinations) {
|
|
|
274
276
|
// Check that all associations are allowed
|
|
275
277
|
const disallowedAssociations = destinations.map((a) => ({
|
|
276
278
|
...a,
|
|
277
|
-
checkResult: checkAssociation(
|
|
279
|
+
checkResult: checkAssociation(ctx, endpoint, group, a),
|
|
278
280
|
})).filter(({ checkResult }) => checkResult !== _Types_1.AssociationCheckResult.OK);
|
|
279
281
|
if (disallowedAssociations.length) {
|
|
280
282
|
let message = `The following associations are not allowed:`;
|
|
@@ -284,7 +286,7 @@ async function addAssociations(applHost, endpoint, group, destinations) {
|
|
|
284
286
|
throw new safe_1.ZWaveError(message, safe_1.ZWaveErrorCodes.AssociationCC_NotAllowed, disallowedAssociations);
|
|
285
287
|
}
|
|
286
288
|
// And add them
|
|
287
|
-
const api = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"],
|
|
289
|
+
const api = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"], ctx, endpoint);
|
|
288
290
|
await api.addDestinations({
|
|
289
291
|
groupId: group,
|
|
290
292
|
nodeIds: nodeAssociations,
|
|
@@ -301,7 +303,7 @@ async function addAssociations(applHost, endpoint, group, destinations) {
|
|
|
301
303
|
// Check that all associations are allowed
|
|
302
304
|
const disallowedAssociations = destinations.map((a) => ({
|
|
303
305
|
...a,
|
|
304
|
-
checkResult: checkAssociation(
|
|
306
|
+
checkResult: checkAssociation(ctx, endpoint, group, a),
|
|
305
307
|
})).filter(({ checkResult }) => checkResult !== _Types_1.AssociationCheckResult.OK);
|
|
306
308
|
if (disallowedAssociations.length) {
|
|
307
309
|
let message = `The associations to the following nodes are not allowed`;
|
|
@@ -310,13 +312,13 @@ async function addAssociations(applHost, endpoint, group, destinations) {
|
|
|
310
312
|
.join("");
|
|
311
313
|
throw new safe_1.ZWaveError(message, safe_1.ZWaveErrorCodes.AssociationCC_NotAllowed, disallowedAssociations);
|
|
312
314
|
}
|
|
313
|
-
const api = API_1.CCAPI.create(safe_1.CommandClasses.Association,
|
|
315
|
+
const api = API_1.CCAPI.create(safe_1.CommandClasses.Association, ctx, endpoint);
|
|
314
316
|
await api.addNodeIds(group, ...destinations.map((a) => a.nodeId));
|
|
315
317
|
// Refresh the association list
|
|
316
318
|
await api.getGroup(group);
|
|
317
319
|
}
|
|
318
320
|
}
|
|
319
|
-
async function removeAssociations(
|
|
321
|
+
async function removeAssociations(ctx, endpoint, group, destinations) {
|
|
320
322
|
const nodeAndEndpointString = `${endpoint.nodeId}${endpoint.index > 0 ? `, endpoint ${endpoint.index}` : ""}`;
|
|
321
323
|
// Split associations into conventional and endpoint associations
|
|
322
324
|
const nodeAssociations = (0, arrays_1.distinct)(destinations
|
|
@@ -334,7 +336,7 @@ async function removeAssociations(applHost, endpoint, group, destinations) {
|
|
|
334
336
|
// and the node supports multi channel associations
|
|
335
337
|
if (endpoint.supportsCC(safe_1.CommandClasses["Multi Channel Association"])) {
|
|
336
338
|
mcInstance = MultiChannelAssociationCC_1.MultiChannelAssociationCC;
|
|
337
|
-
if (group <= mcInstance.getGroupCountCached(
|
|
339
|
+
if (group <= mcInstance.getGroupCountCached(ctx, endpoint)) {
|
|
338
340
|
groupExistsAsMultiChannel = true;
|
|
339
341
|
}
|
|
340
342
|
}
|
|
@@ -345,7 +347,7 @@ async function removeAssociations(applHost, endpoint, group, destinations) {
|
|
|
345
347
|
// or as a multi channel association
|
|
346
348
|
if (endpoint.supportsCC(safe_1.CommandClasses.Association)) {
|
|
347
349
|
assocInstance = AssociationCC_1.AssociationCC;
|
|
348
|
-
if (group <= assocInstance.getGroupCountCached(
|
|
350
|
+
if (group <= assocInstance.getGroupCountCached(ctx, endpoint)) {
|
|
349
351
|
groupExistsAsNodeAssociation = true;
|
|
350
352
|
}
|
|
351
353
|
}
|
|
@@ -364,7 +366,7 @@ async function removeAssociations(applHost, endpoint, group, destinations) {
|
|
|
364
366
|
if (assocInstance
|
|
365
367
|
&& nodeAssociations.length > 0
|
|
366
368
|
&& groupExistsAsNodeAssociation) {
|
|
367
|
-
const api = API_1.CCAPI.create(safe_1.CommandClasses.Association,
|
|
369
|
+
const api = API_1.CCAPI.create(safe_1.CommandClasses.Association, ctx, endpoint);
|
|
368
370
|
await api.removeNodeIds({
|
|
369
371
|
groupId: group,
|
|
370
372
|
nodeIds: nodeAssociations,
|
|
@@ -373,7 +375,7 @@ async function removeAssociations(applHost, endpoint, group, destinations) {
|
|
|
373
375
|
await api.getGroup(group);
|
|
374
376
|
}
|
|
375
377
|
if (mcInstance && groupExistsAsMultiChannel) {
|
|
376
|
-
const api = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"],
|
|
378
|
+
const api = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"], ctx, endpoint);
|
|
377
379
|
await api.removeDestinations({
|
|
378
380
|
groupId: group,
|
|
379
381
|
nodeIds: nodeAssociations,
|
|
@@ -383,11 +385,10 @@ async function removeAssociations(applHost, endpoint, group, destinations) {
|
|
|
383
385
|
await api.getGroup(group);
|
|
384
386
|
}
|
|
385
387
|
}
|
|
386
|
-
function getLifelineGroupIds(
|
|
388
|
+
function getLifelineGroupIds(ctx, endpoint) {
|
|
387
389
|
// For now only support this for the root endpoint - i.e. node
|
|
388
390
|
if (endpoint.index > 0)
|
|
389
391
|
return [];
|
|
390
|
-
const node = endpoint;
|
|
391
392
|
// Some nodes define multiple lifeline groups, so we need to assign us to
|
|
392
393
|
// all of them
|
|
393
394
|
const lifelineGroups = [];
|
|
@@ -397,7 +398,7 @@ function getLifelineGroupIds(applHost, endpoint) {
|
|
|
397
398
|
}
|
|
398
399
|
// We have a device config file that tells us which (additional) association to assign
|
|
399
400
|
let associations;
|
|
400
|
-
const deviceConfig =
|
|
401
|
+
const deviceConfig = ctx.getDeviceConfig?.(endpoint.nodeId);
|
|
401
402
|
if (endpoint.index === 0) {
|
|
402
403
|
// The root endpoint's associations may be configured separately or as part of "endpoints"
|
|
403
404
|
associations = deviceConfig?.associations
|
|
@@ -414,31 +415,31 @@ function getLifelineGroupIds(applHost, endpoint) {
|
|
|
414
415
|
}
|
|
415
416
|
return (0, arrays_1.distinct)(lifelineGroups).sort();
|
|
416
417
|
}
|
|
417
|
-
async function configureLifelineAssociations(
|
|
418
|
+
async function configureLifelineAssociations(ctx, endpoint) {
|
|
418
419
|
// Assign the controller to all lifeline groups
|
|
419
|
-
const ownNodeId =
|
|
420
|
-
const node = endpoint.
|
|
421
|
-
const valueDB =
|
|
422
|
-
const deviceConfig =
|
|
420
|
+
const ownNodeId = ctx.ownNodeId;
|
|
421
|
+
const node = ctx.getNodeOrThrow(endpoint.nodeId);
|
|
422
|
+
const valueDB = ctx.getValueDB(node.id);
|
|
423
|
+
const deviceConfig = ctx.getDeviceConfig?.(node.id);
|
|
423
424
|
// We check if a node supports Multi Channel CC before creating Multi Channel Lifeline Associations (#1109)
|
|
424
425
|
const nodeSupportsMultiChannel = node.supportsCC(safe_1.CommandClasses["Multi Channel"]);
|
|
425
426
|
let assocInstance;
|
|
426
|
-
const assocAPI = API_1.CCAPI.create(safe_1.CommandClasses.Association,
|
|
427
|
+
const assocAPI = API_1.CCAPI.create(safe_1.CommandClasses.Association, ctx, endpoint);
|
|
427
428
|
if (endpoint.supportsCC(safe_1.CommandClasses.Association)) {
|
|
428
429
|
assocInstance = AssociationCC_1.AssociationCC;
|
|
429
430
|
}
|
|
430
431
|
let mcInstance;
|
|
431
432
|
let mcGroupCount = 0;
|
|
432
|
-
const mcAPI = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"],
|
|
433
|
+
const mcAPI = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"], ctx, endpoint);
|
|
433
434
|
if (endpoint.supportsCC(safe_1.CommandClasses["Multi Channel Association"])) {
|
|
434
435
|
mcInstance = MultiChannelAssociationCC_1.MultiChannelAssociationCC;
|
|
435
|
-
mcGroupCount = mcInstance.getGroupCountCached(
|
|
436
|
+
mcGroupCount = mcInstance.getGroupCountCached(ctx, endpoint) ?? 0;
|
|
436
437
|
}
|
|
437
|
-
const lifelineGroups = getLifelineGroupIds(
|
|
438
|
+
const lifelineGroups = getLifelineGroupIds(ctx, node);
|
|
438
439
|
if (lifelineGroups.length === 0) {
|
|
439
440
|
// We can look for the General Lifeline AGI profile as a last resort
|
|
440
441
|
if (endpoint.supportsCC(safe_1.CommandClasses["Association Group Information"])) {
|
|
441
|
-
const agiAPI = API_1.CCAPI.create(safe_1.CommandClasses["Association Group Information"],
|
|
442
|
+
const agiAPI = API_1.CCAPI.create(safe_1.CommandClasses["Association Group Information"], ctx, endpoint);
|
|
442
443
|
// The lifeline MUST be group 1
|
|
443
444
|
const lifeline = await agiAPI
|
|
444
445
|
.getGroupInfo(1, true)
|
|
@@ -450,7 +451,7 @@ async function configureLifelineAssociations(applHost, endpoint) {
|
|
|
450
451
|
}
|
|
451
452
|
}
|
|
452
453
|
if (lifelineGroups.length === 0) {
|
|
453
|
-
|
|
454
|
+
ctx.logNode(node.id, {
|
|
454
455
|
endpoint: endpoint.index,
|
|
455
456
|
message: "No information about Lifeline associations, cannot assign ourselves!",
|
|
456
457
|
level: "warn",
|
|
@@ -459,7 +460,7 @@ async function configureLifelineAssociations(applHost, endpoint) {
|
|
|
459
460
|
valueDB.setValue(AssociationCC_1.AssociationCCValues.hasLifeline.endpoint(endpoint.index), false);
|
|
460
461
|
return;
|
|
461
462
|
}
|
|
462
|
-
|
|
463
|
+
ctx.logNode(node.id, {
|
|
463
464
|
endpoint: endpoint.index,
|
|
464
465
|
message: `Checking/assigning lifeline groups: ${lifelineGroups.join(", ")}
|
|
465
466
|
supports classic associations: ${!!assocInstance}
|
|
@@ -489,7 +490,7 @@ supports multi channel associations: ${!!mcInstance}`,
|
|
|
489
490
|
}
|
|
490
491
|
}
|
|
491
492
|
}
|
|
492
|
-
|
|
493
|
+
ctx.logNode(node.id, {
|
|
493
494
|
endpoint: endpoint.index,
|
|
494
495
|
message: `Configuring lifeline group #${group}:
|
|
495
496
|
group supports multi channel: ${groupSupportsMultiChannelAssociation}
|
|
@@ -502,10 +503,10 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
502
503
|
if (groupSupportsMultiChannelAssociation && mcInstance) {
|
|
503
504
|
if (
|
|
504
505
|
// Only consider a group if it doesn't share its associations with the root endpoint
|
|
505
|
-
mcInstance.getMaxNodesCached(
|
|
506
|
+
mcInstance.getMaxNodesCached(ctx, endpoint, group)
|
|
506
507
|
> 0
|
|
507
508
|
&& !!mcInstance
|
|
508
|
-
.getAllDestinationsCached(
|
|
509
|
+
.getAllDestinationsCached(ctx, endpoint)
|
|
509
510
|
.get(group)
|
|
510
511
|
?.some((addr) => addr.nodeId === ownNodeId
|
|
511
512
|
&& addr.endpoint == undefined)) {
|
|
@@ -515,10 +516,10 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
515
516
|
if (assocInstance) {
|
|
516
517
|
if (
|
|
517
518
|
// Only consider a group if it doesn't share its associations with the root endpoint
|
|
518
|
-
assocInstance.getMaxNodesCached(
|
|
519
|
+
assocInstance.getMaxNodesCached(ctx, endpoint, group)
|
|
519
520
|
> 0
|
|
520
521
|
&& !!assocInstance
|
|
521
|
-
.getAllDestinationsCached(
|
|
522
|
+
.getAllDestinationsCached(ctx, endpoint)
|
|
522
523
|
.get(group)
|
|
523
524
|
?.some((addr) => addr.nodeId === ownNodeId)) {
|
|
524
525
|
return true;
|
|
@@ -530,10 +531,10 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
530
531
|
if (mcInstance) {
|
|
531
532
|
if (
|
|
532
533
|
// Only consider a group if it doesn't share its associations with the root endpoint
|
|
533
|
-
mcInstance.getMaxNodesCached(
|
|
534
|
+
mcInstance.getMaxNodesCached(ctx, endpoint, group)
|
|
534
535
|
> 0
|
|
535
536
|
&& mcInstance
|
|
536
|
-
.getAllDestinationsCached(
|
|
537
|
+
.getAllDestinationsCached(ctx, endpoint)
|
|
537
538
|
.get(group)
|
|
538
539
|
?.some((addr) => addr.nodeId === ownNodeId
|
|
539
540
|
&& addr.endpoint === 0)) {
|
|
@@ -545,7 +546,7 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
545
546
|
// If the node was used with other controller software, there might be
|
|
546
547
|
// invalid lifeline associations which cause reporting problems
|
|
547
548
|
const invalidEndpointAssociations = mcInstance
|
|
548
|
-
?.getAllDestinationsCached(
|
|
549
|
+
?.getAllDestinationsCached(ctx, endpoint)
|
|
549
550
|
.get(group)
|
|
550
551
|
?.filter((addr) => addr.nodeId === ownNodeId
|
|
551
552
|
&& addr.endpoint != undefined
|
|
@@ -554,7 +555,7 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
554
555
|
if (invalidEndpointAssociations.length > 0
|
|
555
556
|
&& mcAPI.isSupported()
|
|
556
557
|
&& groupSupportsMultiChannelAssociation) {
|
|
557
|
-
|
|
558
|
+
ctx.logNode(node.id, {
|
|
558
559
|
endpoint: endpoint.index,
|
|
559
560
|
message: `Found invalid lifeline associations in group #${group}, removing them...`,
|
|
560
561
|
direction: "outbound",
|
|
@@ -582,7 +583,7 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
582
583
|
if (isAssignedAsNodeAssociation(endpoint)) {
|
|
583
584
|
// We already have the correct association
|
|
584
585
|
hasLifeline = true;
|
|
585
|
-
|
|
586
|
+
ctx.logNode(node.id, {
|
|
586
587
|
endpoint: endpoint.index,
|
|
587
588
|
message: `Lifeline group #${group} is already assigned with a node association`,
|
|
588
589
|
direction: "none",
|
|
@@ -590,10 +591,10 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
590
591
|
}
|
|
591
592
|
else if (assocAPI.isSupported()
|
|
592
593
|
// Some endpoint groups don't support having any destinations because they are shared with the root
|
|
593
|
-
&& assocInstance.getMaxNodesCached(
|
|
594
|
+
&& assocInstance.getMaxNodesCached(ctx, endpoint, group)
|
|
594
595
|
> 0) {
|
|
595
596
|
// We can use a node association, but first remove any possible endpoint associations
|
|
596
|
-
|
|
597
|
+
ctx.logNode(node.id, {
|
|
597
598
|
endpoint: endpoint.index,
|
|
598
599
|
message: `Assigning lifeline group #${group} with a node association via Association CC...`,
|
|
599
600
|
direction: "outbound",
|
|
@@ -612,14 +613,14 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
612
613
|
const groupReport = await assocAPI.getGroup(group);
|
|
613
614
|
hasLifeline = !!groupReport?.nodeIds.includes(ownNodeId);
|
|
614
615
|
if (hasLifeline) {
|
|
615
|
-
|
|
616
|
+
ctx.logNode(node.id, {
|
|
616
617
|
endpoint: endpoint.index,
|
|
617
618
|
message: `Lifeline group #${group} was assigned with a node association via Association CC`,
|
|
618
619
|
direction: "none",
|
|
619
620
|
});
|
|
620
621
|
}
|
|
621
622
|
else {
|
|
622
|
-
|
|
623
|
+
ctx.logNode(node.id, {
|
|
623
624
|
endpoint: endpoint.index,
|
|
624
625
|
message: `Assigning lifeline group #${group} with a node association via Association CC did not work`,
|
|
625
626
|
direction: "none",
|
|
@@ -629,9 +630,9 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
629
630
|
// Second try: Node association using the Multi Channel Association CC
|
|
630
631
|
if (!hasLifeline
|
|
631
632
|
&& mcAPI.isSupported()
|
|
632
|
-
&& mcInstance.getMaxNodesCached(
|
|
633
|
+
&& mcInstance.getMaxNodesCached(ctx, endpoint, group) > 0) {
|
|
633
634
|
// We can use a node association, but first remove any possible endpoint associations
|
|
634
|
-
|
|
635
|
+
ctx.logNode(node.id, {
|
|
635
636
|
endpoint: endpoint.index,
|
|
636
637
|
message: `Assigning lifeline group #${group} with a node association via Multi Channel Association CC...`,
|
|
637
638
|
direction: "outbound",
|
|
@@ -650,14 +651,14 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
650
651
|
const groupReport = await mcAPI.getGroup(group);
|
|
651
652
|
hasLifeline = !!groupReport?.nodeIds.includes(ownNodeId);
|
|
652
653
|
if (hasLifeline) {
|
|
653
|
-
|
|
654
|
+
ctx.logNode(node.id, {
|
|
654
655
|
endpoint: endpoint.index,
|
|
655
656
|
message: `Lifeline group #${group} was assigned with a node association via Multi Channel Association CC`,
|
|
656
657
|
direction: "none",
|
|
657
658
|
});
|
|
658
659
|
}
|
|
659
660
|
else {
|
|
660
|
-
|
|
661
|
+
ctx.logNode(node.id, {
|
|
661
662
|
endpoint: endpoint.index,
|
|
662
663
|
message: `Assigning lifeline group #${group} with a node association via Multi Channel Association CC did not work`,
|
|
663
664
|
direction: "none",
|
|
@@ -671,7 +672,7 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
671
672
|
if (isAssignedAsEndpointAssociation(endpoint)) {
|
|
672
673
|
// We already have the correct association
|
|
673
674
|
hasLifeline = true;
|
|
674
|
-
|
|
675
|
+
ctx.logNode(node.id, {
|
|
675
676
|
endpoint: endpoint.index,
|
|
676
677
|
message: `Lifeline group #${group} is already assigned with an endpoint association`,
|
|
677
678
|
direction: "none",
|
|
@@ -679,9 +680,9 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
679
680
|
}
|
|
680
681
|
else if (mcAPI.isSupported()
|
|
681
682
|
&& mcAPI.version >= 3
|
|
682
|
-
&& mcInstance.getMaxNodesCached(
|
|
683
|
+
&& mcInstance.getMaxNodesCached(ctx, endpoint, group) > 0) {
|
|
683
684
|
// We can use a multi channel association, but first remove any possible node associations
|
|
684
|
-
|
|
685
|
+
ctx.logNode(node.id, {
|
|
685
686
|
endpoint: endpoint.index,
|
|
686
687
|
message: `Assigning lifeline group #${group} with a multi channel association...`,
|
|
687
688
|
direction: "outbound",
|
|
@@ -710,14 +711,14 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
710
711
|
const groupReport = await mcAPI.getGroup(group);
|
|
711
712
|
hasLifeline = !!groupReport?.endpoints.some((a) => a.nodeId === ownNodeId && a.endpoint === 0);
|
|
712
713
|
if (hasLifeline) {
|
|
713
|
-
|
|
714
|
+
ctx.logNode(node.id, {
|
|
714
715
|
endpoint: endpoint.index,
|
|
715
716
|
message: `Lifeline group #${group} was assigned with a multi channel association`,
|
|
716
717
|
direction: "none",
|
|
717
718
|
});
|
|
718
719
|
}
|
|
719
720
|
else {
|
|
720
|
-
|
|
721
|
+
ctx.logNode(node.id, {
|
|
721
722
|
endpoint: endpoint.index,
|
|
722
723
|
message: `Assigning lifeline group #${group} with a multi channel association did not work`,
|
|
723
724
|
direction: "none",
|
|
@@ -737,7 +738,7 @@ must use endpoint association: ${mustUseMultiChannelAssociation}`,
|
|
|
737
738
|
?.getAssociationConfigForEndpoint(0, group);
|
|
738
739
|
const rootMustUseNodeAssociation = !nodeSupportsMultiChannel
|
|
739
740
|
|| rootAssocConfig?.multiChannel === false;
|
|
740
|
-
|
|
741
|
+
ctx.logNode(node.id, {
|
|
741
742
|
endpoint: endpoint.index,
|
|
742
743
|
message: `Checking root device for fallback assignment of lifeline group #${group}:
|
|
743
744
|
root supports multi channel: ${nodeSupportsMultiChannel}
|
|
@@ -748,17 +749,17 @@ must use node association: ${rootMustUseNodeAssociation}`,
|
|
|
748
749
|
if (isAssignedAsEndpointAssociation(node)) {
|
|
749
750
|
// We already have the correct association
|
|
750
751
|
hasLifeline = true;
|
|
751
|
-
|
|
752
|
+
ctx.logNode(node.id, {
|
|
752
753
|
endpoint: endpoint.index,
|
|
753
754
|
message: `Lifeline group #${group} is already assigned with a multi channel association on the root device`,
|
|
754
755
|
direction: "none",
|
|
755
756
|
});
|
|
756
757
|
}
|
|
757
758
|
else {
|
|
758
|
-
const rootMCAPI = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"],
|
|
759
|
-
const rootAssocAPI = API_1.CCAPI.create(safe_1.CommandClasses.Association,
|
|
759
|
+
const rootMCAPI = API_1.CCAPI.create(safe_1.CommandClasses["Multi Channel Association"], ctx, node);
|
|
760
|
+
const rootAssocAPI = API_1.CCAPI.create(safe_1.CommandClasses.Association, ctx, node);
|
|
760
761
|
if (rootMCAPI.isSupported()) {
|
|
761
|
-
|
|
762
|
+
ctx.logNode(node.id, {
|
|
762
763
|
endpoint: endpoint.index,
|
|
763
764
|
message: `Assigning lifeline group #${group} with a multi channel association on the root device...`,
|
|
764
765
|
direction: "outbound",
|
|
@@ -792,7 +793,7 @@ must use node association: ${rootMustUseNodeAssociation}`,
|
|
|
792
793
|
}
|
|
793
794
|
}
|
|
794
795
|
if (!hasLifeline) {
|
|
795
|
-
|
|
796
|
+
ctx.logNode(node.id, {
|
|
796
797
|
endpoint: endpoint.index,
|
|
797
798
|
message: `All attempts to assign lifeline group #${group} failed, skipping...`,
|
|
798
799
|
direction: "none",
|
|
@@ -803,31 +804,32 @@ must use node association: ${rootMustUseNodeAssociation}`,
|
|
|
803
804
|
// Remember that we did the association assignment
|
|
804
805
|
valueDB.setValue(AssociationCC_1.AssociationCCValues.hasLifeline.endpoint(endpoint.index), true);
|
|
805
806
|
}
|
|
806
|
-
async function assignLifelineIssueingCommand(
|
|
807
|
-
const node = endpoint.
|
|
807
|
+
async function assignLifelineIssueingCommand(ctx, endpoint, ccId, ccCommand) {
|
|
808
|
+
const node = ctx.getNodeOrThrow(endpoint.nodeId);
|
|
808
809
|
if (node.supportsCC(safe_1.CommandClasses["Association Group Information"])
|
|
809
810
|
&& (node.supportsCC(safe_1.CommandClasses.Association)
|
|
810
811
|
|| node.supportsCC(safe_1.CommandClasses["Multi Channel Association"]))) {
|
|
811
812
|
const groupsIssueingNotifications = AssociationGroupInfoCC_1.AssociationGroupInfoCC
|
|
812
|
-
.findGroupsForIssuedCommand(
|
|
813
|
+
.findGroupsForIssuedCommand(ctx, node, ccId, ccCommand);
|
|
813
814
|
if (groupsIssueingNotifications.length > 0) {
|
|
814
815
|
// We always grab the first group - usually it should be the lifeline
|
|
815
816
|
const groupId = groupsIssueingNotifications[0];
|
|
816
|
-
const existingAssociations = getAssociations(
|
|
817
|
-
|
|
818
|
-
|
|
817
|
+
const existingAssociations = getAssociations(ctx, node).get(groupId)
|
|
818
|
+
?? [];
|
|
819
|
+
if (!existingAssociations.some((a) => a.nodeId === ctx.ownNodeId)) {
|
|
820
|
+
ctx.logNode(node.id, {
|
|
819
821
|
endpoint: endpoint.index,
|
|
820
822
|
message: `Configuring associations to receive ${(0, safe_1.getCCName)(ccId)} commands...`,
|
|
821
823
|
direction: "outbound",
|
|
822
824
|
});
|
|
823
|
-
await addAssociations(
|
|
824
|
-
{ nodeId:
|
|
825
|
+
await addAssociations(ctx, node, groupId, [
|
|
826
|
+
{ nodeId: ctx.ownNodeId },
|
|
825
827
|
]);
|
|
826
828
|
}
|
|
827
829
|
}
|
|
828
830
|
}
|
|
829
831
|
}
|
|
830
|
-
function doesAnyLifelineSendActuatorOrSensorReports(
|
|
832
|
+
function doesAnyLifelineSendActuatorOrSensorReports(ctx, node) {
|
|
831
833
|
// No association support means no unsolicited reports
|
|
832
834
|
if (!node.supportsCC(safe_1.CommandClasses.Association)
|
|
833
835
|
&& !node.supportsCC(safe_1.CommandClasses["Multi Channel Association"])) {
|
|
@@ -838,14 +840,14 @@ function doesAnyLifelineSendActuatorOrSensorReports(applHost, node) {
|
|
|
838
840
|
return safe_1.NOT_KNOWN;
|
|
839
841
|
}
|
|
840
842
|
// Lifeline group IDs include the ones we added via a config file, so they may not be considered true lifelines
|
|
841
|
-
const lifelineGroupIds = getLifelineGroupIds(
|
|
843
|
+
const lifelineGroupIds = getLifelineGroupIds(ctx, node);
|
|
842
844
|
// If any potential lifeline group has the "General: Lifeline" profile, the node MUST send unsolicited reports that way
|
|
843
|
-
if (lifelineGroupIds.some((id) => AssociationGroupInfoCC_1.AssociationGroupInfoCC.getGroupProfileCached(
|
|
845
|
+
if (lifelineGroupIds.some((id) => AssociationGroupInfoCC_1.AssociationGroupInfoCC.getGroupProfileCached(ctx, node, id) === _Types_1.AssociationGroupInfoProfile["General: Lifeline"])) {
|
|
844
846
|
return true;
|
|
845
847
|
}
|
|
846
848
|
// Otherwise check if any of the groups sends any actuator or sensor commands. We'll assume that those are reports
|
|
847
849
|
for (const groupId of lifelineGroupIds) {
|
|
848
|
-
const issuedCommands = AssociationGroupInfoCC_1.AssociationGroupInfoCC.getIssuedCommandsCached(
|
|
850
|
+
const issuedCommands = AssociationGroupInfoCC_1.AssociationGroupInfoCC.getIssuedCommandsCached(ctx, node, groupId);
|
|
849
851
|
if (!issuedCommands)
|
|
850
852
|
continue;
|
|
851
853
|
const commands = [...issuedCommands.keys()];
|