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

Update operational state server and related examples #28577

Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7d8b78e
Reordered Mode Base functions.
hicklin Aug 8, 2023
17b53a6
Moved generic OpState cluster objects into one header file.
hicklin Aug 8, 2023
fce49a6
Reordered OperationalStateServer functions.
hicklin Aug 8, 2023
c78803b
Moved OpState delegate in the server header file.
hicklin Aug 8, 2023
d15ceb7
Updated the TestOperationalStateDelegate inctludes following the oper…
hicklin Aug 8, 2023
9aa030a
Renamed TestOperationalStateDelegate.cpp -> src/app/tests/TestOperati…
hicklin Aug 8, 2023
414520c
Restyled by clang-format
restyled-commits Aug 8, 2023
80f7f84
Minor corrections following revision.
hicklin Aug 8, 2023
b867ba2
Refactored the OperationalState server code to match with other deriv…
hicklin Aug 8, 2023
6064b1b
Merge branch 'master' into refactor_operational_state_and_update_exam…
hicklin Aug 9, 2023
77a1df4
Explicitly initialised the edpoint ID in the operational state exampl…
hicklin Aug 10, 2023
092a645
OpState: Made OpState getters return const.
hicklin Aug 10, 2023
18d65c1
Restyled by clang-format
restyled-commits Aug 10, 2023
143ed43
Moved the responsibility of storing and managing the countdown time a…
hicklin Aug 11, 2023
2a46918
Applied minor review changes.
hicklin Aug 11, 2023
b599b97
OpState: Made the improved the relationship between the Delegate and …
hicklin Aug 11, 2023
516ace1
OpState: Removed the ability to set the OperationalState to the Error…
hicklin Aug 11, 2023
450beb2
OpState: Fixed GetCurrentOperationalError
hicklin Aug 11, 2023
40b0ddb
Restyled by clang-format
restyled-commits Aug 11, 2023
5eafc03
Added checks to the phase and operational state setters to ensure tha…
hicklin Aug 11, 2023
3dfe2c2
Added a safe method to check if two GenericOperationalError objects a…
hicklin Aug 14, 2023
4f0d333
GetInstance returns a const pointer.
hicklin Aug 14, 2023
1c3ae5e
Merge branch 'master' into refactor_operational_state_and_update_exam…
hicklin Aug 14, 2023
568acd5
Restyled by clang-format
restyled-commits Aug 14, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -26,79 +26,33 @@
namespace chip {
namespace app {
namespace Clusters {

namespace OperationalState {

// This is an application level delegate to handle operational state commands according to the specific business logic.
class OperationalStateDelegate : public Delegate
class GenericOperationalStateDelegateImpl : public Delegate
{

public:
/**
* Get the current operational state.
* @return The current operational state value
*/
uint8_t GetCurrentOperationalState() override;

/**
* Get the list of supported operational states.
* Fills in the provided GenericOperationalState with the state at index `index` if there is one,
* or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of states.
* Note: This is used by the SDK to populate the operational state list attribute. If the contents of this list changes,
* the device SHALL call the Instance's ReportOperationalStateListChange method to report that this attribute has changed.
* @param index The index of the state, with 0 representing the first state.
* @param operationalState The GenericOperationalState is filled.
*/
CHIP_ERROR GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) override;

/**
* Get the list of supported operational phases.
* Fills in the provided GenericOperationalPhase with the phase at index `index` if there is one,
* or returns CHIP_ERROR_NOT_FOUND if the index is out of range for the list of phases.
* Note: This is used by the SDK to populate the phase list attribute. If the contents of this list changes, the
* device SHALL call the Instance's ReportPhaseListChange method to report that this attribute has changed.
* @param index The index of the phase, with 0 representing the first phase.
* @param operationalPhase The GenericOperationalPhase is filled.
*/
CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase) override;

/**
* Get current operational error.
* @param error The GenericOperationalError to fill with the current operational error value
*/
void GetCurrentOperationalError(GenericOperationalError & error) override;

/**
* Get current phase
* @param phase The app::DataModel::Nullable<uint8_t> to fill with the current phase value
*/
void GetCurrentPhase(app::DataModel::Nullable<uint8_t> & phase) override;

/**
* Get countdown time
* @param time The app::DataModel::Nullable<uint32_t> to fill with the coutdown time value
*/
void GetCountdownTime(app::DataModel::Nullable<uint32_t> & time) override;

/**
* Set operational error.
* @param opErrState The new operational error.
*/
CHIP_ERROR SetOperationalError(const GenericOperationalError & opErrState) override;

/**
* Set current operational state.
* @param opState The operational state that should now be the current one.
*/
CHIP_ERROR SetOperationalState(uint8_t opState) override;

/**
* Set operational phase.
* @param phase The operational phase that should now be the current one.
*/
CHIP_ERROR SetPhase(const app::DataModel::Nullable<uint8_t> & phase) override;

/**
* Set coutdown time.
* @param time The coutdown time that should now be the current one.
*/
CHIP_ERROR SetCountdownTime(const app::DataModel::Nullable<uint32_t> & time) override;

// command callback
/**
* Handle Command Callback in application: Pause
Expand All @@ -124,27 +78,74 @@ class OperationalStateDelegate : public Delegate
*/
void HandleStopStateCallback(GenericOperationalError & err) override;

OperationalStateDelegate(uint8_t aOperationalState, GenericOperationalError aOperationalError,
Span<const GenericOperationalState> aOperationalStateList,
Span<const GenericOperationalPhase> aOperationalPhaseList,
app::DataModel::Nullable<uint8_t> aPhase = DataModel::Nullable<uint8_t>(),
app::DataModel::Nullable<uint32_t> aCountdownTime = DataModel::Nullable<uint32_t>()) :
mOperationalState(aOperationalState),
mOperationalError(aOperationalError), mOperationalStateList(aOperationalStateList),
mOperationalPhaseList(aOperationalPhaseList), mOperationalPhase(aPhase), mCountdownTime(aCountdownTime)
{}
~OperationalStateDelegate() = default;
protected:
Span<const GenericOperationalState> mOperationalStateList;
Span<const GenericOperationalPhase> mOperationalPhaseList;
};

// This is an application level delegate to handle operational state commands according to the specific business logic.
class OperationalStateDelegate : public GenericOperationalStateDelegateImpl
{
private:
uint8_t mOperationalState;
GenericOperationalError mOperationalError;
app::DataModel::List<const GenericOperationalState> mOperationalStateList;
Span<const GenericOperationalPhase> mOperationalPhaseList;
app::DataModel::Nullable<uint8_t> mOperationalPhase;
app::DataModel::Nullable<uint32_t> mCountdownTime;
const GenericOperationalState opStateList[4] = {
GenericOperationalState(to_underlying(OperationalStateEnum::kStopped)),
GenericOperationalState(to_underlying(OperationalStateEnum::kRunning)),
GenericOperationalState(to_underlying(OperationalStateEnum::kPaused)),
GenericOperationalState(to_underlying(OperationalStateEnum::kError)),
};

const GenericOperationalPhase opPhaseList[1] = {
// Phase List is null
GenericOperationalPhase(DataModel::Nullable<CharSpan>()),
};

public:
OperationalStateDelegate()
{
GenericOperationalStateDelegateImpl::mOperationalStateList = Span<const GenericOperationalState>(opStateList);
GenericOperationalStateDelegateImpl::mOperationalPhaseList = Span<const GenericOperationalPhase>(opPhaseList);
}
};

void Shutdown();

} // namespace OperationalState

namespace RvcOperationalState {

// This is an application level delegate to handle operational state commands according to the specific business logic.
class RvcOperationalStateDelegate : public OperationalState::GenericOperationalStateDelegateImpl
{
private:
const OperationalState::GenericOperationalState rvcOpStateList[7] = {
OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped)),
OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kRunning)),
OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kPaused)),
OperationalState::GenericOperationalState(to_underlying(OperationalState::OperationalStateEnum::kError)),
OperationalState::GenericOperationalState(
to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kSeekingCharger)),
OperationalState::GenericOperationalState(to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kCharging)),
OperationalState::GenericOperationalState(to_underlying(Clusters::RvcOperationalState::OperationalStateEnum::kDocked)),
};

