diff --git a/src/app/WriteHandler.cpp b/src/app/WriteHandler.cpp index 09a9ec0079e901..1974d7e40ce71b 100644 --- a/src/app/WriteHandler.cpp +++ b/src/app/WriteHandler.cpp @@ -258,17 +258,19 @@ CHIP_ERROR WriteHandler::SendWriteResponse(System::PacketBufferTLVWriter && aMes void WriteHandler::DeliverListWriteBegin(const ConcreteAttributePath & aPath) { - if (auto * attrOverride = AttributeAccessInterfaceRegistry::Instance().Get(aPath.mEndpointId, aPath.mClusterId)) + if (mDataModelProvider != nullptr) { - attrOverride->OnListWriteBegin(aPath); + mDataModelProvider->ListAttributeWriteNotification(aPath, DataModel::ListWriteOperation::kListWriteBegin); } } void WriteHandler::DeliverListWriteEnd(const ConcreteAttributePath & aPath, bool writeWasSuccessful) { - if (auto * attrOverride = AttributeAccessInterfaceRegistry::Instance().Get(aPath.mEndpointId, aPath.mClusterId)) + if (mDataModelProvider != nullptr) { - attrOverride->OnListWriteEnd(aPath, writeWasSuccessful); + mDataModelProvider->ListAttributeWriteNotification(aPath, + writeWasSuccessful ? DataModel::ListWriteOperation::kListWriteSuccess + : DataModel::ListWriteOperation::kListWriteFailure); } } diff --git a/src/app/data-model-provider/OperationTypes.h b/src/app/data-model-provider/OperationTypes.h index 35d1654ac12568..51b8056c6fb7c6 100644 --- a/src/app/data-model-provider/OperationTypes.h +++ b/src/app/data-model-provider/OperationTypes.h @@ -73,6 +73,13 @@ enum class ReadFlags : uint32_t kFabricFiltered = 0x0001, // reading is performed fabric-filtered }; +enum class ListWriteOperation : uint8_t +{ + kListWriteBegin = 0, + kListWriteSuccess, + kListWriteFailure +}; + struct ReadAttributeRequest : OperationRequest { ConcreteAttributePath path; diff --git a/src/app/data-model-provider/Provider.h b/src/app/data-model-provider/Provider.h index fc5a204c869785..27a86b63fa0cf2 100644 --- a/src/app/data-model-provider/Provider.h +++ b/src/app/data-model-provider/Provider.h @@ -79,6 +79,15 @@ class Provider : public ProviderMetadataTree /// - validation of ACL/timed interaction flags/writability, if those checks are desired. virtual ActionReturnStatus WriteAttribute(const WriteAttributeRequest & request, AttributeValueDecoder & decoder) = 0; + /// Indicates the start/end of a series of list operations. This function will be called either before the first + /// Write operation or after the last one of a series of consecutive attribute data of the same attribute. + /// + /// 1) This function will be called if the client tries to set a nullable list attribute to null. + /// 2) This function will only be called at the beginning and end of a series of consecutive attribute data + /// blocks for the same attribute, no matter what list operations those data blocks represent. + /// 3) The opType argument indicates the type of notification (Start, Failure, Success). + virtual void ListAttributeWriteNotification(const ConcreteAttributePath & aPath, ListWriteOperation opType) = 0; + /// `handler` is used to send back the reply. /// - returning `std::nullopt` means that return value was placed in handler directly. /// This includes cases where command handling and value return will be done asynchronously. diff --git a/src/data-model-providers/codegen/CodegenDataModelProvider.h b/src/data-model-providers/codegen/CodegenDataModelProvider.h index 764f5f74874673..9edea20ed6a7a7 100644 --- a/src/data-model-providers/codegen/CodegenDataModelProvider.h +++ b/src/data-model-providers/codegen/CodegenDataModelProvider.h @@ -63,6 +63,7 @@ class CodegenDataModelProvider : public DataModel::Provider AttributeValueEncoder & encoder) override; DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request, AttributeValueDecoder & decoder) override; + void ListAttributeWriteNotification(const ConcreteAttributePath & aPath, DataModel::ListWriteOperation opType) override; std::optional Invoke(const DataModel::InvokeRequest & request, TLV::TLVReader & input_arguments, CommandHandler * handler) override; diff --git a/src/data-model-providers/codegen/CodegenDataModelProvider_Write.cpp b/src/data-model-providers/codegen/CodegenDataModelProvider_Write.cpp index 3160bbdaf26722..647ea9d4c0e65b 100644 --- a/src/data-model-providers/codegen/CodegenDataModelProvider_Write.cpp +++ b/src/data-model-providers/codegen/CodegenDataModelProvider_Write.cpp @@ -198,6 +198,28 @@ DataModel::ActionReturnStatus CodegenDataModelProvider::WriteAttribute(const Dat return CHIP_NO_ERROR; } +void CodegenDataModelProvider::ListAttributeWriteNotification(const ConcreteAttributePath & aPath, + DataModel::ListWriteOperation opType) +{ + AttributeAccessInterface * aai = AttributeAccessInterfaceRegistry::Instance().Get(aPath.mEndpointId, aPath.mClusterId); + + if (aai != nullptr) + { + switch (opType) + { + case DataModel::ListWriteOperation::kListWriteBegin: + aai->OnListWriteBegin(aPath); + break; + case DataModel::ListWriteOperation::kListWriteFailure: + aai->OnListWriteEnd(aPath, false); + break; + case DataModel::ListWriteOperation::kListWriteSuccess: + aai->OnListWriteEnd(aPath, true); + break; + } + } +} + void CodegenDataModelProvider::Temporary_ReportAttributeChanged(const AttributePathParams & path) { ContextAttributesChangeListener change_listener(CurrentContext());