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

Closure control cluster server code implementation #37561

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
acc7a7d
Closure control sluster Server Code
satyanaag-silabs Feb 13, 2025
651fb3b
Merge branch 'project-chip:master' into feature/closure_control_serve…
sabollim-silabs Feb 14, 2025
83d5671
Merge branch 'project-chip:master' into feature/closure_control_serve…
sabollim-silabs Feb 17, 2025
88785ee
Restyled by whitespace
restyled-commits Feb 17, 2025
236a68b
Restyled by clang-format
restyled-commits Feb 17, 2025
280df4f
Changing MainState and Countdowntime Implementation
satyanaag-silabs Feb 17, 2025
2e82a85
Handling OverallState and OverallTarget from Instance
satyanaag-silabs Feb 18, 2025
1e81e1d
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 18, 2025
c230a1d
Addressing PR comments
satyanaag-silabs Feb 18, 2025
bccbebe
Restyled by whitespace
restyled-commits Feb 18, 2025
5c130df
Restyled by clang-format
restyled-commits Feb 18, 2025
3ee28a1
Updating missing zap changes
satyanaag-silabs Feb 19, 2025
266ea21
Adding wrapper for struct handling
satyanaag-silabs Feb 19, 2025
b03460e
Restyled by whitespace
restyled-commits Feb 19, 2025
1ad934c
Restyled by clang-format
restyled-commits Feb 19, 2025
e07b850
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 19, 2025
757a2c7
Addressing PR comments
satyanaag-silabs Feb 20, 2025
c437637
Merge branch 'feature/closure_control_server_code' of https://github.…
satyanaag-silabs Feb 20, 2025
18f6829
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 20, 2025
45d3294
Addressing PR comments
satyanaag-silabs Feb 20, 2025
ada6747
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 20, 2025
ed605a7
Restyled by clang-format
restyled-commits Feb 20, 2025
d7b51e7
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 21, 2025
0486d1f
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 24, 2025
968ba9f
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 24, 2025
75559d9
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 24, 2025
2963bab
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 25, 2025
ac42399
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 25, 2025
bd5a0a5
addressing PR comments
satyanaag-silabs Feb 25, 2025
afae064
changing IsEqual to operator==
satyanaag-silabs Feb 26, 2025
270be8e
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 26, 2025
0e4a00d
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 27, 2025
cece03e
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 27, 2025
ba8d87c
Addressing PR comments
satyanaag-silabs Feb 27, 2025
408c94d
Addresssing PR comments
satyanaag-silabs Feb 27, 2025
b4f685e
Removing Fallback feature attribute and commands as FB feature is rem…
satyanaag-silabs Feb 27, 2025
5f8858c
Addressing PR comments
satyanaag-silabs Feb 27, 2025
c282599
Updating countdonwtime quiet reporting policy
satyanaag-silabs Feb 27, 2025
f5f9fed
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 27, 2025
acb1c5b
Restyled by whitespace
restyled-commits Feb 27, 2025
a1766e6
Restyled by clang-format
restyled-commits Feb 27, 2025
4ab2e09
Merge branch 'master' into feature/closure_control_server_code
sabollim-silabs Feb 27, 2025
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
5 changes: 5 additions & 0 deletions src/app/chip_data_model.gni
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,11 @@ template("chip_data_model") {
"${_app_root}/clusters/${cluster}/ArlEncoder.cpp",
"${_app_root}/clusters/${cluster}/ArlEncoder.h",
]
} else if (cluster == "closure-control-server") {
sources += [
"${_app_root}/clusters/${cluster}/${cluster}.cpp",
"${_app_root}/clusters/${cluster}/${cluster}.h",
]
} else {
sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ]
}
Expand Down
284 changes: 284 additions & 0 deletions src/app/clusters/closure-control-server/closure-control-server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
/*
* Copyright (c) 2025 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 "closure-control-server.h"

#include <app/AttributeAccessInterface.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/CommandHandlerInterfaceRegistry.h>
#include <app/ConcreteAttributePath.h>
#include <app/InteractionModelEngine.h>
#include <app/util/attribute-storage.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::DataModel;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::ClosureControl;
using namespace chip::app::Clusters::ClosureControl::Attributes;
using namespace chip::app::Clusters::ClosureControl::Commands;
using chip::Protocols::InteractionModel::Status;

namespace chip {
namespace app {
namespace Clusters {
namespace ClosureControl {

CHIP_ERROR Instance::Init()
{
ReturnErrorOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(this));
VerifyOrReturnError(AttributeAccessInterfaceRegistry::Instance().Register(this), CHIP_ERROR_INCORRECT_STATE);

return CHIP_NO_ERROR;
}

void Instance::Shutdown()
{
CommandHandlerInterfaceRegistry::Instance().UnregisterCommandHandler(this);
AttributeAccessInterfaceRegistry::Instance().Unregister(this);
}

bool Instance::HasFeature(Feature aFeature) const
{
return mFeature.Has(aFeature);
}

bool Instance::SupportsOptAttr(OptionalAttributes aOptionalAttrs) const
{
return mOptionalAttrs.Has(aOptionalAttrs);
}

// AttributeAccessInterface
CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
VerifyOrDie(aPath.mClusterId == ClosureControl::Id);

switch (aPath.mAttributeId)
{
case CountdownTime::Id:
if (SupportsOptAttr(OptionalAttributes::kCountdownTime))
{
return aEncoder.Encode(mDelegate.GetCountdownTime());
}
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
case MainState::Id:
return aEncoder.Encode(mDelegate.GetMainState());
case CurrentErrorList::Id:
return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR { return this->EncodeCurrentErrorList(encoder); });
case OverallState::Id:
return aEncoder.Encode(mDelegate.GetOverallState());
case OverallTarget::Id:
return aEncoder.Encode(mDelegate.GetOverallTarget());
case RestingProcedure::Id:
if (HasFeature(Feature::kFallback))
{
return aEncoder.Encode(mDelegate.GetRestingProcedure());
}
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
case TriggerCondition::Id:
if (HasFeature(Feature::kFallback))
{
return aEncoder.Encode(mDelegate.GetTriggerCondition());
}
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
case TriggerPosition::Id:
if (HasFeature(Feature::kFallback))
{
return aEncoder.Encode(mDelegate.GetTriggerPosition());
}
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
case WaitingDelay::Id:
if (HasFeature(Feature::kFallback))
{
return aEncoder.Encode(mDelegate.GetWaitingDelay());
}
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
case KickoffTimer::Id:
if (HasFeature(Feature::kFallback))
{
return aEncoder.Encode(mDelegate.GetKickoffTimer());
}
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
/* FeatureMap - is held locally */
case FeatureMap::Id:
return aEncoder.Encode(mFeature);
// TODO CHECK CLUSTER REVISION
}
/* Allow all other unhandled attributes to fall through to Ember */
return CHIP_NO_ERROR;
}

