Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restyle Add IM event processing function and callback interface in client side #11890

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/app/ClusterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct ClusterInfo
private:
// Allow AttributePathParams access these constants.
friend struct AttributePathParams;
friend struct ConcreteEventPath;

// The ClusterId, AttributeId and EventId are MEIs,
// 0xFFFF is not a valid manufacturer code, thus 0xFFFF'FFFF is not a valid MEI
Expand Down
63 changes: 63 additions & 0 deletions src/app/ConcreteEventPath.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
*
* Copyright (c) 2021 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 <app/ClusterInfo.h>
#include <app/util/basic-types.h>

namespace chip {
namespace app {

/**
* A representation of a concrete event path.
*/
struct ConcreteEventPath
{
ConcreteEventPath(EndpointId aEndpointId, ClusterId aClusterId, EventId aEventId) :
mEndpointId(aEndpointId), mClusterId(aClusterId), mEventId(aEventId)
{}

ConcreteEventPath() {}

ConcreteEventPath & operator=(ConcreteEventPath && other)
{
if (&other == this)
return *this;

mEndpointId = other.mEndpointId;
mClusterId = other.mClusterId;
mEventId = other.mEventId;
return *this;
}

bool operator==(const ConcreteEventPath & other) const
{
return mEndpointId == other.mEndpointId && mClusterId == other.mClusterId && mEventId == other.mEventId;
}

bool IsValidEventPath() const { return !HasWildcardEventId(); }

inline bool HasWildcardEventId() const { return mEventId == ClusterInfo::kInvalidEventId; }

EndpointId mEndpointId = 0;
ClusterId mClusterId = 0;
EventId mEventId = 0;
};
} // namespace app
} // namespace chip
4 changes: 3 additions & 1 deletion src/app/DeviceControllerInteractionModelDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ class DeviceControllerInteractionModelDelegate : public chip::app::ReadClient::C

void OnDone(app::WriteClient * apWriteClient) override {}

void OnEventData(const app::ReadClient * apReadClient, TLV::TLVReader & aEventList) override {}
void OnEventData(const app::ReadClient * apReadClient, const app::EventHeader & aEventHeader, TLV::TLVReader * apData,
const app::StatusIB * apStatus) override
{}

void OnAttributeData(const app::ReadClient * apReadClient, const app::ConcreteAttributePath & aPath, TLV::TLVReader * apData,
const app::StatusIB & aStatus) override
Expand Down
35 changes: 35 additions & 0 deletions src/app/EventHeader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
*
* Copyright (c) 2021 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 "ConcreteEventPath.h"
#include "EventLoggingTypes.h"
#include <app/util/basic-types.h>

namespace chip {
namespace app {
struct EventHeader
{
ConcreteEventPath mPath;
EventNumber mEventNumber = 0;
PriorityLevel mPriorityLevel = PriorityLevel::Invalid;
Timestamp mTimestamp;
};
} // namespace app
} // namespace chip
20 changes: 11 additions & 9 deletions src/app/EventLoggingTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,23 +104,22 @@ struct EventSchema

/**
* @brief
* The struct that provides an application set system or UTC timestamp.
* The struct that provides an application set System or Epoch timestamp.
*/
struct Timestamp
{
enum class Type
{
kInvalid = 0,
kSystem,
kUTC
kSystem = 0,
kEpoch
};
Timestamp() {}
Timestamp(Type aType) : mType(aType) { mValue = 0; }
Timestamp(Type aType, uint64_t aValue) : mType(aType), mValue(aValue) {}
Timestamp(System::Clock::Timestamp aValue) : mType(Type::kSystem), mValue(aValue.count()) {}
static Timestamp UTC(uint64_t aValue)
{
Timestamp timestamp(Type::kUTC, aValue);
Timestamp timestamp(Type::kEpoch, aValue);
return timestamp;
}
static Timestamp System(System::Clock::Timestamp aValue)
Expand All @@ -129,7 +128,10 @@ struct Timestamp
return timestamp;
}

