blob: 34bbe2d1ba10c0ac5b59a93db9d96279308abffa [file] [log] [blame]
/*
*
* Copyright (c) 2023 Project CHIP Authors
* All rights reserved.
*
* 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.
*/
#pragma once
#include <app-common/zap-generated/cluster-objects.h>
#include <app/util/af-enums.h>
#include <lib/support/CommonIterator.h>
namespace chip {
namespace app {
namespace Clusters {
namespace OperationalState {
constexpr size_t kOperationalStateLabelMaxSize = 64u;
constexpr size_t kOperationalErrorLabelMaxSize = 64u;
constexpr size_t kOperationalErrorDetailsMaxSize = 64u;
constexpr size_t kOperationalPhaseNameMaxSize = 64u;
/**
* A class which represents the operational state of an Operational State cluster derivation instance.
*/
struct GenericOperationalState : public app::Clusters::detail::Structs::OperationalStateStruct::Type
{
GenericOperationalState(uint8_t state = to_underlying(OperationalStateEnum::kStopped), Optional<CharSpan> label = NullOptional)
{
Set(state, label);
}
GenericOperationalState(const GenericOperationalState & op) { *this = op; }
GenericOperationalState & operator=(const GenericOperationalState & op)
{
Set(op.operationalStateID, op.operationalStateLabel);
return *this;
}
void Set(uint8_t state, Optional<CharSpan> label = NullOptional)
{
operationalStateID = state;
if (label.HasValue())
{
memset(mOperationalStateLabelBuffer, 0, sizeof(mOperationalStateLabelBuffer));
if (label.Value().size() > sizeof(mOperationalStateLabelBuffer))
{
memcpy(mOperationalStateLabelBuffer, label.Value().data(), sizeof(mOperationalStateLabelBuffer));
operationalStateLabel.SetValue(CharSpan(mOperationalStateLabelBuffer, sizeof(mOperationalStateLabelBuffer)));
}
else
{
memcpy(mOperationalStateLabelBuffer, label.Value().data(), label.Value().size());
operationalStateLabel.SetValue(CharSpan(mOperationalStateLabelBuffer, label.Value().size()));
}
}
else
{
operationalStateLabel = NullOptional;
}
}
private:
char mOperationalStateLabelBuffer[kOperationalStateLabelMaxSize];
};
/**
* A class which represents the operational error of an Operational State cluster derivation instance.
*/
struct GenericOperationalError : public app::Clusters::detail::Structs::ErrorStateStruct::Type
{
GenericOperationalError(uint8_t state, Optional<chip::CharSpan> label = NullOptional,
Optional<chip::CharSpan> details = NullOptional)
{
Set(state, label, details);
}
GenericOperationalError(const GenericOperationalError & error) { *this = error; }
GenericOperationalError & operator=(const GenericOperationalError & error)
{
Set(error.errorStateID, error.errorStateLabel, error.errorStateDetails);
return *this;
}
void Set(uint8_t state, Optional<chip::CharSpan> label = NullOptional, Optional<chip::CharSpan> details = NullOptional)
{
errorStateID = state;
if (label.HasValue())
{
memset(mErrorStateLabelBuffer, 0, sizeof(mErrorStateLabelBuffer));
if (label.Value().size() > sizeof(mErrorStateLabelBuffer))
{
memcpy(mErrorStateLabelBuffer, label.Value().data(), sizeof(mErrorStateLabelBuffer));
errorStateLabel.SetValue(CharSpan(mErrorStateLabelBuffer, sizeof(mErrorStateLabelBuffer)));
}
else
{
memcpy(mErrorStateLabelBuffer, label.Value().data(), label.Value().size());
errorStateLabel.SetValue(CharSpan(mErrorStateLabelBuffer, label.Value().size()));
}
}
else
{
errorStateLabel = NullOptional;
}
if (details.HasValue())
{
memset(mErrorStateDetailsBuffer, 0, sizeof(mErrorStateDetailsBuffer));
if (details.Value().size() > sizeof(mErrorStateDetailsBuffer))
{
memcpy(mErrorStateDetailsBuffer, details.Value().data(), sizeof(mErrorStateDetailsBuffer));
errorStateDetails.SetValue(CharSpan(mErrorStateDetailsBuffer, sizeof(mErrorStateDetailsBuffer)));
}
else
{
memcpy(mErrorStateDetailsBuffer, details.Value().data(), details.Value().size());
errorStateDetails.SetValue(CharSpan(mErrorStateDetailsBuffer, details.Value().size()));
}
}
else
{
errorStateDetails = NullOptional;
}
}
private:
char mErrorStateLabelBuffer[kOperationalErrorLabelMaxSize];
char mErrorStateDetailsBuffer[kOperationalErrorDetailsMaxSize];
};
/**
* A class which represents the operational phase of an Operational State cluster derivation instance.
*/
struct GenericOperationalPhase
{
GenericOperationalPhase(app::DataModel::Nullable<CharSpan> name) { Set(name); }
GenericOperationalPhase(const GenericOperationalPhase & ph) { *this = ph; }
GenericOperationalPhase & operator=(const GenericOperationalPhase & ph)
{
Set(ph.mPhaseName);
return *this;
}
bool IsMissing() const { return mPhaseName.IsNull(); }
app::DataModel::Nullable<CharSpan> mPhaseName;
private:
void Set(app::DataModel::Nullable<CharSpan> name)
{
if (name.IsNull())
{
mPhaseName.SetNull();
}
else
{
memset(mPhaseNameBuffer, 0, sizeof(mPhaseNameBuffer));
if (name.Value().size() > sizeof(mPhaseNameBuffer))
{
memcpy(mPhaseNameBuffer, name.Value().data(), sizeof(mPhaseNameBuffer));
mPhaseName = app::DataModel::Nullable<CharSpan>(CharSpan(mPhaseNameBuffer, sizeof(mPhaseNameBuffer)));
}
else
{
memcpy(mPhaseNameBuffer, name.Value().data(), name.Value().size());
mPhaseName = app::DataModel::Nullable<CharSpan>(CharSpan(mPhaseNameBuffer, name.Value().size()));
}
}
}
char mPhaseNameBuffer[kOperationalPhaseNameMaxSize];
};
/**
* A delegate to handle application logic of the Operational State aliased Cluster.
* The delegate API assumes there will be separate delegate objects for each cluster instance.
* (i.e. each separate operational state cluster derivation, on each separate endpoint),
* since the delegate methods are not handed the cluster id or endpoint.
*/
class Delegate
{
public:
/**
* Get the current operational state.
* @return The current operational state value
*/
virtual uint8_t GetCurrentOperationalState() = 0;
/**
* 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.
* @param index The index of the state, with 0 representing the first state.
* @param operationalState The GenericOperationalState is filled.
*/
virtual CHIP_ERROR GetOperationalStateAtIndex(size_t index, GenericOperationalState & operationalState) = 0;
/**
* 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.
* @param index The index of the phase, with 0 representing the first phase.
* @param operationalPhase The GenericOperationalPhase is filled.
*/
virtual CHIP_ERROR GetOperationalPhaseAtIndex(size_t index, GenericOperationalPhase & operationalPhase) = 0;
/**
* Get current operational error.
* @param error The GenericOperationalError to fill with the current operational error value
*/
virtual void GetCurrentOperationalError(GenericOperationalError & error) = 0;
/**
* Get current phase
* @param phase The app::DataModel::Nullable<uint8_t> to fill with the current phase value
*/
virtual void GetCurrentPhase(app::DataModel::Nullable<uint8_t> & phase) = 0;
/**
* Get countdown time
* @param time The app::DataModel::Nullable<uint32_t> to fill with the coutdown time value
*/
virtual void GetCountdownTime(app::DataModel::Nullable<uint32_t> & time) = 0;
/**
* Set current operational state.
* @param opState The operational state that should now be the current one.
*/
virtual CHIP_ERROR SetOperationalState(uint8_t opState) = 0;
/**
* Set operational error.
* @param opErrState The new operational error.
*/
virtual CHIP_ERROR SetOperationalError(const GenericOperationalError & opErrState) = 0;
/**
* Set operational phase.
* @param phase The operational phase that should now be the current one.
*/
virtual CHIP_ERROR SetPhase(const app::DataModel::Nullable<uint8_t> & phase) = 0;
/**
* Set coutdown time.
* @param time The coutdown time that should now be the current one.
*/
virtual CHIP_ERROR SetCountdownTime(const app::DataModel::Nullable<uint32_t> & time) = 0;
// command callback
/**
* Handle Command Callback in application: Pause
* @param[out] get operational error after callback.
*/
virtual void HandlePauseStateCallback(GenericOperationalError & err) = 0;
/**
* Handle Command Callback in application: Resume
* @param[out] get operational error after callback.
*/
virtual void HandleResumeStateCallback(GenericOperationalError & err) = 0;
/**
* Handle Command Callback in application: Start
* @param[out] get operational error after callback.
*/
virtual void HandleStartStateCallback(GenericOperationalError & err) = 0;
/**
* Handle Command Callback in application: Stop
* @param[out] get operational error after callback.
*/
virtual void HandleStopStateCallback(GenericOperationalError & err) = 0;
Delegate() = default;
virtual ~Delegate() = default;
};
// @brief Instance getter for the delegate for the given operational state alias cluster on the given endpoint.
// The delegate API assumes there will be separate delegate objects for each cluster instance.
// (i.e. each separate operational state cluster derivation, on each separate endpoint)
// @note This API should always be called prior to using the delegate and the return pointer should never be cached.
// This should be implemented by the application.
// @return Default global delegate instance.
Delegate * GetOperationalStateDelegate(EndpointId endpointId, ClusterId clusterId);
} // namespace OperationalState
} // namespace Clusters
} // namespace app
} // namespace chip