Skip to content

Commit

Permalink
Add laundry-washer-controls-cluster server implementation (#27503)
Browse files Browse the repository at this point in the history
* Add laundry-washer-controls-cluster server implementation

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by clang-format

* Refine the definition

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by clang-format

* * Remove unnecessary code to read the attribute
* Remove the deleget
* Change the implementation to accept the attribute from the example

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by clang-format

* * Add "const" to the read-only attribute
* Remove the empty emberAfLaundryWasherControlsClusterInitCallback() that app-level can implement it

Signed-off-by: Chin-Ran Lo <[email protected]>

* * Add LaundryWasherServer get/set API to access the attributes

Signed-off-by: Chin-Ran Lo <[email protected]>

* * Add the API to get/set the SpinSpeeds and SupportedRinses attribute of LaundryWasherControl cluster
* Save/Load the SpinSpeeds and SupportedRinses attribute to/from the flash

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by whitespace

* Restyled by clang-format

* * Move the release / clean member functions to public
    - ReleaseSpinSpeedList / ClearSpinSpeedList
    - ReleaseSupportedRinsesList / ClearSupportedRinsesList

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by clang-format

* * Add back the delegate interface and report the items one by one
* Remove the data provider

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by whitespace

* Restyled by clang-format

* * Remove the unused definition for storage-key-alloc

Signed-off-by: Chin-Ran Lo <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.cpp

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.h

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.h

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.cpp

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.cpp

Co-authored-by: Boris Zbarsky <[email protected]>

* * Use MutableCharSpan to replace CharSpan
* Add to calculate the delegate id from endpoint

Signed-off-by: Chin-Ran Lo <[email protected]>

* Restyled by clang-format

* * Refine the comment

Signed-off-by: Chin-Ran Lo <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.h

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.h

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/clusters/laundry-washer-controls-server/laundry-washer-controls-server.h

Co-authored-by: Boris Zbarsky <[email protected]>

* Restyled by clang-format

---------

Signed-off-by: Chin-Ran Lo <[email protected]>
Co-authored-by: Restyled.io <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>
  • Loading branch information
3 people authored and pull[bot] committed Sep 11, 2023
1 parent 327bf48 commit 2442321
Show file tree
Hide file tree
Showing 4 changed files with 358 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
*
* 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/AttributeAccessInterface.h>

namespace chip {
namespace app {
namespace Clusters {
namespace LaundryWasherControls {

/** @brief
* Defines methods for implementing application-specific logic for the laundry washer controls cluster.
*/
class Delegate
{
public:
Delegate() = default;
virtual ~Delegate() = default;

/**
* Get the list of supported spin_speed list.
* Fills in the provided spin_speed at index `index` if there is one,
* or returns CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the index is out of range for the list of spin_speed.
* @param index The index of the spin_speed, with 0 representing the first one.
* @param spinSpeed The spin speed is filled.
*/
virtual CHIP_ERROR GetSpinSpeedAtIndex(size_t index, MutableCharSpan & spinSpeed) = 0;

/**
* Get the list of supported rinses list.
* Fills in the provided rinses at index `index` if there is one,
* or returns CHIP_ERROR_PROVIDER_LIST_EXHAUSTED if the index is out of range for the list of rinses.
* @param index The index of the supported rinses with 0 representing the first one.
* @param supportedRinse The supported rinse is filled.
*/
virtual CHIP_ERROR GetSupportedRinseAtIndex(size_t index, NumberOfRinsesEnum & supportedRinse) = 0;
};

} // namespace LaundryWasherControls
} // namespace Clusters
} // namespace app
} // namespace chip
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
/**
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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 <app/util/af.h>
#include <app/util/attribute-storage.h>
#include <app/util/config.h>

#include "laundry-washer-controls-delegate.h"
#include "laundry-washer-controls-server.h"
#include <app-common/zap-generated/attributes/Accessors.h>
#include <app-common/zap-generated/callback.h>
#include <app-common/zap-generated/cluster-objects.h>
#include <app-common/zap-generated/enums.h>
#include <app-common/zap-generated/ids/Attributes.h>
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandler.h>
#include <app/ConcreteAttributePath.h>
#include <app/ConcreteCommandPath.h>
#include <app/server/Server.h>
#include <app/util/error-mapping.h>
#include <lib/core/CHIPEncoding.h>

using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::LaundryWasherControls;
using namespace chip::app::Clusters::LaundryWasherControls::Attributes;
using chip::Protocols::InteractionModel::Status;

static constexpr size_t kLaundryWasherControlsDelegateTableSize =
EMBER_AF_LAUNDRY_WASHER_CONTROLS_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT;

// -----------------------------------------------------------------------------
// Delegate Implementation
//
namespace {
Delegate * gDelegateTable[kLaundryWasherControlsDelegateTableSize] = { nullptr };
}

namespace {
Delegate * GetDelegate(EndpointId endpoint)
{
uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, LaundryWasherControls::Id,
EMBER_AF_LAUNDRY_WASHER_CONTROLS_CLUSTER_SERVER_ENDPOINT_COUNT);
return (ep >= kLaundryWasherControlsDelegateTableSize ? nullptr : gDelegateTable[ep]);
}

} // namespace

LaundryWasherControlsServer LaundryWasherControlsServer::sInstance;

/**********************************************************
* LaundryWasherControlsServer public methods
*********************************************************/
void LaundryWasherControlsServer::SetDefaultDelegate(EndpointId endpoint, Delegate * delegate)
{
uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, LaundryWasherControls::Id,
EMBER_AF_LAUNDRY_WASHER_CONTROLS_CLUSTER_SERVER_ENDPOINT_COUNT);
// if endpoint is found
if (ep < kLaundryWasherControlsDelegateTableSize)
{
gDelegateTable[ep] = delegate;
}
}

