diff --git a/src/app/ClusterInfo.h b/src/app/ClusterInfo.h index f9179ab373db72..01dc5feeacb3d0 100644 --- a/src/app/ClusterInfo.h +++ b/src/app/ClusterInfo.h @@ -25,96 +25,37 @@ namespace chip { namespace app { -static constexpr AttributeId kRootAttributeId = 0xFFFFFFFF; +/** + * ClusterInfo is the representation of an attribute path or an event path used by ReacHandler, ReadClient, WriteHandler, + * Report::Engine etc, it contains a mpNext field so it can be used as a linked list. It uses some invalid values for representing + * the wildcard value for its field. + */ +// TODO: The cluster info should be breaked into AttributeInfo and EventInfo. +// Note: The change will happen after #11171 with a better linked list. struct ClusterInfo { - enum class Flags : uint8_t - { - kFieldIdValid = 0x01, - kListIndexValid = 0x02, - kEventIdValid = 0x03, - }; - bool IsAttributePathSupersetOf(const ClusterInfo & other) const { - if ((other.mEndpointId != mEndpointId) || (other.mClusterId != mClusterId)) - { - return false; - } - - Optional myFieldId = - mFlags.Has(Flags::kFieldIdValid) ? Optional::Value(mFieldId) : Optional::Missing(); - - Optional otherFieldId = other.mFlags.Has(Flags::kFieldIdValid) ? Optional::Value(other.mFieldId) - : Optional::Missing(); - - Optional myListIndex = - mFlags.Has(Flags::kListIndexValid) ? Optional::Value(mListIndex) : Optional::Missing(); - - Optional otherListIndex = other.mFlags.Has(Flags::kListIndexValid) ? Optional::Value(other.mListIndex) - : Optional::Missing(); + VerifyOrReturnError(!mEndpointId.HasValue() || mEndpointId == other.mEndpointId, false); + VerifyOrReturnError(!mClusterId.HasValue() || mClusterId == other.mClusterId, false); + VerifyOrReturnError(!mFieldId.HasValue() || mFieldId == other.mFieldId, false); + VerifyOrReturnError(!mListIndex.HasValue() || mListIndex == other.mListIndex, false); - // If list index exists, field index must exist - // Field 0xFFFFFFF (any) & listindex set is invalid - assert(!(myListIndex.HasValue() && !myFieldId.HasValue())); - assert(!(otherListIndex.HasValue() && !otherFieldId.HasValue())); - assert(!(myFieldId == Optional::Value(kRootAttributeId) && myListIndex.HasValue())); - assert(!(otherFieldId == Optional::Value(kRootAttributeId) && otherListIndex.HasValue())); - - if (myFieldId == Optional::Value(kRootAttributeId)) - { - return true; - } - - if (myFieldId != otherFieldId) - { - return false; - } - - // We only support top layer for attribute representation, either FieldId or FieldId + ListIndex - // Combination: if myFieldId == otherFieldId, ListIndex cannot exist without FieldId - // 1. myListIndex and otherListIndex both missing or both exactly the same, then current is superset of other - // 2. myListIndex is missing, no matter if otherListIndex is missing or not, then current is superset of other - if (myListIndex == otherListIndex) - { - // either both missing or both exactly the same - return true; - } - - if (!myListIndex.HasValue()) - { - // difference is ok only if myListIndex is missing - return true; - } - - return false; + return true; } + bool HasWildcard() const { return !mEndpointId.HasValue() || !mClusterId.HasValue() || !mFieldId.HasValue(); } + ClusterInfo() {} - NodeId mNodeId = 0; - ClusterId mClusterId = 0; - ListIndex mListIndex = 0; - AttributeId mFieldId = 0; - EndpointId mEndpointId = 0; - BitFlags mFlags; - ClusterInfo * mpNext = nullptr; - EventId mEventId = 0; - /* For better structure alignment - * Above ordering is by bit-size to ensure least amount of memory alignment padding. - * Changing order to something more natural (e.g. clusterid before nodeid) will result - * in extra memory alignment padding. - * uint64 mNodeId - * uint16_t mClusterId - * uint16_t mListIndex - * uint8_t FieldId - * uint8_t EndpointId - * uint8_t mDirty - * uint8_t mType - * uint32_t mpNext - * uint16_t EventId - * padding 2 bytes - */ + + Optional mNodeId; + Optional mEndpointId; + Optional mClusterId; + Optional mFieldId; + Optional mEventId; + Optional mListIndex; + ClusterInfo * mpNext = nullptr; // pointer width (uint32 or uint64) }; } // namespace app } // namespace chip diff --git a/src/app/EventManagement.cpp b/src/app/EventManagement.cpp index 2df0de0f36945e..78420052314470 100644 --- a/src/app/EventManagement.cpp +++ b/src/app/EventManagement.cpp @@ -618,8 +618,10 @@ static bool IsInterestedEventPaths(EventLoadOutContext * eventLoadOutContext, co } while (interestedEventPaths != nullptr) { - if (interestedEventPaths->mNodeId == event.mNodeId && interestedEventPaths->mEndpointId == event.mEndpointId && - interestedEventPaths->mClusterId == event.mClusterId && interestedEventPaths->mEventId == event.mEventId) + if (interestedEventPaths->mNodeId == Optional(event.mNodeId) && + interestedEventPaths->mEndpointId == Optional(event.mEndpointId) && + interestedEventPaths->mClusterId == Optional(event.mClusterId) && + interestedEventPaths->mEventId == Optional(event.mEventId)) { return true; } diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 2c33beeec2487d..94a09cb1a3e887 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -471,7 +471,6 @@ void InteractionModelEngine::ReleaseClusterInfoList(ClusterInfo *& aClusterInfo) { lastClusterInfo = lastClusterInfo->mpNext; } - lastClusterInfo->mFlags.ClearAll(); lastClusterInfo->mpNext = mpNextAvailableClusterInfo; mpNextAvailableClusterInfo = aClusterInfo; aClusterInfo = nullptr; @@ -508,7 +507,6 @@ bool InteractionModelEngine::MergeOverlappedAttributePath(ClusterInfo * apAttrib { runner->mListIndex = aAttributePath.mListIndex; runner->mFieldId = aAttributePath.mFieldId; - runner->mFlags = aAttributePath.mFlags; return true; } runner = runner->mpNext; diff --git a/src/app/MessageDef/AttributePath.cpp b/src/app/MessageDef/AttributePath.cpp index 0489eb0695fe6a..a25134446d8c0d 100644 --- a/src/app/MessageDef/AttributePath.cpp +++ b/src/app/MessageDef/AttributePath.cpp @@ -29,6 +29,7 @@ #include #include +#include using namespace chip; using namespace chip::TLV; @@ -193,6 +194,31 @@ CHIP_ERROR AttributePath::Parser::GetListIndex(chip::ListIndex * const apListInd return GetUnsignedInteger(kCsTag_ListIndex, apListIndex); } +CHIP_ERROR AttributePath::Parser::GetNodeId(chip::Optional & aNodeId) const +{ + return GetUnsignedInteger(kCsTag_NodeId, aNodeId); +} + +CHIP_ERROR AttributePath::Parser::GetEndpointId(chip::Optional & aEndpointId) const +{ + return GetUnsignedInteger(kCsTag_EndpointId, aEndpointId); +} + +CHIP_ERROR AttributePath::Parser::GetClusterId(chip::Optional & aClusterId) const +{ + return GetUnsignedInteger(kCsTag_ClusterId, aClusterId); +} + +CHIP_ERROR AttributePath::Parser::GetFieldId(chip::Optional & aFieldId) const +{ + return GetUnsignedInteger(kCsTag_FieldId, aFieldId); +} + +CHIP_ERROR AttributePath::Parser::GetListIndex(chip::Optional & aListIndex) const +{ + return GetUnsignedInteger(kCsTag_ListIndex, aListIndex); +} + CHIP_ERROR AttributePath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const Tag aTag) { mpWriter = apWriter; diff --git a/src/app/MessageDef/AttributePath.h b/src/app/MessageDef/AttributePath.h index 790581dd74b178..b0ce0dbc647c97 100644 --- a/src/app/MessageDef/AttributePath.h +++ b/src/app/MessageDef/AttributePath.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -84,6 +85,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetNodeId(chip::NodeId * const apNodeId) const; + /** + * @brief Get NodeId field, will set the aNodeId to Optional::Missing when value does not exist. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetNodeId(chip::Optional & aNodeId) const; + /** * @brief Get a TLVReader for the EndpointId. Next() must be called before accessing them. * @@ -95,6 +106,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetEndpointId(chip::EndpointId * const apEndpointId) const; + /** + * @brief Gets EndpointId, will set the aEndpointId to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetEndpointId(chip::Optional & aEndpointId) const; + /** * @brief Get a TLVReader for the ClusterId. Next() must be called before accessing them. * @@ -106,6 +127,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetClusterId(chip::ClusterId * const apClusterId) const; + /** + * @brief Gets ClusterId, will set the aClusterId to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetClusterId(chip::Optional & aClusterId) const; + /** * @brief Get a TLVReader for the FieldId. Next() must be called before accessing them. * @@ -117,6 +148,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetFieldId(chip::AttributeId * const apFieldId) const; + /** + * @brief Gets FieldId, will set the aFieldId to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetFieldId(chip::Optional & aFieldId) const; + /** * @brief Get a TLVReader for the ListIndex. Next() must be called before accessing them. * @@ -127,6 +168,16 @@ class Parser : public chip::app::Parser * #CHIP_END_OF_TLV if there is no such element */ CHIP_ERROR GetListIndex(chip::ListIndex * const apListIndex) const; + + /** + * @brief Gets ListIndex, will set the aListIndex to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetListIndex(chip::Optional & aListIndex) const; }; class Builder : public chip::app::Builder diff --git a/src/app/MessageDef/EventPath.cpp b/src/app/MessageDef/EventPath.cpp index 5c134550b5af43..2bb002ab1b8abb 100644 --- a/src/app/MessageDef/EventPath.cpp +++ b/src/app/MessageDef/EventPath.cpp @@ -176,6 +176,26 @@ CHIP_ERROR EventPath::Parser::GetEventId(chip::EventId * const apEventId) const return GetUnsignedInteger(kCsTag_EventId, apEventId); } +CHIP_ERROR EventPath::Parser::GetNodeId(chip::Optional & aNodeId) const +{ + return GetUnsignedInteger(kCsTag_NodeId, aNodeId); +} + +CHIP_ERROR EventPath::Parser::GetEndpointId(chip::Optional & aEndpointId) const +{ + return GetUnsignedInteger(kCsTag_EndpointId, aEndpointId); +} + +CHIP_ERROR EventPath::Parser::GetClusterId(chip::Optional & aClusterId) const +{ + return GetUnsignedInteger(kCsTag_ClusterId, aClusterId); +} + +CHIP_ERROR EventPath::Parser::GetEventId(chip::Optional & aFieldId) const +{ + return GetUnsignedInteger(kCsTag_EventId, aFieldId); +} + CHIP_ERROR EventPath::Builder::_Init(chip::TLV::TLVWriter * const apWriter, const Tag aTag) { mpWriter = apWriter; diff --git a/src/app/MessageDef/EventPath.h b/src/app/MessageDef/EventPath.h index 6acec4fcff2982..04031b6f60123a 100644 --- a/src/app/MessageDef/EventPath.h +++ b/src/app/MessageDef/EventPath.h @@ -84,6 +84,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetNodeId(chip::NodeId * const apNodeId) const; + /** + * @brief Get NodeId field, will set the aNodeId to Optional::Missing when value does not exist. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetNodeId(chip::Optional & aNodeId) const; + /** * @brief Get a TLVReader for the EndpointId. Next() must be called before accessing them. * @@ -95,6 +105,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetEndpointId(chip::EndpointId * const apEndpointId) const; + /* + * @brief Gets EndpointId, will set the aEndpointId to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetEndpointId(chip::Optional & aEndpointId) const; + /** * @brief Get a TLVReader for the ClusterId. Next() must be called before accessing them. * @@ -106,6 +126,16 @@ class Parser : public chip::app::Parser */ CHIP_ERROR GetClusterId(chip::ClusterId * const apClusterId) const; + /** + * @brief Gets ClusterId, will set the aClusterId to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetClusterId(chip::Optional & aClusterId) const; + /** * @brief Get a TLVReader for the EventId. Next() must be called before accessing them. * @@ -116,6 +146,16 @@ class Parser : public chip::app::Parser * #CHIP_END_OF_TLV if there is no such element */ CHIP_ERROR GetEventId(chip::EventId * const apEventId) const; + + /** + * @brief Gets FieldId, will set the aFieldId to Optional::Missing when the field is missing. + * + * @param [in] aListIndex The value for getting list index field. + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types + */ + CHIP_ERROR GetEventId(chip::Optional & aFieldId) const; }; class Builder : public chip::app::Builder diff --git a/src/app/MessageDef/Parser.h b/src/app/MessageDef/Parser.h index 0b027a93002474..3d213e3ea1d1d1 100644 --- a/src/app/MessageDef/Parser.h +++ b/src/app/MessageDef/Parser.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,23 @@ class Parser return GetSimpleValue(aContextTag, chip::TLV::kTLVType_UnsignedInteger, apLValue); }; + template + CHIP_ERROR GetUnsignedInteger(const uint8_t aContextTag, Optional & aValue) const + { + T value; + CHIP_ERROR err = GetSimpleValue(aContextTag, chip::TLV::kTLVType_UnsignedInteger, &value); + aValue.ClearValue(); + if (err == CHIP_NO_ERROR) + { + aValue.SetValue(value); + } + if (err != CHIP_ERROR_END_OF_TLV) + { + return err; + } + return CHIP_NO_ERROR; + }; + template CHIP_ERROR GetSimpleValue(const uint8_t aContextTag, const chip::TLV::TLVType aTLVType, T * const apLValue) const { diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index 0e7ab15fe6e33a..2deab777796ab7 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -477,40 +477,18 @@ CHIP_ERROR ReadClient::ProcessAttributeDataList(TLV::TLVReader & aAttributeDataL err = element.Init(reader); SuccessOrExit(err); - err = element.GetAttributePath(&attributePathParser); - SuccessOrExit(err); - - err = attributePathParser.GetNodeId(&(clusterInfo.mNodeId)); - SuccessOrExit(err); - - err = attributePathParser.GetEndpointId(&(clusterInfo.mEndpointId)); - SuccessOrExit(err); - - err = attributePathParser.GetClusterId(&(clusterInfo.mClusterId)); - SuccessOrExit(err); - - err = attributePathParser.GetFieldId(&(clusterInfo.mFieldId)); - if (CHIP_NO_ERROR == err) - { - clusterInfo.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - } - else if (CHIP_END_OF_TLV == err) - { - err = CHIP_NO_ERROR; - } - SuccessOrExit(err); - - err = attributePathParser.GetListIndex(&(clusterInfo.mListIndex)); - if (CHIP_NO_ERROR == err) - { - VerifyOrExit(clusterInfo.mFlags.Has(ClusterInfo::Flags::kFieldIdValid), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); - clusterInfo.mFlags.Set(ClusterInfo::Flags::kListIndexValid); - } - else if (CHIP_END_OF_TLV == err) - { - err = CHIP_NO_ERROR; - } - SuccessOrExit(err); + SuccessOrExit(err = element.GetAttributePath(&attributePathParser)); + + SuccessOrExit(err = attributePathParser.GetNodeId(clusterInfo.mNodeId)); + SuccessOrExit(err = attributePathParser.GetEndpointId(clusterInfo.mEndpointId)); + SuccessOrExit(err = attributePathParser.GetClusterId(clusterInfo.mClusterId)); + SuccessOrExit(err = attributePathParser.GetFieldId(clusterInfo.mFieldId)); + SuccessOrExit(err = attributePathParser.GetListIndex(clusterInfo.mListIndex)); + VerifyOrExit(!clusterInfo.mListIndex.HasValue() || clusterInfo.mFieldId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + + VerifyOrExit(clusterInfo.mEndpointId.HasValue() && clusterInfo.mClusterId.HasValue() && clusterInfo.mFieldId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); err = element.GetData(&dataReader); if (err == CHIP_END_OF_TLV) diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index 0383cfdc235961..91405af4a43a61 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -333,33 +333,20 @@ CHIP_ERROR ReadHandler::ProcessAttributePathList(AttributePathList::Parser & aAt AttributePath::Parser path; err = path.Init(reader); SuccessOrExit(err); - err = path.GetNodeId(&(clusterInfo.mNodeId)); - SuccessOrExit(err); - err = path.GetEndpointId(&(clusterInfo.mEndpointId)); - SuccessOrExit(err); - err = path.GetClusterId(&(clusterInfo.mClusterId)); - SuccessOrExit(err); - err = path.GetFieldId(&(clusterInfo.mFieldId)); - if (CHIP_NO_ERROR == err) - { - clusterInfo.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - } - else if (CHIP_END_OF_TLV == err) - { - err = CHIP_NO_ERROR; - } - SuccessOrExit(err); + // TODO(#8364): Support wildcard paths here, should check if we have got valid input when implementing wildcard read. + SuccessOrExit(err = path.GetNodeId(clusterInfo.mNodeId)); + SuccessOrExit(err = path.GetEndpointId(clusterInfo.mEndpointId)); + SuccessOrExit(err = path.GetClusterId(clusterInfo.mClusterId)); + SuccessOrExit(err = path.GetFieldId(clusterInfo.mFieldId)); + SuccessOrExit(err = path.GetListIndex(clusterInfo.mListIndex)); + + VerifyOrExit(!clusterInfo.mListIndex.HasValue() || clusterInfo.mFieldId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + + // TODO(#8364): We assume the path is a concrete path here, will be removed when implementing the wildcard read. + VerifyOrExit(clusterInfo.mEndpointId.HasValue() && clusterInfo.mClusterId.HasValue() && clusterInfo.mFieldId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); - err = path.GetListIndex(&(clusterInfo.mListIndex)); - if (CHIP_NO_ERROR == err) - { - VerifyOrExit(clusterInfo.mFlags.Has(ClusterInfo::Flags::kFieldIdValid), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); - clusterInfo.mFlags.Set(ClusterInfo::Flags::kListIndexValid); - } - else if (CHIP_END_OF_TLV == err) - { - err = CHIP_NO_ERROR; - } SuccessOrExit(err); err = InteractionModelEngine::GetInstance()->PushFront(mpAttributeClusterInfoList, clusterInfo); SuccessOrExit(err); @@ -389,21 +376,15 @@ CHIP_ERROR ReadHandler::ProcessEventPathList(EventPathList::Parser & aEventPathL EventPath::Parser path; err = path.Init(reader); SuccessOrExit(err); - err = path.GetNodeId(&(clusterInfo.mNodeId)); - SuccessOrExit(err); - err = path.GetEndpointId(&(clusterInfo.mEndpointId)); - SuccessOrExit(err); - err = path.GetClusterId(&(clusterInfo.mClusterId)); - SuccessOrExit(err); - err = path.GetEventId(&(clusterInfo.mEventId)); - if (CHIP_NO_ERROR == err) - { - clusterInfo.mFlags.Set(ClusterInfo::Flags::kEventIdValid); - } - else if (CHIP_END_OF_TLV == err) - { - err = CHIP_NO_ERROR; - } + SuccessOrExit(err = path.GetNodeId(clusterInfo.mNodeId)); + SuccessOrExit(err = path.GetEndpointId(clusterInfo.mEndpointId)); + SuccessOrExit(err = path.GetClusterId(clusterInfo.mClusterId)); + SuccessOrExit(err = path.GetEventId(clusterInfo.mEventId)); + + // TODO: We assume the path is a concrete path here, will be removed when implementing the wildcard event read. + VerifyOrExit(clusterInfo.mEndpointId.HasValue() && clusterInfo.mClusterId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + SuccessOrExit(err); err = InteractionModelEngine::GetInstance()->PushFront(mpEventClusterInfoList, clusterInfo); SuccessOrExit(err); diff --git a/src/app/WriteHandler.cpp b/src/app/WriteHandler.cpp index 7145f8c275536d..c2fe6b8be1ae9a 100644 --- a/src/app/WriteHandler.cpp +++ b/src/app/WriteHandler.cpp @@ -122,32 +122,17 @@ CHIP_ERROR WriteHandler::ProcessAttributeDataList(TLV::TLVReader & aAttributeDat err = element.GetAttributePath(&attributePath); SuccessOrExit(err); - err = attributePath.GetNodeId(&(clusterInfo.mNodeId)); - SuccessOrExit(err); - - err = attributePath.GetEndpointId(&(clusterInfo.mEndpointId)); - SuccessOrExit(err); - - err = attributePath.GetClusterId(&(clusterInfo.mClusterId)); - SuccessOrExit(err); - - err = attributePath.GetFieldId(&(clusterInfo.mFieldId)); - if (CHIP_NO_ERROR == err) - { - clusterInfo.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - } - else if (CHIP_END_OF_TLV == err) - { - err = CHIP_NO_ERROR; - } - SuccessOrExit(err); - - err = attributePath.GetListIndex(&(clusterInfo.mListIndex)); - if (CHIP_NO_ERROR == err) - { - VerifyOrExit(clusterInfo.mFlags.Has(ClusterInfo::Flags::kFieldIdValid), err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); - clusterInfo.mFlags.Set(ClusterInfo::Flags::kListIndexValid); - } + SuccessOrExit(err = attributePath.GetNodeId(clusterInfo.mNodeId)); + SuccessOrExit(err = attributePath.GetEndpointId(clusterInfo.mEndpointId)); + SuccessOrExit(err = attributePath.GetClusterId(clusterInfo.mClusterId)); + SuccessOrExit(err = attributePath.GetFieldId(clusterInfo.mFieldId)); + SuccessOrExit(err = attributePath.GetListIndex(clusterInfo.mListIndex)); + + VerifyOrExit(!clusterInfo.mListIndex.HasValue() || clusterInfo.mFieldId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); + // Reject all wildcard writes. + VerifyOrExit(clusterInfo.mEndpointId.HasValue() && clusterInfo.mClusterId.HasValue() && clusterInfo.mFieldId.HasValue(), + err = CHIP_ERROR_IM_MALFORMED_ATTRIBUTE_PATH); err = element.GetData(&dataReader); SuccessOrExit(err); diff --git a/src/app/reporting/Engine.cpp b/src/app/reporting/Engine.cpp index f5562d151c72a1..b98c32e85386c9 100644 --- a/src/app/reporting/Engine.cpp +++ b/src/app/reporting/Engine.cpp @@ -65,19 +65,21 @@ CHIP_ERROR Engine::RetrieveClusterData(AttributeDataList::Builder & aAttributeDataList, ClusterInfo & aClusterInfo) { CHIP_ERROR err = CHIP_NO_ERROR; - ConcreteAttributePath path(aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mFieldId); + + // TODO: We assume the path is a concrete path here, will be changed when implementing the wildcard event read. + ConcreteAttributePath path(aClusterInfo.mEndpointId.Value(), aClusterInfo.mClusterId.Value(), aClusterInfo.mFieldId.Value()); AttributeDataElement::Builder attributeDataElementBuilder = aAttributeDataList.CreateAttributeDataElementBuilder(); AttributePath::Builder attributePathBuilder = attributeDataElementBuilder.CreateAttributePathBuilder(); - attributePathBuilder.NodeId(aClusterInfo.mNodeId) - .EndpointId(aClusterInfo.mEndpointId) - .ClusterId(aClusterInfo.mClusterId) - .FieldId(aClusterInfo.mFieldId) + attributePathBuilder.NodeId(aClusterInfo.mNodeId.ValueOr(kUndefinedNodeId)) + .EndpointId(aClusterInfo.mEndpointId.Value()) + .ClusterId(aClusterInfo.mClusterId.Value()) + .FieldId(aClusterInfo.mFieldId.Value()) .EndOfAttributePath(); err = attributePathBuilder.GetError(); SuccessOrExit(err); - ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Field %" PRIx32 " is dirty", aClusterInfo.mClusterId, - aClusterInfo.mFieldId); + ChipLogDetail(DataManagement, " Cluster %" PRIx32 ", Field %" PRIx32 " is dirty", aClusterInfo.mClusterId.Value(), + aClusterInfo.mFieldId.Value()); err = ReadSingleClusterData(path, attributeDataElementBuilder.GetWriter(), nullptr /* data exists */); SuccessOrExit(err); @@ -89,7 +91,7 @@ Engine::RetrieveClusterData(AttributeDataList::Builder & aAttributeDataList, Clu if (err != CHIP_NO_ERROR) { ChipLogError(DataManagement, "Error retrieving data from clusterId: " ChipLogFormatMEI ", err = %" CHIP_ERROR_FORMAT, - ChipLogValueMEI(aClusterInfo.mClusterId), err.Format()); + ChipLogValueMEI(aClusterInfo.mClusterId.Value()), err.Format()); } return err; diff --git a/src/app/tests/TestClusterInfo.cpp b/src/app/tests/TestClusterInfo.cpp index 932fe062104e72..04824f955fd433 100644 --- a/src/app/tests/TestClusterInfo.cpp +++ b/src/app/tests/TestClusterInfo.cpp @@ -34,21 +34,17 @@ void TestAttributePathIncludedSameFieldId(nlTestSuite * apSuite, void * apContex ClusterInfo clusterInfo1; ClusterInfo clusterInfo2; ClusterInfo clusterInfo3; - clusterInfo1.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - clusterInfo2.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - clusterInfo3.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - clusterInfo1.mFieldId = 1; - clusterInfo2.mFieldId = 1; - clusterInfo3.mFieldId = 1; + clusterInfo1.mFieldId.SetValue(1); + clusterInfo2.mFieldId.SetValue(1); + clusterInfo3.mFieldId.SetValue(1); NL_TEST_ASSERT(apSuite, clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); - clusterInfo2.mFlags.Set(ClusterInfo::Flags::kListIndexValid); - clusterInfo2.mListIndex = 1; + clusterInfo2.mListIndex.SetValue(1); NL_TEST_ASSERT(apSuite, clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); - clusterInfo1.mFlags.Set(ClusterInfo::Flags::kListIndexValid); + clusterInfo1.mListIndex.SetValue(0); NL_TEST_ASSERT(apSuite, !clusterInfo1.IsAttributePathSupersetOf(clusterInfo3)); - clusterInfo3.mFlags.Set(ClusterInfo::Flags::kListIndexValid); + clusterInfo3.mListIndex.SetValue(0); NL_TEST_ASSERT(apSuite, clusterInfo1.IsAttributePathSupersetOf(clusterInfo3)); - clusterInfo3.mListIndex = 1; + clusterInfo3.mListIndex.SetValue(1); NL_TEST_ASSERT(apSuite, !clusterInfo1.IsAttributePathSupersetOf(clusterInfo3)); } @@ -56,19 +52,17 @@ void TestAttributePathIncludedDifferentFieldId(nlTestSuite * apSuite, void * apC { ClusterInfo clusterInfo1; ClusterInfo clusterInfo2; - clusterInfo1.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - clusterInfo2.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); - clusterInfo1.mFieldId = 1; - clusterInfo2.mFieldId = 2; + clusterInfo1.mFieldId.SetValue(1); + clusterInfo2.mFieldId.SetValue(2); NL_TEST_ASSERT(apSuite, !clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); - clusterInfo1.mFieldId = 0xFFFFFFFF; - clusterInfo2.mFieldId = 2; + clusterInfo1.mFieldId.ClearValue(); + clusterInfo2.mFieldId.SetValue(2); NL_TEST_ASSERT(apSuite, clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); - clusterInfo1.mFieldId = 0xFFFFFFFF; - clusterInfo2.mFieldId = 0xFFFFFFFF; + clusterInfo1.mFieldId.ClearValue(); + clusterInfo2.mFieldId.ClearValue(); NL_TEST_ASSERT(apSuite, clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); - clusterInfo1.mFieldId = 1; - clusterInfo2.mFieldId = 0xFFFFFFFF; + clusterInfo1.mFieldId.SetValue(1); + clusterInfo2.mFieldId.ClearValue(); NL_TEST_ASSERT(apSuite, !clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); } @@ -76,8 +70,8 @@ void TestAttributePathIncludedDifferentEndpointId(nlTestSuite * apSuite, void * { ClusterInfo clusterInfo1; ClusterInfo clusterInfo2; - clusterInfo1.mEndpointId = 1; - clusterInfo2.mEndpointId = 2; + clusterInfo1.mEndpointId.SetValue(1); + clusterInfo2.mEndpointId.SetValue(2); NL_TEST_ASSERT(apSuite, !clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); } @@ -85,8 +79,8 @@ void TestAttributePathIncludedDifferentClusterId(nlTestSuite * apSuite, void * a { ClusterInfo clusterInfo1; ClusterInfo clusterInfo2; - clusterInfo1.mClusterId = 1; - clusterInfo2.mClusterId = 2; + clusterInfo1.mClusterId.SetValue(1); + clusterInfo2.mClusterId.SetValue(2); NL_TEST_ASSERT(apSuite, !clusterInfo1.IsAttributePathSupersetOf(clusterInfo2)); } } // namespace TestClusterInfo diff --git a/src/app/tests/TestEventLogging.cpp b/src/app/tests/TestEventLogging.cpp index 0511a183f56d1b..4ac802c26cb2d9 100644 --- a/src/app/tests/TestEventLogging.cpp +++ b/src/app/tests/TestEventLogging.cpp @@ -219,15 +219,15 @@ static void CheckLogEventWithEvictToNextBuffer(nlTestSuite * apSuite, void * apC NL_TEST_ASSERT(apSuite, (eid5 + 1) == eid6); chip::app::ClusterInfo testClusterInfo1; - testClusterInfo1.mNodeId = kTestDeviceNodeId1; - testClusterInfo1.mEndpointId = kTestEndpointId; - testClusterInfo1.mClusterId = kLivenessClusterId; - testClusterInfo1.mEventId = kLivenessChangeEvent; + testClusterInfo1.mNodeId.SetValue(kTestDeviceNodeId1); + testClusterInfo1.mEndpointId.SetValue(kTestEndpointId); + testClusterInfo1.mClusterId.SetValue(kLivenessClusterId); + testClusterInfo1.mEventId.SetValue(kLivenessChangeEvent); chip::app::ClusterInfo testClusterInfo2; - testClusterInfo2.mNodeId = kTestDeviceNodeId2; - testClusterInfo2.mEndpointId = kTestEndpointId; - testClusterInfo2.mClusterId = kLivenessClusterId; - testClusterInfo2.mEventId = kLivenessChangeEvent; + testClusterInfo2.mNodeId.SetValue(kTestDeviceNodeId2); + testClusterInfo2.mEndpointId.SetValue(kTestEndpointId); + testClusterInfo2.mClusterId.SetValue(kLivenessClusterId); + testClusterInfo2.mEventId.SetValue(kLivenessChangeEvent); CheckLogReadOut(apSuite, logMgmt, chip::app::PriorityLevel::Info, eid1, 3, &testClusterInfo1); CheckLogReadOut(apSuite, logMgmt, chip::app::PriorityLevel::Info, eid2, 2, &testClusterInfo1); diff --git a/src/app/tests/TestInteractionModelEngine.cpp b/src/app/tests/TestInteractionModelEngine.cpp index b55200f7a901f7..33850bc9c5884e 100644 --- a/src/app/tests/TestInteractionModelEngine.cpp +++ b/src/app/tests/TestInteractionModelEngine.cpp @@ -71,9 +71,9 @@ void TestInteractionModelEngine::TestClusterInfoPushRelease(nlTestSuite * apSuit ClusterInfo clusterInfo2; ClusterInfo clusterInfo3; - clusterInfo1.mEndpointId = 1; - clusterInfo2.mEndpointId = 2; - clusterInfo3.mEndpointId = 3; + clusterInfo1.mEndpointId.SetValue(1); + clusterInfo2.mEndpointId.SetValue(2); + clusterInfo3.mEndpointId.SetValue(3); InteractionModelEngine::GetInstance()->PushFront(clusterInfoList, clusterInfo1); NL_TEST_ASSERT(apSuite, clusterInfoList != nullptr && clusterInfo1.mEndpointId == clusterInfoList->mEndpointId); @@ -99,21 +99,17 @@ void TestInteractionModelEngine::TestMergeOverlappedAttributePath(nlTestSuite * NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); ClusterInfo clusterInfoList[2]; - clusterInfoList[0].mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - clusterInfoList[0].mFieldId = 1; - clusterInfoList[1].mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - clusterInfoList[1].mFieldId = 2; + clusterInfoList[0].mFieldId.SetValue(1); + clusterInfoList[1].mFieldId.SetValue(2); chip::app::ClusterInfo testClusterInfo; - testClusterInfo.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - testClusterInfo.mFieldId = 3; + testClusterInfo.mFieldId.SetValue(3); NL_TEST_ASSERT(apSuite, !InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(clusterInfoList, testClusterInfo)); - testClusterInfo.mFieldId = 0xFFFFFFFF; + testClusterInfo.mFieldId.ClearValue(); NL_TEST_ASSERT(apSuite, InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(clusterInfoList, testClusterInfo)); - testClusterInfo.mFlags.Set(chip::app::ClusterInfo::Flags::kListIndexValid); - testClusterInfo.mFieldId = 1; - testClusterInfo.mListIndex = 2; + testClusterInfo.mFieldId.SetValue(1); + testClusterInfo.mListIndex.SetValue(2); NL_TEST_ASSERT(apSuite, InteractionModelEngine::GetInstance()->MergeOverlappedAttributePath(clusterInfoList, testClusterInfo)); } } // namespace app diff --git a/src/app/tests/TestReadInteraction.cpp b/src/app/tests/TestReadInteraction.cpp index 7f7352560b7b54..216bd02b4bc84d 100644 --- a/src/app/tests/TestReadInteraction.cpp +++ b/src/app/tests/TestReadInteraction.cpp @@ -921,36 +921,30 @@ void TestReadInteraction::TestSubscribeRoundtrip(nlTestSuite * apSuite, void * a NL_TEST_ASSERT(apSuite, delegate.mNumSubscriptions == 1); chip::app::ClusterInfo dirtyPath1; - dirtyPath1.mClusterId = kTestClusterId; - dirtyPath1.mEndpointId = kTestEndpointId; - dirtyPath1.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - dirtyPath1.mFieldId = 1; + dirtyPath1.mClusterId.SetValue(kTestClusterId); + dirtyPath1.mEndpointId.SetValue(kTestEndpointId); + dirtyPath1.mFieldId.SetValue(1); chip::app::ClusterInfo dirtyPath2; - dirtyPath2.mClusterId = kTestClusterId; - dirtyPath2.mEndpointId = kTestEndpointId; - dirtyPath2.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - dirtyPath2.mFieldId = 2; + dirtyPath2.mClusterId.SetValue(kTestClusterId); + dirtyPath2.mEndpointId.SetValue(kTestEndpointId); + dirtyPath2.mFieldId.SetValue(2); chip::app::ClusterInfo dirtyPath3; - dirtyPath2.mClusterId = kTestClusterId; - dirtyPath2.mEndpointId = kTestEndpointId; - dirtyPath2.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - dirtyPath2.mFlags.Set(chip::app::ClusterInfo::Flags::kListIndexValid); - dirtyPath2.mFieldId = 2; - dirtyPath2.mListIndex = 1; + dirtyPath3.mClusterId.SetValue(kTestClusterId); + dirtyPath3.mEndpointId.SetValue(kTestEndpointId); + dirtyPath3.mFieldId.SetValue(2); + dirtyPath3.mListIndex.SetValue(1); chip::app::ClusterInfo dirtyPath4; - dirtyPath4.mClusterId = kTestClusterId; - dirtyPath4.mEndpointId = kTestEndpointId; - dirtyPath4.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - dirtyPath4.mFieldId = 3; + dirtyPath4.mClusterId.SetValue(kTestClusterId); + dirtyPath4.mEndpointId.SetValue(kTestEndpointId); + dirtyPath4.mFieldId.SetValue(3); chip::app::ClusterInfo dirtyPath5; - dirtyPath5.mClusterId = kTestClusterId; - dirtyPath5.mEndpointId = kTestEndpointId; - dirtyPath5.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); - dirtyPath5.mFieldId = 4; + dirtyPath5.mClusterId.SetValue(kTestClusterId); + dirtyPath5.mEndpointId.SetValue(kTestEndpointId); + dirtyPath5.mFieldId.SetValue(4); // Test report with 2 different path delegate.mpReadHandler->mHoldReport = false; diff --git a/src/app/tests/TestWriteInteraction.cpp b/src/app/tests/TestWriteInteraction.cpp index 46df2f2a0b09d9..532395aa85d1d1 100644 --- a/src/app/tests/TestWriteInteraction.cpp +++ b/src/app/tests/TestWriteInteraction.cpp @@ -269,8 +269,9 @@ CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & a writer.Init(attributeDataTLV); writer.CopyElement(TLV::AnonymousTag, aReader); attributeDataTLVLen = writer.GetLengthWritten(); - return aWriteHandler->AddStatus(AttributePathParams(aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mFieldId), - Protocols::InteractionModel::Status::Success); + return aWriteHandler->AddStatus( + AttributePathParams(aClusterInfo.mEndpointId.Value(), aClusterInfo.mClusterId.Value(), aClusterInfo.mFieldId.Value()), + Protocols::InteractionModel::Status::Success); } void TestWriteInteraction::TestWriteRoundtripWithClusterObjects(nlTestSuite * apSuite, void * apContext) diff --git a/src/app/tests/integration/chip_im_initiator.cpp b/src/app/tests/integration/chip_im_initiator.cpp index bd1d7ce307e4ac..a889b67d827376 100644 --- a/src/app/tests/integration/chip_im_initiator.cpp +++ b/src/app/tests/integration/chip_im_initiator.cpp @@ -647,7 +647,8 @@ CHIP_ERROR ReadSingleClusterData(const ConcreteAttributePath & aPath, TLV::TLVWr CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler *) { - if (aClusterInfo.mClusterId != kTestClusterId || aClusterInfo.mEndpointId != kTestEndpointId) + if (!(aClusterInfo.mClusterId == Optional(kTestClusterId)) || + !(aClusterInfo.mEndpointId == Optional(kTestEndpointId))) { return CHIP_ERROR_INVALID_ARGUMENT; } diff --git a/src/app/tests/integration/chip_im_responder.cpp b/src/app/tests/integration/chip_im_responder.cpp index 0aa92dc531fd40..b9df0e0a08c25b 100644 --- a/src/app/tests/integration/chip_im_responder.cpp +++ b/src/app/tests/integration/chip_im_responder.cpp @@ -168,14 +168,13 @@ void InitializeEventLogging(chip::Messaging::ExchangeManager * apMgr) void MutateClusterHandler(chip::System::Layer * systemLayer, void * appState) { chip::app::ClusterInfo dirtyPath; - dirtyPath.mClusterId = kTestClusterId; - dirtyPath.mEndpointId = kTestEndpointId; - dirtyPath.mFlags.Set(chip::app::ClusterInfo::Flags::kFieldIdValid); + dirtyPath.mClusterId.SetValue(kTestClusterId); + dirtyPath.mEndpointId.SetValue(kTestEndpointId); printf("MutateClusterHandler is triggered..."); // send dirty change if (!testSyncReport) { - dirtyPath.mFieldId = 1; + dirtyPath.mFieldId.SetValue(1); chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(dirtyPath); chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), MutateClusterHandler, NULL); @@ -183,7 +182,7 @@ void MutateClusterHandler(chip::System::Layer * systemLayer, void * appState) } else { - dirtyPath.mFieldId = 10; // unknown field + dirtyPath.mFieldId.SetValue(10); // unknown field chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(dirtyPath); // send sync message(empty report) chip::app::InteractionModelEngine::GetInstance()->GetReportingEngine().ScheduleRun(); diff --git a/src/app/util/ember-compatibility-functions.cpp b/src/app/util/ember-compatibility-functions.cpp index 3d7d6e4d368cd4..4a7d67c10d1465 100644 --- a/src/app/util/ember-compatibility-functions.cpp +++ b/src/app/util/ember-compatibility-functions.cpp @@ -443,7 +443,7 @@ static Protocols::InteractionModel::Status WriteSingleClusterDataInternal(Cluste // Passing nullptr as buf to emberAfReadAttribute means we only need attribute type here, and ember will not do data read & // copy in this case. const EmberAfAttributeMetadata * attributeMetadata = emberAfLocateAttributeMetadata( - aClusterInfo.mEndpointId, aClusterInfo.mClusterId, aClusterInfo.mFieldId, CLUSTER_MASK_SERVER, 0); + aClusterInfo.mEndpointId.Value(), aClusterInfo.mClusterId.Value(), aClusterInfo.mFieldId.Value(), CLUSTER_MASK_SERVER, 0); if (attributeMetadata == nullptr) { @@ -464,18 +464,18 @@ static Protocols::InteractionModel::Status WriteSingleClusterDataInternal(Cluste return Protocols::InteractionModel::Status::InvalidValue; } - return ToInteractionModelStatus(emberAfWriteAttributeExternal(aClusterInfo.mEndpointId, aClusterInfo.mClusterId, - aClusterInfo.mFieldId, CLUSTER_MASK_SERVER, 0, attributeData, - attributeMetadata->attributeType)); + return ToInteractionModelStatus(emberAfWriteAttributeExternal(aClusterInfo.mEndpointId.Value(), aClusterInfo.mClusterId.Value(), + aClusterInfo.mFieldId.Value(), CLUSTER_MASK_SERVER, 0, + attributeData, attributeMetadata->attributeType)); } CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * apWriteHandler) { AttributePathParams attributePathParams; - attributePathParams.mNodeId = aClusterInfo.mNodeId; - attributePathParams.mEndpointId = aClusterInfo.mEndpointId; - attributePathParams.mClusterId = aClusterInfo.mClusterId; - attributePathParams.mFieldId = aClusterInfo.mFieldId; + attributePathParams.mNodeId = aClusterInfo.mNodeId.Value(); + attributePathParams.mEndpointId = aClusterInfo.mEndpointId.Value(); + attributePathParams.mClusterId = aClusterInfo.mClusterId.Value(); + attributePathParams.mFieldId = aClusterInfo.mFieldId.Value(); attributePathParams.mFlags.Set(AttributePathParams::Flags::kFieldIdValid); auto imCode = WriteSingleClusterDataInternal(aClusterInfo, aReader, apWriteHandler); @@ -498,10 +498,9 @@ void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clust void MatterReportingAttributeChangeCallback(EndpointId endpoint, ClusterId clusterId, AttributeId attributeId) { ClusterInfo info; - info.mClusterId = clusterId; - info.mFieldId = attributeId; - info.mEndpointId = endpoint; - info.mFlags.Set(ClusterInfo::Flags::kFieldIdValid); + info.mClusterId.SetValue(clusterId); + info.mFieldId.SetValue(attributeId); + info.mEndpointId.SetValue(endpoint); InteractionModelEngine::GetInstance()->GetReportingEngine().SetDirty(info); } diff --git a/src/app/util/im-client-callbacks.cpp b/src/app/util/im-client-callbacks.cpp index c60631f496907c..e24520d1c3e548 100644 --- a/src/app/util/im-client-callbacks.cpp +++ b/src/app/util/im-client-callbacks.cpp @@ -366,7 +366,10 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient TLV::TLVReader * apData, Protocols::InteractionModel::Status status) { ChipLogProgress(Zcl, "ReadAttributesResponse:"); - ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(aPath.mClusterId)); + if (aPath.mClusterId.HasValue()) + { + ChipLogProgress(Zcl, " ClusterId: " ChipLogFormatMEI, ChipLogValueMEI(aPath.mClusterId.Value())); + } Callback::Cancelable * onSuccessCallback = nullptr; Callback::Cancelable * onFailureCallback = nullptr; @@ -378,8 +381,12 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient CHIP_ERROR err = CHIP_NO_ERROR; if (apReadClient->IsSubscriptionType()) { - err = gCallbacks.GetReportCallback(sourceId, aPath.mEndpointId, aPath.mClusterId, aPath.mFieldId, &onSuccessCallback, - &tlvFilter); + if (status == Protocols::InteractionModel::Status::Success) + { + // If the status is success, the path must be a concrete path. + err = gCallbacks.GetReportCallback(sourceId, aPath.mEndpointId.Value(), aPath.mClusterId.Value(), + aPath.mFieldId.Value(), &onSuccessCallback, &tlvFilter); + } } else { @@ -405,7 +412,10 @@ bool IMReadReportAttributesResponseCallback(const app::ReadClient * apReadClient return true; } - ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(aPath.mFieldId)); + if (aPath.mFieldId.HasValue()) + { + ChipLogProgress(Zcl, " attributeId: " ChipLogFormatMEI, ChipLogValueMEI(aPath.mFieldId.Value())); + } LogIMStatus(status); if (status == Protocols::InteractionModel::Status::Success && apData != nullptr) diff --git a/src/controller/CHIPDeviceController.cpp b/src/controller/CHIPDeviceController.cpp index 68ae2034805474..005c04e0978736 100644 --- a/src/controller/CHIPDeviceController.cpp +++ b/src/controller/CHIPDeviceController.cpp @@ -1651,7 +1651,7 @@ void DeviceControllerInteractionModelDelegate::OnReportData(const app::ReadClien CHIP_ERROR DeviceControllerInteractionModelDelegate::ReadError(app::ReadClient * apReadClient, CHIP_ERROR aError) { app::ClusterInfo path; - path.mNodeId = apReadClient->GetPeerNodeId(); + path.mNodeId.SetValue(apReadClient->GetPeerNodeId()); IMReadReportAttributesResponseCallback(apReadClient, path, nullptr, Protocols::InteractionModel::Status::Failure); return CHIP_NO_ERROR; } diff --git a/src/controller/TypedReadCallback.h b/src/controller/TypedReadCallback.h index 3464374f4ae700..2b7720739b9ed3 100644 --- a/src/controller/TypedReadCallback.h +++ b/src/controller/TypedReadCallback.h @@ -54,11 +54,12 @@ class TypedReadCallback final : public app::InteractionModelDelegate Protocols::InteractionModel::Status status) override { CHIP_ERROR err = CHIP_NO_ERROR; - app::ConcreteAttributePath attributePath = { aPath.mEndpointId, aPath.mClusterId, aPath.mFieldId }; + app::ConcreteAttributePath attributePath = { aPath.mEndpointId.Value(), aPath.mClusterId.Value(), aPath.mFieldId.Value() }; typename AttributeTypeInfo::DecodableType value; VerifyOrExit(status == Protocols::InteractionModel::Status::Success, err = CHIP_ERROR_IM_STATUS_CODE_RECEIVED); - VerifyOrExit(aPath.mClusterId == AttributeTypeInfo::GetClusterId() && aPath.mFieldId == AttributeTypeInfo::GetAttributeId(), + VerifyOrExit(aPath.mClusterId == Optional(AttributeTypeInfo::GetClusterId()) && + aPath.mFieldId == Optional(AttributeTypeInfo::GetAttributeId()), CHIP_ERROR_SCHEMA_MISMATCH); VerifyOrExit(apData != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT); diff --git a/src/controller/python/chip/interaction_model/Delegate.cpp b/src/controller/python/chip/interaction_model/Delegate.cpp index 6d127373b597bb..912c203df04a6b 100644 --- a/src/controller/python/chip/interaction_model/Delegate.cpp +++ b/src/controller/python/chip/interaction_model/Delegate.cpp @@ -102,7 +102,9 @@ void PythonInteractionModelDelegate::OnReportData(const app::ReadClient * apRead } if (CHIP_NO_ERROR == err) { - AttributePath path{ .endpointId = aPath.mEndpointId, .clusterId = aPath.mClusterId, .fieldId = aPath.mFieldId }; + AttributePath path{ .endpointId = aPath.mEndpointId.Value(), + .clusterId = aPath.mClusterId.Value(), + .fieldId = aPath.mFieldId.Value() }; onReportDataFunct(apReadClient->GetPeerNodeId(), apReadClient->GetAppIdentifier(), /* TODO: Use real SubscriptionId */ apReadClient->IsSubscriptionType() ? 1 : 0, &path, sizeof(path), writerBuffer, writer.GetLengthWritten(), to_underlying(status)); diff --git a/src/controller/tests/data_model/TestWrite.cpp b/src/controller/tests/data_model/TestWrite.cpp index 4498f096116035..cbf8e5528b7007 100644 --- a/src/controller/tests/data_model/TestWrite.cpp +++ b/src/controller/tests/data_model/TestWrite.cpp @@ -66,8 +66,8 @@ CHIP_ERROR ReadSingleClusterData(const ConcreteAttributePath & aPath, TLV::TLVWr CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & aReader, WriteHandler * aWriteHandler) { - if (aClusterInfo.mClusterId == TestCluster::Id && - aClusterInfo.mFieldId == TestCluster::Attributes::ListStructOctetString::TypeInfo::GetAttributeId()) + if (aClusterInfo.mClusterId == Optional(TestCluster::Id) && + aClusterInfo.mFieldId == Optional(TestCluster::Attributes::ListStructOctetString::TypeInfo::GetAttributeId())) { if (responseDirective == kSendAttributeSuccess) { @@ -87,12 +87,14 @@ CHIP_ERROR WriteSingleClusterData(ClusterInfo & aClusterInfo, TLV::TLVReader & a VerifyOrReturnError(i == 4, CHIP_ERROR_INVALID_ARGUMENT); - AttributePathParams attributePathParams(aClusterInfo.mClusterId, aClusterInfo.mEndpointId, aClusterInfo.mFieldId); + AttributePathParams attributePathParams(aClusterInfo.mClusterId.Value(), aClusterInfo.mEndpointId.Value(), + aClusterInfo.mFieldId.Value()); aWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::Success); } else { - AttributePathParams attributePathParams(aClusterInfo.mClusterId, aClusterInfo.mEndpointId, aClusterInfo.mFieldId); + AttributePathParams attributePathParams(aClusterInfo.mClusterId.Value(), aClusterInfo.mEndpointId.Value(), + aClusterInfo.mFieldId.Value()); aWriteHandler->AddStatus(attributePathParams, Protocols::InteractionModel::Status::Failure); }