CHIP_ERROR Instance::EncodeCurrentErrorList(const AttributeValueEncoder::ListEncodeHelper & encoder)
{
CHIP_ERROR err = CHIP_NO_ERROR;

ReturnErrorOnFailure(mDelegate.StartCurrentErrorListRead());
for (size_t i = 0; true; i++)
{
ClosureErrorEnum error;

err = mDelegate.GetCurrentErrorListAtIndex(i, error);
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
{
// Convert end of list to CHIP_NO_ERROR
err = CHIP_NO_ERROR;
goto exit;
}

// Check if another error occurred before trying to encode
SuccessOrExit(err);

err = encoder.Encode(error);
SuccessOrExit(err);
}

exit:
// Tell the delegate the read is complete
err = mDelegate.EndCurrentErrorListRead();
return err;
}

CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeValueDecoder & aDecoder)
{
switch (aPath.mAttributeId)
{
default:
// Unknown attribute; return error. None of the other attributes for
// this cluster are writable, so should not be ending up in this code to
// start with.
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}
}

// CommandHandlerInterface
void Instance::InvokeCommand(HandlerContext & handlerContext)
{
using namespace Commands;

switch (handlerContext.mRequestPath.mCommandId)
{
case Stop::Id:
if (!HasFeature(Feature::kInstantaneous))
{
HandleCommand<Stop::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleStop(ctx, commandData); });
}
else
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand);
}
return;
case MoveTo::Id:
HandleCommand<MoveTo::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleMoveTo(ctx, commandData); });
return;
case Calibrate::Id:
if (HasFeature(Feature::kCalibration))
{
HandleCommand<Calibrate::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCalibrate(ctx, commandData); });
}
else
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand);
}
return;
case ConfigureFallback::Id:
if (HasFeature(Feature::kFallback))
{
HandleCommand<ConfigureFallback::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleConfigureFallback(ctx, commandData); });
}
else
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand);
}
return;
case CancelFallback::Id:
if (HasFeature(Feature::kFallback))
{
HandleCommand<CancelFallback::DecodableType>(
handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCancelFallback(ctx, commandData); });
}
else
{
handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand);
}
return;
}
}

void Instance::HandleStop(HandlerContext & ctx, const Commands::Stop::DecodableType & commandData)
{
// No parameters for this command
// Call the delegate
Status status = mDelegate.Stop();

ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
}

void Instance::HandleMoveTo(HandlerContext & ctx, const Commands::MoveTo::DecodableType & commandData)
{
const Optional<TagPositionEnum> tag = commandData.tag;
const Optional<TagLatchEnum> latch = commandData.latch;
const Optional<Globals::ThreeLevelAutoEnum> speed = commandData.speed;

// Call the delegate
Status status = mDelegate.MoveTo(tag, latch, speed);

ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
}

void Instance::HandleCalibrate(HandlerContext & ctx, const Commands::Calibrate::DecodableType & commandData)
{
// No parameters for this command
// Call the delegate
Status status = mDelegate.Calibrate();

ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
}

void Instance::HandleConfigureFallback(HandlerContext & ctx, const Commands::ConfigureFallback::DecodableType & commandData)
{
const Optional<RestingProcedureEnum> restingProcedure = commandData.restingProcedure;
const Optional<TriggerConditionEnum> triggerCondition = commandData.triggerCondition;
const Optional<TriggerPositionEnum> triggerPosition = commandData.triggerPosition;
const Optional<uint32_t> waitingDelay = commandData.waitingDelay;

// Call the delegate
Status status = mDelegate.ConfigureFallback(restingProcedure, triggerCondition, triggerPosition, waitingDelay);

ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
}

void Instance::HandleCancelFallback(HandlerContext & ctx, const Commands::CancelFallback::DecodableType & commandData)
{
// No parameters for this command
// Call the delegate
Status status = mDelegate.CancelFallback();

ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status);
}

} // namespace ClosureControl
} // namespace Clusters
} // namespace app
} // namespace chip

// -----------------------------------------------------------------------------
// Plugin initialization

void MatterClosureControlPluginServerInitCallback() {}
Loading
Loading