blob: 5aee2b668f08733d7d98c5fd7b252728d2b6596a [file]
/*
* Copyright (c) 2026 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.
*/
#include "LaundryWasherControlsCluster.h"
#include <app/server-cluster/AttributeListBuilder.h>
#include <clusters/LaundryWasherControls/Metadata.h>
namespace chip::app::Clusters {
using namespace LaundryWasherControls;
using namespace LaundryWasherControls::Attributes;
DataModel::ActionReturnStatus LaundryWasherControlsCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request,
AttributeValueEncoder & encoder)
{
switch (request.path.mAttributeId)
{
case ClusterRevision::Id:
return encoder.Encode(kRevision);
case FeatureMap::Id:
return encoder.Encode(mFeatures);
case SpinSpeeds::Id:
return ReadSpinSpeeds(request.path, encoder);
case SpinSpeedCurrent::Id:
return encoder.Encode(mSpinSpeedCurrent);
case NumberOfRinses::Id:
return encoder.Encode(mNumberOfRinses);
case SupportedRinses::Id:
return ReadSupportedRinses(request.path, encoder);
default:
return Protocols::InteractionModel::Status::UnsupportedAttribute;
}
}
DataModel::ActionReturnStatus LaundryWasherControlsCluster::WriteAttribute(const DataModel::WriteAttributeRequest & request,
AttributeValueDecoder & decoder)
{
switch (request.path.mAttributeId)
{
case SpinSpeedCurrent::Id: {
DataModel::Nullable<uint8_t> spinSpeedCurrent;
ReturnErrorOnFailure(decoder.Decode(spinSpeedCurrent));
return SetSpinSpeedCurrent(spinSpeedCurrent);
}
case NumberOfRinses::Id: {
NumberOfRinsesEnum numberOfRinses;
ReturnErrorOnFailure(decoder.Decode(numberOfRinses));
return SetNumberOfRinses(numberOfRinses);
}
default:
return Protocols::InteractionModel::Status::UnsupportedAttribute;
}
}
CHIP_ERROR LaundryWasherControlsCluster::Attributes(const ConcreteClusterPath & path,
ReadOnlyBufferBuilder<DataModel::AttributeEntry> & builder)
{
AttributeListBuilder::OptionalAttributeEntry optionalAttributes[] = {
{ mFeatures.Has(Feature::kSpin), SpinSpeedCurrent::kMetadataEntry },
{ mFeatures.Has(Feature::kSpin), SpinSpeeds::kMetadataEntry },
{ mFeatures.Has(Feature::kRinse), NumberOfRinses::kMetadataEntry },
{ mFeatures.Has(Feature::kRinse), SupportedRinses::kMetadataEntry },
};
AttributeListBuilder listBuilder(builder);
return listBuilder.Append(Span(kMandatoryMetadata), Span(optionalAttributes));
}
CHIP_ERROR LaundryWasherControlsCluster::SetSpinSpeedCurrent(DataModel::Nullable<uint8_t> spinSpeedCurrent)
{
if (!mFeatures.Has(Feature::kSpin))
{
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}
ReturnErrorOnFailure(SpinSpeedIndexValidity(spinSpeedCurrent));
if (SetAttributeValue(mSpinSpeedCurrent, spinSpeedCurrent, SpinSpeedCurrent::Id) && mDelegate != nullptr)
{
mDelegate->OnSpinSpeedCurrentChanged(spinSpeedCurrent);
}
return CHIP_NO_ERROR;
}
CHIP_ERROR LaundryWasherControlsCluster::SetNumberOfRinses(NumberOfRinsesEnum numberOfRinses)
{
if (!mFeatures.Has(Feature::kRinse))
{
return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute);
}
ReturnErrorOnFailure(NumberOfRinsesValidity(numberOfRinses));
if (SetAttributeValue(mNumberOfRinses, numberOfRinses, NumberOfRinses::Id) && mDelegate != nullptr)
{
mDelegate->OnNumberOfRinsesChanged(numberOfRinses);
}
return CHIP_NO_ERROR;
}
CHIP_ERROR LaundryWasherControlsCluster::SpinSpeedIndexValidity(DataModel::Nullable<uint8_t> spinSpeedCurrent)
{
if (spinSpeedCurrent.IsNull())
{
return CHIP_NO_ERROR;
}
VerifyOrReturnError(mDelegate != nullptr, CHIP_IM_GLOBAL_STATUS(ConstraintError));
VerifyOrReturnError(spinSpeedCurrent.Value() < kMaxSpinSpeedsLength, CHIP_IM_GLOBAL_STATUS(ConstraintError));
char buffer[kMaxSpinSpeedLength];
MutableCharSpan dummy(buffer);
CHIP_ERROR err = mDelegate->GetSpinSpeedAtIndex(spinSpeedCurrent.Value(), dummy);
VerifyOrReturnError(err != CHIP_ERROR_PROVIDER_LIST_EXHAUSTED, CHIP_IM_GLOBAL_STATUS(ConstraintError));
return err;
}
CHIP_ERROR LaundryWasherControlsCluster::NumberOfRinsesValidity(NumberOfRinsesEnum numberOfRinses)
{
VerifyOrReturnError(mDelegate != nullptr, CHIP_IM_GLOBAL_STATUS(InvalidInState));
NumberOfRinsesEnum supportedRinse;
for (uint8_t i = 0; i < kMaxSupportedRinsesLength && mDelegate->GetSupportedRinseAtIndex(i, supportedRinse) == CHIP_NO_ERROR;
++i)
{
if (numberOfRinses == supportedRinse)
{
return CHIP_NO_ERROR;
}
}
return CHIP_IM_GLOBAL_STATUS(InvalidInState);
}
CHIP_ERROR LaundryWasherControlsCluster::ReadSpinSpeeds(const ConcreteAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
VerifyOrReturnError(mDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
for (uint8_t i = 0; i < kMaxSpinSpeedsLength; i++)
{
char buffer[kMaxSpinSpeedLength];
MutableCharSpan spinSpeed(buffer);
auto err = mDelegate->GetSpinSpeedAtIndex(i, spinSpeed);
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
{
return CHIP_NO_ERROR;
}
ReturnErrorOnFailure(err);
ReturnErrorOnFailure(encoder.Encode(spinSpeed));
}
return CHIP_NO_ERROR;
});
}
CHIP_ERROR LaundryWasherControlsCluster::ReadSupportedRinses(const ConcreteAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
VerifyOrReturnError(mDelegate != nullptr, CHIP_ERROR_INCORRECT_STATE);
return aEncoder.EncodeList([this](const auto & encoder) -> CHIP_ERROR {
for (uint8_t i = 0; i < kMaxSupportedRinsesLength; i++)
{
NumberOfRinsesEnum supportedRinse;
auto err = mDelegate->GetSupportedRinseAtIndex(i, supportedRinse);
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
{
return CHIP_NO_ERROR;
}
ReturnErrorOnFailure(err);
ReturnErrorOnFailure(encoder.Encode(supportedRinse));
}
return CHIP_NO_ERROR;
});
}
} // namespace chip::app::Clusters