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

[Scenes] Scene Handler Encode and Decode attribute value list #27089

Merged
Merged
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
79 changes: 79 additions & 0 deletions src/app/clusters/scenes-server/SceneTableImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,85 @@
namespace chip {
namespace scenes {

CHIP_ERROR
DefaultSceneHandlerImpl::EncodeAttributeValueList(
const app::DataModel::List<app::Clusters::Scenes::Structs::AttributeValuePair::Type> & aVlist,
MutableByteSpan & serializedBytes)
{
TLV::TLVWriter writer;
writer.Init(serializedBytes);
ReturnErrorOnFailure(app::DataModel::Encode(writer, TLV::AnonymousTag(), aVlist));
serializedBytes.reduce_size(writer.GetLengthWritten());

return CHIP_NO_ERROR;
}

CHIP_ERROR DefaultSceneHandlerImpl::DecodeAttributeValueList(
const ByteSpan & serializedBytes,
app::DataModel::DecodableList<app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType> & aVlist)
{
TLV::TLVReader reader;

reader.Init(serializedBytes);
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Array, TLV::AnonymousTag()));
ReturnErrorOnFailure(aVlist.Decode(reader));

return CHIP_NO_ERROR;
}

CHIP_ERROR
DefaultSceneHandlerImpl::SerializeAdd(EndpointId endpoint,
const app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet,
MutableByteSpan & serializedBytes)
{
app::Clusters::Scenes::Structs::AttributeValuePair::Type aVPairs[kMaxAvPair];

size_t pairTotal = 0;
// Verify size of list
ReturnErrorOnFailure(extensionFieldSet.attributeValueList.ComputeSize(&pairTotal));
VerifyOrReturnError(pairTotal <= ArraySize(aVPairs), CHIP_ERROR_BUFFER_TOO_SMALL);

uint8_t pairCount = 0;
auto pair_iterator = extensionFieldSet.attributeValueList.begin();
while (pair_iterator.Next())
{
aVPairs[pairCount] = pair_iterator.GetValue();
pairCount++;
}
ReturnErrorOnFailure(pair_iterator.GetStatus());
app::DataModel::List<app::Clusters::Scenes::Structs::AttributeValuePair::Type> attributeValueList(aVPairs, pairCount);

return EncodeAttributeValueList(attributeValueList, serializedBytes);
}

CHIP_ERROR DefaultSceneHandlerImpl::Deserialize(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes,
app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet)
{
app::DataModel::DecodableList<app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType> attributeValueList;

ReturnErrorOnFailure(DecodeAttributeValueList(serializedBytes, attributeValueList));

// Verify size of list
size_t pairTotal = 0;
ReturnErrorOnFailure(attributeValueList.ComputeSize(&pairTotal));
VerifyOrReturnError(pairTotal <= ArraySize(mAVPairs), CHIP_ERROR_BUFFER_TOO_SMALL);

uint8_t pairCount = 0;
auto pair_iterator = attributeValueList.begin();
while (pair_iterator.Next())
{
mAVPairs[pairCount] = pair_iterator.GetValue();
pairCount++;
};
ReturnErrorOnFailure(pair_iterator.GetStatus());

extensionFieldSet.clusterID = cluster;
extensionFieldSet.attributeValueList = mAVPairs;
extensionFieldSet.attributeValueList.reduce_size(pairCount);

return CHIP_NO_ERROR;
}

/// @brief Tags Used to serialize Scenes so they can be stored in flash memory.
/// kSceneCount: Number of scenes in a Fabric
/// kStorageIDArray: Array of StorageID struct
Expand Down
101 changes: 24 additions & 77 deletions src/app/clusters/scenes-server/SceneTableImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,94 +46,41 @@ class DefaultSceneHandlerImpl : public scenes::SceneHandler
DefaultSceneHandlerImpl() = default;
~DefaultSceneHandlerImpl() override{};

/// @brief Encodes an attribute value list into a TLV structure and resizes the buffer to the size of the encoded data
/// @param aVlist[in] Attribute value list to encode
/// @param serializedBytes[out] Buffer to fill from the Attribute value list in a TLV format
/// @return CHIP_ERROR
virtual CHIP_ERROR
EncodeAttributeValueList(const app::DataModel::List<app::Clusters::Scenes::Structs::AttributeValuePair::Type> & aVlist,
MutableByteSpan & serializedBytes);

/// @brief Decodes an attribute value list from a TLV structure and ensure it fits the member pair buffer
/// @param serializedBytes [in] Buffer to read from
/// @param aVlist [out] Attribute value list to fill from the TLV structure. Only valid while the buffer backing
/// serializedBytes exists and its contents are not modified.
/// @return CHIP_ERROR
virtual CHIP_ERROR DecodeAttributeValueList(
const ByteSpan & serializedBytes,
app::DataModel::DecodableList<app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType> & aVlist);