Type mType = Type::kInvalid;
bool IsSystem() { return mType == Type::kSystem; }
bool IsEpoch() { return mType == Type::kEpoch; }

Type mType = Type::kSystem;
uint64_t mValue = 0;
};

Expand All @@ -144,9 +146,9 @@ class EventOptions
kUrgent = 0,
kNotUrgent,
};
EventOptions(void) : mTimestamp(Timestamp::Type::kInvalid), mpEventSchema(nullptr), mUrgent(Type::kNotUrgent) {}
EventOptions(void) : mTimestamp(Timestamp::Type::kSystem), mpEventSchema(nullptr), mUrgent(Type::kNotUrgent) {}

EventOptions(Type aType) : mTimestamp(Timestamp::Type::kInvalid), mpEventSchema(nullptr), mUrgent(aType) {}
EventOptions(Type aType) : mTimestamp(Timestamp::Type::kSystem), mpEventSchema(nullptr), mUrgent(aType) {}

EventOptions(Timestamp aTimestamp) : mTimestamp(aTimestamp), mpEventSchema(nullptr), mUrgent(Type::kNotUrgent) {}

Expand All @@ -167,7 +169,7 @@ struct EventLoadOutContext
{
EventLoadOutContext(TLV::TLVWriter & aWriter, PriorityLevel aPriority, EventNumber aStartingEventNumber) :
mWriter(aWriter), mPriority(aPriority), mStartingEventNumber(aStartingEventNumber),
mCurrentSystemTime(Timestamp::Type::kSystem), mCurrentEventNumber(0), mCurrentUTCTime(Timestamp::Type::kUTC), mFirst(true)
mCurrentSystemTime(Timestamp::Type::kSystem), mCurrentEventNumber(0), mCurrentUTCTime(Timestamp::Type::kEpoch), mFirst(true)
{}

TLV::TLVWriter & mWriter;
Expand Down
47 changes: 2 additions & 45 deletions src/app/EventManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,40 +304,16 @@ CHIP_ERROR EventManagement::ConstructEvent(EventLoadOutContext * apContext, Even
EventReportIB::Builder eventReportBuilder;
EventDataIB::Builder eventDataIBBuilder;
EventPathIB::Builder eventPathBuilder;
EventStatusIB::Builder eventStatusIBBuilder;
StatusIB::Builder statusIBBuilder;
StatusIB status;
uint64_t deltatime = 0;

VerifyOrExit(apContext->mCurrentEventNumber >= apContext->mStartingEventNumber,
/* no-op: don't write event, but advance current event Number */);

VerifyOrExit(apOptions != nullptr, err = CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrExit(apOptions->mTimestamp.mType != Timestamp::Type::kInvalid, err = CHIP_ERROR_INVALID_ARGUMENT);

eventReportBuilder.Init(&(apContext->mWriter));
// TODO: Update IsUrgent, issue 11386
// TODO: Update statusIB, issue 11388
eventStatusIBBuilder = eventReportBuilder.CreateEventStatus();
eventPathBuilder = eventStatusIBBuilder.CreatePath();
err = eventStatusIBBuilder.GetError();
SuccessOrExit(err);
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);
statusIBBuilder = eventStatusIBBuilder.CreateErrorStatus();
err = eventStatusIBBuilder.GetError();
SuccessOrExit(err);
statusIBBuilder.EncodeStatusIB(status);
eventStatusIBBuilder.EndOfEventStatusIB();
err = statusIBBuilder.GetError();
SuccessOrExit(err);

eventDataIBBuilder = eventReportBuilder.CreateEventData();
eventPathBuilder = eventDataIBBuilder.CreatePath();
err = eventDataIBBuilder.GetError();
Expand Down Expand Up @@ -621,23 +597,6 @@ CHIP_ERROR EventManagement::CopyEvent(const TLVReader & aReader, TLVWriter & aWr
ReturnErrorOnFailure(reader.EnterContainer(containerType));
ReturnErrorOnFailure(aWriter.StartContainer(AnonymousTag, kTLVType_Structure, containerType));

ReturnErrorOnFailure(reader.Next());
ReturnErrorOnFailure(reader.EnterContainer(containerType1));
ReturnErrorOnFailure(aWriter.StartContainer(TLV::ContextTag(to_underlying(EventReportIB::Tag::kEventStatus)),
kTLVType_Structure, containerType1));
ReturnErrorOnFailure(reader.Next());
do
{
ReturnErrorOnFailure(aWriter.CopyElement(reader));
} while (CHIP_NO_ERROR == (err = reader.Next()));
if (err == CHIP_END_OF_TLV)
{
err = CHIP_NO_ERROR;
}
ReturnErrorOnFailure(err);
ReturnErrorOnFailure(reader.ExitContainer(containerType1));
ReturnErrorOnFailure(aWriter.EndContainer(containerType1));

ReturnErrorOnFailure(reader.Next());
ReturnErrorOnFailure(reader.EnterContainer(containerType1));
ReturnErrorOnFailure(
Expand Down Expand Up @@ -685,8 +644,7 @@ CHIP_ERROR EventManagement::EventIterator(const TLVReader & aReader, size_t aDep
innerReader.Init(aReader);
ReturnErrorOnFailure(innerReader.EnterContainer(tlvType));
ReturnErrorOnFailure(innerReader.Next());
// Skip EventStatus Element
ReturnErrorOnFailure(innerReader.Next());

ReturnErrorOnFailure(innerReader.EnterContainer(tlvType1));
err = TLV::Utilities::Iterate(innerReader, FetchEventParameters, &event, false /*recurse*/);
if (event.mFieldsToRead != kRequiredEventField)
Expand Down Expand Up @@ -836,8 +794,7 @@ CHIP_ERROR EventManagement::EvictEvent(CHIPCircularTLVBuffer & apBuffer, void *
TLVType containerType1;
ReturnErrorOnFailure(aReader.EnterContainer(containerType));
ReturnErrorOnFailure(aReader.Next());
// Skip EventStatus
ReturnErrorOnFailure(aReader.Next());

ReturnErrorOnFailure(aReader.EnterContainer(containerType1));
EventEnvelopeContext context;
constexpr bool recurse = false;
Expand Down
3 changes: 3 additions & 0 deletions src/app/EventPathParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ struct EventPathParams
EventPathParams(NodeId aNodeId, EndpointId aEndpointId, ClusterId aClusterId, EventId aEventId, bool aIsUrgent) :
mNodeId(aNodeId), mEndpointId(aEndpointId), mClusterId(aClusterId), mEventId(aEventId), mIsUrgent(aIsUrgent)
{}
EventPathParams(EndpointId aEndpointId, ClusterId aClusterId, EventId aEventId) :
EventPathParams(0, aEndpointId, aClusterId, aEventId, false)
{}
EventPathParams() {}
bool IsSamePath(const EventPathParams & other) const
{
Expand Down
99 changes: 99 additions & 0 deletions src/app/MessageDef/EventDataIB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,105 @@ CHIP_ERROR EventDataIB::Parser::GetData(TLV::TLVReader * const apReader) const
return mReader.FindElementWithTag(TLV::ContextTag(to_underlying(Tag::kData)), *apReader);
}

CHIP_ERROR EventDataIB::Parser::ProcessEventPath(EventPathIB::Parser & aEventPath, ConcreteEventPath & aConcreteEventPath)
{
// The ReportData must contain a concrete event path
CHIP_ERROR err = aEventPath.GetEndpoint(&(aConcreteEventPath.mEndpointId));
VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_EVENT_PATH);

err = aEventPath.GetCluster(&(aConcreteEventPath.mClusterId));
VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_EVENT_PATH);

err = aEventPath.GetEvent(&(aConcreteEventPath.mEventId));
VerifyOrReturnError(err == CHIP_NO_ERROR, CHIP_ERROR_IM_MALFORMED_EVENT_PATH);

VerifyOrReturnError(aConcreteEventPath.IsValidEventPath(), CHIP_ERROR_IM_MALFORMED_EVENT_PATH);
return CHIP_NO_ERROR;
}

CHIP_ERROR EventDataIB::Parser::ProcessEventTimestamp(EventHeader & aEventHeader)
{
CHIP_ERROR err = CHIP_NO_ERROR;
uint64_t timeStampVal = 0;
bool hasSystemTimestamp = false;
bool hasEpochTimestamp = false;
bool hasDeltaSystemTimestamp = false;
bool hasDeltaEpochTimestamp = false;

err = GetDeltaSystemTimestamp(&timeStampVal);
if (err == CHIP_END_OF_TLV)
{
err = CHIP_NO_ERROR;
}
else if (err == CHIP_NO_ERROR)
{
VerifyOrReturnError(aEventHeader.mTimestamp.IsSystem(), CHIP_ERROR_IM_MALFORMED_EVENT_DATA_ELEMENT);
aEventHeader.mTimestamp.mValue += timeStampVal;
hasDeltaSystemTimestamp = true;
}
ReturnErrorOnFailure(err);

err = GetDeltaEpochTimestamp(&timeStampVal);
if (err == CHIP_END_OF_TLV)
{
err = CHIP_NO_ERROR;
}
else if (err == CHIP_NO_ERROR)
{
VerifyOrReturnError(aEventHeader.mTimestamp.IsEpoch(), CHIP_ERROR_IM_MALFORMED_EVENT_DATA_ELEMENT);
aEventHeader.mTimestamp.mValue += timeStampVal;
hasDeltaEpochTimestamp = true;
}
ReturnErrorOnFailure(err);

err = GetSystemTimestamp(&timeStampVal);
if (err == CHIP_END_OF_TLV)
{
err = CHIP_NO_ERROR;
}
else if (err == CHIP_NO_ERROR)
{
aEventHeader.mTimestamp.mType = Timestamp::Type::kSystem;
aEventHeader.mTimestamp.mValue = timeStampVal;
hasSystemTimestamp = true;
}
ReturnErrorOnFailure(err);

err = GetEpochTimestamp(&timeStampVal);
if (err == CHIP_END_OF_TLV)
{
err = CHIP_NO_ERROR;
}
else if (err == CHIP_NO_ERROR)
{
aEventHeader.mTimestamp.mType = Timestamp::Type::kEpoch;
aEventHeader.mTimestamp.mValue = timeStampVal;
hasEpochTimestamp = true;
}

if ((hasSystemTimestamp && !hasEpochTimestamp && !hasDeltaSystemTimestamp && !hasDeltaEpochTimestamp) ||
(!hasSystemTimestamp && hasEpochTimestamp && !hasDeltaSystemTimestamp && !hasDeltaEpochTimestamp) ||
(!hasSystemTimestamp && !hasEpochTimestamp && hasDeltaSystemTimestamp && !hasDeltaEpochTimestamp) ||
(!hasSystemTimestamp && !hasEpochTimestamp && !hasDeltaSystemTimestamp && hasDeltaEpochTimestamp))
{
return CHIP_NO_ERROR;
}
return CHIP_ERROR_IM_MALFORMED_EVENT_DATA_ELEMENT;
}

CHIP_ERROR EventDataIB::Parser::DecodeEventHeader(EventHeader & aEventHeader)
{
uint8_t priorityLevel = 0;
EventPathIB::Parser path;
ReturnErrorOnFailure(GetPath(&path));
ReturnErrorOnFailure(ProcessEventPath(path, aEventHeader.mPath));
ReturnErrorOnFailure(GetEventNumber(&(aEventHeader.mEventNumber)));
ReturnErrorOnFailure(GetPriority(&priorityLevel));
aEventHeader.mPriorityLevel = static_cast<PriorityLevel>(priorityLevel);
ReturnErrorOnFailure(ProcessEventTimestamp(aEventHeader));
return CHIP_NO_ERROR;
}

EventPathIB::Builder & EventDataIB::Builder::CreatePath()
{
// skip if error has already been set
Expand Down
Loading