LaundryWasherControlsServer & LaundryWasherControlsServer::Instance()
{
return sInstance;
}

EmberAfStatus LaundryWasherControlsServer::SetSpinSpeedCurrent(EndpointId endpointId,
DataModel::Nullable<uint8_t> newSpinSpeedCurrent)
{
DataModel::Nullable<uint8_t> spinSpeedCurrent;
EmberAfStatus res = SpinSpeedCurrent::Get(endpointId, spinSpeedCurrent);
if ((res == EMBER_ZCL_STATUS_SUCCESS) && (spinSpeedCurrent != newSpinSpeedCurrent))
{
res = SpinSpeedCurrent::Set(endpointId, newSpinSpeedCurrent);
}

return res;
}

EmberAfStatus LaundryWasherControlsServer::GetSpinSpeedCurrent(EndpointId endpointId,
DataModel::Nullable<uint8_t> & spinSpeedCurrent)
{
return SpinSpeedCurrent::Get(endpointId, spinSpeedCurrent);
}

EmberAfStatus LaundryWasherControlsServer::SetNumberOfRinses(EndpointId endpointId, NumberOfRinsesEnum newNumberOfRinses)
{
NumberOfRinsesEnum numberOfRinses;
EmberAfStatus res = NumberOfRinses::Get(endpointId, &numberOfRinses);

if ((res == EMBER_ZCL_STATUS_SUCCESS) && (numberOfRinses != newNumberOfRinses))
{
res = NumberOfRinses::Set(endpointId, newNumberOfRinses);
}

return res;
}

EmberAfStatus LaundryWasherControlsServer::GetNumberOfRinses(EndpointId endpointId, NumberOfRinsesEnum & numberOfRinses)
{
return NumberOfRinses::Get(endpointId, &numberOfRinses);
}

/**********************************************************
* LaundryWasherControlsServer private methods
*********************************************************/
CHIP_ERROR LaundryWasherControlsServer::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
if (aPath.mClusterId != LaundryWasherControls::Id)
{
// We shouldn't have been called at all.
return CHIP_ERROR_INVALID_ARGUMENT;
}
switch (aPath.mAttributeId)
{
case Attributes::SpinSpeeds::Id:
return ReadSpinSpeeds(aPath, aEncoder);
case Attributes::SupportedRinses::Id:
return ReadSupportedRinses(aPath, aEncoder);
default:
break;
}
return CHIP_NO_ERROR;
}

CHIP_ERROR LaundryWasherControlsServer::ReadSpinSpeeds(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder)
{
Delegate * delegate = GetDelegate(aPath.mEndpointId);
VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Delegate is nullptr"));

return aEncoder.EncodeList([delegate](const auto & encoder) -> CHIP_ERROR {
for (uint8_t i = 0; true; i++)
{
char buffer[kMaxSpinSpeedLength];
MutableCharSpan spinSpeed(buffer);
auto err = delegate->GetSpinSpeedAtIndex(i, spinSpeed);
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
{
return CHIP_NO_ERROR;
}
ReturnErrorOnFailure(err);
ReturnErrorOnFailure(encoder.Encode(spinSpeed));
}
});
}

CHIP_ERROR LaundryWasherControlsServer::ReadSupportedRinses(const ConcreteReadAttributePath & aPath,
AttributeValueEncoder & aEncoder)
{
Delegate * delegate = GetDelegate(aPath.mEndpointId);
VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INCORRECT_STATE, ChipLogError(Zcl, "Delegate is nullptr"));

