Skip to content

Commit

Permalink
Added helpers to reduce code copied over when created scene new scene…
Browse files Browse the repository at this point in the history
… handlers
  • Loading branch information
lpbeliveau-silabs committed Nov 1, 2023
1 parent 6ec33d4 commit b3915ca
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 233 deletions.
3 changes: 3 additions & 0 deletions src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ template("chip_data_model") {
"${_app_root}/clusters/scenes-server/ExtensionFieldSetsImpl.h",
"${_app_root}/clusters/scenes-server/SceneTable.h",
"${_app_root}/clusters/scenes-server/SceneTableImpl.h",
"${_app_root}/clusters/scenes-server/SceneHandlerImpl.h",
"${_app_root}/clusters/scenes-server/scenes-server.h",
"${_app_root}/util/binding-table.cpp",
"${_app_root}/util/binding-table.h",
Expand Down Expand Up @@ -279,6 +280,8 @@ template("chip_data_model") {
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
"${_app_root}/clusters/scenes-server/ExtensionFieldSetsImpl.cpp",
"${_app_root}/clusters/scenes-server/SceneTableImpl.cpp",
"${_app_root}/clusters/scenes-server/SceneHandlerImpl.cpp",

]
} else if (cluster == "operational-state-server") {
sources += [
Expand Down
97 changes: 5 additions & 92 deletions src/app/clusters/on-off-server/on-off-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,99 +106,12 @@ static constexpr size_t kOnOffMaxEnpointCount =
#ifdef EMBER_AF_PLUGIN_SCENES
static EmberEventControl sceneHandlerEventControls[kOnOffMaxEnpointCount];
static void sceneOnOffCallback(EndpointId endpoint);
using OnOffEndPointPair = chip::scenes::DefaultSceneHandlerImpl::EndpointStatePair<bool>;

class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl
{
public:
/// @brief Struct to keep track of the desired state of the OnOff attribute between ApplyScene and
/// transition time expiration
struct EndpointStatePair
{
EndpointStatePair(EndpointId endpoint = kInvalidEndpointId, bool status = false) : mEndpoint(endpoint), mState(status) {}
EndpointId mEndpoint;
bool mState;
};

/// @brief Struct holding an array of EndpointStatePair. Handles insertion, get and removal by EndpointID.
/// TODO: Implement generic object to handle this boilerplate array manipulation
struct StatePairBuffer
{
bool IsEmpty() const { return (mPairCount == 0); }

CHIP_ERROR FindPair(const EndpointId endpoint, uint16_t & found_index) const
{
VerifyOrReturnError(!IsEmpty(), CHIP_ERROR_NOT_FOUND);
for (found_index = 0; found_index < mPairCount; found_index++)
{
if (endpoint == mStatePairBuffer[found_index].mEndpoint)
{
return CHIP_NO_ERROR;
}
}

return CHIP_ERROR_NOT_FOUND;
}

CHIP_ERROR InsertPair(const EndpointStatePair & status)
{
uint16_t idx;
CHIP_ERROR err = FindPair(status.mEndpoint, idx);

if (CHIP_NO_ERROR == err)
{
mStatePairBuffer[idx] = status;
}
else if (mPairCount < MAX_ENDPOINT_COUNT)
{
// if not found, insert at the end
mStatePairBuffer[mPairCount] = status;
mPairCount++;
}
else
{
return CHIP_ERROR_NO_MEMORY;
}

return CHIP_NO_ERROR;
}

CHIP_ERROR GetPair(const EndpointId endpoint, EndpointStatePair & status) const
{
uint16_t idx;
ReturnErrorOnFailure(FindPair(endpoint, idx));

status = mStatePairBuffer[idx];
return CHIP_NO_ERROR;
}

/// @brief Removes Pair and decrements Pair count if the endpoint existed in the array
/// @param endpoint : endpoint id of the pair
CHIP_ERROR RemovePair(const EndpointId endpoint)
{
uint16_t position;
VerifyOrReturnValue(CHIP_NO_ERROR == FindPair(endpoint, position), CHIP_NO_ERROR);

uint16_t nextPos = static_cast<uint16_t>(position + 1);
uint16_t moveNum = static_cast<uint16_t>(mPairCount - nextPos);

// Compress array after removal, if the removed position is not the last
if (moveNum)
{
memmove(&mStatePairBuffer[position], &mStatePairBuffer[nextPos], sizeof(EndpointStatePair) * moveNum);
}

mPairCount--;
// Clear last occupied position
mStatePairBuffer[mPairCount].mEndpoint = kInvalidEndpointId;

return CHIP_NO_ERROR;
}

uint16_t mPairCount;
EndpointStatePair mStatePairBuffer[kOnOffMaxEnpointCount];
};

StatePairBuffer mSceneEndpointStatePairs;
DefaultSceneHandlerImpl::StatePairBuffer<bool, kOnOffMaxEnpointCount> mSceneEndpointStatePairs;
// As per spec, 1 attribute is scenable in the on off cluster
static constexpr uint8_t scenableAttributeCount = 1;

Expand Down Expand Up @@ -279,7 +192,7 @@ class DefaultOnOffSceneHandler : public scenes::DefaultSceneHandlerImpl
auto & decodePair = pair_iterator.GetValue();
VerifyOrReturnError(decodePair.attributeID == Attributes::OnOff::Id, CHIP_ERROR_INVALID_ARGUMENT);
ReturnErrorOnFailure(
mSceneEndpointStatePairs.InsertPair(EndpointStatePair(endpoint, static_cast<bool>(decodePair.attributeValue))));
mSceneEndpointStatePairs.InsertPair(OnOffEndPointPair(endpoint, static_cast<bool>(decodePair.attributeValue))));
}
// Verify that the EFS was completely read
CHIP_ERROR err = pair_iterator.GetStatus();
Expand Down Expand Up @@ -328,9 +241,9 @@ static DefaultOnOffSceneHandler sOnOffSceneHandler;

static void sceneOnOffCallback(EndpointId endpoint)
{
DefaultOnOffSceneHandler::EndpointStatePair savedState;
OnOffEndPointPair savedState;
ReturnOnFailure(sOnOffSceneHandler.mSceneEndpointStatePairs.GetPair(endpoint, savedState));
chip::CommandId command = (savedState.mState) ? Commands::On::Id : Commands::Off::Id;
chip::CommandId command = (savedState.mValue) ? Commands::On::Id : Commands::Off::Id;
OnOffServer::Instance().setOnOffValue(endpoint, command, false);
ReturnOnFailure(sOnOffSceneHandler.mSceneEndpointStatePairs.RemovePair(endpoint));
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/clusters/scenes-server/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ static_library("scenes") {
"SceneTable.h",
"SceneTableImpl.cpp",
"SceneTableImpl.h",
"SceneHandlerImpl.cpp",
"SceneHandlerImpl.h",
]

deps = [ "${chip_root}/src/app" ]
Expand Down
99 changes: 99 additions & 0 deletions src/app/clusters/scenes-server/SceneHandlerImpl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
*
* Copyright (c) 2023 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 <app/clusters/scenes-server/SceneHandlerImpl.h>

namespace chip {
namespace scenes {

CHIP_ERROR
DefaultSceneHandlerImpl::EncodeAttributeValueList(const List<AttributeValuePairType> & 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,
DecodableList<AttributeValuePairDecodableType> & 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 ExtensionFieldSetDecodableType & extensionFieldSet,
MutableByteSpan & serializedBytes)
{
AttributeValuePairType 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());
List<AttributeValuePairType> attributeValueList(aVPairs, pairCount);

return EncodeAttributeValueList(attributeValueList, serializedBytes);
}

CHIP_ERROR DefaultSceneHandlerImpl::Deserialize(EndpointId endpoint, ClusterId cluster, const ByteSpan & serializedBytes,
ExtensionFieldSetType & extensionFieldSet)
{
DecodableList<AttributeValuePairDecodableType> 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;
}

} // namespace scenes
} // namespace chip
Loading

0 comments on commit b3915ca

Please sign in to comment.