const OperationalState::GenericOperationalPhase rvcOpPhaseList[1] = {
// Phase List is null
OperationalState::GenericOperationalPhase(DataModel::Nullable<CharSpan>()),
};

public:
RvcOperationalStateDelegate()
{
GenericOperationalStateDelegateImpl::mOperationalStateList =
Span<const OperationalState::GenericOperationalState>(rvcOpStateList);
GenericOperationalStateDelegateImpl::mOperationalPhaseList =
Span<const OperationalState::GenericOperationalPhase>(rvcOpPhaseList);
}
};

void Shutdown();

} // namespace RvcOperationalState
} // namespace Clusters
} // namespace app
} // namespace chip
Original file line number Diff line number Diff line change
Expand Up @@ -17,106 +17,153 @@
*/
#include <operational-state-delegate-impl.h>

namespace chip {
namespace app {
namespace Clusters {
namespace OperationalState {
using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::OperationalState;
using namespace chip::app::Clusters::RvcOperationalState;

using chip::Protocols::InteractionModel::Status;

CHIP_ERROR OperationalStateDelegate::SetOperationalState(uint8_t opState)
CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState)
{
mOperationalState = opState;
if (index >= mOperationalStateList.size())
{
return CHIP_ERROR_NOT_FOUND;
}
operationalState = mOperationalStateList[index];
return CHIP_NO_ERROR;
}

CHIP_ERROR OperationalStateDelegate::SetPhase(const app::DataModel::Nullable<uint8_t> & phase)
CHIP_ERROR GenericOperationalStateDelegateImpl::GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase)
{
mOperationalPhase = phase;
if (index >= mOperationalPhaseList.size())
{
return CHIP_ERROR_NOT_FOUND;
}
operationalPhase = mOperationalPhaseList[index];
return CHIP_NO_ERROR;
}

CHIP_ERROR OperationalStateDelegate::SetCountdownTime(const app::DataModel::Nullable<uint32_t> & time)
void GenericOperationalStateDelegateImpl::HandlePauseStateCallback(GenericOperationalError & err)
{
mCountdownTime = time;
return CHIP_NO_ERROR;
// placeholder implementation
auto error = mServer->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kPaused));
if (error == CHIP_NO_ERROR)
{
err.Set(to_underlying(ErrorStateEnum::kNoError));
}
else
{
err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation));
}
}

