Skip to content

Commit fd800c2

Browse files
Make robotic vacuum cleaner spec compliant (#37718)
* Start new cycle when RVC Run Mode is changed from idle to cleaning/mapping * Fix bug : Last call to onOperationalStateTimeTick happens after state is already set to Stopped resulting in dereferencing a null pointer. Fix this by returning from function if state is stopped * Change RunMode to Idle after cleaning cycle completes * Restyled by whitespace * Fix tags list for Mapping mode * use getters instead of extern --------- Co-authored-by: Restyled.io <commits@restyled.io>
1 parent 97fbc37 commit fd800c2

4 files changed

+62
-1
lines changed

examples/chef/common/chef-rvc-mode-delegate.cpp

+38
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,21 @@ using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::T
2929

3030
#ifdef MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
3131
#include <chef-rvc-mode-delegate.h>
32+
33+
#ifdef MATTER_DM_PLUGIN_RVC_OPERATIONAL_STATE_SERVER
34+
#include <chef-rvc-operational-state-delegate.h>
35+
#endif // MATTER_DM_PLUGIN_RVC_OPERATIONAL_STATE_SERVER
36+
3237
using namespace chip::app::Clusters::RvcRunMode;
3338

3439
static std::unique_ptr<RvcRunModeDelegate> gRvcRunModeDelegate;
3540
static std::unique_ptr<ModeBase::Instance> gRvcRunModeInstance;
3641

42+
chip::app::Clusters::ModeBase::Instance * getRvcRunModeInstance()
43+
{
44+
return gRvcRunModeInstance.get();
45+
}
46+
3747
CHIP_ERROR RvcRunModeDelegate::Init()
3848
{
3949
return CHIP_NO_ERROR;
@@ -51,7 +61,35 @@ void RvcRunModeDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands:
5161
return;
5262
}
5363

64+
#ifdef MATTER_DM_PLUGIN_RVC_OPERATIONAL_STATE_SERVER
65+
OperationalState::GenericOperationalError err(to_underlying(OperationalState::ErrorStateEnum::kNoError));
66+
if (NewMode == RvcRunMode::ModeIdle)
67+
{
68+
if (currentMode != RvcRunMode::ModeIdle)
69+
{ // Stop existing cycle when going from cleaning/mapping to idle.
70+
ChipLogProgress(DeviceLayer, "Stopping RVC cycle: %d", currentMode);
71+
getRvcOperationalStateDelegate()->HandleStopStateCallback(err);
72+
}
73+
}
74+
else
75+
{
76+
if (currentMode == RvcRunMode::ModeIdle)
77+
{ // Start a new cycle when going from idle to clening/mapping.
78+
ChipLogProgress(DeviceLayer, "Starting new RVC cycle: %d", NewMode);
79+
getRvcOperationalStateDelegate()->HandleStartStateCallback(err);
80+
}
81+
}
82+
if (err.IsEqual(OperationalState::GenericOperationalError(to_underlying(OperationalState::ErrorStateEnum::kNoError))))
83+
{
84+
response.status = to_underlying(ModeBase::StatusCode::kSuccess);
85+
}
86+
else
87+
{
88+
response.status = to_underlying(ModeBase::StatusCode::kGenericFailure);
89+
}
90+
#else
5491
response.status = to_underlying(ModeBase::StatusCode::kSuccess);
92+
#endif // MATTER_DM_PLUGIN_RVC_OPERATIONAL_STATE_SERVER
5593
}
5694

5795
CHIP_ERROR RvcRunModeDelegate::GetModeLabelByIndex(uint8_t modeIndex, chip::MutableCharSpan & label)

examples/chef/common/chef-rvc-mode-delegate.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class RvcRunModeDelegate : public ModeBase::Delegate
4242
using ModeTagStructType = detail::Structs::ModeTagStruct::Type;
4343
ModeTagStructType ModeTagsIdle[1] = { { .value = to_underlying(ModeTag::kIdle) } };
4444
ModeTagStructType ModeTagsCleaning[1] = { { .value = to_underlying(ModeTag::kCleaning) } };
45+
ModeTagStructType ModeTagsMapping[1] = { { .value = to_underlying(ModeTag::kMapping) } };
4546

