Skip to content

Commit 4940afb

Browse files
[Silabs] Closure button implementation for silabs paltform (#41455)
* Closure button implementation * Restyled by whitespace * Restyled by clang-format * Addressing PR comments * addressing PR comments * PR comments * Restyled by whitespace * Restyled by clang-format * Updated logic to schedulelambda from apptask and remove unnessary chiplocks * cleanup unnessary changes * Restyled by whitespace * Restyled by clang-format --------- Co-authored-by: Restyled.io <[email protected]>
1 parent b478ae0 commit 4940afb

File tree

4 files changed

+139
-23
lines changed

4 files changed

+139
-23
lines changed

examples/closure-app/silabs/include/AppTask.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ class AppTask : public BaseApplication
7878
*/
7979
static void ButtonEventHandler(uint8_t button, uint8_t btnAction);
8080

81+
/**
82+
* @brief Closure button action event handler
83+
* Handles button press events for closure control operations
84+
*
85+
* @param aEvent pointer to the button event being processed
86+
*/
87+
static void ClosureButtonActionEventHandler(AppEvent * aEvent);
88+
8189
private:
8290
static AppTask sAppTask;
8391

examples/closure-app/silabs/include/ClosureManager.h

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,23 @@ class ClosureManager
156156
*/
157157
const Action_t & GetCurrentAction() const { return mCurrentAction; }
158158

159+
/**
160+
* @brief Checks if a MoveTo action is currently in progress.
161+
*
162+
* @return true if a MoveTo action is in progress, false otherwise.
163+
*/
164+
bool IsClosureControlMotionInProgress() const;
165+
166+
/**
167+
* @brief Gets the ClosureControlEndpoint logic for direct access.
168+
*
169+
* This allows direct access to the cluster logic methods (e.g., HandleMoveTo)
170+
* when called from chip task context (e.g., via ScheduleWork).
171+
*
172+
* @return Reference to the ClosureControlEndpoint logic.
173+
*/
174+
chip::app::Clusters::ClosureControl::ClusterLogic & GetClosureControlLogic() { return mClosureEndpoint1.GetLogic(); }
175+
159176
/**
160177
* @brief Sets the initial state for the ClosureControlEndpoint.
161178
*
@@ -188,10 +205,10 @@ class ClosureManager
188205
// make them thread-safe using mutex or other synchronization mechanisms. Presently, we use
189206
// DeviceLayer::PlatformMgr().LockChipStack() and DeviceLayer::PlatformMgr().UnlockChipStack()
190207
// to ensure that these variables are set in thread safe manner in chip task context.
191-
bool isCalibrationInProgress = false;
192-
bool isMoveToInProgress = false;
193-
bool isSetTargetInProgress = false;
194-
bool isStepActionInProgress = false;
208+
bool mIsCalibrationInProgress = false;
209+
bool mIsMoveToInProgress = false;
210+
bool mIsSetTargetInProgress = false;
211+
bool mIsStepActionInProgress = false;
195212

196213
Action_t mCurrentAction = Action_t::INVALID_ACTION;
197214
chip::EndpointId mCurrentActionEndpointId = chip::kInvalidEndpointId;

examples/closure-app/silabs/src/AppTask.cpp

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <assert.h>
4343
#include <lib/support/BitMask.h>
4444
#include <lib/support/CodeUtils.h>
45+
#include <lib/support/logging/CHIPLogging.h>
4546
#include <platform/CHIPDeviceLayer.h>
4647
#include <platform/silabs/platformAbstraction/SilabsPlatform.h>
4748
#include <setup_payload/OnboardingCodesUtil.h>
@@ -116,11 +117,11 @@ void AppTask::AppTaskMain(void * pvParameter)
116117
CHIP_ERROR err = sAppTask.Init();
117118
if (err != CHIP_NO_ERROR)
118119
{
119-
SILABS_LOG("AppTask.Init() failed");
120+
ChipLogError(AppServer, "AppTask Init failed");
120121
appError(err);
121122
}
122123

123-
SILABS_LOG("App Task started");
124+
ChipLogProgress(AppServer, "App Task started");
124125

125126
while (true)
126127
{
@@ -138,6 +139,92 @@ void AppTask::ButtonEventHandler(uint8_t button, uint8_t btnAction)
138139
AppEvent button_event = {};
139140
button_event.Type = AppEvent::kEventType_Button;
140141
button_event.ButtonEvent.Action = btnAction;
141-
button_event.Handler = BaseApplication::ButtonHandler;
142-
AppTask::GetAppTask().PostEvent(&button_event);
142+
143+
if (button == APP_CLOSURE_BUTTON && btnAction == static_cast<uint8_t>(SilabsPlatform::ButtonAction::ButtonPressed))
144+
{
145+
button_event.Handler = ClosureButtonActionEventHandler;
146+
sAppTask.PostEvent(&button_event);
147+
}
148+
else if (button == APP_FUNCTION_BUTTON)
149+
{
150+
button_event.Handler = BaseApplication::ButtonHandler;
151+
sAppTask.PostEvent(&button_event);
152+
}
153+
}
154+
155+
void AppTask::ClosureButtonActionEventHandler(AppEvent * aEvent)
156+
{
157+
if (aEvent->Type == AppEvent::kEventType_Button)
158+
{
159+
// Schedule work on the chip stack thread to ensure all CHIP API calls are safe
160+
chip::DeviceLayer::PlatformMgr().ScheduleWork(
161+
[](intptr_t) {
162+
// Check if an action is already in progress
163+
if (ClosureManager::GetInstance().IsClosureControlMotionInProgress())
164+
{
165+
// Stop the current action
166+
auto status = ClosureManager::GetInstance().GetClosureControlLogic().HandleStop();
167+
if (status != Protocols::InteractionModel::Status::Success)
168+
{
169+
ChipLogError(AppServer, "Failed to stop closure action: %u", to_underlying(status));
170+
}
171+
}
172+
else
173+
{
174+
DataModel::Nullable<ClosureControl::GenericOverallCurrentState> currentState;
175+
CHIP_ERROR err = ClosureManager::GetInstance().GetClosureControlLogic().GetOverallCurrentState(currentState);
176+
177+
if (err != CHIP_NO_ERROR)
178+
{
179+
ChipLogError(AppServer, "Failed to get current closure state: %s", chip::ErrorStr(err));
180+
return;
181+
}
182+
if (currentState.IsNull())
183+
{
184+
ChipLogError(AppServer, "Failed to get current closure state: currentState is null");
185+
return;
186+
}
187+
if (!currentState.Value().position.HasValue() || currentState.Value().position.Value().IsNull())
188+
{
189+
ChipLogError(AppServer, "Failed to get current closure state: position is null");
190+
return;
191+
}
192+
193+
// Get current position and determine target position (toggle)
194+
auto currentPosition = currentState.Value().position.Value().Value();
195+
ChipLogProgress(AppServer, "Current state - Position: %d", to_underlying(currentPosition));
196+
197+
ClosureControl::TargetPositionEnum targetPosition =
198+
(currentPosition == ClosureControl::CurrentPositionEnum::kFullyOpened)
199+
? ClosureControl::TargetPositionEnum::kMoveToFullyClosed
200+
: ClosureControl::TargetPositionEnum::kMoveToFullyOpen;
201+
ChipLogProgress(AppServer, "Target position: %d", to_underlying(targetPosition));
202+
203+
Optional<bool> latch = chip::NullOptional;
204+
if (currentState.Value().latch.HasValue() && !currentState.Value().latch.Value().IsNull())
205+
{
206+
latch = MakeOptional(false);
207+
}
208+
209+
Optional<Globals::ThreeLevelAutoEnum> speed = NullOptional;
210+
if (currentState.Value().speed.HasValue())
211+
{
212+
speed = chip::MakeOptional(currentState.Value().speed.Value());
213+
}
214+
215+
// Move to the target position with latch set to false and preserved speed value
216+
auto status = ClosureManager::GetInstance().GetClosureControlLogic().HandleMoveTo(MakeOptional(targetPosition),
217+
latch, speed);
218+
if (status != Protocols::InteractionModel::Status::Success)
219+
{
220+
ChipLogError(AppServer, "Failed to move closure to target position: %u", to_underlying(status));
221+
}
222+
}
223+
},
224+
0);
225+
}
226+
else
227+
{
228+
ChipLogError(AppServer, "Unhandled event type in ClosureButtonActionEventHandler");
229+
}
143230
}

examples/closure-app/silabs/src/ClosureManager.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -394,32 +394,32 @@ void ClosureManager::HandleClosureActionComplete(Action_t action)
394394
instance.mClosurePanelEndpoint3.OnCalibrateActionComplete();
395395

396396
DeviceLayer::PlatformMgr().LockChipStack();
397-
isCalibrationInProgress = false;
397+
mIsCalibrationInProgress = false;
398398
DeviceLayer::PlatformMgr().UnlockChipStack();
399399

400400
break;
401401
}
402402
case Action_t::STOP_ACTION: {
403-
if (isCalibrationInProgress)
403+
if (mIsCalibrationInProgress)
404404
{
405405
ChipLogDetail(AppServer, "Stopping calibration action");
406406
instance.mClosureEndpoint1.OnStopCalibrateActionComplete();
407407
instance.mClosurePanelEndpoint2.OnStopCalibrateActionComplete();
408408
instance.mClosurePanelEndpoint3.OnStopCalibrateActionComplete();
409409

410410
DeviceLayer::PlatformMgr().LockChipStack();
411-
isCalibrationInProgress = false;
411+
mIsCalibrationInProgress = false;
412412
DeviceLayer::PlatformMgr().UnlockChipStack();
413413
}
414-
else if (isMoveToInProgress)
414+
else if (mIsMoveToInProgress)
415415
{
416416
ChipLogDetail(AppServer, "Stopping move to action");
417417
instance.mClosureEndpoint1.OnStopMotionActionComplete();
418418
instance.mClosurePanelEndpoint2.OnStopMotionActionComplete();
419419
instance.mClosurePanelEndpoint3.OnStopMotionActionComplete();
420420

421421
DeviceLayer::PlatformMgr().LockChipStack();
422-
isMoveToInProgress = false;
422+
mIsMoveToInProgress = false;
423423
DeviceLayer::PlatformMgr().UnlockChipStack();
424424
}
425425
else
@@ -435,7 +435,7 @@ void ClosureManager::HandleClosureActionComplete(Action_t action)
435435
instance.mClosurePanelEndpoint3.OnMoveToActionComplete();
436436

437437
DeviceLayer::PlatformMgr().LockChipStack();
438-
instance.isMoveToInProgress = false;
438+
instance.mIsMoveToInProgress = false;
439439
DeviceLayer::PlatformMgr().UnlockChipStack();
440440
ChipLogDetail(AppServer, "MoveTo action completed");
441441
break;
@@ -451,7 +451,7 @@ void ClosureManager::HandleClosureActionComplete(Action_t action)
451451
}
452452

453453
DeviceLayer::PlatformMgr().LockChipStack();
454-
instance.isSetTargetInProgress = false;
454+
instance.mIsSetTargetInProgress = false;
455455
DeviceLayer::PlatformMgr().UnlockChipStack();
456456
break;
457457
case Action_t::PANEL_STEP_ACTION:
@@ -466,7 +466,7 @@ void ClosureManager::HandleClosureActionComplete(Action_t action)
466466
}
467467

468468
DeviceLayer::PlatformMgr().LockChipStack();
469-
instance.isStepActionInProgress = false;
469+
instance.mIsStepActionInProgress = false;
470470
DeviceLayer::PlatformMgr().UnlockChipStack();
471471
break;
472472
default:
@@ -489,7 +489,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnCalibrateCommand()
489489
DeviceLayer::PlatformMgr().LockChipStack();
490490
SetCurrentAction(Action_t::CALIBRATE_ACTION);
491491
mCurrentActionEndpointId = mClosureEndpoint1.GetEndpointId();
492-
isCalibrationInProgress = true;
492+
mIsCalibrationInProgress = true;
493493
DeviceLayer::PlatformMgr().UnlockChipStack();
494494

495495
// Post an event to initiate the calibration action asynchronously.
@@ -654,7 +654,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnMoveToCommand(const
654654
{
655655
SetCurrentAction(MOVE_TO_ACTION);
656656
}
657-
isMoveToInProgress = true;
657+
mIsMoveToInProgress = true;
658658
DeviceLayer::PlatformMgr().UnlockChipStack();
659659

660660
// Post an event to initiate the move to action asynchronously.
@@ -816,7 +816,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnSetTargetCommand(con
816816
{
817817
MainStateEnum mClosureEndpoint1MainState;
818818
VerifyOrReturnError(mClosureEndpoint1.GetLogic().GetMainState(mClosureEndpoint1MainState) == CHIP_NO_ERROR, Status::Failure,
819-
ChipLogError(AppServer, "Failed to get main state for Step command on Endpoint 1"));
819+
ChipLogError(AppServer, "Failed to get main state for SetTarget command on Endpoint 1"));
820820

821821
// If this command is received while the MainState attribute is currently either in Disengaged, Protected, Calibrating,
822822
// SetupRequired or Error, then a status code of INVALID_IN_STATE shall be returned.
@@ -827,7 +827,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnSetTargetCommand(con
827827
Status::InvalidInState,
828828
ChipLogError(AppServer, "Step command not allowed in current state: %d", static_cast<int>(mClosureEndpoint1MainState)));
829829

830-
if (isSetTargetInProgress && mCurrentActionEndpointId != endpointId)
830+
if (mIsSetTargetInProgress && mCurrentActionEndpointId != endpointId)
831831
{
832832
ChipLogError(AppServer, "SetTarget action is already in progress on Endpoint %d", mCurrentActionEndpointId);
833833
return Status::Failure;
@@ -886,7 +886,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnSetTargetCommand(con
886886
SetCurrentAction(Action_t::SET_TARGET_ACTION);
887887
}
888888
mCurrentActionEndpointId = endpointId;
889-
isSetTargetInProgress = true;
889+
mIsSetTargetInProgress = true;
890890
DeviceLayer::PlatformMgr().UnlockChipStack();
891891

892892
AppEvent event;
@@ -1113,7 +1113,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnStepCommand(const St
11131113
Status::InvalidInState,
11141114
ChipLogError(AppServer, "Step command not allowed in current state: %d", static_cast<int>(mClosureEndpoint1MainState)));
11151115

1116-
if (isStepActionInProgress && mCurrentActionEndpointId != endpointId)
1116+
if (mIsStepActionInProgress && mCurrentActionEndpointId != endpointId)
11171117
{
11181118
ChipLogError(AppServer, "Step action is already in progress on Endpoint %d", mCurrentActionEndpointId);
11191119
return Status::Failure;
@@ -1145,7 +1145,7 @@ chip::Protocols::InteractionModel::Status ClosureManager::OnStepCommand(const St
11451145
DeviceLayer::PlatformMgr().LockChipStack();
11461146
SetCurrentAction(PANEL_STEP_ACTION);
11471147
mCurrentActionEndpointId = endpointId;
1148-
isStepActionInProgress = true;
1148+
mIsStepActionInProgress = true;
11491149
DeviceLayer::PlatformMgr().UnlockChipStack();
11501150

11511151
AppEvent event;
@@ -1284,3 +1284,7 @@ bool ClosureManager::GetPanelNextPosition(const GenericDimensionStateStruct & cu
12841284
}
12851285
return true;
12861286
}
1287+
bool ClosureManager::IsClosureControlMotionInProgress() const
1288+
{
1289+
return mIsMoveToInProgress;
1290+
}

0 commit comments

Comments
 (0)