uint8_t OperationalStateDelegate::GetCurrentOperationalState()
void GenericOperationalStateDelegateImpl::HandleResumeStateCallback(GenericOperationalError & err)
{
return mOperationalState;
// placeholder implementation
auto error = mServer->SetOperationalState(to_underlying(OperationalStateEnum::kRunning));
if (error == CHIP_NO_ERROR)
{
err.Set(to_underlying(ErrorStateEnum::kNoError));
}
else
{
err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation));
}
}

CHIP_ERROR OperationalStateDelegate::SetOperationalError(const GenericOperationalError & opErrState)
void GenericOperationalStateDelegateImpl::HandleStartStateCallback(GenericOperationalError & err)
{
mOperationalError = opErrState;
return CHIP_NO_ERROR;
// placeholder implementation
auto error = mServer->SetOperationalState(to_underlying(OperationalStateEnum::kRunning));
if (error == CHIP_NO_ERROR)
{
err.Set(to_underlying(ErrorStateEnum::kNoError));
}
else
{
err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation));
}
}

void OperationalStateDelegate::GetCurrentOperationalError(GenericOperationalError & error)
void GenericOperationalStateDelegateImpl::HandleStopStateCallback(GenericOperationalError & err)
{
error = mOperationalError;
// placeholder implementation
auto error = mServer->SetOperationalState(to_underlying(OperationalStateEnum::kStopped));
if (error == CHIP_NO_ERROR)
{
err.Set(to_underlying(ErrorStateEnum::kNoError));
}
else
{
err.Set(to_underlying(ErrorStateEnum::kUnableToCompleteOperation));
}
}

void OperationalStateDelegate::GetCurrentPhase(app::DataModel::Nullable<uint8_t> & phase)
{
phase = mOperationalPhase;
}
// Init Operational State cluster

