diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 5fc0d0c8b97583..28179390cfa8dc 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -186,7 +186,6 @@ static_library("interaction-model") { "WriteClient.h", "reporting/Engine.cpp", "reporting/Engine.h", - "reporting/Read.h", "reporting/ReportScheduler.h", "reporting/ReportSchedulerImpl.cpp", "reporting/ReportSchedulerImpl.h", @@ -199,8 +198,6 @@ static_library("interaction-model") { # # This breaks having `.h` and `.cpp` based off the same compilation unit and # should ideally be cleaned up. - "reporting/Read.cpp", - "reporting/Read.h", "reporting/reporting.h", ] diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index 284aa6fa66db06..ea4c0014e71397 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include @@ -53,6 +52,87 @@ Status EventPathValid(DataModel::Provider * model, const ConcreteEventPath & eve return Status::Success; } +DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, + const Access::SubjectDescriptor & subjectDescriptor, bool isFabricFiltered, + AttributeReportIBs::Builder & reportBuilder, + const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) +{ + ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, + path.mAttributeId); + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Pre, path); + + DataModel::ReadAttributeRequest readRequest; + + if (isFabricFiltered) + { + readRequest.readFlags.Set(DataModel::ReadFlags::kFabricFiltered); + } + readRequest.subjectDescriptor = &subjectDescriptor; + readRequest.path = path; + + DataVersion version = 0; + if (std::optional clusterInfo = dataModel->GetClusterInfo(path); clusterInfo.has_value()) + { + version = clusterInfo->dataVersion; + } + else + { + ChipLogError(DataManagement, "Read request on unknown cluster - no data version available"); + } + + TLV::TLVWriter checkpoint; + reportBuilder.Checkpoint(checkpoint); + + AttributeValueEncoder attributeValueEncoder(reportBuilder, subjectDescriptor, path, version, isFabricFiltered, encoderState); + + DataModel::ActionReturnStatus status = dataModel->ReadAttribute(readRequest, attributeValueEncoder); + + if (status.IsSuccess()) + { + // TODO: this callback being only executed on success is awkward. The Write callback is always done + // for both read and write. + // + // For now this preserves existing/previous code logic, however we should consider to ALWAYS + // call this. + DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, + DataModelCallbacks::OperationOrder::Post, path); + return status; + } + + // Encoder state is relevant for errors in case they are retryable. + // + // Generally only out of space encoding errors would be retryable, however we save the state + // for all errors in case this is information that is useful (retry or error position). + if (encoderState != nullptr) + { + *encoderState = attributeValueEncoder.GetState(); + } + +#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING + // Out of space errors may be chunked data, reporting those cases would be very confusing + // as they are not fully errors. Report only others (which presumably are not recoverable + // and will be sent to the client as well). + if (!status.IsOutOfSpaceEncodingResponse()) + { + DataModel::ActionReturnStatus::StringStorage storage; + ChipLogError(DataManagement, "Failed to read attribute: %s", status.c_str(storage)); + } +#endif + return status; +} + +bool IsClusterDataVersionEqualTo(DataModel::Provider * dataModel, const ConcreteClusterPath & path, DataVersion dataVersion) +{ + std::optional info = dataModel->GetClusterInfo(path); + if (!info.has_value()) + { + return false; + } + + return (info->dataVersion == dataVersion); +} + } // namespace Engine::Engine(InteractionModelEngine * apImEngine) : mpImEngine(apImEngine) {} @@ -85,9 +165,9 @@ bool Engine::IsClusterDataVersionMatch(const SingleLinkedListNodeGetDataModelProvider(), - ConcreteClusterPath(filter->mValue.mEndpointId, filter->mValue.mClusterId), - filter->mValue.mDataVersion.Value())) + if (!IsClusterDataVersionEqualTo(mpImEngine->GetDataModelProvider(), + ConcreteClusterPath(filter->mValue.mEndpointId, filter->mValue.mClusterId), + filter->mValue.mDataVersion.Value())) { existVersionMismatch = true; } @@ -199,8 +279,8 @@ CHIP_ERROR Engine::BuildSingleReportDataAttributeReportIBs(ReportDataMessage::Bu // Load the saved state from previous encoding session for chunking of one single attribute (list chunking). AttributeEncodeState encodeState = apReadHandler->GetAttributeEncodeState(); DataModel::ActionReturnStatus status = - Impl::RetrieveClusterData(mpImEngine->GetDataModelProvider(), apReadHandler->GetSubjectDescriptor(), - apReadHandler->IsFabricFiltered(), attributeReportIBs, pathForRetrieval, &encodeState); + RetrieveClusterData(mpImEngine->GetDataModelProvider(), apReadHandler->GetSubjectDescriptor(), + apReadHandler->IsFabricFiltered(), attributeReportIBs, pathForRetrieval, &encodeState); if (status.IsError()) { // Operation error set, since this will affect early return or override on status encoding diff --git a/src/app/reporting/Read.cpp b/src/app/reporting/Read.cpp deleted file mode 100644 index db55b14cd257b3..00000000000000 --- a/src/app/reporting/Read.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2024 Project CHIP Authors - * All rights reserved. - * - * 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. - */ -#include - -#include -#include -#include -#include -#include -#include - -namespace chip { -namespace app { -namespace reporting { -namespace Impl { - -DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, - const Access::SubjectDescriptor & subjectDescriptor, bool isFabricFiltered, - AttributeReportIBs::Builder & reportBuilder, - const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState) -{ - ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Attribute %" PRIx32 " is dirty", path.mClusterId, - path.mAttributeId); - DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, - DataModelCallbacks::OperationOrder::Pre, path); - - DataModel::ReadAttributeRequest readRequest; - - if (isFabricFiltered) - { - readRequest.readFlags.Set(DataModel::ReadFlags::kFabricFiltered); - } - readRequest.subjectDescriptor = &subjectDescriptor; - readRequest.path = path; - - DataVersion version = 0; - if (std::optional clusterInfo = dataModel->GetClusterInfo(path); clusterInfo.has_value()) - { - version = clusterInfo->dataVersion; - } - else - { - ChipLogError(DataManagement, "Read request on unknown cluster - no data version available"); - } - - TLV::TLVWriter checkpoint; - reportBuilder.Checkpoint(checkpoint); - - AttributeValueEncoder attributeValueEncoder(reportBuilder, subjectDescriptor, path, version, isFabricFiltered, encoderState); - - DataModel::ActionReturnStatus status = dataModel->ReadAttribute(readRequest, attributeValueEncoder); - - if (status.IsSuccess()) - { - // Odd ifdef is to only do this if the `Read-Check` does not do it already. - // TODO: this callback being only executed on success is awkward. The Write callback is always done - // for both read and write. - // - // For now this preserves existing/previous code logic, however we should consider to ALWAYS - // call this. - DataModelCallbacks::GetInstance()->AttributeOperation(DataModelCallbacks::OperationType::Read, - DataModelCallbacks::OperationOrder::Post, path); - return status; - } - - // Encoder state is relevant for errors in case they are retryable. - // - // Generally only out of space encoding errors would be retryable, however we save the state - // for all errors in case this is information that is useful (retry or error position). - if (encoderState != nullptr) - { - *encoderState = attributeValueEncoder.GetState(); - } - - // Out of space errors may be chunked data, reporting those cases would be very confusing - // as they are not fully errors. Report only others (which presumably are not recoverable - // and will be sent to the client as well). - if (!status.IsOutOfSpaceEncodingResponse()) - { - DataModel::ActionReturnStatus::StringStorage storage; -#if CHIP_CONFIG_DATA_MODEL_EXTRA_LOGGING - ChipLogError(DataManagement, "Failed to read attribute: %s", status.c_str(storage)); -#endif - } - return status; -} - -bool IsClusterDataVersionEqualTo(DataModel::Provider * dataModel, const ConcreteClusterPath & path, DataVersion dataVersion) -{ - std::optional info = dataModel->GetClusterInfo(path); - if (!info.has_value()) - { - return false; - } - - return (info->dataVersion == dataVersion); -} - -} // namespace Impl -} // namespace reporting -} // namespace app -} // namespace chip diff --git a/src/app/reporting/Read.h b/src/app/reporting/Read.h deleted file mode 100644 index 6731addfab736e..00000000000000 --- a/src/app/reporting/Read.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2024 Project CHIP Authors - * All rights reserved. - * - * 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. - */ -#pragma once - -#include -#include -#include -#include -#include -#include - -namespace chip { -namespace app { -namespace reporting { -namespace Impl { - -DataModel::ActionReturnStatus RetrieveClusterData(DataModel::Provider * dataModel, - const Access::SubjectDescriptor & subjectDescriptor, bool isFabricFiltered, - AttributeReportIBs::Builder & reportBuilder, - const ConcreteReadAttributePath & path, AttributeEncodeState * encoderState); - -bool IsClusterDataVersionEqualTo(DataModel::Provider * dataModel, const ConcreteClusterPath & path, DataVersion dataVersion); -} // namespace Impl - -} // namespace reporting -} // namespace app -} // namespace chip