Skip to content

Commit 794cc19

Browse files
authored
Chef Oven Mode application code (project-chip#38106)
* Chef OvenMode: Application code * + * + * + * + * + * + * + * + * + * + * +
1 parent 012dfbc commit 794cc19

File tree

6 files changed

+258
-0
lines changed

6 files changed

+258
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include "chef-oven-mode.h"
20+
#include <app-common/zap-generated/attributes/Accessors.h>
21+
#include <app/reporting/reporting.h>
22+
#include <app/util/attribute-storage.h>
23+
#include <app/util/endpoint-config-api.h>
24+
#include <lib/support/logging/CHIPLogging.h>
25+
26+
#ifdef MATTER_DM_PLUGIN_OVEN_MODE_SERVER
27+
28+
using namespace chip;
29+
using namespace chip::app::Clusters;
30+
using namespace chip::app::Clusters::ModeBase;
31+
using chip::Protocols::InteractionModel::Status;
32+
template <typename T>
33+
using List = chip::app::DataModel::List<T>;
34+
using ModeTagStructType = chip::app::Clusters::detail::Structs::ModeTagStruct::Type;
35+
36+
namespace ChefOvenMode {
37+
38+
constexpr size_t kOvenModeTableSize = MATTER_DM_OVEN_MODE_CLUSTER_SERVER_ENDPOINT_COUNT;
39+
static_assert(kOvenModeTableSize <= kEmberInvalidEndpointIndex, "OvenMode table size error");
40+
41+
std::unique_ptr<OvenMode::ChefDelegate> gDelegateTable[kOvenModeTableSize];
42+
std::unique_ptr<ModeBase::Instance> gInstanceTable[kOvenModeTableSize];
43+
44+
/**
45+
* Initializes OvenMode cluster for the app (all endpoints).
46+
*/
47+
void InitChefOvenModeCluster()
48+
{
49+
const uint16_t endpointCount = emberAfEndpointCount();
50+
51+
for (uint16_t endpointIndex = 0; endpointIndex < endpointCount; endpointIndex++)
52+
{
53+
EndpointId endpointId = emberAfEndpointFromIndex(endpointIndex);
54+
if (endpointId == kInvalidEndpointId)
55+
{
56+
continue;
57+
}
58+
59+
// Check if endpoint has OvenMode cluster enabled
60+
uint16_t epIndex =
61+
emberAfGetClusterServerEndpointIndex(endpointId, OvenMode::Id, MATTER_DM_OVEN_MODE_CLUSTER_SERVER_ENDPOINT_COUNT);
62+
if (epIndex >= kOvenModeTableSize)
63+
continue;
64+
65+
gDelegateTable[epIndex] = std::make_unique<OvenMode::ChefDelegate>();
66+
gDelegateTable[epIndex]->Init();
67+
68+
uint32_t featureMap = 0;
69+
VerifyOrDieWithMsg(OvenMode::Attributes::FeatureMap::Get(endpointId, &featureMap) == Status::Success, DeviceLayer,
70+
"Failed to read OvenMode feature map for endpoint %d", endpointId);
71+
gInstanceTable[epIndex] =
72+
std::make_unique<ModeBase::Instance>(gDelegateTable[epIndex].get(), endpointId, OvenMode::Id, featureMap);
73+
gInstanceTable[epIndex]->Init();
74+
75+
ChipLogProgress(DeviceLayer, "Endpoint %d OvenMode Initialized.", endpointId);
76+
}
77+
}
78+
} // namespace ChefOvenMode
79+
80+
CHIP_ERROR OvenMode::ChefDelegate::Init()
81+
{
82+
return CHIP_NO_ERROR;
83+
}
84+
85+
void OvenMode::ChefDelegate::HandleChangeToMode(uint8_t NewMode, ModeBase::Commands::ChangeToModeResponse::Type & response)
86+
{
87+
EndpointId endpointId = mInstance->GetEndpointId();
88+
ChipLogDetail(DeviceLayer, "HandleChangeToMode: Endpoint %d", endpointId);
89+
response.status = to_underlying(ModeBase::StatusCode::kSuccess);
90+
}
91+
92+
CHIP_ERROR OvenMode::ChefDelegate::GetModeLabelByIndex(uint8_t modeIndex, chip::MutableCharSpan & label)
93+
{
94+
EndpointId endpointId = mInstance->GetEndpointId();
95+
ChipLogDetail(DeviceLayer, "GetModeLabelByIndex: Endpoint %d", endpointId);
96+
if (modeIndex >= MATTER_ARRAY_SIZE(kModeOptions))
97+
{
98+
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
99+
}
100+
return chip::CopyCharSpanToMutableCharSpan(kModeOptions[modeIndex].label, label);
101+
}
102+
103+
CHIP_ERROR OvenMode::ChefDelegate::GetModeValueByIndex(uint8_t modeIndex, uint8_t & value)
104+
{
105+
EndpointId endpointId = mInstance->GetEndpointId();
106+
ChipLogDetail(DeviceLayer, "GetModeValueByIndex: Endpoint %d", endpointId);
107+
if (modeIndex >= MATTER_ARRAY_SIZE(kModeOptions))
108+
{
109+
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
110+
}
111+
value = kModeOptions[modeIndex].mode;
112+
return CHIP_NO_ERROR;
113+
}
114+
115+
CHIP_ERROR OvenMode::ChefDelegate::GetModeTagsByIndex(uint8_t modeIndex, List<ModeTagStructType> & tags)
116+
{
117+
EndpointId endpointId = mInstance->GetEndpointId();
118+
ChipLogDetail(DeviceLayer, "GetModeTagsByIndex: Endpoint %d", endpointId);
119+
if (modeIndex >= MATTER_ARRAY_SIZE(kModeOptions))
120+
{
121+
return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED;
122+
}
123+
124+
if (tags.size() < kModeOptions[modeIndex].modeTags.size())
125+
{
126+
return CHIP_ERROR_INVALID_ARGUMENT;
127+
}
128+
129+
std::copy(kModeOptions[modeIndex].modeTags.begin(), kModeOptions[modeIndex].modeTags.end(), tags.begin());
130+
tags.reduce_size(kModeOptions[modeIndex].modeTags.size());
131+
132+
return CHIP_NO_ERROR;
133+
}
134+
135+
#endif // MATTER_DM_PLUGIN_OVEN_MODE_SERVER
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
*
3+
* Copyright (c) 2025 Project CHIP Authors
4+
* All rights reserved.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
#include <app/clusters/mode-base-server/mode-base-server.h>
20+
#include <app/util/config.h>
21+
#include <cstring>
22+
#include <utility>
23+
24+
#pragma once
25+
26+
#ifdef MATTER_DM_PLUGIN_OVEN_MODE_SERVER
27+
28+
namespace chip {
29+
namespace app {
30+
namespace Clusters {
31+
namespace OvenMode {
32+
33+
const uint8_t ModeBake = 0;
34+
const uint8_t ModeConvection = 1;
35+
const uint8_t ModeGrill = 2;
36+
const uint8_t ModeRoast = 3;
37+
const uint8_t ModeClean = 4;
38+
const uint8_t ModeConvectionBake = 5;
39+
const uint8_t ModeConvectionRoast = 6;
40+
const uint8_t ModeWarming = 7;
41+
const uint8_t ModeProofing = 8;
42+
43+
class ChefDelegate : public ModeBase::Delegate
44+
{
45+
private:
46+
using ModeTagStructType = detail::Structs::ModeTagStruct::Type;
47+
ModeTagStructType ModeTagsBake[1] = { { .value = to_underlying(ModeTag::kBake) } };
48+
ModeTagStructType ModeTagsConvection[1] = { { .value = to_underlying(ModeTag::kConvection) } };
49+
ModeTagStructType ModeTagsGrill[1] = { { .value = to_underlying(ModeTag::kGrill) } };
50+
ModeTagStructType ModeTagsRoast[1] = { { .value = to_underlying(ModeTag::kRoast) } };
51+
ModeTagStructType ModeTagsClean[1] = { { .value = to_underlying(ModeTag::kClean) } };
52+
ModeTagStructType ModeTagsConvectionBake[1] = { { .value = to_underlying(ModeTag::kConvectionBake) } };
53+
ModeTagStructType ModeTagsConvectionRoast[1] = { { .value = to_underlying(ModeTag::kConvectionRoast) } };
54+
ModeTagStructType ModeTagsWarming[1] = { { .value = to_underlying(ModeTag::kWarming) } };
55+
ModeTagStructType ModeTagsProofing[1] = { { .value = to_underlying(ModeTag::kProofing) } };
56+
57+
const detail::Structs::ModeOptionStruct::Type kModeOptions[9] = {
58+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Bake"),
59+
.mode = ModeBake,
60+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsBake) },
61+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Convection"),
62+
.mode = ModeConvection,
63+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsConvection) },
64+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Grill"),
65+
.mode = ModeGrill,
66+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsGrill) },
67+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Roast"),
68+
.mode = ModeRoast,
69+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsRoast) },
70+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Clean"),
71+
.mode = ModeClean,
72+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsClean) },
73+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Convection Bake"),
74+
.mode = ModeConvectionBake,
75+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsConvectionBake) },
76+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Convection Roast"),
77+
.mode = ModeConvectionRoast,
78+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsConvectionRoast) },
79+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Warming"),
80+
.mode = ModeWarming,
81+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsWarming) },
82+
detail::Structs::ModeOptionStruct::Type{ .label = CharSpan::fromCharString("Proofing"),
83+
.mode = ModeProofing,
84+
.modeTags = DataModel::List<const ModeTagStructType>(ModeTagsProofing) },
85+
};
86+
87+
public:
88+
CHIP_ERROR Init() override;
89+
90+
CHIP_ERROR GetModeLabelByIndex(uint8_t modeIndex, MutableCharSpan & label) override;
91+
92+
CHIP_ERROR GetModeValueByIndex(uint8_t modeIndex, uint8_t & value) override;
93+
94+
CHIP_ERROR GetModeTagsByIndex(uint8_t modeIndex, DataModel::List<detail::Structs::ModeTagStruct::Type> & modeTags) override;
95+
96+
void HandleChangeToMode(uint8_t NewMode, ModeBase::Commands::ChangeToModeResponse::Type & response) override;
97+
98+
~ChefDelegate() = default;
99+
ChefDelegate() = default;
100+
};
101+
102+
} // namespace OvenMode
103+
} // namespace Clusters
104+
} // namespace app
105+
} // namespace chip
106+
107+
namespace ChefOvenMode {
108+
void InitChefOvenModeCluster();
109+
} // namespace ChefOvenMode
110+
111+
#endif // MATTER_DM_PLUGIN_OVEN_MODE_SERVER