void OperationalStateDelegate::GetCountdownTime(app::DataModel::Nullable<uint32_t> & time)
{
time = mCountdownTime;
}
static OperationalState::Instance * gOperationalStateInstance = nullptr;
static OperationalStateDelegate * gOperationalStateDelegate = nullptr;

CHIP_ERROR OperationalStateDelegate::GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState)
void OperationalState::Shutdown()
{
if (index > mOperationalStateList.size() - 1)
if (gOperationalStateInstance != nullptr)
{
return CHIP_ERROR_NOT_FOUND;
delete gOperationalStateInstance;
gOperationalStateInstance = nullptr;
}
operationalState = mOperationalStateList[index];
return CHIP_NO_ERROR;
}

CHIP_ERROR OperationalStateDelegate::GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase)
{
if (index > mOperationalPhaseList.size() - 1)
if (gOperationalStateDelegate != nullptr)
{
return CHIP_ERROR_NOT_FOUND;
delete gOperationalStateDelegate;
gOperationalStateDelegate = nullptr;
}
operationalPhase = mOperationalPhaseList[index];
return CHIP_NO_ERROR;
}

void OperationalStateDelegate::HandlePauseStateCallback(GenericOperationalError & err)
void emberAfOperationalStateClusterInitCallback(chip::EndpointId endpointId)
{
// placeholder implementation
mOperationalState = to_underlying(OperationalStateEnum::kPaused);
err.Set(to_underlying(ErrorStateEnum::kNoError));
}
VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1.
VerifyOrDie(gOperationalStateInstance == nullptr && gOperationalStateDelegate == nullptr);

void OperationalStateDelegate::HandleResumeStateCallback(GenericOperationalError & err)
{
// placeholder implementation
mOperationalState = to_underlying(OperationalStateEnum::kRunning);
err.Set(to_underlying(ErrorStateEnum::kNoError));
gOperationalStateDelegate = new OperationalStateDelegate;
EndpointId operationalStateEndpoint = 0x01;
gOperationalStateInstance = new Instance(gOperationalStateDelegate, operationalStateEndpoint, Clusters::OperationalState::Id);

gOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped));
gOperationalStateInstance->SetOperationalError(to_underlying(OperationalState::ErrorStateEnum::kNoError));

gOperationalStateInstance->Init();
}

void OperationalStateDelegate::HandleStartStateCallback(GenericOperationalError & err)
// Init RVC Operational State cluster

static OperationalState::Instance * gRvcOperationalStateInstance = nullptr;
static RvcOperationalStateDelegate * gRvcOperationalStateDelegate = nullptr;

void RvcOperationalState::Shutdown()
{
// placeholder implementation
mOperationalState = to_underlying(OperationalStateEnum::kRunning);
err.Set(to_underlying(ErrorStateEnum::kNoError));
if (gRvcOperationalStateInstance != nullptr)
{
delete gRvcOperationalStateInstance;
gRvcOperationalStateInstance = nullptr;
}
if (gRvcOperationalStateDelegate != nullptr)
{
delete gRvcOperationalStateDelegate;
gRvcOperationalStateDelegate = nullptr;
}
}

void OperationalStateDelegate::HandleStopStateCallback(GenericOperationalError & err)
void emberAfRvcOperationalStateClusterInitCallback(chip::EndpointId endpointId)
{
// placeholder implementation
mOperationalState = to_underlying(OperationalStateEnum::kStopped);
err.Set(to_underlying(ErrorStateEnum::kNoError));
}
VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1.
VerifyOrDie(gRvcOperationalStateInstance == nullptr && gRvcOperationalStateDelegate == nullptr);

} // namespace OperationalState
} // namespace Clusters
} // namespace app
} // namespace chip
gRvcOperationalStateDelegate = new RvcOperationalStateDelegate;
EndpointId operationalStateEndpoint = 0x01;
gRvcOperationalStateInstance =
new Instance(gRvcOperationalStateDelegate, operationalStateEndpoint, Clusters::RvcOperationalState::Id);

gRvcOperationalStateInstance->SetOperationalState(to_underlying(OperationalState::OperationalStateEnum::kStopped));
gRvcOperationalStateInstance->SetOperationalError(to_underlying(OperationalState::ErrorStateEnum::kNoError));

gRvcOperationalStateInstance->Init();
}
Loading