Skip to content

Commit

Permalink
[Im] Add ClusterObjects API for AttributeWrite in CHIPClusters.cpp (p…
Browse files Browse the repository at this point in the history
…roject-chip#10488)

* [IM] Use ClusterObjects for WriteInteractions

* Run Codegen

* Changes as per review feedback

* Update ids/Attribute.zapt and cluster-objects.zapt

* Fix mOnError call

* Rerun codegen after merge

* Remove char string workarounds that are not needed

* Comment fix

* Do not replace existing WriteAttribute* api by templates

* Run Codegen

* Do not include template in CHIPClustersTest since they are not used (and makes the build slow)

Co-authored-by: Jerry Johns <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>
  • Loading branch information
3 people authored Oct 25, 2021
1 parent ab8cc00 commit 9b9f6f3
Show file tree
Hide file tree
Showing 38 changed files with 7,007 additions and 6,319 deletions.
38 changes: 0 additions & 38 deletions src/app/InteractionModelDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,44 +101,6 @@ class InteractionModelDelegate
*/
virtual CHIP_ERROR ReadError(ReadClient * apReadClient, CHIP_ERROR aError) { return CHIP_ERROR_NOT_IMPLEMENTED; }

/**
* Notification that a WriteClient has received a Write Response containing a status code.
* aAttributeIndex is processing attribute index which can identify attribute if there exists multiple attribute changes with
* same attribute path
*/
virtual CHIP_ERROR WriteResponseStatus(const WriteClient * apWriteClient, const StatusIB & aStatusIB,
AttributePathParams & aAttributePathParams, uint8_t aAttributeIndex)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

/**
* Notification that a Write Response has been processed and application can do further work .
*/
virtual CHIP_ERROR WriteResponseProcessed(const WriteClient * apWriteClient) { return CHIP_ERROR_NOT_IMPLEMENTED; }

/**
* Notification that a Write Client has received a Write Response and fails to process a attribute data element in that
* write response
*/
virtual CHIP_ERROR WriteResponseProtocolError(const WriteClient * apWriteClient, uint8_t aAttributeIndex)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

/**
* Notification that a write client encountered an asynchronous failure.
* @param[in] apWriteClient A current write client which can identify the write client to the consumer, particularly
* during multiple write interactions
* @param[in] aError A error that could be CHIP_ERROR_TIMEOUT when write client fails to receive, or other error when
* fail to process write response.
* @retval # CHIP_ERROR_NOT_IMPLEMENTED if not implemented
*/
virtual CHIP_ERROR WriteResponseError(const WriteClient * apWriteClient, CHIP_ERROR aError)
{
return CHIP_ERROR_NOT_IMPLEMENTED;
}

/**
* Notification that a Subscribe Response has been processed and application can do further work .
*/
Expand Down
34 changes: 32 additions & 2 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,36 @@ uint32_t InteractionModelEngine::GetNumActiveReadHandlers() const
return numActive;
}

uint32_t InteractionModelEngine::GetNumActiveWriteClients() const
{
uint32_t numActive = 0;

for (auto & writeClient : mWriteClients)
{
if (!writeClient.IsFree())
{
numActive++;
}
}

return numActive;
}

uint32_t InteractionModelEngine::GetNumActiveWriteHandlers() const
{
uint32_t numActive = 0;

for (auto & writeHandler : mWriteHandlers)
{
if (!writeHandler.IsFree())
{
numActive++;
}
}

return numActive;
}