examples/chef/common/stubs.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ const Clusters::Descriptor::Structs::SemanticTagStruct::Type freezerTagList[]
8585
#include "window-covering/chef-window-covering.h"
8686
#endif // MATTER_DM_PLUGIN_WINDOW_COVERING_SERVER
8787

88+
#ifdef MATTER_DM_PLUGIN_OVEN_MODE_SERVER
89+
#include "oven-mode/chef-oven-mode.h"
90+
#endif // MATTER_DM_PLUGIN_OVEN_MODE_SERVER
91+
8892
Protocols::InteractionModel::Status emberAfExternalAttributeReadCallback(EndpointId endpoint, ClusterId clusterId,
8993
const EmberAfAttributeMetadata * attributeMetadata,
9094
uint8_t * buffer, uint16_t maxReadLength)
@@ -364,6 +368,11 @@ void ApplicationInit()
364368
ChipLogProgress(NotSpecified, "Initializing WindowCovering cluster delegate.");
365369
ChefWindowCovering::InitChefWindowCoveringCluster();
366370
#endif // MATTER_DM_PLUGIN_WINDOW_COVERING_SERVER
371+
372+
#ifdef MATTER_DM_PLUGIN_OVEN_MODE_SERVER
373+
ChipLogProgress(NotSpecified, "Initializing OvenMode cluster.");
374+
ChefOvenMode::InitChefOvenModeCluster();
375+
#endif // MATTER_DM_PLUGIN_OVEN_MODE_SERVER
367376
}
368377