/// @brief From command AddScene, allows handler to filter through clusters in command to serialize only the supported ones.
/// @param endpoint[in] Endpoint ID
/// @param extensionFieldSet[in] ExtensionFieldSets provided by the AddScene Command, pre initialized
/// @param serialisedBytes[out] Buffer to fill from the ExtensionFieldSet in command
/// @return CHIP_NO_ERROR if successful, CHIP_ERROR_INVALID_ARGUMENT if the cluster is not supported, CHIP_ERROR value otherwise
/// @param serializedBytes[out] Buffer to fill from the ExtensionFieldSet in command
/// @return CHIP_NO_ERROR if successful, CHIP_ERROR_INVALID_ARGUMENT if the cluster is not supported, CHIP_ERROR value
/// otherwise
virtual CHIP_ERROR SerializeAdd(EndpointId endpoint,
const app::Clusters::Scenes::Structs::ExtensionFieldSet::DecodableType & extensionFieldSet,
MutableByteSpan & serializedBytes) override
{
app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType aVPair;
TLV::TLVWriter writer;
TLV::TLVType outer;
size_t pairTotal = 0;
uint8_t pairCount = 0;

// Verify size of list
ReturnErrorOnFailure(extensionFieldSet.attributeValueList.ComputeSize(&pairTotal));
VerifyOrReturnError(pairTotal <= ArraySize(mAVPairs), CHIP_ERROR_BUFFER_TOO_SMALL);

auto pair_iterator = extensionFieldSet.attributeValueList.begin();
while (pair_iterator.Next())
{
aVPair = pair_iterator.GetValue();
mAVPairs[pairCount].attributeID = aVPair.attributeID;
mAVPairs[pairCount].attributeValue = aVPair.attributeValue;
pairCount++;
}
ReturnErrorOnFailure(pair_iterator.GetStatus());

app::DataModel::List<app::Clusters::Scenes::Structs::AttributeValuePair::Type> attributeValueList;
attributeValueList = mAVPairs;
attributeValueList.reduce_size(pairCount);

writer.Init(serializedBytes);
ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer));
ReturnErrorOnFailure(app::DataModel::Encode(
writer, TLV::ContextTag(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList),
attributeValueList));
ReturnErrorOnFailure(writer.EndContainer(outer));

return CHIP_NO_ERROR;
}
MutableByteSpan & serializedBytes) override;

/// @brief Simulates taking data from nvm and loading it in a command object if the cluster is supported by the endpoint
/// @param endpoint target endpoint
/// @param cluster target cluster
/// @param serialisedBytes data to deserialize into EFS
/// @param serializedBytes data to deserialize into EFS
/// @return CHIP_NO_ERROR if Extension Field Set was successfully populated, CHIP_ERROR_INVALID_ARGUMENT if the cluster is not
/// supported, specific CHIP_ERROR otherwise
virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, const ByteSpan & serialisedBytes,
app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet) override
{
app::DataModel::DecodableList<app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType> attributeValueList;
app::Clusters::Scenes::Structs::AttributeValuePair::DecodableType decodePair;

TLV::TLVReader reader;
TLV::TLVType outer;
size_t pairTotal = 0;
uint8_t pairCount = 0;

extensionFieldSet.clusterID = cluster;
reader.Init(serialisedBytes);
ReturnErrorOnFailure(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()));
ReturnErrorOnFailure(reader.EnterContainer(outer));
ReturnErrorOnFailure(reader.Next(
TLV::kTLVType_Array, TLV::ContextTag(app::Clusters::Scenes::Structs::ExtensionFieldSet::Fields::kAttributeValueList)));
attributeValueList.Decode(reader);

// Verify size of list
ReturnErrorOnFailure(attributeValueList.ComputeSize(&pairTotal));
VerifyOrReturnError(pairTotal <= ArraySize(mAVPairs), CHIP_ERROR_BUFFER_TOO_SMALL);

auto pair_iterator = attributeValueList.begin();
while (pair_iterator.Next())
{
decodePair = pair_iterator.GetValue();
mAVPairs[pairCount].attributeID = decodePair.attributeID;
mAVPairs[pairCount].attributeValue = decodePair.attributeValue;
pairCount++;
};
ReturnErrorOnFailure(pair_iterator.GetStatus());

ReturnErrorOnFailure(reader.ExitContainer(outer));
extensionFieldSet.attributeValueList = mAVPairs;
extensionFieldSet.attributeValueList.reduce_size(pairCount);

return CHIP_NO_ERROR;
}
virtual CHIP_ERROR Deserialize(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes,
app::Clusters::Scenes::Structs::ExtensionFieldSet::Type & extensionFieldSet) override;

private:
app::Clusters::Scenes::Structs::AttributeValuePair::Type mAVPairs[kMaxAvPair];
Expand Down
Loading