4647
const detail::Structs::ModeOptionStruct::Type kModeOptions[3] = {
4748
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Idle"),
@@ -52,7 +53,7 @@ class RvcRunModeDelegate : public ModeBase::Delegate
5253
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsCleaning) },
5354
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Mapping"),
5455
.mode = ModeMapping,
55-
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsIdle) },
56+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsMapping) },
5657
};
5758

5859
CHIP_ERROR Init() override;
@@ -122,6 +123,8 @@ void Shutdown();
122123
} // namespace chip
123124

124125
#ifdef MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
126+
chip::app::Clusters::ModeBase::Instance * getRvcRunModeInstance();
127+
125128
chip::Protocols::InteractionModel::Status chefRvcRunModeWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId,
126129
const EmberAfAttributeMetadata * attributeMetadata,
127130
uint8_t * buffer);

examples/chef/common/chef-rvc-operational-state-delegate.cpp

+18
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,18 @@ using namespace chip::app::Clusters::OperationalState;
2828
using namespace chip::app::Clusters::RvcOperationalState;
2929
using chip::Protocols::InteractionModel::Status;
3030

31+
#ifdef MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
32+
#include <chef-rvc-mode-delegate.h>
33+
#endif // MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
34+
3135
static std::unique_ptr<RvcOperationalStateDelegate> gRvcOperationalStateDelegate;
3236
static std::unique_ptr<RvcOperationalState::Instance> gRvcOperationalStateInstance;
3337

38+
RvcOperationalStateDelegate * getRvcOperationalStateDelegate()
39+
{
40+
return gRvcOperationalStateDelegate.get();
41+
}
42+
3443
static void onOperationalStateTimerTick(System::Layer * systemLayer, void * data);
3544

3645
DataModel::Nullable<uint32_t> RvcOperationalStateDelegate::GetCountdownTime()
@@ -176,6 +185,11 @@ static void onOperationalStateTimerTick(System::Layer * systemLayer, void * data
176185
OperationalState::OperationalStateEnum state =
177186
static_cast<OperationalState::OperationalStateEnum>(instance->GetCurrentOperationalState());
178187

188+
if (state == OperationalState::OperationalStateEnum::kStopped) // Do not continue the timer when RVC has stopped.
189+
{
190+
return;
191+
}
192+
179193
if (gRvcOperationalStateDelegate->mCountdownTime.IsNull())
180194
{
181195
if (state == OperationalState::OperationalStateEnum::kRunning)
@@ -223,6 +237,10 @@ static void onOperationalStateTimerTick(System::Layer * systemLayer, void * data
223237
gRvcOperationalStateDelegate->mRunningTime = 0;
224238
gRvcOperationalStateDelegate->mPausedTime = 0;
225239
gRvcOperationalStateDelegate->mCountdownTime.SetNull();
240+
241+
#ifdef MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
242+
getRvcRunModeInstance()->UpdateCurrentMode(RvcRunMode::ModeIdle);
243+
#endif // MATTER_DM_PLUGIN_RVC_RUN_MODE_SERVER
226244
}
227245
}
228246
}

examples/chef/common/chef-rvc-operational-state-delegate.h

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,8 @@ void Shutdown();
122122
} // namespace app
123123
} // namespace chip
124124

125+
chip::app::Clusters::RvcOperationalState::RvcOperationalStateDelegate * getRvcOperationalStateDelegate();
126+
125127
chip::Protocols::InteractionModel::Status chefRvcOperationalStateWriteCallback(chip::EndpointId endpoint, chip::ClusterId clusterId,
126128
const EmberAfAttributeMetadata * attributeMetadata,
127129
uint8_t * buffer);

0 commit comments

Comments
 (0)