369378
void ApplicationShutdown()

examples/chef/esp32/main/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ set(SRC_DIRS_LIST
4848
"${CHEF}/common/clusters/low-power/"
4949
"${CHEF}/common/clusters/media-input/"
5050
"${CHEF}/common/clusters/media-playback/"
51+
"${CHEF}/common/clusters/oven-mode/"
5152
"${CHEF}/common/clusters/refrigerator-and-temperature-controlled-cabinet-mode/"
5253
"${CHEF}/common/clusters/resource-monitoring/"
5354
"${CHEF}/common/clusters/switch/"

examples/chef/linux/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ executable("${sample_name}") {
6060
"${project_dir}/common/clusters/low-power/LowPowerManager.cpp",
6161
"${project_dir}/common/clusters/media-input/MediaInputManager.cpp",
6262
"${project_dir}/common/clusters/media-playback/MediaPlaybackManager.cpp",
63+
"${project_dir}/common/clusters/oven-mode/chef-oven-mode.cpp",
6364
"${project_dir}/common/clusters/refrigerator-and-temperature-controlled-cabinet-mode/tcc-mode.cpp",
6465
"${project_dir}/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp",
6566
"${project_dir}/common/clusters/switch/SwitchEventHandler.cpp",

examples/chef/nrfconnect/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ target_sources(app PRIVATE
9797
${CHEF}/common/clusters/low-power/LowPowerManager.cpp
9898
${CHEF}/common/clusters/media-input/MediaInputManager.cpp
9999
${CHEF}/common/clusters/media-playback/MediaPlaybackManager.cpp
100+
${CHEF}/common/clusters/oven-mode/chef-oven-mode.cpp
100101
${CHEF}/common/clusters/refrigerator-and-temperature-controlled-cabinet-mode/tcc-mode.cpp
101102
${CHEF}/common/clusters/resource-monitoring/chef-resource-monitoring-delegates.cpp
102103
${CHEF}/common/clusters/switch/SwitchEventHandler.cpp

0 commit comments

Comments
 (0)