CHIP_ERROR InteractionModelEngine::ShutdownSubscription(uint64_t aSubscriptionId)
{
CHIP_ERROR err = CHIP_ERROR_KEY_NOT_FOUND;
Expand All @@ -196,7 +226,7 @@ CHIP_ERROR InteractionModelEngine::ShutdownSubscription(uint64_t aSubscriptionId
return err;
}

CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClientHandle & apWriteClient, uint64_t aApplicationIdentifier)
CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClientHandle & apWriteClient, WriteClient::Callback * apCallback)
{
apWriteClient.SetWriteClient(nullptr);

Expand All @@ -207,7 +237,7 @@ CHIP_ERROR InteractionModelEngine::NewWriteClient(WriteClientHandle & apWriteCli
continue;
}

ReturnLogErrorOnFailure(writeClient.Init(mpExchangeMgr, mpDelegate, aApplicationIdentifier));
ReturnLogErrorOnFailure(writeClient.Init(mpExchangeMgr, apCallback));
apWriteClient.SetWriteClient(&writeClient);
return CHIP_NO_ERROR;
}
Expand Down
5 changes: 4 additions & 1 deletion src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate, public Comman
* @retval #CHIP_ERROR_NO_MEMORY If there is no WriteClient available
* @retval #CHIP_NO_ERROR On success.
*/
CHIP_ERROR NewWriteClient(WriteClientHandle & apWriteClient, uint64_t aApplicationIdentifier = 0);
CHIP_ERROR NewWriteClient(WriteClientHandle & apWriteClient, WriteClient::Callback * callback);

/**
* Allocate a ReadClient that can be used to do a read interaction. If the call succeeds, the consumer
Expand All @@ -156,6 +156,9 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate, public Comman
uint32_t GetNumActiveReadHandlers() const;
uint32_t GetNumActiveReadClients() const;

uint32_t GetNumActiveWriteHandlers() const;
uint32_t GetNumActiveWriteClients() const;

/**
* Get read client index in mReadClients
*
Expand Down
8 changes: 4 additions & 4 deletions src/app/MessageDef/AttributePath.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const

#if CHIP_DETAIL_LOGGING
{
uint64_t nodeId;
chip::NodeId nodeId;
reader.Get(nodeId);
PRETTY_PRINT("\tNodeId = 0x%" PRIx64 ",", nodeId);
}
Expand All @@ -90,7 +90,7 @@ CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const
VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
#if CHIP_DETAIL_LOGGING
{
uint16_t endpointId;
chip::EndpointId endpointId;
reader.Get(endpointId);
PRETTY_PRINT("\tEndpointId = 0x%" PRIx16 ",", endpointId);
}
Expand Down Expand Up @@ -118,9 +118,9 @@ CHIP_ERROR AttributePath::Parser::CheckSchemaValidity() const
VerifyOrExit(chip::TLV::kTLVType_UnsignedInteger == reader.GetType(), err = CHIP_ERROR_WRONG_TLV_TYPE);
#if CHIP_DETAIL_LOGGING
{
uint8_t fieldTag;
chip::AttributeId fieldTag;
reader.Get(fieldTag);
PRETTY_PRINT("\tFieldTag = 0x%" PRIx8 ",", fieldTag);
PRETTY_PRINT("\tFieldTag = " ChipLogFormatMEI ",", ChipLogValueMEI(fieldTag));
}
#endif // CHIP_DETAIL_LOGGING
break;
Expand Down
6 changes: 6 additions & 0 deletions src/app/MessageDef/StatusIB.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ namespace chip {
namespace app {
struct StatusIB
{
StatusIB() = default;
StatusIB(Protocols::InteractionModel::Status imStatus) : mStatus(imStatus) {}
StatusIB(Protocols::InteractionModel::Status imStatus, ClusterStatus clusterStatus) :
mStatus(imStatus), mClusterStatus(clusterStatus)
{}

enum class Tag : uint8_t
{
kStatus = 0,
Expand Down
42 changes: 17 additions & 25 deletions src/app/WriteClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@
*
*/

#include "lib/core/CHIPError.h"
#include <app/AppBuildConfig.h>
#include <app/InteractionModelEngine.h>
#include <app/WriteClient.h>