return aEncoder.EncodeList([delegate](const auto & encoder) -> CHIP_ERROR {
for (uint8_t i = 0; true; i++)
{
NumberOfRinsesEnum supportedRinse;
auto err = delegate->GetSupportedRinseAtIndex(i, supportedRinse);
if (err == CHIP_ERROR_PROVIDER_LIST_EXHAUSTED)
{
return CHIP_NO_ERROR;
}
ReturnErrorOnFailure(err);
ReturnErrorOnFailure(encoder.Encode(supportedRinse));
}
});
}

/**********************************************************
* Register LaundryWasherControlsServer
*********************************************************/

void MatterLaundryWasherControlsPluginServerInitCallback()
{
LaundryWasherControlsServer & laundryWasherControlsServer = LaundryWasherControlsServer::Instance();
registerAttributeAccessOverride(&laundryWasherControlsServer);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
*
* Copyright (c) 2023 Project CHIP Authors
*
* 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 "laundry-washer-controls-delegate.h"
#include <app-common/zap-generated/cluster-objects.h>
#include <app/AttributeAccessInterface.h>
#include <app/util/af.h>

namespace chip {
namespace app {
namespace Clusters {
namespace LaundryWasherControls {

/**
* @brief LaundryWasherControls Server Plugin class
*/
class LaundryWasherControlsServer : public AttributeAccessInterface
{
public:
LaundryWasherControlsServer() : AttributeAccessInterface(Optional<EndpointId>::Missing(), LaundryWasherControls::Id) {}
static LaundryWasherControlsServer & Instance();

static constexpr uint8_t kMaxSpinSpeedLength = 64;

/**
* Set the default delegate of laundry washer server at endpoint x
* @param endpoint ID of the endpoint
* @param delegate The default delegate at the endpoint
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
*/
static void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate);

/**
* Init the laundry washer server.
* @param void
* @return CHIP_ERROR CHIP_NO_ERROR on success, or corresponding error code.
*/
// CHIP_ERROR Init();

/**
* @brief Set the attribute newSpinSpeedCurrent
*
* @param endpointId ID of the endpoint
* @param newSpinSpeedCurrent attribute SpinSpeedCurrent
* @return true on success, false on failure
*/
EmberAfStatus SetSpinSpeedCurrent(EndpointId endpointId, DataModel::Nullable<uint8_t> newSpinSpeedCurrent);

/**
* @brief Get the attribute newSpinSpeedCurrent
*
* @param endpointId ID of the endpoint
* @param SpinSpeedCurrent attribute SpinSpeedCurrent
* @return true on success, false on failure
*/
EmberAfStatus GetSpinSpeedCurrent(EndpointId endpointId, DataModel::Nullable<uint8_t> & spinSpeedCurrent);

/**
* @brief Set the attribute NumberOfRinses
*
* @param endpointId ID of the endpoint
* @param newNumberOfRinses attribute NumberOfRinses
* @return true on success, false on failure
*/
EmberAfStatus SetNumberOfRinses(EndpointId endpointId, NumberOfRinsesEnum newNumberOfRinses);

/**
* @brief Get the attribute NumberOfRinses
*
* @param endpointId ID of the endpoint
* @param NumberOfRinses attribute NumberOfRinses
* @return true on success, false on failure
*/
EmberAfStatus GetNumberOfRinses(EndpointId endpointId, NumberOfRinsesEnum & numberOfRinses);

private:
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
CHIP_ERROR ReadSpinSpeeds(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder);
CHIP_ERROR ReadSupportedRinses(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder);

static LaundryWasherControlsServer sInstance;
};

} // namespace LaundryWasherControls
} // namespace Clusters
} // namespace app
} // namespace chip
1 change: 1 addition & 0 deletions src/app/zap_cluster_list.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@
"UNIT_TESTING_CLUSTER": ["test-cluster-server"],
"USER_LABEL_CLUSTER": ["user-label-server"],
"WAKE_ON_LAN_CLUSTER": ["wake-on-lan-server"],
"LAUNDRY_WASHER_CONTROLS_CLUSTER": ["laundry-washer-controls-server"],
"WIFI_NETWORK_DIAGNOSTICS_CLUSTER": ["wifi-network-diagnostics-server"],
"WINDOW_COVERING_CLUSTER": ["window-covering-server"],
"ZLL_COMMISSIONING_CLUSTER": []
Expand Down

0 comments on commit 2442321

Please sign in to comment.