From 13760744be9e7f49268eeb93b7c479a3a666d732 Mon Sep 17 00:00:00 2001 From: yunhanw-google Date: Tue, 2 Nov 2021 10:09:53 -0700 Subject: [PATCH] add event status IB and update event path IB (#11307) --- src/app/BUILD.gn | 2 + src/app/EventManagement.cpp | 17 +-- src/app/MessageDef/EventPathIB.cpp | 152 +++++++++++++----------- src/app/MessageDef/EventPathIB.h | 69 +++++++---- src/app/MessageDef/EventPaths.cpp | 21 ++-- src/app/MessageDef/EventStatusIB.cpp | 140 ++++++++++++++++++++++ src/app/MessageDef/EventStatusIB.h | 114 ++++++++++++++++++ src/app/MessageDef/ReadRequestMessage.h | 4 +- src/app/ReadClient.cpp | 8 +- src/app/ReadHandler.cpp | 8 +- src/app/tests/TestMessageDef.cpp | 70 ++++++++++- 11 files changed, 477 insertions(+), 128 deletions(-) create mode 100644 src/app/MessageDef/EventStatusIB.cpp create mode 100644 src/app/MessageDef/EventStatusIB.h diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 5817f598e9e6f8..d4cda3aaba227f 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -72,6 +72,8 @@ static_library("app") { "MessageDef/EventPathIB.h", "MessageDef/EventPaths.cpp", "MessageDef/EventPaths.h", + "MessageDef/EventStatusIB.cpp", + "MessageDef/EventStatusIB.h", "MessageDef/InvokeRequestMessage.cpp", "MessageDef/InvokeRequests.cpp", "MessageDef/InvokeResponseIB.cpp", diff --git a/src/app/EventManagement.cpp b/src/app/EventManagement.cpp index e5880426162f0e..c328c938996bfd 100644 --- a/src/app/EventManagement.cpp +++ b/src/app/EventManagement.cpp @@ -318,10 +318,11 @@ CHIP_ERROR EventManagement::ConstructEvent(EventLoadOutContext * apContext, Even SuccessOrExit(err); // TODO: Revisit NodeId since the the encoding spec and the IM seem to disagree on how this stuff works - eventPathBuilder.NodeId(apOptions->mpEventSchema->mNodeId) - .EndpointId(apOptions->mpEventSchema->mEndpointId) - .ClusterId(apOptions->mpEventSchema->mClusterId) - .EventId(apOptions->mpEventSchema->mEventId) + eventPathBuilder.Node(apOptions->mpEventSchema->mNodeId) + .Endpoint(apOptions->mpEventSchema->mEndpointId) + .Cluster(apOptions->mpEventSchema->mClusterId) + .Event(apOptions->mpEventSchema->mEventId) + .IsUrgent(false) .EndOfEventPathIB(); err = eventPathBuilder.GetError(); SuccessOrExit(err); @@ -753,10 +754,10 @@ CHIP_ERROR EventManagement::FetchEventParameters(const TLVReader & aReader, size { EventPathIB::Parser path; ReturnErrorOnFailure(path.Init(aReader)); - ReturnErrorOnFailure(path.GetNodeId(&(envelope->mNodeId))); - ReturnErrorOnFailure(path.GetEndpointId(&(envelope->mEndpointId))); - ReturnErrorOnFailure(path.GetClusterId(&(envelope->mClusterId))); - ReturnErrorOnFailure(path.GetEventId(&(envelope->mEventId))); + ReturnErrorOnFailure(path.GetNode(&(envelope->mNodeId))); + ReturnErrorOnFailure(path.GetEndpoint(&(envelope->mEndpointId))); + ReturnErrorOnFailure(path.GetCluster(&(envelope->mClusterId))); + ReturnErrorOnFailure(path.GetEvent(&(envelope->mEventId))); envelope->mFieldsToRead |= 1 << EventDataElement::kCsTag_EventPath; } diff --git a/src/app/MessageDef/EventPathIB.cpp b/src/app/MessageDef/EventPathIB.cpp index a4f8ca846a8f97..12d35064206d2e 100644 --- a/src/app/MessageDef/EventPathIB.cpp +++ b/src/app/MessageDef/EventPathIB.cpp @@ -31,17 +31,14 @@ #include -using namespace chip; -using namespace chip::TLV; - namespace chip { namespace app { #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK CHIP_ERROR EventPathIB::Parser::CheckSchemaValidity() const { - CHIP_ERROR err = CHIP_NO_ERROR; - uint16_t TagPresenceMask = 0; - chip::TLV::TLVReader reader; + CHIP_ERROR err = CHIP_NO_ERROR; + int TagPresenceMask = 0; + TLV::TLVReader reader; PRETTY_PRINT("EventPath ="); PRETTY_PRINT("{"); @@ -51,65 +48,81 @@ CHIP_ERROR EventPathIB::Parser::CheckSchemaValidity() const while (CHIP_NO_ERROR == (err = reader.Next())) { - VerifyOrExit(chip::TLV::IsContextTag(reader.GetTag()), err = CHIP_ERROR_INVALID_TLV_TAG); - switch (chip::TLV::TagNumFromTag(reader.GetTag())) + VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); + uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag()); + switch (tagNum) { - case kCsTag_NodeId: + case to_underlying(Tag::kNode): // check if this tag has appeared before - VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_NodeId)), err = CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_NodeId); - VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kNode))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kNode)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { - uint64_t nodeId; - reader.Get(nodeId); - PRETTY_PRINT("\tNodeId = 0x%" PRIx64 ",", nodeId); + NodeId node; + reader.Get(node); + PRETTY_PRINT("\tNode = 0x%" PRIx64 ",", node); } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_EndpointId: + case to_underlying(Tag::kEndpoint): // check if this tag has appeared before - VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_EndpointId)), err = CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_EndpointId); - VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kEndpoint))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kEndpoint)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { - uint16_t endpointId; - reader.Get(endpointId); - PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId); + EndpointId endpoint; + reader.Get(endpoint); + PRETTY_PRINT("\tEndpoint = 0x%" PRIx16 ",", endpoint); } #endif // CHIP_DETAIL_LOGGING break; - case kCsTag_ClusterId: + case to_underlying(Tag::kCluster): // check if this tag has appeared before - VerifyOrExit(!(TagPresenceMask & (1 << kCsTag_ClusterId)), err = CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << kCsTag_ClusterId); - VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kCluster))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kCluster)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { - chip::ClusterId clusterId; - reader.Get(clusterId); - PRETTY_PRINT("\tClusterId = 0x%" PRIx32 ",", clusterId); + ClusterId cluster; + reader.Get(cluster); + PRETTY_PRINT("\tCluster = 0x%" PRIx32 ",", cluster); } #endif // CHIP_DETAIL_LOGGING break; - case chip::app::EventPathIB::kCsTag_EventId: + case to_underlying(Tag::kEvent): // check if this tag has appeared before - VerifyOrExit(!(TagPresenceMask & (1 << chip::app::EventPathIB::kCsTag_EventId)), err = CHIP_ERROR_INVALID_TLV_TAG); - TagPresenceMask |= (1 << chip::app::EventPathIB::kCsTag_EventId); - VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kEvent))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kEvent)); + VerifyOrReturnError(TLV::kTLVType_UnsignedInteger == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); #if CHIP_DETAIL_LOGGING { - chip::EventId eventId; - reader.Get(eventId); - PRETTY_PRINT("\tEventId = 0x%" PRIx16 ",", eventId); + EventId event; + reader.Get(event); + PRETTY_PRINT("\tEvent = 0x%" PRIx16 ",", event); + } +#endif // CHIP_DETAIL_LOGGING + break; + case to_underlying(Tag::kIsUrgent): + // check if this tag has appeared before + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kIsUrgent))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kIsUrgent)); + VerifyOrReturnError(TLV::kTLVType_Boolean == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); + +#if CHIP_DETAIL_LOGGING + { + bool isUrgent; + ReturnErrorOnFailure(reader.Get(isUrgent)); + PRETTY_PRINT("\tisUrgent = %s, ", isUrgent ? "true" : "false"); } #endif // CHIP_DETAIL_LOGGING break; default: - ExitNow(err = CHIP_ERROR_INVALID_TLV_TAG); + PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); + break; } } @@ -119,83 +132,86 @@ CHIP_ERROR EventPathIB::Parser::CheckSchemaValidity() const // if we have exhausted this container if (CHIP_END_OF_TLV == err) { - // check for required fields: - const uint16_t RequiredFields = (1 << kCsTag_EndpointId) | (1 << kCsTag_ClusterId); - - if ((TagPresenceMask & RequiredFields) == RequiredFields) - { - err = CHIP_NO_ERROR; - } - else - { - err = CHIP_ERROR_IM_MALFORMED_EVENT_PATH; - } + err = CHIP_NO_ERROR; } - SuccessOrExit(err); - err = reader.ExitContainer(mOuterContainerType); - -exit: + ReturnErrorOnFailure(err); + ReturnErrorOnFailure(reader.ExitContainer(mOuterContainerType)); return err; } #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK -CHIP_ERROR EventPathIB::Parser::GetNodeId(chip::NodeId * const apNodeId) const +CHIP_ERROR EventPathIB::Parser::GetNode(NodeId * const apNode) const { - return GetUnsignedInteger(kCsTag_NodeId, apNodeId); + return GetUnsignedInteger(to_underlying(Tag::kNode), apNode); } -CHIP_ERROR EventPathIB::Parser::GetEndpointId(chip::EndpointId * const apEndpointID) const +CHIP_ERROR EventPathIB::Parser::GetEndpoint(EndpointId * const apEndpoint) const { - return GetUnsignedInteger(kCsTag_EndpointId, apEndpointID); + return GetUnsignedInteger(to_underlying(Tag::kEndpoint), apEndpoint); } -CHIP_ERROR EventPathIB::Parser::GetClusterId(chip::ClusterId * const apClusterId) const +CHIP_ERROR EventPathIB::Parser::GetCluster(ClusterId * const apCluster) const { - return GetUnsignedInteger(kCsTag_ClusterId, apClusterId); + return GetUnsignedInteger(to_underlying(Tag::kCluster), apCluster); } -CHIP_ERROR EventPathIB::Parser::GetEventId(chip::EventId * const apEventId) const +CHIP_ERROR EventPathIB::Parser::GetEvent(EventId * const apEvent) const { - return GetUnsignedInteger(kCsTag_EventId, apEventId); + return GetUnsignedInteger(to_underlying(Tag::kEvent), apEvent); +} + +CHIP_ERROR EventPathIB::Parser::GetIsUrgent(bool * const apIsUrgent) const +{ + return GetSimpleValue(to_underlying(Tag::kIsUrgent), TLV::kTLVType_Boolean, apIsUrgent); +} + +EventPathIB::Builder & EventPathIB::Builder::Node(const NodeId aNode) +{ + // skip if error has already been set + if (mError == CHIP_NO_ERROR) + { + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kNode)), aNode); + } + return *this; } -EventPathIB::Builder & EventPathIB::Builder::NodeId(const uint64_t aNodeId) +EventPathIB::Builder & EventPathIB::Builder::Endpoint(const EndpointId aEndpoint) { // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_NodeId), aNodeId); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kEndpoint)), aEndpoint); } return *this; } -EventPathIB::Builder & EventPathIB::Builder::EndpointId(const chip::EndpointId aEndpointId) +EventPathIB::Builder & EventPathIB::Builder::Cluster(const ClusterId aCluster) { // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EndpointId), aEndpointId); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kCluster)), aCluster); } return *this; } -EventPathIB::Builder & EventPathIB::Builder::ClusterId(const chip::ClusterId aClusterId) +EventPathIB::Builder & EventPathIB::Builder::Event(const EventId aEvent) { // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_ClusterId), aClusterId); + mError = mpWriter->Put(TLV::ContextTag(to_underlying(Tag::kEvent)), aEvent); } return *this; } -EventPathIB::Builder & EventPathIB::Builder::EventId(const chip::EventId aEventId) +EventPathIB::Builder & EventPathIB::Builder::IsUrgent(const bool aIsUrgent) { // skip if error has already been set if (mError == CHIP_NO_ERROR) { - mError = mpWriter->Put(chip::TLV::ContextTag(kCsTag_EventId), aEventId); + mError = mpWriter->PutBoolean(TLV::ContextTag(to_underlying(Tag::kIsUrgent)), aIsUrgent); } return *this; } diff --git a/src/app/MessageDef/EventPathIB.h b/src/app/MessageDef/EventPathIB.h index e159c2868a8c32..8b2d6a1fe486ad 100644 --- a/src/app/MessageDef/EventPathIB.h +++ b/src/app/MessageDef/EventPathIB.h @@ -36,12 +36,13 @@ namespace chip { namespace app { namespace EventPathIB { -enum +enum class Tag : uint8_t { - kCsTag_NodeId = 0, - kCsTag_EndpointId = 1, - kCsTag_ClusterId = 2, - kCsTag_EventId = 3, + kNode = 0, + kEndpoint = 1, + kCluster = 2, + kEvent = 3, + kIsUrgent = 4, }; class Parser : public ListParser @@ -67,24 +68,24 @@ class Parser : public ListParser /** * @brief Get a TLVReader for the NodeId. Next() must be called before accessing them. * - * @param [in] apNodeId A pointer to apNodeId + * @param [in] apNode A pointer to apNode * * @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_END_OF_TLV if there is no such element */ - CHIP_ERROR GetNodeId(NodeId * const apNodeId) const; + CHIP_ERROR GetNode(NodeId * const apNode) const; /** * @brief Get a TLVReader for the EndpointId. Next() must be called before accessing them. * - * @param [in] apEndpointId A pointer to apEndpointId + * @param [in] apEndpoint A pointer to apEndpoint * * @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_END_OF_TLV if there is no such element */ - CHIP_ERROR GetEndpointId(EndpointId * const apEndpointId) const; + CHIP_ERROR GetEndpoint(EndpointId * const apEndpoint) const; /** * @brief Get a TLVReader for the ClusterId. Next() must be called before accessing them. @@ -95,7 +96,7 @@ class Parser : public ListParser * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types * #CHIP_END_OF_TLV if there is no such element */ - CHIP_ERROR GetClusterId(ClusterId * const apClusterId) const; + CHIP_ERROR GetCluster(ClusterId * const apCluster) const; /** * @brief Get a TLVReader for the EventId. Next() must be called before accessing them. @@ -106,38 +107,58 @@ class Parser : public ListParser * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not any of the defined unsigned integer types * #CHIP_END_OF_TLV if there is no such element */ - CHIP_ERROR GetEventId(EventId * const apEventId) const; + CHIP_ERROR GetEvent(EventId * const apEvent) const; + + /** + * @brief Get a TLVReader for the EventId. Next() must be called before accessing them. + * + * @param [in] apEventId A pointer to apEventId + * + * @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_END_OF_TLV if there is no such element + */ + CHIP_ERROR GetIsUrgent(bool * const apIsUrgent) const; }; class Builder : public ListBuilder { public: /** - * @brief Inject NodeId into the TLV stream. + * @brief Inject Node into the TLV stream. + * + * @param [in] aNode NodeId for this event path + * + * @return A reference to *this + */ + EventPathIB::Builder & Node(const NodeId aNode); + + /** + * @brief Inject Endpoint into the TLV stream. * - * @param [in] aNodeId NodeId for this event path + * @param [in] aEndpoint EndpointId for this eevent path * * @return A reference to *this */ - EventPathIB::Builder & NodeId(const chip::NodeId aNodeId); + EventPathIB::Builder & Endpoint(const EndpointId aEndpoint); /** - * @brief Inject EndpointId into the TLV stream. + * @brief Inject Cluster into the TLV stream. * - * @param [in] aEndpointId EndpointId for this eevent path + * @param [in] aCluster ClusterId for this event path * * @return A reference to *this */ - EventPathIB::Builder & EndpointId(const chip::EndpointId aEndpointId); + EventPathIB::Builder & Cluster(const ClusterId aCluster); /** - * @brief Inject ClusterId into the TLV stream. + * @brief Inject Event into the TLV stream. * - * @param [in] aClusterId ClusterId for this event path + * @param [in] aEvent ClusterId for this event path * * @return A reference to *this */ - EventPathIB::Builder & ClusterId(const chip::ClusterId aClusterId); + EventPathIB::Builder & Event(const EventId aEvent); /** * @brief Inject EventId into the TLV stream. @@ -146,7 +167,7 @@ class Builder : public ListBuilder * * @return A reference to *this */ - EventPathIB::Builder & EventId(const chip::EventId aEventId); + EventPathIB::Builder & IsUrgent(const bool aIsUrgent); /** * @brief Mark the end of this EventPath @@ -155,6 +176,6 @@ class Builder : public ListBuilder */ EventPathIB::Builder & EndOfEventPathIB(); }; -}; // namespace EventPathIB -}; // namespace app -}; // namespace chip +} // namespace EventPathIB +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/EventPaths.cpp b/src/app/MessageDef/EventPaths.cpp index 61639ef41dc3fb..134e3cc75ae0f3 100644 --- a/src/app/MessageDef/EventPaths.cpp +++ b/src/app/MessageDef/EventPaths.cpp @@ -38,7 +38,7 @@ CHIP_ERROR EventPaths::Parser::CheckSchemaValidity() const { CHIP_ERROR err = CHIP_NO_ERROR; size_t NumPath = 0; - chip::TLV::TLVReader reader; + TLV::TLVReader reader; PRETTY_PRINT("EventPaths ="); PRETTY_PRINT("["); @@ -48,17 +48,15 @@ CHIP_ERROR EventPaths::Parser::CheckSchemaValidity() const while (CHIP_NO_ERROR == (err = reader.Next())) { - VerifyOrExit(chip::TLV::AnonymousTag == reader.GetTag(), err = CHIP_ERROR_INVALID_TLV_TAG); - VerifyOrExit(chip::TLV::kTLVType_List == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE); + VerifyOrReturnError(TLV::AnonymousTag == reader.GetTag(), CHIP_ERROR_INVALID_TLV_TAG); + VerifyOrReturnError(TLV::kTLVType_List == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); { EventPathIB::Parser path; - err = path.Init(reader); - SuccessOrExit(err); + ReturnErrorOnFailure(path.Init(reader)); PRETTY_PRINT_INCDEPTH(); - err = path.CheckSchemaValidity(); - SuccessOrExit(err); + ReturnErrorOnFailure(path.CheckSchemaValidity()); PRETTY_PRINT_DECDEPTH(); } @@ -73,12 +71,9 @@ CHIP_ERROR EventPaths::Parser::CheckSchemaValidity() const { err = CHIP_NO_ERROR; } - SuccessOrExit(err); - err = reader.ExitContainer(mOuterContainerType); - -exit: - - return err; + ReturnErrorOnFailure(err); + ReturnErrorOnFailure(reader.ExitContainer(mOuterContainerType)); + return CHIP_NO_ERROR; } #endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK diff --git a/src/app/MessageDef/EventStatusIB.cpp b/src/app/MessageDef/EventStatusIB.cpp new file mode 100644 index 00000000000000..536f28b703f8b5 --- /dev/null +++ b/src/app/MessageDef/EventStatusIB.cpp @@ -0,0 +1,140 @@ +/** + * + * Copyright (c) 2021 Project CHIP Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "EventStatusIB.h" +#include "MessageDefHelper.h" +#include "StructBuilder.h" +#include "StructParser.h" + +#include +#include +#include + +#include + +namespace chip { +namespace app { +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK +CHIP_ERROR EventStatusIB::Parser::CheckSchemaValidity() const +{ + CHIP_ERROR err = CHIP_NO_ERROR; + int TagPresenceMask = 0; + TLV::TLVReader reader; + + PRETTY_PRINT("EventStatusIB ="); + PRETTY_PRINT("{"); + + // make a copy of the reader + reader.Init(mReader); + + while (CHIP_NO_ERROR == (err = reader.Next())) + { + VerifyOrReturnError(TLV::IsContextTag(reader.GetTag()), CHIP_ERROR_INVALID_TLV_TAG); + uint32_t tagNum = TLV::TagNumFromTag(reader.GetTag()); + switch (tagNum) + { + case to_underlying(Tag::kPath): + // check if this tag has appeared before + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kPath))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kPath)); + { + EventPathIB::Parser path; + ReturnErrorOnFailure(path.Init(reader)); + + PRETTY_PRINT_INCDEPTH(); + ReturnErrorOnFailure(path.CheckSchemaValidity()); + PRETTY_PRINT_DECDEPTH(); + } + break; + case to_underlying(Tag::kErrorStatus): + // check if this tag has appeared before + VerifyOrReturnError(!(TagPresenceMask & (1 << to_underlying(Tag::kErrorStatus))), CHIP_ERROR_INVALID_TLV_TAG); + TagPresenceMask |= (1 << to_underlying(Tag::kErrorStatus)); + { + StatusIB::Parser errorStatus; + ReturnErrorOnFailure(errorStatus.Init(reader)); + + PRETTY_PRINT_INCDEPTH(); + ReturnErrorOnFailure(errorStatus.CheckSchemaValidity()); + PRETTY_PRINT_DECDEPTH(); + } + break; + default: + PRETTY_PRINT("Unknown tag num %" PRIu32, tagNum); + break; + } + } + + PRETTY_PRINT("},"); + PRETTY_PRINT(""); + + if (CHIP_END_OF_TLV == err) + { + const int RequiredFields = (1 << to_underlying(Tag::kPath)) | (1 << to_underlying(Tag::kErrorStatus)); + + if ((TagPresenceMask & RequiredFields) == RequiredFields) + { + err = CHIP_NO_ERROR; + } + } + + ReturnErrorOnFailure(err); + ReturnErrorOnFailure(reader.ExitContainer(mOuterContainerType)); + return CHIP_NO_ERROR; +} +#endif // CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + +CHIP_ERROR EventStatusIB::Parser::GetPath(EventPathIB::Parser * const apPath) const +{ + TLV::TLVReader reader; + ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(to_underlying(Tag::kPath)), reader)); + ReturnErrorOnFailure(apPath->Init(reader)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EventStatusIB::Parser::GetErrorStatus(StatusIB::Parser * const apErrorStatus) const +{ + TLV::TLVReader reader; + ReturnErrorOnFailure(mReader.FindElementWithTag(TLV::ContextTag(to_underlying(Tag::kErrorStatus)), reader)); + ReturnErrorOnFailure(apErrorStatus->Init(reader)); + return CHIP_NO_ERROR; +} + +EventPathIB::Builder & EventStatusIB::Builder::CreatePath() +{ + if (mError == CHIP_NO_ERROR) + { + mError = mPath.Init(mpWriter, to_underlying(Tag::kPath)); + } + return mPath; +} + +StatusIB::Builder & EventStatusIB::Builder::CreateErrorStatus() +{ + if (mError == CHIP_NO_ERROR) + { + mError = mErrorStatus.Init(mpWriter, to_underlying(Tag::kErrorStatus)); + } + return mErrorStatus; +} + +EventStatusIB::Builder & EventStatusIB::Builder::EndOfEventStatusIB() +{ + EndOfContainer(); + return *this; +} +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/EventStatusIB.h b/src/app/MessageDef/EventStatusIB.h new file mode 100644 index 00000000000000..f51eae5e156d69 --- /dev/null +++ b/src/app/MessageDef/EventStatusIB.h @@ -0,0 +1,114 @@ +/** + * + * Copyright (c) 2021 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "EventPathIB.h" +#include "StatusIB.h" +#include "StructBuilder.h" +#include "StructParser.h" + +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace EventStatusIB { +enum class Tag : uint8_t +{ + kPath = 0, + kErrorStatus = 1, +}; + +class Parser : public StructParser +{ +public: +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + /** + * @brief Roughly verify the message is correctly formed + * 1) all mandatory tags are present + * 2) all elements have expected data type + * 3) any tag can only appear once + * 4) At the top level of the structure, unknown tags are ignored for forward compatibility + * @note The main use of this function is to print out what we're + * receiving during protocol development and debugging. + * The encoding rule has changed in IM encoding spec so this + * check is only "roughly" conformant now. + * + * @return #CHIP_NO_ERROR on success + */ + CHIP_ERROR CheckSchemaValidity() const; +#endif + + /** + * @brief Get a TLVReader for the EventPathIB. Next() must be called before accessing them. + * + * @param [in] apPath A pointer to apPath + * + * @return #CHIP_NO_ERROR on success + * #CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not a Path + * #CHIP_END_OF_TLV if there is no such element + */ + CHIP_ERROR GetPath(EventPathIB::Parser * const apPath) const; + + /** + * @brief Get a TLVReader for the StatusIB. Next() must be called before accessing them. + * + * @param [in] apErrorStatus A pointer to apErrorStatus + * + * @return #CHIP_NO_ERROR on success + * # CHIP_ERROR_WRONG_TLV_TYPE if there is such element but it's not a structure + * #CHIP_END_OF_TLV if there is no such element + */ + CHIP_ERROR GetErrorStatus(StatusIB::Parser * const apErrorStatus) const; +}; + +class Builder : public StructBuilder +{ +public: + /** + * @brief Initialize a EventPathIB::Builder for writing into the TLV stream + * + * @return A reference to EventPathIB::Builder + */ + EventPathIB::Builder & CreatePath(); + + /** + * @brief Initialize a StatusIB::Builder for writing into the TLV stream + * + * @return A reference to StatusIB::Builder + */ + StatusIB::Builder & CreateErrorStatus(); + + /** + * @brief Mark the end of this EventStatusIB + * + * @return A reference to *this + */ + EventStatusIB::Builder & EndOfEventStatusIB(); + +private: + EventPathIB::Builder mPath; + StatusIB::Builder mErrorStatus; +}; +} // namespace EventStatusIB +} // namespace app +} // namespace chip diff --git a/src/app/MessageDef/ReadRequestMessage.h b/src/app/MessageDef/ReadRequestMessage.h index 116b5fe903be79..66137d53f0d602 100644 --- a/src/app/MessageDef/ReadRequestMessage.h +++ b/src/app/MessageDef/ReadRequestMessage.h @@ -43,8 +43,8 @@ namespace ReadRequestMessage { enum { kCsTag_AttributePathList = 0, - kCsTag_EventPaths = 1, - kCsTag_AttributeDataVersionList = 2, + kCsTag_AttributeDataVersionList = 1, + kCsTag_EventPaths = 2, kCsTag_EventNumber = 3, }; diff --git a/src/app/ReadClient.cpp b/src/app/ReadClient.cpp index a77794af73f7d9..d3516d1aabe796 100644 --- a/src/app/ReadClient.cpp +++ b/src/app/ReadClient.cpp @@ -236,10 +236,10 @@ CHIP_ERROR ReadClient::GenerateEventPaths(EventPaths::Builder & aEventPathsBuild { EventPathIB::Builder eventPathBuilder = aEventPathsBuilder.CreateEventPath(); EventPathParams eventPath = apEventPathParamsList[eventIndex]; - eventPathBuilder.NodeId(eventPath.mNodeId) - .EventId(eventPath.mEventId) - .EndpointId(eventPath.mEndpointId) - .ClusterId(eventPath.mClusterId) + eventPathBuilder.Node(eventPath.mNodeId) + .Event(eventPath.mEventId) + .Endpoint(eventPath.mEndpointId) + .Cluster(eventPath.mClusterId) .EndOfEventPathIB(); SuccessOrExit(err = eventPathBuilder.GetError()); } diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index a1589a6fa1450e..c2ec72d32f3924 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -391,13 +391,13 @@ CHIP_ERROR ReadHandler::ProcessEventPaths(EventPaths::Parser & aEventPathsParser EventPathIB::Parser path; err = path.Init(reader); SuccessOrExit(err); - err = path.GetNodeId(&(clusterInfo.mNodeId)); + err = path.GetNode(&(clusterInfo.mNodeId)); SuccessOrExit(err); - err = path.GetEndpointId(&(clusterInfo.mEndpointId)); + err = path.GetEndpoint(&(clusterInfo.mEndpointId)); SuccessOrExit(err); - err = path.GetClusterId(&(clusterInfo.mClusterId)); + err = path.GetCluster(&(clusterInfo.mClusterId)); SuccessOrExit(err); - err = path.GetEventId(&(clusterInfo.mEventId)); + err = path.GetEvent(&(clusterInfo.mEventId)); if (CHIP_NO_ERROR == err) { clusterInfo.mFlags.Set(ClusterInfo::Flags::kEventIdValid); diff --git a/src/app/tests/TestMessageDef.cpp b/src/app/tests/TestMessageDef.cpp index 2b2e68aa802f20..0200590b14c776 100644 --- a/src/app/tests/TestMessageDef.cpp +++ b/src/app/tests/TestMessageDef.cpp @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -190,7 +191,7 @@ void ParseAttributePathList(nlTestSuite * apSuite, chip::TLV::TLVReader & aReade void BuildEventPath(nlTestSuite * apSuite, EventPathIB::Builder & aEventPathBuilder) { CHIP_ERROR err = CHIP_NO_ERROR; - aEventPathBuilder.NodeId(1).EndpointId(2).ClusterId(3).EventId(4).EndOfEventPathIB(); + aEventPathBuilder.Node(1).Endpoint(2).Cluster(3).Event(4).IsUrgent(true).EndOfEventPathIB(); err = aEventPathBuilder.GetError(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); } @@ -202,22 +203,26 @@ void ParseEventPath(nlTestSuite * apSuite, EventPathIB::Parser & aEventPathParse chip::EndpointId endpointId = 2; chip::ClusterId clusterId = 3; chip::EventId eventId = 4; + bool isUrgent = false; #if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK err = aEventPathParser.CheckSchemaValidity(); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); #endif - err = aEventPathParser.GetNodeId(&nodeId); + err = aEventPathParser.GetNode(&nodeId); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR && nodeId == 1); - err = aEventPathParser.GetEndpointId(&endpointId); + err = aEventPathParser.GetEndpoint(&endpointId); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR && endpointId == 2); - err = aEventPathParser.GetClusterId(&clusterId); + err = aEventPathParser.GetCluster(&clusterId); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR && clusterId == 3); - err = aEventPathParser.GetEventId(&eventId); + err = aEventPathParser.GetEvent(&eventId); NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR && eventId == 4); + + err = aEventPathParser.GetIsUrgent(&isUrgent); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR && isUrgent == true); } void BuildEventPaths(nlTestSuite * apSuite, EventPaths::Builder & aEventPathsBuilder) @@ -411,6 +416,36 @@ void ParseStatusIB(nlTestSuite * apSuite, StatusIB::Parser & aStatusIBParser) !statusIB.mClusterStatus.HasValue()); } +void BuildEventStatusIB(nlTestSuite * apSuite, EventStatusIB::Builder & aEventStatusIBBuilder) +{ + EventPathIB::Builder eventPathBuilder = aEventStatusIBBuilder.CreatePath(); + NL_TEST_ASSERT(apSuite, aEventStatusIBBuilder.GetError() == CHIP_NO_ERROR); + BuildEventPath(apSuite, eventPathBuilder); + + StatusIB::Builder statusIBBuilder = aEventStatusIBBuilder.CreateErrorStatus(); + NL_TEST_ASSERT(apSuite, statusIBBuilder.GetError() == CHIP_NO_ERROR); + BuildStatusIB(apSuite, statusIBBuilder); + + aEventStatusIBBuilder.EndOfEventStatusIB(); + NL_TEST_ASSERT(apSuite, aEventStatusIBBuilder.GetError() == CHIP_NO_ERROR); +} + +void ParseEventStatusIB(nlTestSuite * apSuite, EventStatusIB::Parser & aEventStatusIBParser) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + EventPathIB::Parser eventPathParser; + StatusIB::Parser statusParser; +#if CHIP_CONFIG_IM_ENABLE_SCHEMA_CHECK + err = aEventStatusIBParser.CheckSchemaValidity(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); +#endif + err = aEventStatusIBParser.GetPath(&eventPathParser); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + err = aEventStatusIBParser.GetErrorStatus(&statusParser); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); +} + void BuildAttributeStatusIB(nlTestSuite * apSuite, AttributeStatusIB::Builder & aAttributeStatusIBBuilder) { AttributePath::Builder attributePathBuilder = aAttributeStatusIBBuilder.CreateAttributePathBuilder(); @@ -1450,6 +1485,30 @@ void StatusIBTest(nlTestSuite * apSuite, void * apContext) ParseStatusIB(apSuite, StatusIBParser); } +void EventStatusIBTest(nlTestSuite * apSuite, void * apContext) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + EventStatusIB::Builder eventStatusIBBuilder; + EventStatusIB::Parser eventStatusIBParser; + chip::System::PacketBufferTLVWriter writer; + chip::System::PacketBufferTLVReader reader; + writer.Init(chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSize)); + eventStatusIBBuilder.Init(&writer); + BuildEventStatusIB(apSuite, eventStatusIBBuilder); + chip::System::PacketBufferHandle buf; + err = writer.Finalize(&buf); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + DebugPrettyPrint(buf); + + reader.Init(std::move(buf)); + err = reader.Next(); + NL_TEST_ASSERT(apSuite, err == CHIP_NO_ERROR); + + eventStatusIBParser.Init(reader); + ParseEventStatusIB(apSuite, eventStatusIBParser); +} + void AttributeStatusIBTest(nlTestSuite * apSuite, void * apContext) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -1964,6 +2023,7 @@ const nlTest sTests[] = NL_TEST_DEF("EventDataElementTest", EventDataElementTest), NL_TEST_DEF("EventListTest", EventListTest), NL_TEST_DEF("StatusIBTest", StatusIBTest), + NL_TEST_DEF("EventStatusIBTest", EventStatusIBTest), NL_TEST_DEF("AttributeStatusIBTest", AttributeStatusIBTest), NL_TEST_DEF("AttributeStatusListTest", AttributeStatusListTest), NL_TEST_DEF("AttributeDataElementTest", AttributeDataElementTest),