Skip to content

Commit 1a1dbaa

Browse files
andy31415austina-csa
authored andcommitted
Post merge review updates for CommandHandler updates (project-chip#33658)
* Several updates: comments and remove inline * Restyle * Move TryAddResponseData into the cpp instead of the header * Add override, virtual was a copy and paste * Name argument * Argument renaming and comment update * Move EncoderToTLV into DataModel as it looks like a more generic place, maybe we end up re-using it * Restyle * Update copyright year * Renames based on review comments * More renames of args * Fix compile * Slight comment update * More comment update after self-review * More comment update after self-review * Some renaming * Restyle * One more rename: EncodableType * EncodeTo should be const
1 parent a3e0f22 commit 1a1dbaa

File tree

4 files changed

+111
-87
lines changed

4 files changed

+111
-87
lines changed

src/app/CommandHandler.cpp

+20
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,26 @@ Status CommandHandler::OnInvokeCommandRequest(CommandHandlerExchangeInterface &
113113
return status;
114114
}
115115

116+
CHIP_ERROR CommandHandler::TryAddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
117+
DataModel::EncodableToTLV & aEncodable)
118+
{
119+
ConcreteCommandPath responseCommandPath = { aRequestCommandPath.mEndpointId, aRequestCommandPath.mClusterId,
120+
aResponseCommandId };
121+
122+
InvokeResponseParameters prepareParams(aRequestCommandPath);
123+
prepareParams.SetStartOrEndDataStruct(false);
124+
125+
{
126+
ScopedChange<bool> internalCallToAddResponse(mInternalCallToAddResponseData, true);
127+
ReturnErrorOnFailure(PrepareInvokeResponseCommand(responseCommandPath, prepareParams));
128+
}
129+
130+
TLV::TLVWriter * writer = GetCommandDataIBTLVWriter();
131+
VerifyOrReturnError(writer != nullptr, CHIP_ERROR_INCORRECT_STATE);
132+
ReturnErrorOnFailure(aEncodable.EncodeTo(*writer, TLV::ContextTag(CommandDataIB::Tag::kFields)));
133+
return FinishCommand(/* aEndDataStruct = */ false);
134+
}
135+
116136
CHIP_ERROR CommandHandler::ValidateInvokeRequestMessageAndBuildRegistry(InvokeRequestMessage::Parser & invokeRequestMessage)
117137
{
118138
CHIP_ERROR err = CHIP_NO_ERROR;

src/app/CommandHandler.h

+28-87
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include <app/CommandHandlerExchangeInterface.h>
3434
#include <app/CommandPathRegistry.h>
3535
#include <app/ConcreteCommandPath.h>
36+
#include <app/data-model/EncodableToTLV.h>
3637
#include <app/data-model/Encode.h>
3738
#include <lib/core/CHIPCore.h>
3839
#include <lib/core/TLV.h>
@@ -56,32 +57,6 @@
5657
namespace chip {
5758
namespace app {
5859

59-
/// Defines an abstract class of something that can be encoded
60-
/// into a TLV with a given data tag
61-
class EncoderToTLV
62-
{
63-
public:
64-
virtual ~EncoderToTLV() = default;
65-
66-
virtual CHIP_ERROR Encode(TLV::TLVWriter &, TLV::Tag tag) = 0;
67-
};
68-
69-
/// An `EncoderToTLV` the uses `DataModel::Encode` to encode things.
70-
///
71-
/// Generally useful to encode things like <ClusterName>::Commands::<CommandName>::Type
72-
/// structures.
73-
template <typename T>
74-
class DataModelEncoderToTLV : public EncoderToTLV
75-
{
76-
public:
77-
DataModelEncoderToTLV(const T & value) : mValue(value) {}
78-
79-
virtual CHIP_ERROR Encode(TLV::TLVWriter & writer, TLV::Tag tag) { return DataModel::Encode(writer, tag, mValue); }
80-
81-
private:
82-
const T & mValue;
83-
};
84-
8560
class CommandHandler
8661
{
8762
public:
@@ -267,7 +242,7 @@ class CommandHandler
267242
* Adds the given command status and returns any failures in adding statuses (e.g. out
268243
* of buffer space) to the caller
269244
*/
270-
CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus,
245+
CHIP_ERROR FallibleAddStatus(const ConcreteCommandPath & aRequestCommandPath, const Protocols::InteractionModel::Status aStatus,
271246
const char * context = nullptr);
272247

273248
/**
@@ -277,9 +252,9 @@ class CommandHandler
277252
void AddStatus(const ConcreteCommandPath & aCommandPath, const Protocols::InteractionModel::Status aStatus,
278253
const char * context = nullptr);
279254

280-
CHIP_ERROR AddClusterSpecificSuccess(const ConcreteCommandPath & aCommandPath, ClusterStatus aClusterStatus);
255+
CHIP_ERROR AddClusterSpecificSuccess(const ConcreteCommandPath & aRequestCommandPath, ClusterStatus aClusterStatus);
281256

282-
CHIP_ERROR AddClusterSpecificFailure(const ConcreteCommandPath & aCommandPath, ClusterStatus aClusterStatus);
257+
CHIP_ERROR AddClusterSpecificFailure(const ConcreteCommandPath & aRequestCommandPath, ClusterStatus aClusterStatus);
283258

284259
/**
285260
* This adds a new CommandDataIB element into InvokeResponses for the associated
@@ -350,37 +325,34 @@ class CommandHandler
350325
* @param [in] aRequestCommandPath the concrete path of the command we are
351326
* responding to.
352327
* @param [in] aData the data for the response.
353-
*
354-
* NOTE: this is a convenience function for `AddResponseDataViaEncoder`
355328
*/
356329
template <typename CommandData>
357-
inline CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
330+
CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
358331
{
359-
DataModelEncoderToTLV<CommandData> encoder(aData);
360-
return AddResponseDataViaEncoder(aRequestCommandPath, CommandData::GetCommandId(), encoder);
332+
DataModel::EncodableType<CommandData> encoder(aData);
333+
return AddResponseData(aRequestCommandPath, CommandData::GetCommandId(), encoder);
361334
}
362335

363336
/**
364-
* API for adding a data response. The encoded is generally expected to encode
365-
* a ClusterName::Commands::CommandName::Type struct, but any
366-
* object should work.
337+
* API for adding a data response. The `aEncodable` is generally expected to encode
338+
* a ClusterName::Commands::CommandName::Type struct, however any object should work.
367339
*
368340
* @param [in] aRequestCommandPath the concrete path of the command we are
369341
* responding to.
370-
* @param [in] commandId the command whose content is being encoded.
371-
* @param [in] encoder - an encoder that places the command data structure for `commandId`
372-
* into a TLV Writer.
342+
* @param [in] aResponseCommandId the command whose content is being encoded.
343+
* @param [in] aEncodable - an encodable that places the command data structure
344+
* for `aResponseCommandId` into a TLV Writer.
373345
*
374346
* Most applications are likely to use `AddResponseData` as a more convenient
375347
* one-call that auto-sets command ID and creates the underlying encoders.
376348
*/
377-
CHIP_ERROR AddResponseDataViaEncoder(const ConcreteCommandPath & aRequestCommandPath, CommandId commandId,
378-
EncoderToTLV & encoder)
349+
CHIP_ERROR AddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
350+
DataModel::EncodableToTLV & aEncodable)
379351
{
380352
// Return early when response should not be sent out.
381353
VerifyOrReturnValue(ResponsesAccepted(), CHIP_NO_ERROR);
382354
return TryAddingResponse(
383-
[&]() -> CHIP_ERROR { return TryAddResponseDataViaEncoder(aRequestCommandPath, commandId, encoder); });
355+
[&]() -> CHIP_ERROR { return TryAddResponseData(aRequestCommandPath, aResponseCommandId, aEncodable); });
384356
}
385357

386358
/**
@@ -398,21 +370,22 @@ class CommandHandler
398370
* @param [in] aData the data for the response.
399371
*/
400372
template <typename CommandData>
401-
inline void AddResponse(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
373+
void AddResponse(const ConcreteCommandPath & aRequestCommandPath, const CommandData & aData)
402374
{
403-
DataModelEncoderToTLV<CommandData> encoder(aData);
404-
return AddResponseViaEncoder(aRequestCommandPath, CommandData::GetCommandId(), encoder);
375+
DataModel::EncodableType<CommandData> encodable(aData);
376+
return AddResponse(aRequestCommandPath, CommandData::GetCommandId(), encodable);
405377
}
406378

407379
/**
408-
* API for adding a response with a given encoder of TLV data.
380+
* API for adding a response with a given encodable of TLV data.
409381
*
410-
* The encoder would generally encode a ClusterName::Commands::CommandName::Type with
382+
* The encodable would generally encode a ClusterName::Commands::CommandName::Type with
411383
* the corresponding `GetCommandId` call.
412384
*/
413-
void AddResponseViaEncoder(const ConcreteCommandPath & aRequestCommandPath, CommandId commandId, EncoderToTLV & encoder)
385+
void AddResponse(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
386+
DataModel::EncodableToTLV & aEncodable)
414387
{
415-
if (AddResponseDataViaEncoder(aRequestCommandPath, commandId, encoder) != CHIP_NO_ERROR)
388+
if (AddResponseData(aRequestCommandPath, aResponseCommandId, aEncodable) != CHIP_NO_ERROR)
416389
{
417390
AddStatus(aRequestCommandPath, Protocols::InteractionModel::Status::Failure);
418391
}
@@ -666,49 +639,17 @@ class CommandHandler
666639

667640
CHIP_ERROR AddStatusInternal(const ConcreteCommandPath & aCommandPath, const StatusIB & aStatus);
668641

669-
/**
670-
* Non-templated function called before DataModel::Encode when attempting to add a response,
671-
* which does all the work needed before encoding the actual type-dependent data into the buffer.
672-
*
673-
* **Important:** If this function fails, the TLV buffer may be left in an inconsistent state.
674-
* Callers should create snapshots as necessary before invoking this function and implement
675-
* rollback mechanisms if needed.
676-
*
677-
* **Usage:** This function is intended to be called exclusively by TryAddResponseData. It was
678-
* factored out to optimize code size.
679-
*
680-
* @param aRequestCommandPath The concrete path of the command being responded to.
681-
* @param aResponseCommandPath The concrete path of the command response.
682-
*/
683-
CHIP_ERROR TryAddResponseDataPreEncode(const ConcreteCommandPath & aRequestCommandPath,
684-
const ConcreteCommandPath & aResponseCommandPath)
685-
{
686-
InvokeResponseParameters prepareParams(aRequestCommandPath);
687-
prepareParams.SetStartOrEndDataStruct(false);
688-
689-
ScopedChange<bool> internalCallToAddResponse(mInternalCallToAddResponseData, true);
690-
return PrepareInvokeResponseCommand(aResponseCommandPath, prepareParams);
691-
}
692-
693642
/**
694643
* If this function fails, it may leave our TLV buffer in an inconsistent state.
695644
* Callers should snapshot as needed before calling this function, and roll back
696645
* as needed afterward.
697646
*
698-
* @param [in] aRequestCommandPath the concrete path of the command we are
699-
* responding to.
700-
* @param [in] aData the data for the response.
647+
* @param [in] aRequestCommandPath the concrete path of the command we are responding to
648+
* @param [in] aResponseCommandId the id of the command to encode
649+
* @param [in] aEncodable the data to encode for the given aResponseCommandId
701650
*/
702-
CHIP_ERROR TryAddResponseDataViaEncoder(const ConcreteCommandPath & aRequestCommandPath, CommandId commandId,
703-
EncoderToTLV & encoder)
704-
{
705-
ConcreteCommandPath responseCommandPath = { aRequestCommandPath.mEndpointId, aRequestCommandPath.mClusterId, commandId };
706-
ReturnErrorOnFailure(TryAddResponseDataPreEncode(aRequestCommandPath, responseCommandPath));
707-
TLV::TLVWriter * writer = GetCommandDataIBTLVWriter();
708-
VerifyOrReturnError(writer != nullptr, CHIP_ERROR_INCORRECT_STATE);
709-
ReturnErrorOnFailure(encoder.Encode(*writer, TLV::ContextTag(CommandDataIB::Tag::kFields)));
710-
return FinishCommand(/* aEndDataStruct = */ false);
711-
}
651+
CHIP_ERROR TryAddResponseData(const ConcreteCommandPath & aRequestCommandPath, CommandId aResponseCommandId,
652+
DataModel::EncodableToTLV & aEncodable);
712653

713654
void SetExchangeInterface(CommandHandlerExchangeInterface * commandResponder);
714655

src/app/data-model/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ source_set("data-model") {
1818
"BasicTypes.h",
1919
"DecodableList.h",
2020
"Decode.h",
21+
"EncodableToTLV.h",
2122
"Encode.h",
2223
"FabricScoped.h",
2324
"FabricScopedPreEncodedValue.cpp",

src/app/data-model/EncodableToTLV.h

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#include <app/data-model/Encode.h>
21+
#include <lib/core/CHIPError.h>
22+
#include <lib/core/TLV.h>
23+
24+
namespace chip {
25+
namespace app {
26+
namespace DataModel {
27+
28+
/// Defines an abstract class of something that can be encoded
29+
/// into a TLV with a given data tag
30+
class EncodableToTLV
31+
{
32+
public:
33+
virtual ~EncodableToTLV() = default;
34+
35+
virtual CHIP_ERROR EncodeTo(TLV::TLVWriter & writer, TLV::Tag tag) const = 0;
36+
};
37+
38+
/// An `EncodableToTLV` that uses `DataModel::Encode` to encode things in one call.
39+
///
40+
/// Applicable to any type for which `chip::app::DataModel::Encode` works. In
41+
/// particular, types like <ClusterName>::Commands::<CommandName>::Type
42+
/// can be used as a type here.
43+
template <typename T>
44+
class EncodableType : public EncodableToTLV
45+
{
46+
public:
47+
/// Encodes the given value via `DataModel::Encode` when the underlying
48+
/// encode is called.
49+
///
50+
/// LIFETIME NOTE: uses a reference to value, so value must live longer than
51+
/// this object.
52+
EncodableType(const T & value) : mValue(value) {}
53+
54+
CHIP_ERROR EncodeTo(TLV::TLVWriter & writer, TLV::Tag tag) const override { return DataModel::Encode(writer, tag, mValue); }
55+
56+
private:
57+
const T & mValue;
58+
};
59+
60+
} // namespace DataModel
61+
} // namespace app
62+
} // namespace chip

0 commit comments

Comments
 (0)