diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
index 728437e3b2c6fd..d774d02d7edf8a 100644
--- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
+++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter
@@ -1461,6 +1461,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
index de169f34582b4d..03153a971457cb 100644
--- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
+++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
@@ -1090,6 +1090,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/bridge-app/bridge-common/bridge-app.matter b/examples/bridge-app/bridge-common/bridge-app.matter
index 64b03dc44a04ff..f4572fce80c57a 100644
--- a/examples/bridge-app/bridge-common/bridge-app.matter
+++ b/examples/bridge-app/bridge-common/bridge-app.matter
@@ -415,6 +415,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter
index 5b089349467146..055f1a73ff67a2 100644
--- a/examples/light-switch-app/light-switch-common/light-switch-app.matter
+++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter
@@ -500,6 +500,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/lighting-app/lighting-common/lighting-app.matter b/examples/lighting-app/lighting-common/lighting-app.matter
index 2d2773162d0210..ef2f89ee2ef987 100644
--- a/examples/lighting-app/lighting-common/lighting-app.matter
+++ b/examples/lighting-app/lighting-common/lighting-app.matter
@@ -513,6 +513,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/lock-app/lock-common/lock-app.matter b/examples/lock-app/lock-common/lock-app.matter
index 5cd6c2ca19741e..d5bd0bf37b4c5f 100644
--- a/examples/lock-app/lock-common/lock-app.matter
+++ b/examples/lock-app/lock-common/lock-app.matter
@@ -822,6 +822,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/log-source-app/log-source-common/log-source-app.matter b/examples/log-source-app/log-source-common/log-source-app.matter
index 27160f8d1f08c7..df13f0c7ec186d 100644
--- a/examples/log-source-app/log-source-common/log-source-app.matter
+++ b/examples/log-source-app/log-source-common/log-source-app.matter
@@ -147,6 +147,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter
index aafc6c5134704b..e8b97b93ae88cf 100644
--- a/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter
+++ b/examples/ota-provider-app/ota-provider-common/ota-provider-app.matter
@@ -241,6 +241,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter
index 4364dd66e2926a..09184a341332a4 100644
--- a/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter
+++ b/examples/ota-requestor-app/ota-requestor-common/ota-requestor-app.matter
@@ -175,6 +175,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/placeholder/linux/apps/app1/config.matter b/examples/placeholder/linux/apps/app1/config.matter
index 832f9ca426152c..2d534e90856768 100644
--- a/examples/placeholder/linux/apps/app1/config.matter
+++ b/examples/placeholder/linux/apps/app1/config.matter
@@ -608,6 +608,7 @@ client cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
@@ -654,6 +655,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/placeholder/linux/apps/app2/config.matter b/examples/placeholder/linux/apps/app2/config.matter
index 832f9ca426152c..2d534e90856768 100644
--- a/examples/placeholder/linux/apps/app2/config.matter
+++ b/examples/placeholder/linux/apps/app2/config.matter
@@ -608,6 +608,7 @@ client cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
@@ -654,6 +655,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/pump-app/pump-common/pump-app.matter b/examples/pump-app/pump-common/pump-app.matter
index f9f71aafd60633..4e1febd4c9a69f 100644
--- a/examples/pump-app/pump-common/pump-app.matter
+++ b/examples/pump-app/pump-common/pump-app.matter
@@ -215,6 +215,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter
index bd4f0b6618d76a..5c9fd57944fd1b 100644
--- a/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter
+++ b/examples/pump-controller-app/pump-controller-common/pump-controller-app.matter
@@ -238,6 +238,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter b/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter
index 5a5c5da7c76e32..335c0909c0729b 100644
--- a/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter
+++ b/examples/temperature-measurement-app/esp32/main/temperature-measurement.matter
@@ -250,6 +250,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/thermostat/thermostat-common/thermostat.matter b/examples/thermostat/thermostat-common/thermostat.matter
index 6dcea48abc753b..a86aad69a981d9 100644
--- a/examples/thermostat/thermostat-common/thermostat.matter
+++ b/examples/thermostat/thermostat-common/thermostat.matter
@@ -262,6 +262,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/tv-app/tv-common/tv-app.matter b/examples/tv-app/tv-common/tv-app.matter
index 4759b9fbe1cfd9..7654b8170e0789 100644
--- a/examples/tv-app/tv-common/tv-app.matter
+++ b/examples/tv-app/tv-common/tv-app.matter
@@ -575,6 +575,7 @@ client cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
@@ -633,6 +634,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter
index b91d285c9f8c2e..5cf1206172b3b6 100644
--- a/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter
+++ b/examples/tv-casting-app/tv-casting-common/tv-casting-app.matter
@@ -555,6 +555,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/examples/window-app/common/window-app.matter b/examples/window-app/common/window-app.matter
index e60eb56acf245a..a867592109f8cd 100644
--- a/examples/window-app/common/window-app.matter
+++ b/examples/window-app/common/window-app.matter
@@ -227,6 +227,7 @@ server cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp
index 64aa0c9520954b..f86eecf51eea6e 100644
--- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp
+++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp
@@ -129,7 +129,10 @@ CHIP_ERROR GeneralCommissioningAttrAccess::ReadBasicCommissioningInfo(AttributeV
// TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize
// the CommissioningParameters at the beginning of commissioning flow.
- basicCommissioningInfo.failSafeExpiryLengthSeconds = CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC;
+ basicCommissioningInfo.failSafeExpiryLengthSeconds = CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC;
+ basicCommissioningInfo.maxCumulativeFailsafeSeconds = CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC;
+ static_assert(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC >= CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC,
+ "Max cumulative failsafe seconds must be larger than failsafe expiry length seconds");
return aEncoder.Encode(basicCommissioningInfo);
}
@@ -140,7 +143,7 @@ CHIP_ERROR GeneralCommissioningAttrAccess::ReadSupportsConcurrentConnection(Attr
// TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize
// the CommissioningParameters at the beginning of commissioning flow.
- supportsConcurrentConnection = (CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC) != 0;
+ supportsConcurrentConnection = (CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION) != 0;
return aEncoder.Encode(supportsConcurrentConnection);
}
diff --git a/src/app/tests/suites/certification/Test_TC_CGEN_2_1.yaml b/src/app/tests/suites/certification/Test_TC_CGEN_2_1.yaml
index 97ce7e6e23a017..22ad7b6b227053 100644
--- a/src/app/tests/suites/certification/Test_TC_CGEN_2_1.yaml
+++ b/src/app/tests/suites/certification/Test_TC_CGEN_2_1.yaml
@@ -71,4 +71,8 @@ tests:
command: "readAttribute"
attribute: "BasicCommissioningInfo"
response:
- value: { FailSafeExpiryLengthSeconds: 60 }
+ value:
+ {
+ FailSafeExpiryLengthSeconds: 60,
+ MaxCumulativeFailsafeSeconds: 900,
+ }
diff --git a/src/app/zap-templates/zcl/data-model/chip/general-commissioning-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/general-commissioning-cluster.xml
index eb1006294b7db2..0d913e68dc9653 100644
--- a/src/app/zap-templates/zcl/data-model/chip/general-commissioning-cluster.xml
+++ b/src/app/zap-templates/zcl/data-model/chip/general-commissioning-cluster.xml
@@ -32,7 +32,8 @@ limitations under the License.
-
+
+
General
diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter
index 955a9825ea593e..5eed4607ec1fbb 100644
--- a/src/controller/data_model/controller-clusters.matter
+++ b/src/controller/data_model/controller-clusters.matter
@@ -1811,6 +1811,7 @@ client cluster GeneralCommissioning = 48 {
struct BasicCommissioningInfo {
int16u failSafeExpiryLengthSeconds = 0;
+ int16u maxCumulativeFailsafeSeconds = 1;
}
attribute access(write: administer) int64u breadcrumb = 0;
diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
index 0df4dd0bdbacdf..6a9db8dfb84e5a 100644
--- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
+++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
@@ -6508,6 +6508,12 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR
chip::JniReferences::GetInstance().CreateBoxedObject(
value_failSafeExpiryLengthSecondsClassName.c_str(), value_failSafeExpiryLengthSecondsCtorSignature.c_str(),
cppValue.failSafeExpiryLengthSeconds, value_failSafeExpiryLengthSeconds);
+ jobject value_maxCumulativeFailsafeSeconds;
+ std::string value_maxCumulativeFailsafeSecondsClassName = "java/lang/Integer";
+ std::string value_maxCumulativeFailsafeSecondsCtorSignature = "(I)V";
+ chip::JniReferences::GetInstance().CreateBoxedObject(
+ value_maxCumulativeFailsafeSecondsClassName.c_str(), value_maxCumulativeFailsafeSecondsCtorSignature.c_str(),
+ cppValue.maxCumulativeFailsafeSeconds, value_maxCumulativeFailsafeSeconds);
jclass basicCommissioningInfoStructClass;
err = chip::JniReferences::GetInstance().GetClassRef(
@@ -6519,7 +6525,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR
return nullptr;
}
jmethodID basicCommissioningInfoStructCtor =
- env->GetMethodID(basicCommissioningInfoStructClass, "", "(Ljava/lang/Integer;)V");
+ env->GetMethodID(basicCommissioningInfoStructClass, "", "(Ljava/lang/Integer;Ljava/lang/Integer;)V");
if (basicCommissioningInfoStructCtor == nullptr)
{
ChipLogError(Zcl, "Could not find ChipStructs$GeneralCommissioningClusterBasicCommissioningInfo constructor");
@@ -6527,7 +6533,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR
}
value = env->NewObject(basicCommissioningInfoStructClass, basicCommissioningInfoStructCtor,
- value_failSafeExpiryLengthSeconds);
+ value_failSafeExpiryLengthSeconds, value_maxCumulativeFailsafeSeconds);
return value;
}
case Attributes::RegulatoryConfig::Id: {
diff --git a/src/controller/java/zap-generated/chip/devicecontroller/ChipStructs.java b/src/controller/java/zap-generated/chip/devicecontroller/ChipStructs.java
index 4affe8b8bd6946..9d8a6817b40d2e 100644
--- a/src/controller/java/zap-generated/chip/devicecontroller/ChipStructs.java
+++ b/src/controller/java/zap-generated/chip/devicecontroller/ChipStructs.java
@@ -722,9 +722,12 @@ public String toString() {
public static class GeneralCommissioningClusterBasicCommissioningInfo {
public Integer failSafeExpiryLengthSeconds;
+ public Integer maxCumulativeFailsafeSeconds;
- public GeneralCommissioningClusterBasicCommissioningInfo(Integer failSafeExpiryLengthSeconds) {
+ public GeneralCommissioningClusterBasicCommissioningInfo(
+ Integer failSafeExpiryLengthSeconds, Integer maxCumulativeFailsafeSeconds) {
this.failSafeExpiryLengthSeconds = failSafeExpiryLengthSeconds;
+ this.maxCumulativeFailsafeSeconds = maxCumulativeFailsafeSeconds;
}
@Override
@@ -734,6 +737,9 @@ public String toString() {
output.append("\tfailSafeExpiryLengthSeconds: ");
output.append(failSafeExpiryLengthSeconds);
output.append("\n");
+ output.append("\tmaxCumulativeFailsafeSeconds: ");
+ output.append(maxCumulativeFailsafeSeconds);
+ output.append("\n");
output.append("}\n");
return output.toString();
}
diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py
index 4671cffdbd430e..db8c72de63c343 100644
--- a/src/controller/python/chip/clusters/Objects.py
+++ b/src/controller/python/chip/clusters/Objects.py
@@ -9306,9 +9306,11 @@ def descriptor(cls) -> ClusterObjectDescriptor:
return ClusterObjectDescriptor(
Fields = [
ClusterObjectFieldDescriptor(Label="failSafeExpiryLengthSeconds", Tag=0, Type=uint),
+ ClusterObjectFieldDescriptor(Label="maxCumulativeFailsafeSeconds", Tag=1, Type=uint),
])
failSafeExpiryLengthSeconds: 'uint' = 0
+ maxCumulativeFailsafeSeconds: 'uint' = 0
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm
index 98b0a58b532c52..f784bf3cc356bb 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPAttributeTLVValueDecoder.mm
@@ -6815,6 +6815,7 @@ id CHIPDecodeAttributeValue(const ConcreteAttributePath & aPath, TLV::TLVReader
CHIPGeneralCommissioningClusterBasicCommissioningInfo * _Nonnull value;
value = [CHIPGeneralCommissioningClusterBasicCommissioningInfo new];
value.failSafeExpiryLengthSeconds = [NSNumber numberWithUnsignedShort:cppValue.failSafeExpiryLengthSeconds];
+ value.maxCumulativeFailsafeSeconds = [NSNumber numberWithUnsignedShort:cppValue.maxCumulativeFailsafeSeconds];
return value;
}
case Attributes::RegulatoryConfig::Id: {
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm
index d6862c8a24b0c5..de5dcf7ddd2a57 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPCallbackBridge.mm
@@ -4569,6 +4569,7 @@
CHIPGeneralCommissioningClusterBasicCommissioningInfo * _Nonnull objCValue;
objCValue = [CHIPGeneralCommissioningClusterBasicCommissioningInfo new];
objCValue.failSafeExpiryLengthSeconds = [NSNumber numberWithUnsignedShort:value.failSafeExpiryLengthSeconds];
+ objCValue.maxCumulativeFailsafeSeconds = [NSNumber numberWithUnsignedShort:value.maxCumulativeFailsafeSeconds];
DispatchSuccess(context, objCValue);
};
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.h
index c92fd3dd0554c9..7ddfd47e1191ee 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.h
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.h
@@ -210,6 +210,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface CHIPGeneralCommissioningClusterBasicCommissioningInfo : NSObject
@property (strong, nonatomic) NSNumber * _Nonnull failSafeExpiryLengthSeconds;
+@property (strong, nonatomic) NSNumber * _Nonnull maxCumulativeFailsafeSeconds;
- (instancetype)init;
@end
diff --git a/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.mm
index 1ba999b68586a1..b48612737d31ba 100644
--- a/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/CHIPStructsObjc.mm
@@ -677,14 +677,17 @@ - (instancetype)init
if (self = [super init]) {
_failSafeExpiryLengthSeconds = @(0);
+
+ _maxCumulativeFailsafeSeconds = @(0);
}
return self;
}
- (NSString *)description
{
- NSString * descriptionString = [NSString
- stringWithFormat:@"<%@: failSafeExpiryLengthSeconds:%@; >", NSStringFromClass([self class]), _failSafeExpiryLengthSeconds];
+ NSString * descriptionString =
+ [NSString stringWithFormat:@"<%@: failSafeExpiryLengthSeconds:%@; maxCumulativeFailsafeSeconds:%@; >",
+ NSStringFromClass([self class]), _failSafeExpiryLengthSeconds, _maxCumulativeFailsafeSeconds];
return descriptionString;
}
diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h
index 286efee3a7c1a2..1ec81fdc5e5bfd 100644
--- a/src/include/platform/CHIPDeviceConfig.h
+++ b/src/include/platform/CHIPDeviceConfig.h
@@ -257,6 +257,16 @@
#define CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC 60
#endif // CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC
+/**
+ * CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC
+ *
+ * The default conservative value in seconds denoting the maximum total duration for which a fail safe
+ * timer can be re-armed.
+ */
+#ifndef CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC
+#define CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC 900
+#endif // CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC
+
/**
* CHIP_DEVICE_CONFIG_SUPPORTS_CONCURRENT_CONNECTION
*
diff --git a/src/include/platform/FailSafeContext.h b/src/include/platform/FailSafeContext.h
index ce7a3300efd97e..1af60d71a21a37 100644
--- a/src/include/platform/FailSafeContext.h
+++ b/src/include/platform/FailSafeContext.h
@@ -116,6 +116,12 @@ class FailSafeContext
*/
static void HandleArmFailSafeTimer(System::Layer * layer, void * aAppState);
+ /**
+ * @brief
+ * The callback function to be called when max cumulative time expires.
+ */
+ static void HandleMaxCumulativeFailSafeTimer(System::Layer * layer, void * aAppState);
+
/**
* @brief
* The callback function to be called asynchronously after various cleanup work has completed
diff --git a/src/platform/FailSafeContext.cpp b/src/platform/FailSafeContext.cpp
index 6bb4a0c3d19b9f..376881b05fab51 100644
--- a/src/platform/FailSafeContext.cpp
+++ b/src/platform/FailSafeContext.cpp
@@ -41,6 +41,12 @@ void FailSafeContext::HandleArmFailSafeTimer(System::Layer * layer, void * aAppS
failSafeContext->FailSafeTimerExpired();
}
+void FailSafeContext::HandleMaxCumulativeFailSafeTimer(System::Layer * layer, void * aAppState)
+{
+ FailSafeContext * failSafeContext = reinterpret_cast(aAppState);
+ failSafeContext->FailSafeTimerExpired();
+}
+
void FailSafeContext::HandleDisarmFailSafe(intptr_t arg)
{
FailSafeContext * failSafeContext = reinterpret_cast(arg);
@@ -85,19 +91,36 @@ void FailSafeContext::ScheduleFailSafeCleanup(FabricIndex fabricIndex, bool addN
CHIP_ERROR FailSafeContext::ArmFailSafe(FabricIndex accessingFabricIndex, System::Clock::Timeout expiryLength)
{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+ bool cancelTimersIfError = false;
+ if (!mFailSafeArmed)
+ {
+ System::Clock::Timeout maxCumulativeTimeout = System::Clock::Seconds32(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC);
+ SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(maxCumulativeTimeout, HandleMaxCumulativeFailSafeTimer, this));
+ cancelTimersIfError = true;
+ }
+
+ SuccessOrExit(err = DeviceLayer::SystemLayer().StartTimer(expiryLength, HandleArmFailSafeTimer, this));
+ SuccessOrExit(err = CommitToStorage());
+ SuccessOrExit(err = ConfigurationMgr().SetFailSafeArmed(true));
+
mFailSafeArmed = true;
mFabricIndex = accessingFabricIndex;
- ReturnErrorOnFailure(DeviceLayer::SystemLayer().StartTimer(expiryLength, HandleArmFailSafeTimer, this));
- ReturnErrorOnFailure(CommitToStorage());
- ReturnErrorOnFailure(ConfigurationMgr().SetFailSafeArmed(true));
+exit:
- return CHIP_NO_ERROR;
+ if (err != CHIP_NO_ERROR && cancelTimersIfError)
+ {
+ DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
+ DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
+ }
+ return err;
}
void FailSafeContext::DisarmFailSafe()
{
DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
+ DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
ResetState();
@@ -200,6 +223,7 @@ void FailSafeContext::ForceFailSafeTimerExpiry()
// Cancel the timer since we force its action
DeviceLayer::SystemLayer().CancelTimer(HandleArmFailSafeTimer, this);
+ DeviceLayer::SystemLayer().CancelTimer(HandleMaxCumulativeFailSafeTimer, this);
FailSafeTimerExpired();
}
diff --git a/zzz_generated/app-common/app-common/zap-generated/af-structs.h b/zzz_generated/app-common/app-common/zap-generated/af-structs.h
index a1f08695b65e13..63d56c9b1c21c2 100644
--- a/zzz_generated/app-common/app-common/zap-generated/af-structs.h
+++ b/zzz_generated/app-common/app-common/zap-generated/af-structs.h
@@ -230,6 +230,7 @@ typedef struct _ApplicationBasicApplication
typedef struct _BasicCommissioningInfo
{
uint16_t FailSafeExpiryLengthSeconds;
+ uint16_t MaxCumulativeFailsafeSeconds;
} BasicCommissioningInfo;
// Struct for BatChargeFaultChangeType
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
index 033396bf54cd60..96350ecdc42032 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp
@@ -7536,6 +7536,8 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & writer, TLV::Tag tag) const
ReturnErrorOnFailure(writer.StartContainer(tag, TLV::kTLVType_Structure, outer));
ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kFailSafeExpiryLengthSeconds)),
failSafeExpiryLengthSeconds));
+ ReturnErrorOnFailure(DataModel::Encode(writer, TLV::ContextTag(to_underlying(Fields::kMaxCumulativeFailsafeSeconds)),
+ maxCumulativeFailsafeSeconds));
ReturnErrorOnFailure(writer.EndContainer(outer));
return CHIP_NO_ERROR;
}
@@ -7558,6 +7560,9 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader)
case to_underlying(Fields::kFailSafeExpiryLengthSeconds):
ReturnErrorOnFailure(DataModel::Decode(reader, failSafeExpiryLengthSeconds));
break;
+ case to_underlying(Fields::kMaxCumulativeFailsafeSeconds):
+ ReturnErrorOnFailure(DataModel::Decode(reader, maxCumulativeFailsafeSeconds));
+ break;
default:
break;
}
diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
index e2cd041e6e6ffb..fbcc15db54da6a 100644
--- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
+++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h
@@ -9596,13 +9596,15 @@ namespace Structs {
namespace BasicCommissioningInfo {
enum class Fields
{
- kFailSafeExpiryLengthSeconds = 0,
+ kFailSafeExpiryLengthSeconds = 0,
+ kMaxCumulativeFailsafeSeconds = 1,
};
struct Type
{
public:
- uint16_t failSafeExpiryLengthSeconds = static_cast(0);
+ uint16_t failSafeExpiryLengthSeconds = static_cast(0);
+ uint16_t maxCumulativeFailsafeSeconds = static_cast(0);
CHIP_ERROR Decode(TLV::TLVReader & reader);
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp
index b3fe22bc7ed722..cf421bbc12b938 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp
+++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp
@@ -249,18 +249,26 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label,
ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("BasicCommissioningInfo.failSafeExpiryLengthSeconds",
"failSafeExpiryLengthSeconds",
value.isMember("failSafeExpiryLengthSeconds")));
+ ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("BasicCommissioningInfo.maxCumulativeFailsafeSeconds",
+ "maxCumulativeFailsafeSeconds",
+ value.isMember("maxCumulativeFailsafeSeconds")));
char labelWithMember[kMaxLabelLength];
snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "failSafeExpiryLengthSeconds");
ReturnErrorOnFailure(
ComplexArgumentParser::Setup(labelWithMember, request.failSafeExpiryLengthSeconds, value["failSafeExpiryLengthSeconds"]));
+ snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "maxCumulativeFailsafeSeconds");
+ ReturnErrorOnFailure(
+ ComplexArgumentParser::Setup(labelWithMember, request.maxCumulativeFailsafeSeconds, value["maxCumulativeFailsafeSeconds"]));
+
return CHIP_NO_ERROR;
}
void ComplexArgumentParser::Finalize(chip::app::Clusters::GeneralCommissioning::Structs::BasicCommissioningInfo::Type & request)
{
ComplexArgumentParser::Finalize(request.failSafeExpiryLengthSeconds);
+ ComplexArgumentParser::Finalize(request.maxCumulativeFailsafeSeconds);
}
CHIP_ERROR ComplexArgumentParser::Setup(const char * label,
chip::app::Clusters::PowerSource::Structs::BatChargeFaultChangeType::Type & request,
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
index 437372a39a1745..23e44936358f23 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
+++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
@@ -259,6 +259,14 @@ DataModelLogger::LogValue(const char * label, size_t indent,
return err;
}
}
+ {
+ CHIP_ERROR err = LogValue("MaxCumulativeFailsafeSeconds", indent + 1, value.maxCumulativeFailsafeSeconds);
+ if (err != CHIP_NO_ERROR)
+ {
+ DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'MaxCumulativeFailsafeSeconds'");
+ return err;
+ }
+ }
DataModelLogger::LogString(indent, "}");
return CHIP_NO_ERROR;
diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h
index f6da56d8b6a647..3dcb212672e811 100644
--- a/zzz_generated/chip-tool/zap-generated/test/Commands.h
+++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h
@@ -13258,6 +13258,8 @@ class Test_TC_CGEN_2_1Suite : public TestCommand
VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
VerifyOrReturn(
CheckValue("basicCommissioningInfo.failSafeExpiryLengthSeconds", value.failSafeExpiryLengthSeconds, 60U));
+ VerifyOrReturn(
+ CheckValue("basicCommissioningInfo.maxCumulativeFailsafeSeconds", value.maxCumulativeFailsafeSeconds, 900U));
}
break;
default:
diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/CHIPTestClustersObjc.mm b/zzz_generated/darwin-framework-tool/zap-generated/cluster/CHIPTestClustersObjc.mm
index e685dbe0682138..f76b2976d3c3b6 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/CHIPTestClustersObjc.mm
+++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/CHIPTestClustersObjc.mm
@@ -9257,6 +9257,7 @@ new CHIPDefaultSuccessCallbackBridge(
using TypeInfo = GeneralCommissioning::Attributes::BasicCommissioningInfo::TypeInfo;
TypeInfo::Type cppValue;
cppValue.failSafeExpiryLengthSeconds = value.failSafeExpiryLengthSeconds.unsignedShortValue;
+ cppValue.maxCumulativeFailsafeSeconds = value.maxCumulativeFailsafeSeconds.unsignedShortValue;
auto successFn = Callback::FromCancelable(success);
auto failureFn = Callback::FromCancelable(failure);
return self.cppCluster.WriteAttribute(cppValue, successFn->mContext, successFn->mCall, failureFn->mCall);
diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
index 307c3f6f9a69c0..318a16153f5a92 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
+++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
@@ -22442,6 +22442,8 @@ class Test_TC_CGEN_2_1 : public TestCommandBridge {
id actualValue = value;
VerifyOrReturn(CheckValue("FailSafeExpiryLengthSeconds",
((CHIPGeneralCommissioningClusterBasicCommissioningInfo *) actualValue).failSafeExpiryLengthSeconds, 60U));
+ VerifyOrReturn(CheckValue("MaxCumulativeFailsafeSeconds",
+ ((CHIPGeneralCommissioningClusterBasicCommissioningInfo *) actualValue).maxCumulativeFailsafeSeconds, 900U));
}
NextTest();