diff --git a/examples/refrigerator-app/silabs/BUILD.gn b/examples/refrigerator-app/silabs/BUILD.gn index 6f4faa35ccd553..9e63c6c10e164b 100644 --- a/examples/refrigerator-app/silabs/BUILD.gn +++ b/examples/refrigerator-app/silabs/BUILD.gn @@ -140,6 +140,7 @@ silabs_executable("refrigerator_app") { "src/AppTask.cpp", "src/RefrigeratorManager.cpp", "src/ZclCallbacks.cpp", + "src/refrigerator-and-temperature-controlled-cabinet-mode.cpp", ] if (use_temp_sensor) { diff --git a/examples/refrigerator-app/silabs/include/RefrigeratorManager.h b/examples/refrigerator-app/silabs/include/RefrigeratorManager.h index 9c6167cacc7789..5a794d508a374b 100644 --- a/examples/refrigerator-app/silabs/include/RefrigeratorManager.h +++ b/examples/refrigerator-app/silabs/include/RefrigeratorManager.h @@ -39,15 +39,6 @@ using namespace chip::app::Clusters::RefrigeratorAndTemperatureControlledCabinet using namespace chip::DeviceLayer; using chip::Protocols::InteractionModel::Status; -// AppCluster Spec Table 85. -enum SUPPORTED_MODES -{ - NORMAL = 0x0000, - ENERGY_SAVE = 0x0004, - RAPID_COOL = 0x4000, - RAPID_FREEZE = 0x4001, -}; - class RefrigeratorManager { public: diff --git a/examples/refrigerator-app/silabs/include/refrigerator-and-temperature-controlled-cabinet-mode.h b/examples/refrigerator-app/silabs/include/refrigerator-and-temperature-controlled-cabinet-mode.h new file mode 100644 index 00000000000000..9a0d2252359959 --- /dev/null +++ b/examples/refrigerator-app/silabs/include/refrigerator-and-temperature-controlled-cabinet-mode.h @@ -0,0 +1,71 @@ +/* + * + * Copyright (c) 2024 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 +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { + +namespace RefrigeratorAndTemperatureControlledCabinetMode { + +const uint8_t ModeRapidCool = 0; +const uint8_t ModeRapidFreeze = 1; + +/// This is an application level delegate to handle LaundryWasherMode commands according to the specific business logic. +class RefrigeratorAndTemperatureControlledCabinetModeDelegate : public ModeBase::Delegate +{ +private: + using ModeTagStructType = detail::Structs::ModeTagStruct::Type; + ModeTagStructType modeTagsRapidCool[1] = { { .value = to_underlying(ModeTag::kRapidCool) } }; + ModeTagStructType modeTagsRapidFreeze[2] = { { .value = to_underlying(ModeBase::ModeTag::kMax) }, + { .value = to_underlying(ModeTag::kRapidFreeze) } }; + + const detail::Structs::ModeOptionStruct::Type kModeOptions[2] = { + detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Rapid Cool"), + .mode = ModeRapidCool, + .modeTags = DataModel::List(modeTagsRapidCool) }, + detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Rapid Freeze"), + .mode = ModeRapidFreeze, + .modeTags = DataModel::List(modeTagsRapidFreeze) }, + }; + + CHIP_ERROR Init() override; + void HandleChangeToMode(uint8_t mode, ModeBase::Commands::ChangeToModeResponse::Type & response) override; + CHIP_ERROR GetModeLabelByIndex(uint8_t modeIndex, MutableCharSpan & label) override; + CHIP_ERROR GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) override; + CHIP_ERROR GetModeTagsByIndex(uint8_t modeIndex, DataModel::List & tags) override; + +public: + ~RefrigeratorAndTemperatureControlledCabinetModeDelegate() override = default; +}; + +ModeBase::Instance * Instance(); + +void Shutdown(); + +} // namespace LaundryWasherMode + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/refrigerator-app/silabs/src/ZclCallbacks.cpp b/examples/refrigerator-app/silabs/src/ZclCallbacks.cpp index e0d578dd644d09..3f56f024c93145 100644 --- a/examples/refrigerator-app/silabs/src/ZclCallbacks.cpp +++ b/examples/refrigerator-app/silabs/src/ZclCallbacks.cpp @@ -70,17 +70,6 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & } } -/** @brief Refrigerator And TemperatureControlled Cabinet Mode Cluster Init - * - * This function is called when a specific cluster is initialized. It gives the - * application an opportunity to take care of cluster initialization procedures. - * It is called exactly once for each endpoint where cluster is present. - * - * @param endpoint Ver.: always - * - */ -void emberAfRefrigeratorAndTemperatureControlledCabinetModeClusterInitCallback(EndpointId endpoint) {} - /** @brief Refrigerator Alarm Cluster Init * * This function is called when a specific cluster is initialized. It gives the @@ -102,25 +91,3 @@ void emberAfRefrigeratorAlarmClusterInitCallback(EndpointId endpoint) {} * */ void emberAfTemperatureControlClusterInitCallback(EndpointId endpoint) {} - -// /** -// * @brief Handles the SetTemperature command for the Temperature Control Cluster. -// * -// * This function is called when the SetTemperature command is received from a client. -// * It is responsible for setting the temperature for the cabinet as per the command data. -// * -// * @param CommandHandler commandObj Pointer to the command handler object. -// * @param const ConcreteCommandPath commandPath The path of the command received. -// * @param const DecodableType & commandData -// * The data decoded from the SetTemperature command, which includes the desired temperature. -// * -// * @return bool Returns true if the command was handled successfully, false otherwise. -// * -// * @note The actual implementation to set the temperature is yet to be added. -// */ -// bool emberAfTemperatureControlClusterSetTemperatureCallback( -// chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, -// const chip::app::Clusters::TemperatureControl::Commands::SetTemperature::DecodableType & commandData) { -// // TODO: Add implementation to set the temperature for the cabinet -// return true; -// } diff --git a/examples/refrigerator-app/silabs/src/refrigerator-and-temperature-controlled-cabinet-mode.cpp b/examples/refrigerator-app/silabs/src/refrigerator-and-temperature-controlled-cabinet-mode.cpp new file mode 100644 index 00000000000000..75a558b9be9f66 --- /dev/null +++ b/examples/refrigerator-app/silabs/src/refrigerator-and-temperature-controlled-cabinet-mode.cpp @@ -0,0 +1,105 @@ +/* + * + * Copyright (c) 2024 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 +#include + +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::RefrigeratorAndTemperatureControlledCabinetMode; +using chip::Protocols::InteractionModel::Status; +template +using List = chip::app::DataModel::List; +using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::Type; + +static RefrigeratorAndTemperatureControlledCabinetModeDelegate * gRefrigeratorAndTemperatureControlledCabinetModeDelegate = nullptr; +static ModeBase::Instance * gRefrigeratorAndTemperatureControlledCabinetModeInstance = nullptr; + +CHIP_ERROR RefrigeratorAndTemperatureControlledCabinetModeDelegate::Init() +{ + return CHIP_NO_ERROR; +} + +void RefrigeratorAndTemperatureControlledCabinetModeDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands::ChangeToModeResponse::Type & response) +{ + response.status = to_underlying(ModeBase::StatusCode::kSuccess); +} + +CHIP_ERROR RefrigeratorAndTemperatureControlledCabinetModeDelegate::GetModeLabelByIndex(uint8_t modeIndex, chip::MutableCharSpan & label) +{ + if (modeIndex >= ArraySize(kModeOptions)) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + return chip::CopyCharSpanToMutableCharSpan(kModeOptions[modeIndex].label, label); +} + +CHIP_ERROR RefrigeratorAndTemperatureControlledCabinetModeDelegate::GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) +{ + if (modeIndex >= ArraySize(kModeOptions)) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + value = kModeOptions[modeIndex].mode; + return CHIP_NO_ERROR; +} + +CHIP_ERROR RefrigeratorAndTemperatureControlledCabinetModeDelegate::GetModeTagsByIndex(uint8_t modeIndex, List & tags) +{ + if (modeIndex >= ArraySize(kModeOptions)) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + + if (tags.size() < kModeOptions[modeIndex].modeTags.size()) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + std::copy(kModeOptions[modeIndex].modeTags.begin(), kModeOptions[modeIndex].modeTags.end(), tags.begin()); + tags.reduce_size(kModeOptions[modeIndex].modeTags.size()); + + return CHIP_NO_ERROR; +} + +ModeBase::Instance * RefrigeratorAndTemperatureControlledCabinetMode::Instance() +{ + return gRefrigeratorAndTemperatureControlledCabinetModeInstance; +} + +void RefrigeratorAndTemperatureControlledCabinetMode::Shutdown() +{ + if (gRefrigeratorAndTemperatureControlledCabinetModeInstance != nullptr) + { + delete gRefrigeratorAndTemperatureControlledCabinetModeInstance; + gRefrigeratorAndTemperatureControlledCabinetModeInstance = nullptr; + } + if (gRefrigeratorAndTemperatureControlledCabinetModeDelegate != nullptr) + { + delete gRefrigeratorAndTemperatureControlledCabinetModeDelegate; + gRefrigeratorAndTemperatureControlledCabinetModeDelegate = nullptr; + } +} + +void emberAfRefrigeratorAndTemperatureControlledCabinetModeClusterInitCallback(chip::EndpointId endpointId) +{ + VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. + VerifyOrDie(gRefrigeratorAndTemperatureControlledCabinetModeDelegate == nullptr && gRefrigeratorAndTemperatureControlledCabinetModeInstance == nullptr); + gRefrigeratorAndTemperatureControlledCabinetModeDelegate = new RefrigeratorAndTemperatureControlledCabinetMode::RefrigeratorAndTemperatureControlledCabinetModeDelegate; + gRefrigeratorAndTemperatureControlledCabinetModeInstance = + new ModeBase::Instance(gRefrigeratorAndTemperatureControlledCabinetModeDelegate, 0x1, RefrigeratorAndTemperatureControlledCabinetMode::Id, chip::to_underlying(Feature::kOnOff)); + gRefrigeratorAndTemperatureControlledCabinetModeInstance->Init(); +}