Fix reporting for Administrator Commissioning attributes. (#23589)
* Fix reporting for Administrator Commissioning attributes.
Nothing was marking the attributes dirty when the data backing them changed.
* Remove the dependency of af-types.h from reporting.h, so reporting.h can be
part of the SDK library, not the app.
* Move reporting.h to the same library as the other reporting files.
* Fix the one example app that was using the EmberAfAttributeType bits in
reporting.h.
* Fix color control server depending on reporting.h to get af-types.h.
* Add convenience MakeNullable methods, like we have for Optional.
* Make sure we call MatterReportingAttributeChangeCallback as needed in
CommissioningWindowManager.
* Add a unit test that fails without these changes.
* Fix the existing TestCommissioningWindow unit test to not hardcode fabric
indices, since that's not needed anymore.
* Address review comment.
diff --git a/examples/bridge-app/linux/main.cpp b/examples/bridge-app/linux/main.cpp
index 5007cee..a1b54c5 100644
--- a/examples/bridge-app/linux/main.cpp
+++ b/examples/bridge-app/linux/main.cpp
@@ -420,9 +420,7 @@
if (itemChangedMask & DevicePowerSource::kChanged_BatLevel)
{
- uint8_t batChargeLevel = dev->GetBatChargeLevel();
- MatterReportingAttributeChangeCallback(dev->GetEndpointId(), PowerSource::Id, PowerSource::Attributes::BatChargeLevel::Id,
- ZCL_INT8U_ATTRIBUTE_TYPE, &batChargeLevel);
+ MatterReportingAttributeChangeCallback(dev->GetEndpointId(), PowerSource::Id, PowerSource::Attributes::BatChargeLevel::Id);
}
if (itemChangedMask & DevicePowerSource::kChanged_Description)
diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn
index 734baf6..83d6c7d 100644
--- a/src/app/BUILD.gn
+++ b/src/app/BUILD.gn
@@ -183,6 +183,7 @@
"WriteHandler.cpp",
"reporting/Engine.cpp",
"reporting/Engine.h",
+ "reporting/reporting.h",
]
public_deps = [
diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni
index da193e7..8eaecc3 100644
--- a/src/app/chip_data_model.gni
+++ b/src/app/chip_data_model.gni
@@ -94,7 +94,6 @@
"${_app_root}/clusters/on-off-server/on-off-server.h",
"${_app_root}/clusters/scenes/scenes-tokens.h",
"${_app_root}/clusters/scenes/scenes.h",
- "${_app_root}/reporting/reporting.h",
"${_app_root}/util/DataModelHandler.cpp",
"${_app_root}/util/af-event.cpp",
"${_app_root}/util/attribute-size-util.cpp",
diff --git a/src/app/clusters/color-control-server/color-control-server.h b/src/app/clusters/color-control-server/color-control-server.h
index 32ac777..22cb14e 100644
--- a/src/app/clusters/color-control-server/color-control-server.h
+++ b/src/app/clusters/color-control-server/color-control-server.h
@@ -19,7 +19,7 @@
#include <app-common/zap-generated/cluster-objects.h>
#include <app/ConcreteCommandPath.h>
-#include <app/reporting/reporting.h>
+#include <app/util/af-types.h>
#include <app/util/basic-types.h>
/**********************************************************
diff --git a/src/app/data-model/Nullable.h b/src/app/data-model/Nullable.h
index c0e2a7e..46586e0 100644
--- a/src/app/data-model/Nullable.h
+++ b/src/app/data-model/Nullable.h
@@ -86,6 +86,18 @@
bool operator!=(const Nullable & other) const { return !(*this == other); }
};
+template <class T>
+constexpr Nullable<std::decay_t<T>> MakeNullable(T && value)
+{
+ return Nullable<std::decay_t<T>>(InPlace, std::forward<T>(value));
+}
+
+template <class T, class... Args>
+constexpr Nullable<T> MakeNullable(Args &&... args)
+{
+ return Nullable<T>(InPlace, std::forward<Args>(args)...);
+}
+
} // namespace DataModel
} // namespace app
} // namespace chip
diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp
index e4dcdfc..6e25f59 100644
--- a/src/app/reporting/Engine.cpp
+++ b/src/app/reporting/Engine.cpp
@@ -964,3 +964,10 @@
void __attribute__((weak)) MatterPreAttributeReadCallback(const chip::app::ConcreteAttributePath & attributePath) {}
void __attribute__((weak)) MatterPostAttributeReadCallback(const chip::app::ConcreteAttributePath & attributePath) {}
+
+// TODO: MatterReportingAttributeChangeCallback should just live in libCHIP,
+// instead of being in ember-compatibility-functions. It does not depend on any
+// app-specific generated bits.
+void __attribute__((weak))
+MatterReportingAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId)
+{}
diff --git a/src/app/reporting/reporting.h b/src/app/reporting/reporting.h
index eaed8e8..02a8aec 100644
--- a/src/app/reporting/reporting.h
+++ b/src/app/reporting/reporting.h
@@ -18,20 +18,13 @@
#pragma once
#include <app/ConcreteAttributePath.h>
-#include <app/util/af-types.h>
/** @brief Reporting Attribute Change
*
* This function is called by the framework when an attribute managed by the
* framework changes. The application should call this function when an
- * externally-managed attribute changes. The application should use the change
- * notification to inform its reporting decisions.
- */
-void MatterReportingAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId,
- EmberAfAttributeType type, uint8_t * data);
-
-/*
- * Same but with just an attribute path and no data available.
+ * externally-managed attribute changes. This function triggers attribute
+ * reports for subscriptions as needed.
*/
void MatterReportingAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId);
diff --git a/src/app/server/CommissioningWindowManager.cpp b/src/app/server/CommissioningWindowManager.cpp
index 4256f9b..949b460 100644
--- a/src/app/server/CommissioningWindowManager.cpp
+++ b/src/app/server/CommissioningWindowManager.cpp
@@ -15,6 +15,7 @@
* limitations under the License.
*/
+#include <app/reporting/reporting.h>
#include <app/server/CommissioningWindowManager.h>
#include <app/server/Dnssd.h>
#include <app/server/Server.h>
@@ -28,6 +29,9 @@
using namespace chip::System::Clock;
using AdministratorCommissioning::CommissioningWindowStatus;
+using chip::app::DataModel::MakeNullable;
+using chip::app::DataModel::Nullable;
+using chip::app::DataModel::NullNullable;
namespace {
@@ -93,10 +97,11 @@
mECMDiscriminator = 0;
mECMIterations = 0;
mECMSaltLength = 0;
- mWindowStatus = CommissioningWindowStatus::kWindowNotOpen;
- mOpenerFabricIndex.SetNull();
- mOpenerVendorId.SetNull();
+ UpdateWindowStatus(CommissioningWindowStatus::kWindowNotOpen);
+
+ UpdateOpenerFabricIndex(NullNullable);
+ UpdateOpenerVendorId(NullNullable);
memset(&mECMPASEVerifier, 0, sizeof(mECMPASEVerifier));
memset(mECMSalt, 0, sizeof(mECMSalt));
@@ -294,8 +299,8 @@
{
ReturnErrorOnFailure(OpenBasicCommissioningWindow(commissioningTimeout, CommissioningWindowAdvertisement::kDnssdOnly));
- mOpenerFabricIndex.SetNonNull(fabricIndex);
- mOpenerVendorId.SetNonNull(vendorId);
+ UpdateOpenerFabricIndex(MakeNullable(fabricIndex));
+ UpdateOpenerVendorId(MakeNullable(vendorId));
return CHIP_NO_ERROR;
}
@@ -329,8 +334,8 @@
}
else
{
- mOpenerFabricIndex.SetNonNull(fabricIndex);
- mOpenerVendorId.SetNonNull(vendorId);
+ UpdateOpenerFabricIndex(MakeNullable(fabricIndex));
+ UpdateOpenerVendorId(MakeNullable(vendorId));
}
return err;
@@ -356,6 +361,10 @@
CommissioningWindowStatus CommissioningWindowManager::CommissioningWindowStatusForCluster() const
{
+ // If the condition we use to determine whether we were opened via the
+ // cluster ever changes, make sure whatever code affects that condition
+ // marks calls MatterReportingAttributeChangeCallback for WindowStatus as
+ // needed.
if (mOpenerVendorId.IsNull())
{
// Not opened via the cluster.
@@ -375,7 +384,7 @@
if (!mOpenerFabricIndex.IsNull() && mOpenerFabricIndex.Value() == removedIndex)
{
// Per spec, we should clear out the stale fabric index.
- mOpenerFabricIndex.SetNull();
+ UpdateOpenerFabricIndex(NullNullable);
}
}
@@ -424,11 +433,11 @@
if (mUseECM)
{
- mWindowStatus = CommissioningWindowStatus::kEnhancedWindowOpen;
+ UpdateWindowStatus(CommissioningWindowStatus::kEnhancedWindowOpen);
}
else
{
- mWindowStatus = CommissioningWindowStatus::kBasicWindowOpen;
+ UpdateWindowStatus(CommissioningWindowStatus::kBasicWindowOpen);
}
if (mAppDelegate != nullptr)
@@ -526,4 +535,51 @@
}
}
+void CommissioningWindowManager::UpdateWindowStatus(CommissioningWindowStatus aNewStatus)
+{
+ CommissioningWindowStatus oldClusterStatus = CommissioningWindowStatusForCluster();
+ mWindowStatus = aNewStatus;
+ if (CommissioningWindowStatusForCluster() != oldClusterStatus)
+ {
+ // The Administrator Commissioning cluster is always on the root endpoint.
+ MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::WindowStatus::Id);
+ }
+}
+
+void CommissioningWindowManager::UpdateOpenerVendorId(Nullable<VendorId> aNewOpenerVendorId)
+{
+ // Changing the opener vendor id affects what
+ // CommissioningWindowStatusForCluster() returns.
+ CommissioningWindowStatus oldClusterStatus = CommissioningWindowStatusForCluster();
+
+ if (mOpenerVendorId != aNewOpenerVendorId)
+ {
+ // The Administrator Commissioning cluster is always on the root endpoint.
+ MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::AdminVendorId::Id);
+ }
+
+ mOpenerVendorId = aNewOpenerVendorId;
+
+ if (CommissioningWindowStatusForCluster() != oldClusterStatus)
+ {
+ // The Administrator Commissioning cluster is always on the root endpoint.
+ MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::WindowStatus::Id);
+ }
+}
+
+void CommissioningWindowManager::UpdateOpenerFabricIndex(Nullable<FabricIndex> aNewOpenerFabricIndex)
+{
+ if (mOpenerFabricIndex != aNewOpenerFabricIndex)
+ {
+ // The Administrator Commissioning cluster is always on the root endpoint.
+ MatterReportingAttributeChangeCallback(kRootEndpointId, AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::AdminFabricIndex::Id);
+ }
+
+ mOpenerFabricIndex = aNewOpenerFabricIndex;
+}
+
} // namespace chip
diff --git a/src/app/server/CommissioningWindowManager.h b/src/app/server/CommissioningWindowManager.h
index 9381a2c..bb2cf00 100644
--- a/src/app/server/CommissioningWindowManager.h
+++ b/src/app/server/CommissioningWindowManager.h
@@ -171,6 +171,14 @@
*/
void ExpireFailSafeIfArmed();
+ /**
+ * Helpers to ensure the right attribute reporting happens when our state is
+ * updated.
+ */
+ void UpdateWindowStatus(app::Clusters::AdministratorCommissioning::CommissioningWindowStatus aNewStatus);
+ void UpdateOpenerVendorId(app::DataModel::Nullable<VendorId> aNewOpenerVendorId);
+ void UpdateOpenerFabricIndex(app::DataModel::Nullable<FabricIndex> aNewOpenerFabricIndex);
+
AppDelegate * mAppDelegate = nullptr;
Server * mServer = nullptr;
diff --git a/src/app/tests/TestCommissionManager.cpp b/src/app/tests/TestCommissionManager.cpp
index 580b62e..7a05cbd 100644
--- a/src/app/tests/TestCommissionManager.cpp
+++ b/src/app/tests/TestCommissionManager.cpp
@@ -38,6 +38,45 @@
void InitDataModelHandler(chip::Messaging::ExchangeManager * exchangeMgr) {}
namespace {
+bool sAdminFabricIndexDirty = false;
+bool sAdminVendorIdDirty = false;
+bool sWindowStatusDirty = false;
+
+void ResetDirtyFlags()
+{
+ sAdminFabricIndexDirty = false;
+ sAdminVendorIdDirty = false;
+ sWindowStatusDirty = false;
+}
+
+} // namespace
+
+void MatterReportingAttributeChangeCallback(chip::EndpointId endpoint, chip::ClusterId clusterId, chip::AttributeId attributeId)
+{
+ using namespace chip::app::Clusters;
+ using namespace chip::app::Clusters::AdministratorCommissioning::Attributes;
+ if (endpoint != chip::kRootEndpointId || clusterId != AdministratorCommissioning::Id)
+ {
+ return;
+ }
+
+ switch (attributeId)
+ {
+ case WindowStatus::Id:
+ sWindowStatusDirty = true;
+ break;
+ case AdminVendorId::Id:
+ sAdminVendorIdDirty = true;
+ break;
+ case AdminFabricIndex::Id:
+ sAdminFabricIndexDirty = true;
+ break;
+ default:
+ break;
+ }
+}
+
+namespace {
static constexpr int kTestTaskWaitSeconds = 2;
@@ -85,7 +124,11 @@
void CheckCommissioningWindowManagerBasicWindowOpenCloseTask(intptr_t context)
{
- nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
CHIP_ERROR err = commissionMgr.OpenBasicCommissioningWindow(commissionMgr.MaxCommissioningTimeout(),
CommissioningWindowAdvertisement::kDnssdOnly);
@@ -97,8 +140,15 @@
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerFabricIndex().IsNull());
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerVendorId().IsNull());
NL_TEST_ASSERT(suite, !chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
commissionMgr.CloseCommissioningWindow();
NL_TEST_ASSERT(suite, !commissionMgr.IsCommissioningWindowOpen());
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
}
void CheckCommissioningWindowManagerBasicWindowOpenClose(nlTestSuite * suite, void *)
@@ -110,7 +160,11 @@
void CheckCommissioningWindowManagerBasicWindowOpenCloseFromClusterTask(intptr_t context)
{
- nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
constexpr auto fabricIndex = static_cast<chip::FabricIndex>(1);
constexpr auto vendorId = static_cast<chip::VendorId>(0xFFF3);
@@ -126,10 +180,24 @@
NL_TEST_ASSERT(suite, !commissionMgr.GetOpenerVendorId().IsNull());
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerVendorId().Value() == vendorId);
NL_TEST_ASSERT(suite, !chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
+ NL_TEST_ASSERT(suite, sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, sAdminVendorIdDirty);
+
+ ResetDirtyFlags();
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
commissionMgr.CloseCommissioningWindow();
NL_TEST_ASSERT(suite, !commissionMgr.IsCommissioningWindowOpen());
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerFabricIndex().IsNull());
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerVendorId().IsNull());
+ NL_TEST_ASSERT(suite, sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, sAdminVendorIdDirty);
+
+ ResetDirtyFlags();
}
void CheckCommissioningWindowManagerBasicWindowOpenCloseFromCluster(nlTestSuite * suite, void *)
@@ -147,11 +215,18 @@
NL_TEST_ASSERT(suite,
commissionMgr.CommissioningWindowStatusForCluster() ==
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
}
void CheckCommissioningWindowManagerWindowTimeoutTask(intptr_t context)
{
- nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(1);
constexpr uint16_t kTimeoutMs = 1000;
@@ -164,6 +239,10 @@
commissionMgr.CommissioningWindowStatusForCluster() ==
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen);
NL_TEST_ASSERT(suite, !chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(kTimeoutMs + kSleepPadding),
CheckCommissioningWindowManagerWindowClosedTask, suite);
}
@@ -183,17 +262,28 @@
NL_TEST_ASSERT(suite,
commissionMgr.CommissioningWindowStatusForCluster() ==
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
commissionMgr.OnSessionEstablishmentStarted();
commissionMgr.OnSessionEstablishmentError(CHIP_ERROR_INTERNAL);
NL_TEST_ASSERT(suite, commissionMgr.IsCommissioningWindowOpen());
NL_TEST_ASSERT(suite,
commissionMgr.CommissioningWindowStatusForCluster() ==
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
}
void CheckCommissioningWindowManagerWindowTimeoutWithSessionEstablishmentErrorsTask(intptr_t context)
{
- nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ nlTestSuite * suite = reinterpret_cast<nlTestSuite *>(context);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
CommissioningWindowManager & commissionMgr = Server::GetInstance().GetCommissioningWindowManager();
constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(1);
constexpr uint16_t kTimeoutMs = 1000;
@@ -205,10 +295,14 @@
commissionMgr.CommissioningWindowStatusForCluster() ==
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen);
NL_TEST_ASSERT(suite, !chip::DeviceLayer::ConnectivityMgr().IsBLEAdvertisingEnabled());
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(kTimeoutMs + kSleepPadding),
CheckCommissioningWindowManagerWindowClosedTask, suite);
// Simulate a session establishment error during that window, such that the
- // delay for the error plust hte window size exceeds our "timeout + padding" above.
+ // delay for the error plus the window size exceeds our "timeout + padding" above.
chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(kTimeoutMs / 4 * 3),
SimulateFailedSessionEstablishmentTask, suite);
}
@@ -233,6 +327,10 @@
uint8_t salt[chip::kSpake2p_Min_PBKDF_Salt_Length];
chip::ByteSpan saltData(salt);
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
+
constexpr auto fabricIndex = static_cast<chip::FabricIndex>(1);
constexpr auto vendorId = static_cast<chip::VendorId>(0xFFF3);
err = commissionMgr.OpenEnhancedCommissioningWindow(commissionMgr.MaxCommissioningTimeout(), newDiscriminator, verifier,
@@ -247,6 +345,14 @@
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerFabricIndex().Value() == fabricIndex);
NL_TEST_ASSERT(suite, !commissionMgr.GetOpenerVendorId().IsNull());
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerVendorId().Value() == vendorId);
+ NL_TEST_ASSERT(suite, sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, sAdminVendorIdDirty);
+
+ ResetDirtyFlags();
+ NL_TEST_ASSERT(suite, !sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, !sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, !sAdminVendorIdDirty);
commissionMgr.CloseCommissioningWindow();
NL_TEST_ASSERT(suite, !commissionMgr.IsCommissioningWindowOpen());
@@ -255,6 +361,11 @@
chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus::kWindowNotOpen);
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerFabricIndex().IsNull());
NL_TEST_ASSERT(suite, commissionMgr.GetOpenerVendorId().IsNull());
+ NL_TEST_ASSERT(suite, sWindowStatusDirty);
+ NL_TEST_ASSERT(suite, sAdminFabricIndexDirty);
+ NL_TEST_ASSERT(suite, sAdminVendorIdDirty);
+
+ ResetDirtyFlags();
}
void CheckCommissioningWindowManagerEnhancedWindow(nlTestSuite * suite, void *)
diff --git a/src/app/tests/suites/TestCommissioningWindow.yaml b/src/app/tests/suites/TestCommissioningWindow.yaml
index bade4a2..5ec5bc4 100644
--- a/src/app/tests/suites/TestCommissioningWindow.yaml
+++ b/src/app/tests/suites/TestCommissioningWindow.yaml
@@ -27,12 +27,6 @@
payload:
type: char_string
defaultValue: "MT:-24J0AFN00KA0648G00" # This value needs to be generated automatically
- alphaIndex:
- type: int8u
- defaultValue: 1
- betaIndex:
- type: int8u
- defaultValue: 2
tests:
- label: "Wait for the commissioned device to be retrieved for alpha"
@@ -48,10 +42,7 @@
command: "readAttribute"
attribute: "CurrentFabricIndex"
response:
- # We could saveAs here, but then when we try to compare to it later
- # the nullable-vs-non-nullable compare fails to work right. For now
- # just use a config variable.
- value: alphaIndex
+ saveAs: alphaIndex
- label: "Check that commissioning window is not open"
command: "readAttribute"
@@ -172,10 +163,7 @@
command: "readAttribute"
attribute: "CurrentFabricIndex"
response:
- # We could saveAs here, but then when we try to compare to it later
- # the nullable-vs-non-nullable compare fails to work right. For now
- # just use a config variable.
- value: betaIndex
+ saveAs: betaIndex
- label: "Open Commissioning Window from beta"
identity: "beta"
diff --git a/src/app/tests/suites/TestSubscribe_AdministratorCommissioning.yaml b/src/app/tests/suites/TestSubscribe_AdministratorCommissioning.yaml
new file mode 100644
index 0000000..ecda538
--- /dev/null
+++ b/src/app/tests/suites/TestSubscribe_AdministratorCommissioning.yaml
@@ -0,0 +1,135 @@
+# Copyright (c) 2021 Project CHIP Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+name: Subscribe Tests - Administrator Commissioning Cluster
+
+config:
+ nodeId: 0x12344321
+ cluster: "AdministratorCommissioning"
+ endpoint: 0
+ ourVendorId:
+ type: int16u
+ defaultValue: 0xFFF1
+
+tests:
+ - label: "Wait for the commissioned device to be retrieved"
+ cluster: "DelayCommands"
+ command: "WaitForCommissionee"
+ arguments:
+ values:
+ - name: "nodeId"
+ value: nodeId
+
+ - label: "Get ourfabric index"
+ cluster: "Operational Credentials"
+ command: "readAttribute"
+ attribute: "CurrentFabricIndex"
+ response:
+ saveAs: ourFabricIndex
+
+ - label: "Subscribe WindowStatus Attribute"
+ command: "subscribeAttribute"
+ attribute: "WindowStatus"
+ minInterval: 2
+ maxInterval: 50
+ response:
+ value: 0
+
+ - label: "Open the commissioning window 1"
+ command: "OpenBasicCommissioningWindow"
+ timedInteractionTimeoutMs: 10000
+ arguments:
+ values:
+ - name: "CommissioningTimeout"
+ value: 180
+
+ - label: "Check for first attribute report for WindowStatus"
+ command: "waitForReport"
+ attribute: "WindowStatus"
+ response:
+ value: 2
+
+ - label: "Close the commissioning window 1"
+ command: "RevokeCommissioning"
+ timedInteractionTimeoutMs: 10000
+
+ - label: "Check for second attribute report for WindowStatus"
+ command: "waitForReport"
+ attribute: "WindowStatus"
+ response:
+ value: 0
+
+ - label: "Subscribe AdminVendorId Attribute"
+ command: "subscribeAttribute"
+ attribute: "AdminVendorId"
+ minInterval: 2
+ maxInterval: 50
+ response:
+ value: null
+
+ - label: "Open the commissioning window 2"
+ command: "OpenBasicCommissioningWindow"
+ timedInteractionTimeoutMs: 10000
+ arguments:
+ values:
+ - name: "CommissioningTimeout"
+ value: 180
+
+ - label: "Check for first attribute report for AdminVendorId"
+ command: "waitForReport"
+ attribute: "AdminVendorId"
+ response:
+ value: ourVendorId
+
+ - label: "Close the commissioning window 2"
+ command: "RevokeCommissioning"
+ timedInteractionTimeoutMs: 10000
+
+ - label: "Check for second attribute report for AdminVendorId"
+ command: "waitForReport"
+ attribute: "AdminVendorId"
+ response:
+ value: null
+
+ - label: "Subscribe AdminFabricIndex Attribute"
+ command: "subscribeAttribute"
+ attribute: "AdminFabricIndex"
+ minInterval: 2
+ maxInterval: 50
+ response:
+ value: null
+
+ - label: "Open the commissioning window 3"
+ command: "OpenBasicCommissioningWindow"
+ timedInteractionTimeoutMs: 10000
+ arguments:
+ values:
+ - name: "CommissioningTimeout"
+ value: 180
+
+ - label: "Check for first attribute report for AdminFabricIndex"
+ command: "waitForReport"
+ attribute: "AdminFabricIndex"
+ response:
+ value: ourFabricIndex
+
+ - label: "Close the commissioning window 2"
+ command: "RevokeCommissioning"
+ timedInteractionTimeoutMs: 10000
+
+ - label: "Check for second attribute report for AdminFabricIndex"
+ command: "waitForReport"
+ attribute: "AdminFabricIndex"
+ response:
+ value: null
diff --git a/src/app/tests/suites/ciTests.json b/src/app/tests/suites/ciTests.json
index 17bfa98..58a3bd5 100644
--- a/src/app/tests/suites/ciTests.json
+++ b/src/app/tests/suites/ciTests.json
@@ -227,7 +227,10 @@
],
"MultiAdmin": ["TestMultiAdmin"],
"SoftwareDiagnostics": ["Test_TC_DGSW_1_1"],
- "Subscriptions": ["TestSubscribe_OnOff"],
+ "Subscriptions": [
+ "TestSubscribe_OnOff",
+ "TestSubscribe_AdministratorCommissioning"
+ ],
"DoorLock": [
"DL_UsersAndCredentials",
"DL_LockUnlock",
diff --git a/src/app/util/attribute-table.cpp b/src/app/util/attribute-table.cpp
index 2a86c16..3c05b68 100644
--- a/src/app/util/attribute-table.cpp
+++ b/src/app/util/attribute-table.cpp
@@ -359,7 +359,7 @@
// The callee will weed out attributes that do not need to be stored.
emAfSaveAttributeToStorageIfNeeded(data, endpoint, cluster, metadata);
- MatterReportingAttributeChangeCallback(endpoint, cluster, attributeID, dataType, data);
+ MatterReportingAttributeChangeCallback(endpoint, cluster, attributeID);
// Post write attribute callback for all attributes changes, regardless
// of cluster.
diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp
index 648e296..683da9c 100644
--- a/src/app/util/ember-compatibility-functions.cpp
+++ b/src/app/util/ember-compatibility-functions.cpp
@@ -1107,15 +1107,6 @@
} // namespace app
} // namespace chip
-void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId,
- EmberAfAttributeType type, uint8_t * data)
-{
- IgnoreUnusedVariable(type);
- IgnoreUnusedVariable(data);
-
- MatterReportingAttributeChangeCallback(endpoint, clusterId, attributeId);
-}
-
void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId)
{
// Attribute writes have asserted this already, but this assert should catch
diff --git a/zzz_generated/chip-tool/zap-generated/test/Commands.h b/zzz_generated/chip-tool/zap-generated/test/Commands.h
index 1c8402f..d387909 100644
--- a/zzz_generated/chip-tool/zap-generated/test/Commands.h
+++ b/zzz_generated/chip-tool/zap-generated/test/Commands.h
@@ -235,6 +235,7 @@
printf("TestMultiAdmin\n");
printf("Test_TC_DGSW_1_1\n");
printf("TestSubscribe_OnOff\n");
+ printf("TestSubscribe_AdministratorCommissioning\n");
printf("DL_UsersAndCredentials\n");
printf("DL_LockUnlock\n");
printf("DL_Schedules\n");
@@ -63169,8 +63170,6 @@
AddArgument("cluster", &mCluster);
AddArgument("discriminator", 0, UINT16_MAX, &mDiscriminator);
AddArgument("payload", &mPayload);
- AddArgument("alphaIndex", 0, UINT8_MAX, &mAlphaIndex);
- AddArgument("betaIndex", 0, UINT8_MAX, &mBetaIndex);
AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
}
@@ -63188,10 +63187,10 @@
chip::Optional<chip::CharSpan> mCluster;
chip::Optional<uint16_t> mDiscriminator;
chip::Optional<chip::CharSpan> mPayload;
- chip::Optional<uint8_t> mAlphaIndex;
- chip::Optional<uint8_t> mBetaIndex;
chip::Optional<uint16_t> mTimeout;
+ uint8_t alphaIndex;
+ uint8_t betaIndex;
chip::app::DataModel::Nullable<uint16_t> adminVendorId;
chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; }
@@ -63215,7 +63214,7 @@
{
uint8_t value;
VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
- VerifyOrReturn(CheckValue("currentFabricIndex", value, mAlphaIndex.HasValue() ? mAlphaIndex.Value() : 1U));
+ alphaIndex = value;
}
break;
case 2:
@@ -63259,8 +63258,7 @@
chip::app::DataModel::Nullable<chip::FabricIndex> value;
VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
VerifyOrReturn(CheckValueNonNull("adminFabricIndex", value));
- VerifyOrReturn(
- CheckValue("adminFabricIndex.Value()", value.Value(), mAlphaIndex.HasValue() ? mAlphaIndex.Value() : 1U));
+ VerifyOrReturn(CheckValue("adminFabricIndex.Value()", value.Value(), alphaIndex));
}
break;
case 8:
@@ -63338,7 +63336,7 @@
{
uint8_t value;
VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
- VerifyOrReturn(CheckValue("currentFabricIndex", value, mBetaIndex.HasValue() ? mBetaIndex.Value() : 2U));
+ betaIndex = value;
}
break;
case 20:
@@ -63358,8 +63356,7 @@
chip::app::DataModel::Nullable<chip::FabricIndex> value;
VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
VerifyOrReturn(CheckValueNonNull("adminFabricIndex", value));
- VerifyOrReturn(
- CheckValue("adminFabricIndex.Value()", value.Value(), mBetaIndex.HasValue() ? mBetaIndex.Value() : 2U));
+ VerifyOrReturn(CheckValue("adminFabricIndex.Value()", value.Value(), betaIndex));
}
break;
case 23:
@@ -63579,7 +63576,7 @@
LogStep(24, "Remove beta fabric");
ListFreer listFreer;
chip::app::Clusters::OperationalCredentials::Commands::RemoveFabric::Type value;
- value.fabricIndex = mBetaIndex.HasValue() ? mBetaIndex.Value() : 2U;
+ value.fabricIndex = betaIndex;
return SendCommand(kIdentityAlpha, GetEndpoint(0), OperationalCredentials::Id,
OperationalCredentials::Commands::RemoveFabric::Id, value, chip::NullOptional
@@ -64290,6 +64287,295 @@
}
};
+class TestSubscribe_AdministratorCommissioningSuite : public TestCommand
+{
+public:
+ TestSubscribe_AdministratorCommissioningSuite(CredentialIssuerCommands * credsIssuerConfig) :
+ TestCommand("TestSubscribe_AdministratorCommissioning", 17, credsIssuerConfig)
+ {
+ AddArgument("nodeId", 0, UINT64_MAX, &mNodeId);
+ AddArgument("cluster", &mCluster);
+ AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint);
+ AddArgument("ourVendorId", 0, UINT16_MAX, &mOurVendorId);
+ AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
+ }
+
+ ~TestSubscribe_AdministratorCommissioningSuite() {}
+
+ chip::System::Clock::Timeout GetWaitDuration() const override
+ {
+ return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds));
+ }
+
+private:
+ chip::Optional<chip::NodeId> mNodeId;
+ chip::Optional<chip::CharSpan> mCluster;
+ chip::Optional<chip::EndpointId> mEndpoint;
+ chip::Optional<uint16_t> mOurVendorId;
+ chip::Optional<uint16_t> mTimeout;
+
+ uint8_t ourFabricIndex;
+
+ chip::EndpointId GetEndpoint(chip::EndpointId endpoint) { return mEndpoint.HasValue() ? mEndpoint.Value() : endpoint; }
+
+ //
+ // Tests methods
+ //
+
+ void OnResponse(const chip::app::StatusIB & status, chip::TLV::TLVReader * data) override
+ {
+ bool shouldContinue = false;
+
+ switch (mTestIndex - 1)
+ {
+ case 0:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ shouldContinue = true;
+ break;
+ case 1:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ uint8_t value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ ourFabricIndex = value;
+ }
+ break;
+ case 2:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValue("windowStatus", value, 0U));
+ }
+ break;
+ case 3:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 4:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValue("windowStatus", value, 2U));
+ }
+ shouldContinue = true;
+ break;
+ case 5:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 6:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::Clusters::AdministratorCommissioning::CommissioningWindowStatus value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValue("windowStatus", value, 0U));
+ }
+ shouldContinue = true;
+ break;
+ case 7:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::DataModel::Nullable<uint16_t> value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValueNull("adminVendorId", value));
+ }
+ break;
+ case 8:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 9:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::DataModel::Nullable<uint16_t> value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValueNonNull("adminVendorId", value));
+ VerifyOrReturn(
+ CheckValue("adminVendorId.Value()", value.Value(), mOurVendorId.HasValue() ? mOurVendorId.Value() : 65521U));
+ }
+ shouldContinue = true;
+ break;
+ case 10:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 11:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::DataModel::Nullable<uint16_t> value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValueNull("adminVendorId", value));
+ }
+ shouldContinue = true;
+ break;
+ case 12:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::DataModel::Nullable<chip::FabricIndex> value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValueNull("adminFabricIndex", value));
+ }
+ break;
+ case 13:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 14:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::DataModel::Nullable<chip::FabricIndex> value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValueNonNull("adminFabricIndex", value));
+ VerifyOrReturn(CheckValue("adminFabricIndex.Value()", value.Value(), ourFabricIndex));
+ }
+ shouldContinue = true;
+ break;
+ case 15:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 16:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ {
+ chip::app::DataModel::Nullable<chip::FabricIndex> value;
+ VerifyOrReturn(CheckDecodeValue(chip::app::DataModel::Decode(*data, value)));
+ VerifyOrReturn(CheckValueNull("adminFabricIndex", value));
+ }
+ shouldContinue = true;
+ break;
+ default:
+ LogErrorOnFailure(ContinueOnChipMainThread(CHIP_ERROR_INVALID_ARGUMENT));
+ }
+
+ if (shouldContinue)
+ {
+ ContinueOnChipMainThread(CHIP_NO_ERROR);
+ }
+ }
+
+ CHIP_ERROR DoTestStep(uint16_t testIndex) override
+ {
+ using namespace chip::app::Clusters;
+ switch (testIndex)
+ {
+ case 0: {
+ LogStep(0, "Wait for the commissioned device to be retrieved");
+ ListFreer listFreer;
+ chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value;
+ value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
+ return WaitForCommissionee(kIdentityAlpha, value);
+ }
+ case 1: {
+ LogStep(1, "Get ourfabric index");
+ return ReadAttribute(kIdentityAlpha, GetEndpoint(0), OperationalCredentials::Id,
+ OperationalCredentials::Attributes::CurrentFabricIndex::Id, true, chip::NullOptional);
+ }
+ case 2: {
+ LogStep(2, "Subscribe WindowStatus Attribute");
+ return SubscribeAttribute(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::WindowStatus::Id, 2, 50, true, chip::NullOptional,
+ chip::NullOptional, /* autoResubscribe = */ chip::NullOptional);
+ }
+ case 3: {
+ LogStep(3, "Open the commissioning window 1");
+ ListFreer listFreer;
+ chip::app::Clusters::AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type value;
+ value.commissioningTimeout = 180U;
+ return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Id, value,
+ chip::Optional<uint16_t>(10000), chip::NullOptional
+
+ );
+ }
+ case 4: {
+ LogStep(4, "Check for first attribute report for WindowStatus");
+ return WaitForReport();
+ }
+ case 5: {
+ LogStep(5, "Close the commissioning window 1");
+ ListFreer listFreer;
+ chip::app::Clusters::AdministratorCommissioning::Commands::RevokeCommissioning::Type value;
+ return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Commands::RevokeCommissioning::Id, value,
+ chip::Optional<uint16_t>(10000), chip::NullOptional
+
+ );
+ }
+ case 6: {
+ LogStep(6, "Check for second attribute report for WindowStatus");
+ return WaitForReport();
+ }
+ case 7: {
+ LogStep(7, "Subscribe AdminVendorId Attribute");
+ return SubscribeAttribute(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::AdminVendorId::Id, 2, 50, true, chip::NullOptional,
+ chip::NullOptional, /* autoResubscribe = */ chip::NullOptional);
+ }
+ case 8: {
+ LogStep(8, "Open the commissioning window 2");
+ ListFreer listFreer;
+ chip::app::Clusters::AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type value;
+ value.commissioningTimeout = 180U;
+ return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Id, value,
+ chip::Optional<uint16_t>(10000), chip::NullOptional
+
+ );
+ }
+ case 9: {
+ LogStep(9, "Check for first attribute report for AdminVendorId");
+ return WaitForReport();
+ }
+ case 10: {
+ LogStep(10, "Close the commissioning window 2");
+ ListFreer listFreer;
+ chip::app::Clusters::AdministratorCommissioning::Commands::RevokeCommissioning::Type value;
+ return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Commands::RevokeCommissioning::Id, value,
+ chip::Optional<uint16_t>(10000), chip::NullOptional
+
+ );
+ }
+ case 11: {
+ LogStep(11, "Check for second attribute report for AdminVendorId");
+ return WaitForReport();
+ }
+ case 12: {
+ LogStep(12, "Subscribe AdminFabricIndex Attribute");
+ return SubscribeAttribute(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Attributes::AdminFabricIndex::Id, 2, 50, true, chip::NullOptional,
+ chip::NullOptional, /* autoResubscribe = */ chip::NullOptional);
+ }
+ case 13: {
+ LogStep(13, "Open the commissioning window 3");
+ ListFreer listFreer;
+ chip::app::Clusters::AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Type value;
+ value.commissioningTimeout = 180U;
+ return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Commands::OpenBasicCommissioningWindow::Id, value,
+ chip::Optional<uint16_t>(10000), chip::NullOptional
+
+ );
+ }
+ case 14: {
+ LogStep(14, "Check for first attribute report for AdminFabricIndex");
+ return WaitForReport();
+ }
+ case 15: {
+ LogStep(15, "Close the commissioning window 2");
+ ListFreer listFreer;
+ chip::app::Clusters::AdministratorCommissioning::Commands::RevokeCommissioning::Type value;
+ return SendCommand(kIdentityAlpha, GetEndpoint(0), AdministratorCommissioning::Id,
+ AdministratorCommissioning::Commands::RevokeCommissioning::Id, value,
+ chip::Optional<uint16_t>(10000), chip::NullOptional
+
+ );
+ }
+ case 16: {
+ LogStep(16, "Check for second attribute report for AdminFabricIndex");
+ return WaitForReport();
+ }
+ }
+ return CHIP_NO_ERROR;
+ }
+};
+
class DL_UsersAndCredentialsSuite : public TestCommand
{
public:
@@ -104645,6 +104931,7 @@
make_unique<TestMultiAdminSuite>(credsIssuerConfig),
make_unique<Test_TC_DGSW_1_1Suite>(credsIssuerConfig),
make_unique<TestSubscribe_OnOffSuite>(credsIssuerConfig),
+ make_unique<TestSubscribe_AdministratorCommissioningSuite>(credsIssuerConfig),
make_unique<DL_UsersAndCredentialsSuite>(credsIssuerConfig),
make_unique<DL_LockUnlockSuite>(credsIssuerConfig),
make_unique<DL_SchedulesSuite>(credsIssuerConfig),
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 0c4c3e8..3fb1a5c 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
+++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h
@@ -216,6 +216,7 @@
printf("TestMultiAdmin\n");
printf("Test_TC_DGSW_1_1\n");
printf("TestSubscribe_OnOff\n");
+ printf("TestSubscribe_AdministratorCommissioning\n");
printf("DL_UsersAndCredentials\n");
printf("DL_LockUnlock\n");
printf("DL_Schedules\n");
@@ -100150,8 +100151,6 @@
AddArgument("cluster", &mCluster);
AddArgument("discriminator", 0, UINT16_MAX, &mDiscriminator);
AddArgument("payload", &mPayload);
- AddArgument("alphaIndex", 0, UINT8_MAX, &mAlphaIndex);
- AddArgument("betaIndex", 0, UINT8_MAX, &mBetaIndex);
AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
}
// NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull)
@@ -100408,8 +100407,6 @@
chip::Optional<chip::CharSpan> mCluster;
chip::Optional<uint16_t> mDiscriminator;
chip::Optional<chip::CharSpan> mPayload;
- chip::Optional<uint8_t> mAlphaIndex;
- chip::Optional<uint8_t> mBetaIndex;
chip::Optional<uint16_t> mTimeout;
CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrievedForAlpha_0()
@@ -100418,6 +100415,7 @@
value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
return WaitForCommissionee("alpha", value);
}
+ NSNumber * _Nonnull alphaIndex;
CHIP_ERROR TestGetAlphasFabricIndex_1()
{
@@ -100432,8 +100430,7 @@
VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
{
- id actualValue = value;
- VerifyOrReturn(CheckValue("CurrentFabricIndex", actualValue, mAlphaIndex.HasValue() ? mAlphaIndex.Value() : 1U));
+ alphaIndex = value;
}
NextTest();
@@ -100569,8 +100566,12 @@
{
id actualValue = value;
- VerifyOrReturn(CheckValueNonNull("AdminFabricIndex", actualValue));
- VerifyOrReturn(CheckValue("AdminFabricIndex", actualValue, mAlphaIndex.HasValue() ? mAlphaIndex.Value() : 1U));
+ if (alphaIndex == nil) {
+ VerifyOrReturn(CheckValueNull("AdminFabricIndex", actualValue));
+ } else {
+ VerifyOrReturn(CheckValueNonNull("AdminFabricIndex", actualValue));
+ VerifyOrReturn(CheckValue("AdminFabricIndex", actualValue, alphaIndex));
+ }
}
NextTest();
@@ -100792,6 +100793,7 @@
return CHIP_NO_ERROR;
}
+ NSNumber * _Nonnull betaIndex;
CHIP_ERROR TestGetBetasFabricIndex_19()
{
@@ -100806,8 +100808,7 @@
VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
{
- id actualValue = value;
- VerifyOrReturn(CheckValue("CurrentFabricIndex", actualValue, mBetaIndex.HasValue() ? mBetaIndex.Value() : 2U));
+ betaIndex = value;
}
NextTest();
@@ -100874,8 +100875,12 @@
{
id actualValue = value;
- VerifyOrReturn(CheckValueNonNull("AdminFabricIndex", actualValue));
- VerifyOrReturn(CheckValue("AdminFabricIndex", actualValue, mBetaIndex.HasValue() ? mBetaIndex.Value() : 2U));
+ if (betaIndex == nil) {
+ VerifyOrReturn(CheckValueNull("AdminFabricIndex", actualValue));
+ } else {
+ VerifyOrReturn(CheckValueNonNull("AdminFabricIndex", actualValue));
+ VerifyOrReturn(CheckValue("AdminFabricIndex", actualValue, betaIndex));
+ }
}
NextTest();
@@ -100918,8 +100923,7 @@
VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
__auto_type * params = [[MTROperationalCredentialsClusterRemoveFabricParams alloc] init];
- params.fabricIndex
- = mBetaIndex.HasValue() ? [NSNumber numberWithUnsignedChar:mBetaIndex.Value()] : [NSNumber numberWithUnsignedChar:2U];
+ params.fabricIndex = [betaIndex copy];
[cluster removeFabricWithParams:params
completion:^(
MTROperationalCredentialsClusterNOCResponseParams * _Nullable values, NSError * _Nullable err) {
@@ -102208,6 +102212,695 @@
}
};
+class TestSubscribe_AdministratorCommissioning : public TestCommandBridge {
+public:
+ // NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced
+ TestSubscribe_AdministratorCommissioning()
+ : TestCommandBridge("TestSubscribe_AdministratorCommissioning")
+ , mTestIndex(0)
+ {
+ AddArgument("nodeId", 0, UINT64_MAX, &mNodeId);
+ AddArgument("cluster", &mCluster);
+ AddArgument("endpoint", 0, UINT16_MAX, &mEndpoint);
+ AddArgument("ourVendorId", 0, UINT16_MAX, &mOurVendorId);
+ AddArgument("timeout", 0, UINT16_MAX, &mTimeout);
+ }
+ // NOLINTEND(clang-analyzer-nullability.NullPassedToNonnull)
+
+ ~TestSubscribe_AdministratorCommissioning() {}
+
+ /////////// TestCommand Interface /////////
+ void NextTest() override
+ {
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ if (0 == mTestIndex) {
+ ChipLogProgress(chipTool, " **** Test Start: TestSubscribe_AdministratorCommissioning\n");
+ }
+
+ if (mTestCount == mTestIndex) {
+ ChipLogProgress(chipTool, " **** Test Complete: TestSubscribe_AdministratorCommissioning\n");
+ SetCommandExitStatus(CHIP_NO_ERROR);
+ return;
+ }
+
+ Wait();
+
+ // Ensure we increment mTestIndex before we start running the relevant
+ // command. That way if we lose the timeslice after we send the message
+ // but before our function call returns, we won't end up with an
+ // incorrect mTestIndex value observed when we get the response.
+ switch (mTestIndex++) {
+ case 0:
+ ChipLogProgress(chipTool, " ***** Test Step 0 : Wait for the commissioned device to be retrieved\n");
+ err = TestWaitForTheCommissionedDeviceToBeRetrieved_0();
+ break;
+ case 1:
+ ChipLogProgress(chipTool, " ***** Test Step 1 : Get ourfabric index\n");
+ err = TestGetOurfabricIndex_1();
+ break;
+ case 2:
+ ChipLogProgress(chipTool, " ***** Test Step 2 : Report: Subscribe WindowStatus Attribute\n");
+ err = TestReportSubscribeWindowStatusAttribute_2();
+ break;
+ case 3:
+ ChipLogProgress(chipTool, " ***** Test Step 3 : Subscribe WindowStatus Attribute\n");
+ err = TestSubscribeWindowStatusAttribute_3();
+ break;
+ case 4:
+ ChipLogProgress(chipTool, " ***** Test Step 4 : Open the commissioning window 1\n");
+ err = TestOpenTheCommissioningWindow1_4();
+ break;
+ case 5:
+ ChipLogProgress(chipTool, " ***** Test Step 5 : Check for first attribute report for WindowStatus\n");
+ err = TestCheckForFirstAttributeReportForWindowStatus_5();
+ break;
+ case 6:
+ ChipLogProgress(chipTool, " ***** Test Step 6 : Close the commissioning window 1\n");
+ err = TestCloseTheCommissioningWindow1_6();
+ break;
+ case 7:
+ ChipLogProgress(chipTool, " ***** Test Step 7 : Check for second attribute report for WindowStatus\n");
+ err = TestCheckForSecondAttributeReportForWindowStatus_7();
+ break;
+ case 8:
+ ChipLogProgress(chipTool, " ***** Test Step 8 : Report: Subscribe AdminVendorId Attribute\n");
+ err = TestReportSubscribeAdminVendorIdAttribute_8();
+ break;
+ case 9:
+ ChipLogProgress(chipTool, " ***** Test Step 9 : Subscribe AdminVendorId Attribute\n");
+ err = TestSubscribeAdminVendorIdAttribute_9();
+ break;
+ case 10:
+ ChipLogProgress(chipTool, " ***** Test Step 10 : Open the commissioning window 2\n");
+ err = TestOpenTheCommissioningWindow2_10();
+ break;
+ case 11:
+ ChipLogProgress(chipTool, " ***** Test Step 11 : Check for first attribute report for AdminVendorId\n");
+ err = TestCheckForFirstAttributeReportForAdminVendorId_11();
+ break;
+ case 12:
+ ChipLogProgress(chipTool, " ***** Test Step 12 : Close the commissioning window 2\n");
+ err = TestCloseTheCommissioningWindow2_12();
+ break;
+ case 13:
+ ChipLogProgress(chipTool, " ***** Test Step 13 : Check for second attribute report for AdminVendorId\n");
+ err = TestCheckForSecondAttributeReportForAdminVendorId_13();
+ break;
+ case 14:
+ ChipLogProgress(chipTool, " ***** Test Step 14 : Report: Subscribe AdminFabricIndex Attribute\n");
+ err = TestReportSubscribeAdminFabricIndexAttribute_14();
+ break;
+ case 15:
+ ChipLogProgress(chipTool, " ***** Test Step 15 : Subscribe AdminFabricIndex Attribute\n");
+ err = TestSubscribeAdminFabricIndexAttribute_15();
+ break;
+ case 16:
+ ChipLogProgress(chipTool, " ***** Test Step 16 : Open the commissioning window 3\n");
+ err = TestOpenTheCommissioningWindow3_16();
+ break;
+ case 17:
+ ChipLogProgress(chipTool, " ***** Test Step 17 : Check for first attribute report for AdminFabricIndex\n");
+ err = TestCheckForFirstAttributeReportForAdminFabricIndex_17();
+ break;
+ case 18:
+ ChipLogProgress(chipTool, " ***** Test Step 18 : Close the commissioning window 2\n");
+ err = TestCloseTheCommissioningWindow2_18();
+ break;
+ case 19:
+ ChipLogProgress(chipTool, " ***** Test Step 19 : Check for second attribute report for AdminFabricIndex\n");
+ err = TestCheckForSecondAttributeReportForAdminFabricIndex_19();
+ break;
+ }
+
+ if (CHIP_NO_ERROR != err) {
+ ChipLogError(chipTool, " ***** Test Failure: %s\n", chip::ErrorStr(err));
+ SetCommandExitStatus(err);
+ }
+ }
+
+ void OnStatusUpdate(const chip::app::StatusIB & status) override
+ {
+ switch (mTestIndex - 1) {
+ case 0:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 1:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 2:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 3:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 4:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 5:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 6:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 7:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 8:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 9:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 10:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 11:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 12:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 13:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 14:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 15:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 16:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 17:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 18:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ case 19:
+ VerifyOrReturn(CheckValue("status", chip::to_underlying(status.mStatus), 0));
+ break;
+ }
+
+ // Go on to the next test.
+ ContinueOnChipMainThread(CHIP_NO_ERROR);
+ }
+
+ chip::System::Clock::Timeout GetWaitDuration() const override
+ {
+ return chip::System::Clock::Seconds16(mTimeout.ValueOr(kTimeoutInSeconds));
+ }
+
+private:
+ std::atomic_uint16_t mTestIndex;
+ const uint16_t mTestCount = 20;
+
+ chip::Optional<chip::NodeId> mNodeId;
+ chip::Optional<chip::CharSpan> mCluster;
+ chip::Optional<chip::EndpointId> mEndpoint;
+ chip::Optional<uint16_t> mOurVendorId;
+ chip::Optional<uint16_t> mTimeout;
+
+ CHIP_ERROR TestWaitForTheCommissionedDeviceToBeRetrieved_0()
+ {
+ chip::app::Clusters::DelayCommands::Commands::WaitForCommissionee::Type value;
+ value.nodeId = mNodeId.HasValue() ? mNodeId.Value() : 305414945ULL;
+ return WaitForCommissionee("alpha", value);
+ }
+ NSNumber * _Nonnull ourFabricIndex;
+
+ CHIP_ERROR TestGetOurfabricIndex_1()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterOperationalCredentials * cluster =
+ [[MTRBaseClusterOperationalCredentials alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ [cluster readAttributeCurrentFabricIndexWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Get ourfabric index Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ ourFabricIndex = value;
+ }
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+ bool testSendClusterTestSubscribe_AdministratorCommissioning_2_WaitForReport_Fulfilled = false;
+ ResponseHandler _Nullable test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported = nil;
+
+ CHIP_ERROR TestReportSubscribeWindowStatusAttribute_2()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Report: Subscribe WindowStatus Attribute Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValue("WindowStatus", actualValue, 0U));
+ }
+
+ testSendClusterTestSubscribe_AdministratorCommissioning_2_WaitForReport_Fulfilled = true;
+ };
+
+ NextTest();
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestSubscribeWindowStatusAttribute_3()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ uint16_t minIntervalArgument = 2U;
+ uint16_t maxIntervalArgument = 50U;
+ MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(minIntervalArgument)
+ maxInterval:@(maxIntervalArgument)];
+ params.filterByFabric = true;
+ params.replaceExistingSubscriptions = true;
+ [cluster subscribeAttributeWindowStatusWithParams:params
+ subscriptionEstablished:^{
+ VerifyOrReturn(testSendClusterTestSubscribe_AdministratorCommissioning_2_WaitForReport_Fulfilled,
+ SetCommandExitStatus(CHIP_ERROR_INCORRECT_STATE));
+ NextTest();
+ }
+ reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Subscribe WindowStatus Attribute Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+ if (test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported != nil) {
+ ResponseHandler callback = test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported;
+ test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported = nil;
+ callback(value, err);
+ }
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestOpenTheCommissioningWindow1_4()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ __auto_type * params = [[MTRAdministratorCommissioningClusterOpenBasicCommissioningWindowParams alloc] init];
+ params.commissioningTimeout = [NSNumber numberWithUnsignedShort:180U];
+ [cluster openBasicCommissioningWindowWithParams:params
+ completion:^(NSError * _Nullable err) {
+ NSLog(@"Open the commissioning window 1 Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCheckForFirstAttributeReportForWindowStatus_5()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Check for first attribute report for WindowStatus Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValue("WindowStatus", actualValue, 2U));
+ }
+
+ NextTest();
+ };
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCloseTheCommissioningWindow1_6()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ [cluster revokeCommissioningWithCompletion:^(NSError * _Nullable err) {
+ NSLog(@"Close the commissioning window 1 Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCheckForSecondAttributeReportForWindowStatus_7()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_WindowStatus_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Check for second attribute report for WindowStatus Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValue("WindowStatus", actualValue, 0U));
+ }
+
+ NextTest();
+ };
+
+ return CHIP_NO_ERROR;
+ }
+ bool testSendClusterTestSubscribe_AdministratorCommissioning_8_WaitForReport_Fulfilled = false;
+ ResponseHandler _Nullable test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported = nil;
+
+ CHIP_ERROR TestReportSubscribeAdminVendorIdAttribute_8()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Report: Subscribe AdminVendorId Attribute Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValueNull("AdminVendorId", actualValue));
+ }
+
+ testSendClusterTestSubscribe_AdministratorCommissioning_8_WaitForReport_Fulfilled = true;
+ };
+
+ NextTest();
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestSubscribeAdminVendorIdAttribute_9()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ uint16_t minIntervalArgument = 2U;
+ uint16_t maxIntervalArgument = 50U;
+ MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(minIntervalArgument)
+ maxInterval:@(maxIntervalArgument)];
+ params.filterByFabric = true;
+ params.replaceExistingSubscriptions = true;
+ [cluster subscribeAttributeAdminVendorIdWithParams:params
+ subscriptionEstablished:^{
+ VerifyOrReturn(testSendClusterTestSubscribe_AdministratorCommissioning_8_WaitForReport_Fulfilled,
+ SetCommandExitStatus(CHIP_ERROR_INCORRECT_STATE));
+ NextTest();
+ }
+ reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Subscribe AdminVendorId Attribute Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+ if (test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported != nil) {
+ ResponseHandler callback = test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported;
+ test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported = nil;
+ callback(value, err);
+ }
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestOpenTheCommissioningWindow2_10()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ __auto_type * params = [[MTRAdministratorCommissioningClusterOpenBasicCommissioningWindowParams alloc] init];
+ params.commissioningTimeout = [NSNumber numberWithUnsignedShort:180U];
+ [cluster openBasicCommissioningWindowWithParams:params
+ completion:^(NSError * _Nullable err) {
+ NSLog(@"Open the commissioning window 2 Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCheckForFirstAttributeReportForAdminVendorId_11()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported = ^(
+ NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Check for first attribute report for AdminVendorId Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValueNonNull("AdminVendorId", actualValue));
+ VerifyOrReturn(CheckValue("AdminVendorId", actualValue, mOurVendorId.HasValue() ? mOurVendorId.Value() : 65521U));
+ }
+
+ NextTest();
+ };
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCloseTheCommissioningWindow2_12()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ [cluster revokeCommissioningWithCompletion:^(NSError * _Nullable err) {
+ NSLog(@"Close the commissioning window 2 Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCheckForSecondAttributeReportForAdminVendorId_13()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_AdminVendorId_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Check for second attribute report for AdminVendorId Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValueNull("AdminVendorId", actualValue));
+ }
+
+ NextTest();
+ };
+
+ return CHIP_NO_ERROR;
+ }
+ bool testSendClusterTestSubscribe_AdministratorCommissioning_14_WaitForReport_Fulfilled = false;
+ ResponseHandler _Nullable test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported = nil;
+
+ CHIP_ERROR TestReportSubscribeAdminFabricIndexAttribute_14()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Report: Subscribe AdminFabricIndex Attribute Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValueNull("AdminFabricIndex", actualValue));
+ }
+
+ testSendClusterTestSubscribe_AdministratorCommissioning_14_WaitForReport_Fulfilled = true;
+ };
+
+ NextTest();
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestSubscribeAdminFabricIndexAttribute_15()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ uint16_t minIntervalArgument = 2U;
+ uint16_t maxIntervalArgument = 50U;
+ MTRSubscribeParams * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(minIntervalArgument)
+ maxInterval:@(maxIntervalArgument)];
+ params.filterByFabric = true;
+ params.replaceExistingSubscriptions = true;
+ [cluster subscribeAttributeAdminFabricIndexWithParams:params
+ subscriptionEstablished:^{
+ VerifyOrReturn(testSendClusterTestSubscribe_AdministratorCommissioning_14_WaitForReport_Fulfilled,
+ SetCommandExitStatus(CHIP_ERROR_INCORRECT_STATE));
+ NextTest();
+ }
+ reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Subscribe AdminFabricIndex Attribute Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+ if (test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported != nil) {
+ ResponseHandler callback = test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported;
+ test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported = nil;
+ callback(value, err);
+ }
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestOpenTheCommissioningWindow3_16()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ __auto_type * params = [[MTRAdministratorCommissioningClusterOpenBasicCommissioningWindowParams alloc] init];
+ params.commissioningTimeout = [NSNumber numberWithUnsignedShort:180U];
+ [cluster openBasicCommissioningWindowWithParams:params
+ completion:^(NSError * _Nullable err) {
+ NSLog(@"Open the commissioning window 3 Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCheckForFirstAttributeReportForAdminFabricIndex_17()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Check for first attribute report for AdminFabricIndex Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ if (ourFabricIndex == nil) {
+ VerifyOrReturn(CheckValueNull("AdminFabricIndex", actualValue));
+ } else {
+ VerifyOrReturn(CheckValueNonNull("AdminFabricIndex", actualValue));
+ VerifyOrReturn(CheckValue("AdminFabricIndex", actualValue, ourFabricIndex));
+ }
+ }
+
+ NextTest();
+ };
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCloseTheCommissioningWindow2_18()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ [cluster revokeCommissioningWithCompletion:^(NSError * _Nullable err) {
+ NSLog(@"Close the commissioning window 2 Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ NextTest();
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+
+ CHIP_ERROR TestCheckForSecondAttributeReportForAdminFabricIndex_19()
+ {
+ MTRBaseDevice * device = GetDevice("alpha");
+ MTRBaseClusterAdministratorCommissioning * cluster =
+ [[MTRBaseClusterAdministratorCommissioning alloc] initWithDevice:device endpointID:@(0) queue:mCallbackQueue];
+ VerifyOrReturnError(cluster != nil, CHIP_ERROR_INCORRECT_STATE);
+
+ test_TestSubscribe_AdministratorCommissioning_AdminFabricIndex_Reported
+ = ^(NSNumber * _Nullable value, NSError * _Nullable err) {
+ NSLog(@"Check for second attribute report for AdminFabricIndex Error: %@", err);
+
+ VerifyOrReturn(CheckValue("status", err ? err.code : 0, 0));
+
+ {
+ id actualValue = value;
+ VerifyOrReturn(CheckValueNull("AdminFabricIndex", actualValue));
+ }
+
+ NextTest();
+ };
+
+ return CHIP_NO_ERROR;
+ }
+};
+
class DL_UsersAndCredentials : public TestCommandBridge {
public:
// NOLINTBEGIN(clang-analyzer-nullability.NullPassedToNonnull): Test constructor nullability not enforced
@@ -125555,6 +126248,7 @@
make_unique<TestMultiAdmin>(),
make_unique<Test_TC_DGSW_1_1>(),
make_unique<TestSubscribe_OnOff>(),
+ make_unique<TestSubscribe_AdministratorCommissioning>(),
make_unique<DL_UsersAndCredentials>(),
make_unique<DL_LockUnlock>(),
make_unique<DL_Schedules>(),