namespace chip {
namespace app {

CHIP_ERROR WriteClient::Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate,
uint64_t aApplicationIdentifier)
CHIP_ERROR WriteClient::Init(Messaging::ExchangeManager * apExchangeMgr, Callback * apCallback)
{
VerifyOrReturnError(apExchangeMgr != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
VerifyOrReturnError(mpExchangeMgr == nullptr, CHIP_ERROR_INCORRECT_STATE);
Expand All @@ -49,9 +49,8 @@ CHIP_ERROR WriteClient::Init(Messaging::ExchangeManager * apExchangeMgr, Interac

ClearExistingExchangeContext();
mpExchangeMgr = apExchangeMgr;
mpDelegate = apDelegate;
mpCallback = apCallback;
mAttributeStatusIndex = 0;
mAppIdentifier = aApplicationIdentifier;
MoveToState(State::Initialized);

return CHIP_NO_ERROR;
Expand All @@ -70,9 +69,10 @@ void WriteClient::ShutdownInternal()

mpExchangeMgr = nullptr;
mpExchangeCtx = nullptr;
mpDelegate = nullptr;
mAttributeStatusIndex = 0;
ClearState();

mpCallback->OnDone(this);
}

void WriteClient::ClearExistingExchangeContext()
Expand Down Expand Up @@ -287,25 +287,19 @@ CHIP_ERROR WriteClient::OnMessageReceived(Messaging::ExchangeContext * apExchang

VerifyOrDie(apExchangeContext == mpExchangeCtx);

// Verify that the message is an Write Response.
// If not, close the exchange and free the payload.
if (!aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::WriteResponse))
{
ExitNow();
}
// Verify that the message is an Write Response. If not, this is an unexpected message.
// Signal the error through the error callback and shutdown the client.
VerifyOrExit(aPayloadHeader.HasMessageType(Protocols::InteractionModel::MsgType::WriteResponse),
err = CHIP_ERROR_INVALID_MESSAGE_TYPE);

err = ProcessWriteResponseMessage(std::move(aPayload));

exit:
if (mpDelegate != nullptr)
if (mpCallback != nullptr)
{
if (err != CHIP_NO_ERROR)
{
mpDelegate->WriteResponseError(this, err);
}
else
{
mpDelegate->WriteResponseProcessed(this);
mpCallback->OnError(this, err);
}
}
ShutdownInternal();
Expand All @@ -317,9 +311,9 @@ void WriteClient::OnResponseTimeout(Messaging::ExchangeContext * apExchangeConte
ChipLogProgress(DataManagement, "Time out! failed to receive write response from Exchange: " ChipLogFormatExchange,
ChipLogValueExchange(apExchangeContext));

if (mpDelegate != nullptr)
if (mpCallback != nullptr)
{
mpDelegate->WriteResponseError(this, CHIP_ERROR_TIMEOUT);
mpCallback->OnError(this, CHIP_ERROR_TIMEOUT);
}
ShutdownInternal();
}
Expand Down Expand Up @@ -366,17 +360,15 @@ CHIP_ERROR WriteClient::ProcessAttributeStatusIB(AttributeStatusIB::Parser & aAt
{
err = StatusIBParser.DecodeStatusIB(statusIB);
SuccessOrExit(err);
if (mpDelegate != nullptr)
if (mpCallback != nullptr)
{
mpDelegate->WriteResponseStatus(this, statusIB, attributePathParams, mAttributeStatusIndex);
ConcreteAttributePath path(attributePathParams.mEndpointId, attributePathParams.mClusterId,
attributePathParams.mFieldId);
mpCallback->OnResponse(this, path, statusIB);
}
}

exit:
if (err != CHIP_NO_ERROR && mpDelegate != nullptr)
{
mpDelegate->WriteResponseProtocolError(this, mAttributeStatusIndex);
}
return err;
}

Expand Down
60 changes: 54 additions & 6 deletions src/app/WriteClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include <app/AttributePathParams.h>
#include <app/ConcreteAttributePath.h>
#include <app/InteractionModelDelegate.h>
#include <app/MessageDef/AttributeDataList.h>
#include <app/MessageDef/AttributeStatusIB.h>
Expand Down Expand Up @@ -51,6 +52,55 @@ class InteractionModelEngine;
class WriteClient : public Messaging::ExchangeDelegate
{
public:
class Callback
{
public:
virtual ~Callback() = default;

/**
* OnResponse will be called when a write response has been received
* and processed for the given path.
*
* The WriteClient object MUST continue to exist after this call is completed. The application shall wait until it
* receives an OnDone call before it shuts down the object.
*
* @param[in] apWriteClient: The write client object that initiated the write transaction.
* @param[in] aPath: The attribute path field in write response.
* @param[in] attributeStatus: Attribute-specific status, containing an InteractionModel::Status code as well as
* an optional cluster-specific status code.
*/
virtual void OnResponse(const WriteClient * apWriteClient, const ConcreteAttributePath & aPath, StatusIB attributeStatus) {}

/**
* OnError will be called when an error occurs *after* a successful call to SendWriteRequest(). The following
* errors will be delivered through this call in the aError field:
*
* - CHIP_ERROR_TIMEOUT: A response was not received within the expected response timeout.
* - CHIP_ERROR_*TLV*: A malformed, non-compliant response was received from the server.
* - CHIP_ERROR*: All other cases.
*
* The WriteClient object MUST continue to exist after this call is completed. The application shall wait until it
* receives an OnDone call before it shuts down the object.
*
* @param[in] apWriteClient: The write client object that initiated the attribute write transaction.
* @param[in] aError: A system error code that conveys the overall error code.
*/
virtual void OnError(const WriteClient * apWriteClient, CHIP_ERROR aError) {}

/**
* OnDone will be called when WriteClient has finished all work and is reserved for future WriteClient ownership change.
* (#10366) Users may use this function to release their own objects related to this write interaction.
*
* This function will:
* - Always be called exactly *once* for a given WriteClient instance.
* - Be called even in error circumstances.
* - Only be called after a successful call to SendWriteRequest as been made.
*
* @param[in] apWriteClient: The write client object of the terminated write transaction.
*/
virtual void OnDone(WriteClient * apWriteClient) = 0;
};

/**
* Shutdown the WriteClient. This terminates this instance
* of the object and releases all held resources.
Expand All @@ -61,8 +111,6 @@ class WriteClient : public Messaging::ExchangeDelegate
CHIP_ERROR FinishAttribute();
TLV::TLVWriter * GetAttributeDataElementTLVWriter();

uint64_t GetAppIdentifier() const { return mAppIdentifier; }
void SetAppIdentifier(uint64_t aAppIdentifier) { mAppIdentifier = aAppIdentifier; }
NodeId GetSourceNodeId() const
{
return mpExchangeCtx != nullptr ? mpExchangeCtx->GetSecureSession().GetPeerNodeId() : kUndefinedNodeId;
Expand Down Expand Up @@ -109,8 +157,7 @@ class WriteClient : public Messaging::ExchangeDelegate
* @retval #CHIP_ERROR_INCORRECT_STATE incorrect state if it is already initialized
* @retval #CHIP_NO_ERROR On success.
*/
CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, InteractionModelDelegate * apDelegate,
uint64_t aApplicationIdentifier);
CHIP_ERROR Init(Messaging::ExchangeManager * apExchangeMgr, Callback * apDelegate);

virtual ~WriteClient() = default;

Expand Down Expand Up @@ -140,12 +187,11 @@ class WriteClient : public Messaging::ExchangeDelegate

Messaging::ExchangeManager * mpExchangeMgr = nullptr;
Messaging::ExchangeContext * mpExchangeCtx = nullptr;
InteractionModelDelegate * mpDelegate = nullptr;
Callback * mpCallback = nullptr;
State mState = State::Uninitialized;
System::PacketBufferTLVWriter mMessageWriter;
WriteRequest::Builder mWriteRequestBuilder;
uint8_t mAttributeStatusIndex = 0;
uint64_t mAppIdentifier = 0;
};

class WriteClientHandle
Expand Down Expand Up @@ -173,6 +219,8 @@ class WriteClientHandle
*/
WriteClient * operator->() const { return mpWriteClient; }

WriteClient * Get() const { return mpWriteClient; }

/**
* Finalize the message and send it to the desired node. The underlying write object will always be released, and the user
* should not use this object after calling this function.
Expand Down
Loading

0 comments on commit 9b9f6f3

Please sign in to comment.