TBRM: Add missing PendingDatasetTimestamp attribute and CASE session check (#34768)
* TBRM: Add missing PendingDatasetTimestamp attribute and CASE session check
* review change
* zap regenerate and update the Test_TC_TBRM_2_1.yaml
* Restyled by clang-format
* Read function error map to IM-space error
* Add attribute report for PendingDatasetTimestamp
* review changes
---------
Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.matter b/examples/network-manager-app/network-manager-common/network-manager-app.matter
index bbd20d4..3f24e4b 100644
--- a/examples/network-manager-app/network-manager-common/network-manager-app.matter
+++ b/examples/network-manager-app/network-manager-common/network-manager-app.matter
@@ -1518,6 +1518,7 @@
provisional readonly attribute int16u threadVersion = 2;
provisional readonly attribute boolean interfaceEnabled = 3;
provisional readonly attribute nullable int64u activeDatasetTimestamp = 4;
+ provisional readonly attribute nullable int64u pendingDatasetTimestamp = 5;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -1879,6 +1880,7 @@
callback attribute threadVersion;
callback attribute interfaceEnabled;
callback attribute activeDatasetTimestamp;
+ callback attribute pendingDatasetTimestamp;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
diff --git a/examples/network-manager-app/network-manager-common/network-manager-app.zap b/examples/network-manager-app/network-manager-common/network-manager-app.zap
index 0a14bcb..7c1445a 100644
--- a/examples/network-manager-app/network-manager-common/network-manager-app.zap
+++ b/examples/network-manager-app/network-manager-common/network-manager-app.zap
@@ -3420,7 +3420,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3436,7 +3436,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3452,7 +3452,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3468,7 +3468,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3484,6 +3484,22 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PendingDatasetTimestamp",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int64u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
"defaultValue": "",
"reportable": 1,
"minInterval": 1,
@@ -3500,7 +3516,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3516,7 +3532,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3532,7 +3548,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3548,7 +3564,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
@@ -3564,7 +3580,7 @@
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp
index 5592da4..4956f3f 100644
--- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp
+++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.cpp
@@ -38,6 +38,7 @@
#include "platform/CHIPDeviceEvent.h"
#include "platform/PlatformManager.h"
#include "protocols/interaction_model/StatusCode.h"
+#include <optional>
namespace chip {
namespace app {
@@ -46,21 +47,24 @@
using Protocols::InteractionModel::Status;
-static bool IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx)
+bool ServerInstance::IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx)
{
+#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
+ if (mSkipCASESessionCheck)
+ {
+ return true;
+ }
+#endif // CONFIG_BUILD_FOR_HOST_UNIT_TEST
Messaging::ExchangeContext * exchangeCtx = ctx.mCommandHandler.GetExchangeContext();
return exchangeCtx && exchangeCtx->HasSessionHandle() && exchangeCtx->GetSessionHandle()->IsSecureSession() &&
exchangeCtx->GetSessionHandle()->AsSecureSession()->GetSecureSessionType() == Transport::SecureSession::Type::kCASE;
}
-Status ServerInstance::HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type,
+Status ServerInstance::HandleGetDatasetRequest(CommandHandlerInterface::HandlerContext & ctx, Delegate::DatasetType type,
Thread::OperationalDataset & dataset)
{
VerifyOrDie(mDelegate);
- if (!isOverCASESession)
- {
- return Status::UnsupportedAccess;
- }
+ VerifyOrReturnValue(IsCommandOverCASESession(ctx), Status::UnsupportedAccess);
CHIP_ERROR err = mDelegate->GetDataset(dataset, type);
if (err != CHIP_NO_ERROR)
@@ -70,7 +74,7 @@
return Status::Success;
}
-Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandler * commandHandler,
+Status ServerInstance::HandleSetActiveDatasetRequest(CommandHandlerInterface::HandlerContext & ctx,
const Commands::SetActiveDatasetRequest::DecodableType & req)
{
// The SetActiveDatasetRequest command SHALL be FailSafeArmed. Upon receiving this command, the Thread BR will set its
@@ -80,7 +84,8 @@
// reverted. If the FailSafe timer expires before the Thread BR responds, the Thread BR will respond with a timeout status and
// the active dataset should also be reverted.
VerifyOrDie(mDelegate);
- VerifyOrReturnValue(mFailsafeContext.IsFailSafeArmed(commandHandler->GetAccessingFabricIndex()), Status::FailsafeRequired);
+ VerifyOrReturnValue(IsCommandOverCASESession(ctx), Status::UnsupportedAccess);
+ VerifyOrReturnValue(mFailsafeContext.IsFailSafeArmed(ctx.mCommandHandler.GetAccessingFabricIndex()), Status::FailsafeRequired);
Thread::OperationalDataset activeDataset;
Thread::OperationalDataset currentActiveDataset;
@@ -101,17 +106,19 @@
{
return Status::Busy;
}
- commandHandler->FlushAcksRightAwayOnSlowCommand();
- mAsyncCommandHandle = CommandHandler::Handle(commandHandler);
+ ctx.mCommandHandler.FlushAcksRightAwayOnSlowCommand();
+ mAsyncCommandHandle = CommandHandler::Handle(&ctx.mCommandHandler);
mBreadcrumb = req.breadcrumb;
mSetActiveDatasetSequenceNumber++;
mDelegate->SetActiveDataset(activeDataset, mSetActiveDatasetSequenceNumber, this);
return Status::Success;
}
-Status ServerInstance::HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req)
+Status ServerInstance::HandleSetPendingDatasetRequest(CommandHandlerInterface::HandlerContext & ctx,
+ const Commands::SetPendingDatasetRequest::DecodableType & req)
{
VerifyOrDie(mDelegate);
+ VerifyOrReturnValue(IsCommandOverCASESession(ctx), Status::UnsupportedAccess);
if (!mDelegate->GetPanChangeSupported())
{
return Status::UnsupportedCommand;
@@ -143,21 +150,21 @@
case Commands::GetActiveDatasetRequest::Id:
HandleCommand<Commands::GetActiveDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
Thread::OperationalDataset dataset;
- Status status = HandleGetActiveDatasetRequest(IsCommandOverCASESession(ctx), dataset);
+ Status status = HandleGetActiveDatasetRequest(ctx, dataset);
AddDatasetResponse(ctx, status, dataset);
});
break;
case Commands::GetPendingDatasetRequest::Id:
HandleCommand<Commands::GetPendingDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
Thread::OperationalDataset dataset;
- Status status = HandleGetPendingDatasetRequest(IsCommandOverCASESession(ctx), dataset);
+ Status status = HandleGetPendingDatasetRequest(ctx, dataset);
AddDatasetResponse(ctx, status, dataset);
});
break;
case Commands::SetActiveDatasetRequest::Id:
HandleCommand<Commands::SetActiveDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
mPath = ctx.mRequestPath;
- Status status = HandleSetActiveDatasetRequest(&ctx.mCommandHandler, req);
+ Status status = HandleSetActiveDatasetRequest(ctx, req);
if (status != Status::Success)
{
// If status is not Success, we should immediately report the status. Otherwise the async work will report the
@@ -168,7 +175,8 @@
break;
case Commands::SetPendingDatasetRequest::Id:
HandleCommand<Commands::SetPendingDatasetRequest::DecodableType>(ctxt, [this](HandlerContext & ctx, const auto & req) {
- ctx.mCommandHandler.AddStatus(ctx.mRequestPath, HandleSetPendingDatasetRequest(req));
+ Status status = HandleSetPendingDatasetRequest(ctx, req);
+ ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
});
break;
default:
@@ -199,16 +207,28 @@
return CHIP_NO_ERROR;
}
-Optional<uint64_t> ServerInstance::ReadActiveDatasetTimestamp()
+std::optional<uint64_t> ServerInstance::ReadActiveDatasetTimestamp()
{
uint64_t activeDatasetTimestampValue = 0;
Thread::OperationalDataset activeDataset;
if ((mDelegate->GetDataset(activeDataset, Delegate::DatasetType::kActive) == CHIP_NO_ERROR) &&
(activeDataset.GetActiveTimestamp(activeDatasetTimestampValue) == CHIP_NO_ERROR))
{
- return MakeOptional(activeDatasetTimestampValue);
+ return std::make_optional(activeDatasetTimestampValue);
}
- return NullOptional;
+ return std::nullopt;
+}
+
+std::optional<uint64_t> ServerInstance::ReadPendingDatasetTimestamp()
+{
+ uint64_t pendingDatasetTimestampValue = 0;
+ Thread::OperationalDataset pendingDataset;
+ if ((mDelegate->GetDataset(pendingDataset, Delegate::DatasetType::kPending) == CHIP_NO_ERROR) &&
+ (pendingDataset.GetActiveTimestamp(pendingDatasetTimestampValue) == CHIP_NO_ERROR))
+ {
+ return std::make_optional(pendingDatasetTimestampValue);
+ }
+ return std::nullopt;
}
CHIP_ERROR ServerInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
@@ -259,9 +279,13 @@
break;
}
case Attributes::ActiveDatasetTimestamp::Id: {
- Optional<uint64_t> activeDatasetTimestamp = ReadActiveDatasetTimestamp();
- status = activeDatasetTimestamp.HasValue() ? aEncoder.Encode(DataModel::MakeNullable(activeDatasetTimestamp.Value()))
- : aEncoder.EncodeNull();
+ std::optional<uint64_t> activeDatasetTimestamp = ReadActiveDatasetTimestamp();
+ status = activeDatasetTimestamp.has_value() ? aEncoder.Encode(activeDatasetTimestamp.value()) : aEncoder.EncodeNull();
+ break;
+ }
+ case Attributes::PendingDatasetTimestamp::Id: {
+ std::optional<uint64_t> pendingDatasetTimestamp = ReadPendingDatasetTimestamp();
+ status = pendingDatasetTimestamp.has_value() ? aEncoder.Encode(pendingDatasetTimestamp.value()) : aEncoder.EncodeNull();
break;
}
default:
diff --git a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h
index 639e7b1..ae8f656 100644
--- a/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h
+++ b/src/app/clusters/thread-border-router-management-server/thread-border-router-management-server.h
@@ -64,25 +64,30 @@
// TODO: Split the business logic from the unit test class
friend class TestThreadBorderRouterManagementCluster;
// Command Handlers
- Status HandleGetActiveDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset)
+ Status HandleGetActiveDatasetRequest(HandlerContext & ctx, Thread::OperationalDataset & dataset)
{
- return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kActive, dataset);
+ return HandleGetDatasetRequest(ctx, Delegate::DatasetType::kActive, dataset);
}
- Status HandleGetPendingDatasetRequest(bool isOverCASESession, Thread::OperationalDataset & dataset)
+ Status HandleGetPendingDatasetRequest(HandlerContext & ctx, Thread::OperationalDataset & dataset)
{
- return HandleGetDatasetRequest(isOverCASESession, Delegate::DatasetType::kPending, dataset);
+ return HandleGetDatasetRequest(ctx, Delegate::DatasetType::kPending, dataset);
}
- Status HandleSetActiveDatasetRequest(CommandHandler * commandHandler,
- const Commands::SetActiveDatasetRequest::DecodableType & req);
- Status HandleSetPendingDatasetRequest(const Commands::SetPendingDatasetRequest::DecodableType & req);
- Status HandleGetDatasetRequest(bool isOverCASESession, Delegate::DatasetType type, Thread::OperationalDataset & dataset);
+ Status HandleSetActiveDatasetRequest(HandlerContext & ctx, const Commands::SetActiveDatasetRequest::DecodableType & req);
+ Status HandleSetPendingDatasetRequest(HandlerContext & ctx, const Commands::SetPendingDatasetRequest::DecodableType & req);
+ Status HandleGetDatasetRequest(HandlerContext & ctx, Delegate::DatasetType type, Thread::OperationalDataset & dataset);
// Attribute Read handlers
void ReadFeatureMap(BitFlags<Feature> & feature);
- Optional<uint64_t> ReadActiveDatasetTimestamp();
+ std::optional<uint64_t> ReadActiveDatasetTimestamp();
+ std::optional<uint64_t> ReadPendingDatasetTimestamp();
CHIP_ERROR ReadBorderRouterName(MutableCharSpan & borderRouterName);
CHIP_ERROR ReadBorderAgentID(MutableByteSpan & borderAgentId);
+#if CONFIG_BUILD_FOR_HOST_UNIT_TEST
+ void SetSkipCASESessionCheck(bool skipCheck) { mSkipCASESessionCheck = skipCheck; }
+ bool mSkipCASESessionCheck;
+#endif
+ bool IsCommandOverCASESession(CommandHandlerInterface::HandlerContext & ctx);
static void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
void OnFailSafeTimerExpired();
void CommitSavedBreadcrumb();
diff --git a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp
index a691582..92018cf 100644
--- a/src/app/tests/TestThreadBorderRouterManagementCluster.cpp
+++ b/src/app/tests/TestThreadBorderRouterManagementCluster.cpp
@@ -17,18 +17,23 @@
#include <app-common/zap-generated/cluster-objects.h>
#include <app/CommandHandler.h>
+#include <app/CommandHandlerInterface.h>
+#include <app/ConcreteCommandPath.h>
#include <app/FailSafeContext.h>
#include <app/clusters/thread-border-router-management-server/thread-border-router-management-server.h>
#include <cstdint>
#include <cstring>
#include <lib/core/CASEAuthTag.h>
#include <lib/core/CHIPError.h>
+#include <lib/core/DataModelTypes.h>
#include <lib/core/Optional.h>
+#include <lib/core/TLVReader.h>
#include <lib/support/BitFlags.h>
#include <lib/support/CHIPMem.h>
#include <lib/support/Span.h>
#include <lib/support/ThreadOperationalDataset.h>
#include <lib/support/tests/ExtraPwTestMacros.h>
+#include <optional>
#include <protocols/interaction_model/StatusCode.h>
#include <pw_unit_test/framework.h>
@@ -153,10 +158,10 @@
static TestDelegate sTestDelegate;
static ServerInstance sTestSeverInstance(kTestEndpointId, &sTestDelegate, sTestFailsafeContext);
-class TestSetActiveDatasetCommandHandler : public CommandHandler
+class TestCommandHandler : public CommandHandler
{
public:
- TestSetActiveDatasetCommandHandler() : mClusterStatus(Protocols::InteractionModel::Status::Success) {}
+ TestCommandHandler() : mClusterStatus(Protocols::InteractionModel::Status::Success) {}
CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aRequestCommandPath,
const Protocols::InteractionModel::ClusterStatusCode & aStatus, const char * context = nullptr)
{
@@ -197,7 +202,7 @@
Protocols::InteractionModel::ClusterStatusCode mClusterStatus;
};
-TestSetActiveDatasetCommandHandler sTestCommandHandler;
+TestCommandHandler sTestCommandHandler;
class TestThreadBorderRouterManagementCluster : public ::testing::Test
{
@@ -256,25 +261,31 @@
EXPECT_TRUE(agentIdSpan.data_equal(ByteSpan(sTestDelegate.kTestBorderAgentId)));
// ActiveDatasetTimestamp attribute
// The active dataset timestamp should be null when no active dataset is configured
- Optional<uint64_t> timestamp = sTestSeverInstance.ReadActiveDatasetTimestamp();
- EXPECT_FALSE(timestamp.HasValue());
+ std::optional<uint64_t> timestamp = sTestSeverInstance.ReadActiveDatasetTimestamp();
+ EXPECT_FALSE(timestamp.has_value());
}
TEST_F_FROM_FIXTURE(TestThreadBorderRouterManagementCluster, TestCommandHandle)
{
// Test GetActiveDatasetRequest and GetPendingDatasetRequest commands
Thread::OperationalDataset dataset;
+ ThreadBorderRouterManagement::Commands::SetActiveDatasetRequest::DecodableType req1;
+ Commands::SetPendingDatasetRequest::DecodableType req2;
using DatasetType = Delegate::DatasetType;
using Status = Protocols::InteractionModel::Status;
- // The GetDataset requests should over CASE session.
- EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(false /* isOverCASESession */, DatasetType::kActive, dataset),
- Status::UnsupportedAccess);
- EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(false, DatasetType::kPending, dataset), Status::UnsupportedAccess);
+ ConcreteCommandPath testPath(kInvalidEndpointId, kInvalidClusterId, kInvalidCommandId);
+ TLV::TLVReader testTLVReader;
+ CommandHandlerInterface::HandlerContext ctx(sTestCommandHandler, testPath, testTLVReader);
+ // All the command should be over CASE session.
+ EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(ctx, DatasetType::kActive, dataset), Status::UnsupportedAccess);
+ EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(ctx, DatasetType::kPending, dataset), Status::UnsupportedAccess);
+ EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(ctx, req1), Status::UnsupportedAccess);
+ EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(ctx, req2), Status::UnsupportedAccess);
+ sTestSeverInstance.SetSkipCASESessionCheck(true);
// The GetDataset should return NotFound when no dataset is configured.
- EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::NotFound);
- EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::NotFound);
+ EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(ctx, DatasetType::kActive, dataset), Status::NotFound);
+ EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(ctx, DatasetType::kPending, dataset), Status::NotFound);
// Test SetActiveDatasetRequest
- ThreadBorderRouterManagement::Commands::SetActiveDatasetRequest::DecodableType req1;
uint8_t invalidDataset[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 };
uint8_t validDataset[] = { 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x0b, 0x35, 0x06,
0x00, 0x04, 0x00, 0x1f, 0xff, 0xe0, 0x02, 0x08, 0xde, 0xaa, 0x00, 0xbe, 0xef, 0x00, 0xca, 0xef, 0x07,
@@ -282,19 +293,19 @@
0xc5, 0x25, 0x7f, 0x68, 0x4c, 0x54, 0x9d, 0x6a, 0x57, 0x5e, 0x03, 0x0a, 0x4f, 0x70, 0x65, 0x6e, 0x54,
0x68, 0x72, 0x65, 0x61, 0x64, 0x01, 0x02, 0xc1, 0x15, 0x04, 0x10, 0xcb, 0x13, 0x47, 0xeb, 0x0c, 0xd4,
0xb3, 0x5c, 0xd1, 0x42, 0xda, 0x5e, 0x6d, 0xf1, 0x8b, 0x88, 0x0c, 0x04, 0x02, 0xa0, 0xf7, 0xf8 };
- Optional<uint64_t> activeDatasetTimestamp = chip::NullOptional;
- activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp();
- EXPECT_FALSE(activeDatasetTimestamp.HasValue());
+ std::optional<uint64_t> activeDatasetTimestamp = std::nullopt;
+ activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp();
+ EXPECT_FALSE(activeDatasetTimestamp.has_value());
req1.activeDataset = ByteSpan(invalidDataset);
// SetActiveDatasetRequest is FailsafeRequired.
- EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::FailsafeRequired);
+ EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(ctx, req1), Status::FailsafeRequired);
EXPECT_EQ(sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)), CHIP_NO_ERROR);
// SetActiveDatasetRequest should return InvalidCommand when dataset is invalid.
- EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::InvalidCommand);
+ EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(ctx, req1), Status::InvalidCommand);
req1.activeDataset = ByteSpan(validDataset);
- EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::Success);
+ EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(ctx, req1), Status::Success);
// When the Server is handling a SetActiveDatasetRequest command, it should return Busy after receiving another one.
- EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::Busy);
+ EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(ctx, req1), Status::Busy);
EXPECT_FALSE(sTestDelegate.mInterfaceEnabled);
EXPECT_EQ(sTestDelegate.mSetActiveDatasetCommandSequenceNum, static_cast<unsigned int>(1));
// Activate the dataset.
@@ -303,30 +314,29 @@
Protocols::InteractionModel::ClusterStatusCode(Protocols::InteractionModel::Status::Success));
sTestFailsafeContext.DisarmFailSafe();
// The Dataset should be updated.
- EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kActive, dataset), Status::Success);
+ EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(ctx, DatasetType::kActive, dataset), Status::Success);
EXPECT_TRUE(dataset.AsByteSpan().data_equal(ByteSpan(validDataset)));
EXPECT_TRUE(sTestDelegate.mInterfaceEnabled);
activeDatasetTimestamp = sTestSeverInstance.ReadActiveDatasetTimestamp();
// activeDatasetTimestamp should have value.
- EXPECT_TRUE(activeDatasetTimestamp.HasValue());
+ EXPECT_TRUE(activeDatasetTimestamp.has_value());
EXPECT_EQ(sTestFailsafeContext.ArmFailSafe(kTestAccessingFabricIndex, System::Clock::Seconds16(1)), CHIP_NO_ERROR);
// When ActiveDatasetTimestamp is not null, the set active dataset request should return InvalidInState.
- EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(&sTestCommandHandler, req1), Status::InvalidInState);
+ EXPECT_EQ(sTestSeverInstance.HandleSetActiveDatasetRequest(ctx, req1), Status::InvalidInState);
sTestFailsafeContext.DisarmFailSafe();
// Test SetPendingDatasetRequest command
- Commands::SetPendingDatasetRequest::DecodableType req2;
sTestDelegate.mPanChangeSupported = false;
req2.pendingDataset = ByteSpan(validDataset);
// SetPendingDatasetRequest is supported when PANChange feature is enabled.
- EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(req2), Status::UnsupportedCommand);
+ EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(ctx, req2), Status::UnsupportedCommand);
sTestDelegate.mPanChangeSupported = true;
req2.pendingDataset = ByteSpan(invalidDataset);
// SetPendingDatasetRequest should return InvalidCommand when dataset is invalid.
- EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(req2), Status::InvalidCommand);
+ EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(ctx, req2), Status::InvalidCommand);
req2.pendingDataset = ByteSpan(validDataset);
// Success SetPendingDatasetRequest
- EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(req2), Status::Success);
- EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(true, DatasetType::kPending, dataset), Status::Success);
+ EXPECT_EQ(sTestSeverInstance.HandleSetPendingDatasetRequest(ctx, req2), Status::Success);
+ EXPECT_EQ(sTestSeverInstance.HandleGetDatasetRequest(ctx, DatasetType::kPending, dataset), Status::Success);
EXPECT_TRUE(dataset.AsByteSpan().data_equal(ByteSpan(validDataset)));
}
diff --git a/src/app/tests/suites/certification/Test_TC_TBRM_2_1.yaml b/src/app/tests/suites/certification/Test_TC_TBRM_2_1.yaml
index dd58b93..7ee1e74 100644
--- a/src/app/tests/suites/certification/Test_TC_TBRM_2_1.yaml
+++ b/src/app/tests/suites/certification/Test_TC_TBRM_2_1.yaml
@@ -74,10 +74,10 @@
response:
constraints:
type: int64u
- # TODO: Attribute missing from cluster XML
- # - label: "TH reads the PendingDatasetTimestamp attribute from the DUT"
- # command: readAttribute
- # attribute: PendingDatasetTimestamp
- # response:
- # constraints:
- # type: int64u
+
+ - label: "TH reads the PendingDatasetTimestamp attribute from the DUT"
+ command: readAttribute
+ attribute: PendingDatasetTimestamp
+ response:
+ constraints:
+ type: int64u
diff --git a/src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml
index d7565e0..d05ce70 100644
--- a/src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml
+++ b/src/app/zap-templates/zcl/data-model/chip/thread-border-router-management-cluster.xml
@@ -43,6 +43,8 @@
<attribute side="server" code="0x0004" apiMaturity="provisional" define="ACTIVE_DATASET_TIMESTAMP" type="int64u" isNullable="true">ActiveDatasetTimestamp</attribute>
+ <attribute side="server" code="0x0005" apiMaturity="provisional" define="PENDING_DATASET_TIMESTAMP" type="int64u" isNullable="true">PendingDatasetTimestamp</attribute>
+
<command source="client" code="0x00" apiMaturity="provisional" name="GetActiveDatasetRequest" response="DatasetResponse" optional="false">
<description>Command to request the active operational dataset of the Thread network to which the border router is connected. This command must be sent over a valid CASE session</description>
<access op="invoke" privilege="manage"/>
diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json
index 4de0247..1273348 100644
--- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json
+++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json
@@ -320,6 +320,7 @@
"ThreadVersion",
"InterfaceEnabled",
"ActiveDatasetTimestamp",
+ "PendingDatasetTimestamp",
"FeatureMap"
],
"Thread Network Diagnostics": [
diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json
index 3a17b76..f4979fb 100644
--- a/src/app/zap-templates/zcl/zcl.json
+++ b/src/app/zap-templates/zcl/zcl.json
@@ -318,6 +318,7 @@
"ThreadVersion",
"InterfaceEnabled",
"ActiveDatasetTimestamp",
+ "PendingDatasetTimestamp",
"FeatureMap"
],
"Thread Network Diagnostics": [
diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter
index 810f828..a6dad3f 100644
--- a/src/controller/data_model/controller-clusters.matter
+++ b/src/controller/data_model/controller-clusters.matter
@@ -8243,6 +8243,7 @@
provisional readonly attribute int16u threadVersion = 2;
provisional readonly attribute boolean interfaceEnabled = 3;
provisional readonly attribute nullable int64u activeDatasetTimestamp = 4;
+ provisional readonly attribute nullable int64u pendingDatasetTimestamp = 5;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java
index 1086397..cdb08fa 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java
@@ -54619,6 +54619,7 @@
private static final long THREAD_VERSION_ATTRIBUTE_ID = 2L;
private static final long INTERFACE_ENABLED_ATTRIBUTE_ID = 3L;
private static final long ACTIVE_DATASET_TIMESTAMP_ATTRIBUTE_ID = 4L;
+ private static final long PENDING_DATASET_TIMESTAMP_ATTRIBUTE_ID = 5L;
private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L;
private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L;
private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L;
@@ -54740,6 +54741,10 @@
void onSuccess(@Nullable Long value);
}
+ public interface PendingDatasetTimestampAttributeCallback extends BaseAttributeCallback {
+ void onSuccess(@Nullable Long value);
+ }
+
public interface GeneratedCommandListAttributeCallback extends BaseAttributeCallback {
void onSuccess(List<Long> value);
}
@@ -54886,6 +54891,32 @@
}, ACTIVE_DATASET_TIMESTAMP_ATTRIBUTE_ID, minInterval, maxInterval);
}
+ public void readPendingDatasetTimestampAttribute(
+ PendingDatasetTimestampAttributeCallback callback) {
+ ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, PENDING_DATASET_TIMESTAMP_ATTRIBUTE_ID);
+
+ readAttribute(new ReportCallbackImpl(callback, path) {
+ @Override
+ public void onSuccess(byte[] tlv) {
+ @Nullable Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv);
+ callback.onSuccess(value);
+ }
+ }, PENDING_DATASET_TIMESTAMP_ATTRIBUTE_ID, true);
+ }
+
+ public void subscribePendingDatasetTimestampAttribute(
+ PendingDatasetTimestampAttributeCallback callback, int minInterval, int maxInterval) {
+ ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, PENDING_DATASET_TIMESTAMP_ATTRIBUTE_ID);
+
+ subscribeAttribute(new ReportCallbackImpl(callback, path) {
+ @Override
+ public void onSuccess(byte[] tlv) {
+ @Nullable Long value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv);
+ callback.onSuccess(value);
+ }
+ }, PENDING_DATASET_TIMESTAMP_ATTRIBUTE_ID, minInterval, maxInterval);
+ }
+
public void readGeneratedCommandListAttribute(
GeneratedCommandListAttributeCallback callback) {
ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID);
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java
index 9a5fd56..6859e8b 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java
@@ -14867,6 +14867,7 @@
ThreadVersion(2L),
InterfaceEnabled(3L),
ActiveDatasetTimestamp(4L),
+ PendingDatasetTimestamp(5L),
GeneratedCommandList(65528L),
AcceptedCommandList(65529L),
EventList(65530L),
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java
index d2703a0..1295c78 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java
@@ -18094,6 +18094,27 @@
}
}
+ public static class DelegatedThreadBorderRouterManagementClusterPendingDatasetTimestampAttributeCallback implements ChipClusters.ThreadBorderRouterManagementCluster.PendingDatasetTimestampAttributeCallback, DelegatedClusterCallback {
+ private ClusterCommandCallback callback;
+ @Override
+ public void setCallbackDelegate(ClusterCommandCallback callback) {
+ this.callback = callback;
+ }
+
+ @Override
+ public void onSuccess(@Nullable Long value) {
+ Map<CommandResponseInfo, Object> responseValues = new LinkedHashMap<>();
+ CommandResponseInfo commandResponseInfo = new CommandResponseInfo("value", "Long");
+ responseValues.put(commandResponseInfo, value);
+ callback.onSuccess(responseValues);
+ }
+
+ @Override
+ public void onError(Exception ex) {
+ callback.onFailure(ex);
+ }
+ }
+
public static class DelegatedThreadBorderRouterManagementClusterGeneratedCommandListAttributeCallback implements ChipClusters.ThreadBorderRouterManagementCluster.GeneratedCommandListAttributeCallback, DelegatedClusterCallback {
private ClusterCommandCallback callback;
@Override
diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java
index 7aa5a71..c96de69 100644
--- a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java
+++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java
@@ -17129,6 +17129,17 @@
readThreadBorderRouterManagementActiveDatasetTimestampCommandParams
);
result.put("readActiveDatasetTimestampAttribute", readThreadBorderRouterManagementActiveDatasetTimestampAttributeInteractionInfo);
+ Map<String, CommandParameterInfo> readThreadBorderRouterManagementPendingDatasetTimestampCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
+ InteractionInfo readThreadBorderRouterManagementPendingDatasetTimestampAttributeInteractionInfo = new InteractionInfo(
+ (cluster, callback, commandArguments) -> {
+ ((ChipClusters.ThreadBorderRouterManagementCluster) cluster).readPendingDatasetTimestampAttribute(
+ (ChipClusters.ThreadBorderRouterManagementCluster.PendingDatasetTimestampAttributeCallback) callback
+ );
+ },
+ () -> new ClusterInfoMapping.DelegatedThreadBorderRouterManagementClusterPendingDatasetTimestampAttributeCallback(),
+ readThreadBorderRouterManagementPendingDatasetTimestampCommandParams
+ );
+ result.put("readPendingDatasetTimestampAttribute", readThreadBorderRouterManagementPendingDatasetTimestampAttributeInteractionInfo);
Map<String, CommandParameterInfo> readThreadBorderRouterManagementGeneratedCommandListCommandParams = new LinkedHashMap<String, CommandParameterInfo>();
InteractionInfo readThreadBorderRouterManagementGeneratedCommandListAttributeInteractionInfo = new InteractionInfo(
(cluster, callback, commandArguments) -> {
diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadBorderRouterManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadBorderRouterManagementCluster.kt
index b212ff7..efbb1b5 100644
--- a/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadBorderRouterManagementCluster.kt
+++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/ThreadBorderRouterManagementCluster.kt
@@ -58,6 +58,17 @@
object SubscriptionEstablished : ActiveDatasetTimestampAttributeSubscriptionState()
}
+ class PendingDatasetTimestampAttribute(val value: ULong?)
+
+ sealed class PendingDatasetTimestampAttributeSubscriptionState {
+ data class Success(val value: ULong?) : PendingDatasetTimestampAttributeSubscriptionState()
+
+ data class Error(val exception: Exception) :
+ PendingDatasetTimestampAttributeSubscriptionState()
+
+ object SubscriptionEstablished : PendingDatasetTimestampAttributeSubscriptionState()
+ }
+
class GeneratedCommandListAttribute(val value: List<UInt>)
sealed class GeneratedCommandListAttributeSubscriptionState {
@@ -655,6 +666,101 @@
}
}
+ suspend fun readPendingDatasetTimestampAttribute(): PendingDatasetTimestampAttribute {
+ val ATTRIBUTE_ID: UInt = 5u
+
+ val attributePath =
+ AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
+
+ val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath))
+
+ val response = controller.read(readRequest)
+
+ if (response.successes.isEmpty()) {
+ logger.log(Level.WARNING, "Read command failed")
+ throw IllegalStateException("Read command failed with failures: ${response.failures}")
+ }
+
+ logger.log(Level.FINE, "Read command succeeded")
+
+ val attributeData =
+ response.successes.filterIsInstance<ReadData.Attribute>().firstOrNull {
+ it.path.attributeId == ATTRIBUTE_ID
+ }
+
+ requireNotNull(attributeData) { "Pendingdatasettimestamp attribute not found in response" }
+
+ // Decode the TLV data into the appropriate type
+ val tlvReader = TlvReader(attributeData.data)
+ val decodedValue: ULong? =
+ if (!tlvReader.isNull()) {
+ tlvReader.getULong(AnonymousTag)
+ } else {
+ tlvReader.getNull(AnonymousTag)
+ null
+ }
+
+ return PendingDatasetTimestampAttribute(decodedValue)
+ }
+
+ suspend fun subscribePendingDatasetTimestampAttribute(
+ minInterval: Int,
+ maxInterval: Int,
+ ): Flow<PendingDatasetTimestampAttributeSubscriptionState> {
+ val ATTRIBUTE_ID: UInt = 5u
+ val attributePaths =
+ listOf(
+ AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID)
+ )
+
+ val subscribeRequest: SubscribeRequest =
+ SubscribeRequest(
+ eventPaths = emptyList(),
+ attributePaths = attributePaths,
+ minInterval = Duration.ofSeconds(minInterval.toLong()),
+ maxInterval = Duration.ofSeconds(maxInterval.toLong()),
+ )
+
+ return controller.subscribe(subscribeRequest).transform { subscriptionState ->
+ when (subscriptionState) {
+ is SubscriptionState.SubscriptionErrorNotification -> {
+ emit(
+ PendingDatasetTimestampAttributeSubscriptionState.Error(
+ Exception(
+ "Subscription terminated with error code: ${subscriptionState.terminationCause}"
+ )
+ )
+ )
+ }
+ is SubscriptionState.NodeStateUpdate -> {
+ val attributeData =
+ subscriptionState.updateState.successes
+ .filterIsInstance<ReadData.Attribute>()
+ .firstOrNull { it.path.attributeId == ATTRIBUTE_ID }
+
+ requireNotNull(attributeData) {
+ "Pendingdatasettimestamp attribute not found in Node State update"
+ }
+
+ // Decode the TLV data into the appropriate type
+ val tlvReader = TlvReader(attributeData.data)
+ val decodedValue: ULong? =
+ if (!tlvReader.isNull()) {
+ tlvReader.getULong(AnonymousTag)
+ } else {
+ tlvReader.getNull(AnonymousTag)
+ null
+ }
+
+ decodedValue?.let { emit(PendingDatasetTimestampAttributeSubscriptionState.Success(it)) }
+ }
+ SubscriptionState.SubscriptionEstablished -> {
+ emit(PendingDatasetTimestampAttributeSubscriptionState.SubscriptionEstablished)
+ }
+ }
+ }
+ }
+
suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute {
val ATTRIBUTE_ID: UInt = 65528u
diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
index ebcec56..ffa1de1 100644
--- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
+++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp
@@ -38890,6 +38890,29 @@
}
return value;
}
+ case Attributes::PendingDatasetTimestamp::Id: {
+ using TypeInfo = Attributes::PendingDatasetTimestamp::TypeInfo;
+ TypeInfo::DecodableType cppValue;
+ *aError = app::DataModel::Decode(aReader, cppValue);
+ if (*aError != CHIP_NO_ERROR)
+ {
+ return nullptr;
+ }
+ jobject value;
+ if (cppValue.IsNull())
+ {
+ value = nullptr;
+ }
+ else
+ {
+ std::string valueClassName = "java/lang/Long";
+ std::string valueCtorSignature = "(J)V";
+ jlong jnivalue = static_cast<jlong>(cppValue.Value());
+ chip::JniReferences::GetInstance().CreateBoxedObject<jlong>(valueClassName.c_str(), valueCtorSignature.c_str(),
+ jnivalue, value);
+ }
+ return value;
+ }
case Attributes::GeneratedCommandList::Id: {
using TypeInfo = Attributes::GeneratedCommandList::TypeInfo;
TypeInfo::DecodableType cppValue;
diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py
index e897286..3c67676 100644
--- a/src/controller/python/chip/clusters/CHIPClusters.py
+++ b/src/controller/python/chip/clusters/CHIPClusters.py
@@ -11970,6 +11970,12 @@
"type": "int",
"reportable": True,
},
+ 0x00000005: {
+ "attributeName": "PendingDatasetTimestamp",
+ "attributeId": 0x00000005,
+ "type": "int",
+ "reportable": True,
+ },
0x0000FFF8: {
"attributeName": "GeneratedCommandList",
"attributeId": 0x0000FFF8,
diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py
index 670c710..92ea677 100644
--- a/src/controller/python/chip/clusters/Objects.py
+++ b/src/controller/python/chip/clusters/Objects.py
@@ -42067,6 +42067,7 @@
ClusterObjectFieldDescriptor(Label="threadVersion", Tag=0x00000002, Type=uint),
ClusterObjectFieldDescriptor(Label="interfaceEnabled", Tag=0x00000003, Type=bool),
ClusterObjectFieldDescriptor(Label="activeDatasetTimestamp", Tag=0x00000004, Type=typing.Union[Nullable, uint]),
+ ClusterObjectFieldDescriptor(Label="pendingDatasetTimestamp", Tag=0x00000005, Type=typing.Union[Nullable, uint]),
ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]),
ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]),
ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]),
@@ -42080,6 +42081,7 @@
threadVersion: 'uint' = None
interfaceEnabled: 'bool' = None
activeDatasetTimestamp: 'typing.Union[Nullable, uint]' = None
+ pendingDatasetTimestamp: 'typing.Union[Nullable, uint]' = None
generatedCommandList: 'typing.List[uint]' = None
acceptedCommandList: 'typing.List[uint]' = None
eventList: 'typing.List[uint]' = None
@@ -42250,6 +42252,22 @@
value: 'typing.Union[Nullable, uint]' = NullValue
@dataclass
+ class PendingDatasetTimestamp(ClusterAttributeDescriptor):
+ @ChipUtility.classproperty
+ def cluster_id(cls) -> int:
+ return 0x00000452
+
+ @ChipUtility.classproperty
+ def attribute_id(cls) -> int:
+ return 0x00000005
+
+ @ChipUtility.classproperty
+ def attribute_type(cls) -> ClusterObjectFieldDescriptor:
+ return ClusterObjectFieldDescriptor(Type=typing.Union[Nullable, uint])
+
+ value: 'typing.Union[Nullable, uint]' = NullValue
+
+ @dataclass
class GeneratedCommandList(ClusterAttributeDescriptor):
@ChipUtility.classproperty
def cluster_id(cls) -> int:
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm
index 06aa9c0..925ef9c 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm
@@ -5490,6 +5490,9 @@
case Attributes::ActiveDatasetTimestamp::Id: {
return YES;
}
+ case Attributes::PendingDatasetTimestamp::Id: {
+ return YES;
+ }
case Attributes::GeneratedCommandList::Id: {
return YES;
}
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm
index 95001d3..332c53d 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm
@@ -15879,6 +15879,21 @@
}
return value;
}
+ case Attributes::PendingDatasetTimestamp::Id: {
+ using TypeInfo = Attributes::PendingDatasetTimestamp::TypeInfo;
+ TypeInfo::DecodableType cppValue;
+ *aError = DataModel::Decode(aReader, cppValue);
+ if (*aError != CHIP_NO_ERROR) {
+ return nil;
+ }
+ NSNumber * _Nullable value;
+ if (cppValue.IsNull()) {
+ value = nil;
+ } else {
+ value = [NSNumber numberWithUnsignedLongLong:cppValue.Value()];
+ }
+ return value;
+ }
default: {
break;
}
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
index b8dfaa1..5456773 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h
@@ -13493,6 +13493,12 @@
reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE;
+ (void)readAttributeActiveDatasetTimestampWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE;
+- (void)readAttributePendingDatasetTimestampWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE;
+- (void)subscribeAttributePendingDatasetTimestampWithParams:(MTRSubscribeParams *)params
+ subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
+ reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE;
++ (void)readAttributePendingDatasetTimestampWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE;
+
- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE;
- (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params
subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
index 2cd1653..992d7ce 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm
@@ -95178,6 +95178,42 @@
completion:completion];
}
+- (void)readAttributePendingDatasetTimestampWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
+{
+ using TypeInfo = ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::TypeInfo;
+ [self.device _readKnownAttributeWithEndpointID:self.endpointID
+ clusterID:@(TypeInfo::GetClusterId())
+ attributeID:@(TypeInfo::GetAttributeId())
+ params:nil
+ queue:self.callbackQueue
+ completion:completion];
+}
+
+- (void)subscribeAttributePendingDatasetTimestampWithParams:(MTRSubscribeParams * _Nonnull)params
+ subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished
+ reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler
+{
+ using TypeInfo = ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::TypeInfo;
+ [self.device _subscribeToKnownAttributeWithEndpointID:self.endpointID
+ clusterID:@(TypeInfo::GetClusterId())
+ attributeID:@(TypeInfo::GetAttributeId())
+ params:params
+ queue:self.callbackQueue
+ reportHandler:reportHandler
+ subscriptionEstablished:subscriptionEstablished];
+}
+
++ (void)readAttributePendingDatasetTimestampWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion
+{
+ using TypeInfo = ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::TypeInfo;
+ [clusterStateCacheContainer
+ _readKnownCachedAttributeWithEndpointID:static_cast<chip::EndpointId>([endpoint unsignedShortValue])
+ clusterID:TypeInfo::GetClusterId()
+ attributeID:TypeInfo::GetAttributeId()
+ queue:queue
+ completion:completion];
+}
+
- (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion
{
using TypeInfo = ThreadBorderRouterManagement::Attributes::GeneratedCommandList::TypeInfo;
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
index aa19732..2e5c8cc 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h
@@ -4432,6 +4432,7 @@
MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeThreadVersionID MTR_PROVISIONALLY_AVAILABLE = 0x00000002,
MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeInterfaceEnabledID MTR_PROVISIONALLY_AVAILABLE = 0x00000003,
MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeActiveDatasetTimestampID MTR_PROVISIONALLY_AVAILABLE = 0x00000004,
+ MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributePendingDatasetTimestampID MTR_PROVISIONALLY_AVAILABLE = 0x00000005,
MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID,
MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID,
MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID,
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm
index 3383cab..fa08192 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterNames.mm
@@ -7598,6 +7598,10 @@
result = @"ActiveDatasetTimestamp";
break;
+ case MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributePendingDatasetTimestampID:
+ result = @"PendingDatasetTimestamp";
+ break;
+
case MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeGeneratedCommandListID:
result = @"GeneratedCommandList";
break;
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
index 6b44112..4a2c3d6 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h
@@ -6230,6 +6230,8 @@
- (NSDictionary<NSString *, id> * _Nullable)readAttributeActiveDatasetTimestampWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE;
+- (NSDictionary<NSString *, id> * _Nullable)readAttributePendingDatasetTimestampWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE;
+
- (NSDictionary<NSString *, id> * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE;
- (NSDictionary<NSString *, id> * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE;
diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
index 361abcf..90ff967 100644
--- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
+++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm
@@ -17340,6 +17340,11 @@
return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeThreadBorderRouterManagementID) attributeID:@(MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeActiveDatasetTimestampID) params:params];
}
+- (NSDictionary<NSString *, id> * _Nullable)readAttributePendingDatasetTimestampWithParams:(MTRReadParams * _Nullable)params
+{
+ return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeThreadBorderRouterManagementID) attributeID:@(MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributePendingDatasetTimestampID) params:params];
+}
+
- (NSDictionary<NSString *, id> * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params
{
return [self.device readAttributeWithEndpointID:self.endpointID clusterID:@(MTRClusterIDTypeThreadBorderRouterManagementID) attributeID:@(MTRAttributeIDTypeClusterThreadBorderRouterManagementAttributeGeneratedCommandListID) params:params];
diff --git a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp
index e1efc53..b08b0ab 100644
--- a/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp
+++ b/src/platform/OpenThread/GenericThreadBorderRouterDelegate.cpp
@@ -167,6 +167,12 @@
delegate->mpAttributeChangeCallback->ReportAttributeChanged(Attributes::ActiveDatasetTimestamp::Id);
});
}
+ if (event->ThreadStateChange.OpenThread.Flags & OT_CHANGED_PENDING_DATASET)
+ {
+ DeviceLayer::SystemLayer().ScheduleLambda([delegate]() {
+ delegate->mpAttributeChangeCallback->ReportAttributeChanged(Attributes::PendingDatasetTimestamp::Id);
+ });
+ }
}
}
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 bea7e01..878090f 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
@@ -24398,6 +24398,8 @@
return DataModel::Decode(reader, interfaceEnabled);
case Attributes::ActiveDatasetTimestamp::TypeInfo::GetAttributeId():
return DataModel::Decode(reader, activeDatasetTimestamp);
+ case Attributes::PendingDatasetTimestamp::TypeInfo::GetAttributeId():
+ return DataModel::Decode(reader, pendingDatasetTimestamp);
case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId():
return DataModel::Decode(reader, generatedCommandList);
case Attributes::AcceptedCommandList::TypeInfo::GetAttributeId():
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 07107fe..472ce88 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
@@ -36667,6 +36667,18 @@
static constexpr bool MustUseTimedWrite() { return false; }
};
} // namespace ActiveDatasetTimestamp
+namespace PendingDatasetTimestamp {
+struct TypeInfo
+{
+ using Type = chip::app::DataModel::Nullable<uint64_t>;
+ using DecodableType = chip::app::DataModel::Nullable<uint64_t>;
+ using DecodableArgType = const chip::app::DataModel::Nullable<uint64_t> &;
+
+ static constexpr ClusterId GetClusterId() { return Clusters::ThreadBorderRouterManagement::Id; }
+ static constexpr AttributeId GetAttributeId() { return Attributes::PendingDatasetTimestamp::Id; }
+ static constexpr bool MustUseTimedWrite() { return false; }
+};
+} // namespace PendingDatasetTimestamp
namespace GeneratedCommandList {
struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo
{
@@ -36717,6 +36729,7 @@
Attributes::ThreadVersion::TypeInfo::DecodableType threadVersion = static_cast<uint16_t>(0);
Attributes::InterfaceEnabled::TypeInfo::DecodableType interfaceEnabled = static_cast<bool>(0);
Attributes::ActiveDatasetTimestamp::TypeInfo::DecodableType activeDatasetTimestamp;
+ Attributes::PendingDatasetTimestamp::TypeInfo::DecodableType pendingDatasetTimestamp;
Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList;
Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList;
Attributes::EventList::TypeInfo::DecodableType eventList;
diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h
index b78c1e3..85d56a9 100644
--- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h
+++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h
@@ -6826,6 +6826,10 @@
static constexpr AttributeId Id = 0x00000004;
} // namespace ActiveDatasetTimestamp
+namespace PendingDatasetTimestamp {
+static constexpr AttributeId Id = 0x00000005;
+} // namespace PendingDatasetTimestamp
+
namespace GeneratedCommandList {
static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id;
} // namespace GeneratedCommandList
diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
index 98d6d9c..3bd7961 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
+++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h
@@ -11337,6 +11337,7 @@
| * ThreadVersion | 0x0002 |
| * InterfaceEnabled | 0x0003 |
| * ActiveDatasetTimestamp | 0x0004 |
+| * PendingDatasetTimestamp | 0x0005 |
| * GeneratedCommandList | 0xFFF8 |
| * AcceptedCommandList | 0xFFF9 |
| * EventList | 0xFFFA |
@@ -25680,19 +25681,20 @@
//
// Attributes
//
- make_unique<ReadAttribute>(Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "border-router-name", Attributes::BorderRouterName::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "border-agent-id", Attributes::BorderAgentID::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "thread-version", Attributes::ThreadVersion::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "interface-enabled", Attributes::InterfaceEnabled::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "active-dataset-timestamp", Attributes::ActiveDatasetTimestamp::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "feature-map", Attributes::FeatureMap::Id, credsIssuerConfig), //
- make_unique<ReadAttribute>(Id, "cluster-revision", Attributes::ClusterRevision::Id, credsIssuerConfig), //
- make_unique<WriteAttribute<>>(Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "border-router-name", Attributes::BorderRouterName::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "border-agent-id", Attributes::BorderAgentID::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "thread-version", Attributes::ThreadVersion::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "interface-enabled", Attributes::InterfaceEnabled::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "active-dataset-timestamp", Attributes::ActiveDatasetTimestamp::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "pending-dataset-timestamp", Attributes::PendingDatasetTimestamp::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "attribute-list", Attributes::AttributeList::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "feature-map", Attributes::FeatureMap::Id, credsIssuerConfig), //
+ make_unique<ReadAttribute>(Id, "cluster-revision", Attributes::ClusterRevision::Id, credsIssuerConfig), //
+ make_unique<WriteAttribute<>>(Id, credsIssuerConfig), //
make_unique<WriteAttribute<chip::CharSpan>>(Id, "border-router-name", Attributes::BorderRouterName::Id,
WriteCommandType::kForceWrite, credsIssuerConfig), //
make_unique<WriteAttribute<chip::ByteSpan>>(Id, "border-agent-id", Attributes::BorderAgentID::Id,
@@ -25704,6 +25706,9 @@
make_unique<WriteAttribute<chip::app::DataModel::Nullable<uint64_t>>>(Id, "active-dataset-timestamp", 0, UINT64_MAX,
Attributes::ActiveDatasetTimestamp::Id,
WriteCommandType::kForceWrite, credsIssuerConfig), //
+ make_unique<WriteAttribute<chip::app::DataModel::Nullable<uint64_t>>>(Id, "pending-dataset-timestamp", 0, UINT64_MAX,
+ Attributes::PendingDatasetTimestamp::Id,
+ WriteCommandType::kForceWrite, credsIssuerConfig), //
make_unique<WriteAttributeAsComplex<chip::app::DataModel::List<const chip::CommandId>>>(
Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite,
credsIssuerConfig), //
@@ -25723,6 +25728,8 @@
make_unique<SubscribeAttribute>(Id, "thread-version", Attributes::ThreadVersion::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "interface-enabled", Attributes::InterfaceEnabled::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "active-dataset-timestamp", Attributes::ActiveDatasetTimestamp::Id,
+ credsIssuerConfig), //
+ make_unique<SubscribeAttribute>(Id, "pending-dataset-timestamp", Attributes::PendingDatasetTimestamp::Id,
credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), //
make_unique<SubscribeAttribute>(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), //
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 afebe69..51f73a1 100644
--- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
+++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp
@@ -17232,6 +17232,11 @@
ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value));
return DataModelLogger::LogValue("ActiveDatasetTimestamp", 1, value);
}
+ case ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::Id: {
+ chip::app::DataModel::Nullable<uint64_t> value;
+ ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value));
+ return DataModelLogger::LogValue("PendingDatasetTimestamp", 1, value);
+ }
case ThreadBorderRouterManagement::Attributes::GeneratedCommandList::Id: {
chip::app::DataModel::DecodableList<chip::CommandId> value;
ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value));
diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
index 8e18e60..3ca43d8 100644
--- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
+++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h
@@ -147933,6 +147933,7 @@
| * ThreadVersion | 0x0002 |
| * InterfaceEnabled | 0x0003 |
| * ActiveDatasetTimestamp | 0x0004 |
+| * PendingDatasetTimestamp | 0x0005 |
| * GeneratedCommandList | 0xFFF8 |
| * AcceptedCommandList | 0xFFF9 |
| * EventList | 0xFFFA |
@@ -148592,6 +148593,91 @@
#if MTR_ENABLE_PROVISIONAL
/*
+ * Attribute PendingDatasetTimestamp
+ */
+class ReadThreadBorderRouterManagementPendingDatasetTimestamp : public ReadAttribute {
+public:
+ ReadThreadBorderRouterManagementPendingDatasetTimestamp()
+ : ReadAttribute("pending-dataset-timestamp")
+ {
+ }
+
+ ~ReadThreadBorderRouterManagementPendingDatasetTimestamp()
+ {
+ }
+
+ CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
+ {
+ constexpr chip::ClusterId clusterId = chip::app::Clusters::ThreadBorderRouterManagement::Id;
+ constexpr chip::AttributeId attributeId = chip::app::Clusters::ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::Id;
+
+ ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId);
+
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
+ __auto_type * cluster = [[MTRBaseClusterThreadBorderRouterManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
+ [cluster readAttributePendingDatasetTimestampWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) {
+ NSLog(@"ThreadBorderRouterManagement.PendingDatasetTimestamp response %@", [value description]);
+ if (error == nil) {
+ RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value);
+ } else {
+ LogNSError("ThreadBorderRouterManagement PendingDatasetTimestamp read Error", error);
+ RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error);
+ }
+ SetCommandExitStatus(error);
+ }];
+ return CHIP_NO_ERROR;
+ }
+};
+
+class SubscribeAttributeThreadBorderRouterManagementPendingDatasetTimestamp : public SubscribeAttribute {
+public:
+ SubscribeAttributeThreadBorderRouterManagementPendingDatasetTimestamp()
+ : SubscribeAttribute("pending-dataset-timestamp")
+ {
+ }
+
+ ~SubscribeAttributeThreadBorderRouterManagementPendingDatasetTimestamp()
+ {
+ }
+
+ CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override
+ {
+ constexpr chip::ClusterId clusterId = chip::app::Clusters::ThreadBorderRouterManagement::Id;
+ constexpr chip::CommandId attributeId = chip::app::Clusters::ThreadBorderRouterManagement::Attributes::PendingDatasetTimestamp::Id;
+
+ ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId);
+ dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL);
+ __auto_type * cluster = [[MTRBaseClusterThreadBorderRouterManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue];
+ __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)];
+ if (mKeepSubscriptions.HasValue()) {
+ params.replaceExistingSubscriptions = !mKeepSubscriptions.Value();
+ }
+ if (mFabricFiltered.HasValue()) {
+ params.filterByFabric = mFabricFiltered.Value();
+ }
+ if (mAutoResubscribe.HasValue()) {
+ params.resubscribeAutomatically = mAutoResubscribe.Value();
+ }
+ [cluster subscribeAttributePendingDatasetTimestampWithParams:params
+ subscriptionEstablished:^() { mSubscriptionEstablished = YES; }
+ reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) {
+ NSLog(@"ThreadBorderRouterManagement.PendingDatasetTimestamp response %@", [value description]);
+ if (error == nil) {
+ RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value);
+ } else {
+ RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error);
+ }
+ SetCommandExitStatus(error);
+ }];
+
+ return CHIP_NO_ERROR;
+ }
+};
+
+#endif // MTR_ENABLE_PROVISIONAL
+#if MTR_ENABLE_PROVISIONAL
+
+/*
* Attribute GeneratedCommandList
*/
class ReadThreadBorderRouterManagementGeneratedCommandList : public ReadAttribute {
@@ -197665,6 +197751,10 @@
make_unique<SubscribeAttributeThreadBorderRouterManagementActiveDatasetTimestamp>(), //
#endif // MTR_ENABLE_PROVISIONAL
#if MTR_ENABLE_PROVISIONAL
+ make_unique<ReadThreadBorderRouterManagementPendingDatasetTimestamp>(), //
+ make_unique<SubscribeAttributeThreadBorderRouterManagementPendingDatasetTimestamp>(), //
+#endif // MTR_ENABLE_PROVISIONAL
+#if MTR_ENABLE_PROVISIONAL
make_unique<ReadThreadBorderRouterManagementGeneratedCommandList>(), //
make_unique<SubscribeAttributeThreadBorderRouterManagementGeneratedCommandList>(), //
#endif // MTR_ENABLE_PROVISIONAL