Skip to content

Commit b5e49ad

Browse files
authored
Merge branch 'master' into feature/app-install-flow-public
2 parents 6f340c5 + 024b09b commit b5e49ad

File tree

6 files changed

+407
-2
lines changed

6 files changed

+407
-2
lines changed

docs/guides/esp32/providers.md

+2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ Below are the providers that have been implemented:
1515
- [Device Info Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32DeviceInfoProvider.h#L31)
1616
This provider provides fixed labels, supported calendar types, and supported
1717
locales from the factory partition.
18+
- [Supported Modes](https://github.com/project-chip/connectedhomeip/blob/master/examples/platform/esp32/mode-support/static-supported-modes-manager.h#L28)
19+
This provider offers the supported modes for the mode-select cluster.
1820

1921
More information can be found in the [factory data guide](factory_data.md).
2022

examples/all-clusters-app/esp32/main/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ set(SRC_DIRS_LIST
3434
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
3535
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
3636
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/shell_extension"
37+
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/mode-support"
3738
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/server"
3839
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/icd/server"
3940
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/util"
@@ -105,6 +106,8 @@ set(SRC_DIRS_LIST
105106
)
106107

107108

109+
set(EXCLUDE_SRCS "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp")
110+
108111
if (CONFIG_ENABLE_PW_RPC)
109112
# Append additional directories for RPC build
110113
set(PRIV_INCLUDE_DIRS_LIST "${PRIV_INCLUDE_DIRS_LIST}"

examples/all-clusters-app/esp32/main/main.cpp

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <common/Esp32ThreadInit.h>
4242
#include <credentials/DeviceAttestationCredsProvider.h>
4343
#include <credentials/examples/DeviceAttestationCredsExample.h>
44+
#include <examples/platform/esp32/mode-support/static-supported-modes-manager.h>
4445
#include <platform/ESP32/ESP32Utils.h>
4546
#include <static-supported-temperature-levels.h>
4647

@@ -121,6 +122,13 @@ static void InitServer(intptr_t context)
121122
#if CONFIG_DEVICE_TYPE_M5STACK
122123
SetupPretendDevices();
123124
#endif
125+
CHIP_ERROR err =
126+
app::Clusters::ModeSelect::StaticSupportedModesManager::getStaticSupportedModesManagerInstance().InitEndpointArray(
127+
FIXED_ENDPOINT_COUNT);
128+
if (err != CHIP_NO_ERROR)
129+
{
130+
ESP_LOGE(TAG, "Failed to initialize endpoint array for supported-modes, err:%" CHIP_ERROR_FORMAT, err.Format());
131+
}
124132

125133
app::Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate);
126134
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 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 "static-supported-modes-manager.h"
20+
#include <platform/ESP32/ESP32Config.h>
21+
22+
using namespace chip;
23+
using namespace chip::app::Clusters;
24+
using namespace chip::DeviceLayer::Internal;
25+
using namespace chip::app::Clusters::ModeSelect;
26+
using chip::Protocols::InteractionModel::Status;
27+
28+
using ModeOptionStructType = Structs::ModeOptionStruct::Type;
29+
using SemanticTag = Structs::SemanticTagStruct::Type;
30+
31+
template <typename T>
32+
using List = app::DataModel::List<T>;
33+
34+
SupportedModesManager::ModeOptionsProvider * StaticSupportedModesManager::epModeOptionsProviderList = nullptr;
35+
36+
const StaticSupportedModesManager StaticSupportedModesManager::instance = StaticSupportedModesManager();
37+
38+
int StaticSupportedModesManager::mSize = 0;
39+
40+
CHIP_ERROR StaticSupportedModesManager::InitEndpointArray(int size)
41+
{
42+
if (epModeOptionsProviderList != nullptr)
43+
{
44+
ChipLogError(Zcl, "Cannot allocate epModeOptionsProviderList");
45+
return CHIP_ERROR_INCORRECT_STATE;
46+
}
47+
mSize = size;
48+
epModeOptionsProviderList = new SupportedModesManager::ModeOptionsProvider[mSize];
49+
if (epModeOptionsProviderList == nullptr)
50+
{
51+
ChipLogError(Zcl, "Failed to allocate memory to epModeOptionsProviderList");
52+
return CHIP_ERROR_NO_MEMORY;
53+
}
54+
for (int i = 0; i < mSize; i++)
55+
{
56+
epModeOptionsProviderList[i] = ModeOptionsProvider();
57+
}
58+
return CHIP_NO_ERROR;
59+
}
60+
61+
SupportedModesManager::ModeOptionsProvider StaticSupportedModesManager::getModeOptionsProvider(EndpointId endpointId) const
62+
{
63+
if (epModeOptionsProviderList[endpointId].begin() != nullptr && epModeOptionsProviderList[endpointId].end() != nullptr)
64+
{
65+
return ModeOptionsProvider(epModeOptionsProviderList[endpointId].begin(), epModeOptionsProviderList[endpointId].end());
66+
}
67+
68+
ModeOptionStructType * modeOptionStructList = nullptr;
69+
SemanticTag * semanticTags = nullptr;
70+
71+
char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
72+
uint32_t supportedModeCount = 0;
73+
74+
VerifyOrReturnValue(ESP32Config::KeyAllocator::SupportedModesCount(keyBuf, sizeof(keyBuf), endpointId) == CHIP_NO_ERROR,
75+
ModeOptionsProvider(nullptr, nullptr));
76+
ESP32Config::Key countKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
77+
VerifyOrReturnValue(ESP32Config::ReadConfigValue(countKey, supportedModeCount) == CHIP_NO_ERROR,
78+
ModeOptionsProvider(nullptr, nullptr));
79+
80+
modeOptionStructList = new ModeOptionStructType[supportedModeCount];
81+
if (modeOptionStructList == nullptr)
82+
{
83+
return ModeOptionsProvider(nullptr, nullptr);
84+
}
85+
86+
epModeOptionsProviderList[endpointId] = ModeOptionsProvider(modeOptionStructList, modeOptionStructList + supportedModeCount);
87+
88+
for (int index = 0; index < supportedModeCount; index++)
89+
{
90+
Structs::ModeOptionStruct::Type option;
91+
uint32_t supportedModeMode = 0;
92+
uint32_t semanticTagCount = 0;
93+
size_t outLen = 0;
94+
95+
memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength);
96+
VerifyOrReturnValue(ESP32Config::KeyAllocator::SupportedModesLabel(keyBuf, sizeof(keyBuf), endpointId, index) ==
97+
CHIP_NO_ERROR,
98+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
99+
ESP32Config::Key labelKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
100+
VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(labelKey, nullptr, 0, outLen) == CHIP_NO_ERROR,
101+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
102+
103+
char * modeLabel = new char[outLen + 1];
104+
if (modeLabel == nullptr)
105+
{
106+
CleanUp(endpointId);
107+
return ModeOptionsProvider(nullptr, nullptr);
108+
}
109+
110+
VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(labelKey, modeLabel, outLen + 1, outLen) == CHIP_NO_ERROR,
111+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
112+
113+
memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength);
114+
VerifyOrReturnValue(ESP32Config::KeyAllocator::SupportedModesValue(keyBuf, sizeof(keyBuf), endpointId, index) ==
115+
CHIP_NO_ERROR,
116+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
117+
ESP32Config::Key modeKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
118+
VerifyOrReturnValue(ESP32Config::ReadConfigValue(labelKey, supportedModeMode) == CHIP_NO_ERROR,
119+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
120+
121+
memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength);
122+
VerifyOrReturnValue(ESP32Config::KeyAllocator::SemanticTagsCount(keyBuf, sizeof(keyBuf), endpointId, index) ==
123+
CHIP_NO_ERROR,
124+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
125+
ESP32Config::Key stCountKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
126+
VerifyOrReturnValue(ESP32Config::ReadConfigValue(stCountKey, semanticTagCount) == CHIP_NO_ERROR,
127+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
128+
129+
semanticTags = new SemanticTag[semanticTagCount];
130+
if (semanticTags == nullptr)
131+
{
132+
CleanUp(endpointId);
133+
return ModeOptionsProvider(nullptr, nullptr);
134+
}
135+
for (auto stIndex = 0; stIndex < semanticTagCount; stIndex++)
136+
{
137+
138+
uint32_t semanticTagValue = 0;
139+
uint32_t semanticTagMfgCode = 0;
140+
SemanticTag tag;
141+
142+
memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength);
143+
VerifyOrReturnValue(ESP32Config::KeyAllocator::SemanticTagValue(keyBuf, sizeof(keyBuf), endpointId, index, stIndex) ==
144+
CHIP_NO_ERROR,
145+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
146+
ESP32Config::Key stValueKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
147+
VerifyOrReturnValue(ESP32Config::ReadConfigValue(stValueKey, semanticTagValue) == CHIP_NO_ERROR,
148+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
149+
150+
memset(keyBuf, 0, sizeof(char) * ESP32Config::kMaxConfigKeyNameLength);
151+
VerifyOrReturnValue(ESP32Config::KeyAllocator::SemanticTagMfgCode(keyBuf, sizeof(keyBuf), endpointId, index, stIndex) ==
152+
CHIP_NO_ERROR,
153+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
154+
ESP32Config::Key stMfgCodeKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
155+
VerifyOrReturnValue(ESP32Config::ReadConfigValue(stMfgCodeKey, semanticTagMfgCode) == CHIP_NO_ERROR,
156+
ModeOptionsProvider(nullptr, nullptr), CleanUp(endpointId));
157+
158+
tag.value = static_cast<uint16_t>(semanticTagValue);
159+
tag.mfgCode = static_cast<chip::VendorId>(semanticTagMfgCode);
160+
semanticTags[stIndex] = tag;
161+
}
162+
163+
option.label = chip::CharSpan::fromCharString(modeLabel);
164+
option.mode = static_cast<uint8_t>(supportedModeMode);
165+
option.semanticTags = DataModel::List<const SemanticTag>(semanticTags, semanticTagCount);
166+
167+
modeOptionStructList[index] = option;
168+
}
169+
170+
return ModeOptionsProvider(modeOptionStructList, modeOptionStructList + supportedModeCount);
171+
}
172+
173+
Status StaticSupportedModesManager::getModeOptionByMode(unsigned short endpointId, unsigned char mode,
174+
const ModeOptionStructType ** dataPtr) const
175+
{
176+
auto modeOptionsProvider = this->getModeOptionsProvider(endpointId);
177+
if (modeOptionsProvider.begin() == nullptr)
178+
{
179+
return Status::UnsupportedCluster;
180+
}
181+
auto * begin = modeOptionsProvider.begin();
182+
auto * end = modeOptionsProvider.end();
183+
184+
for (auto * it = begin; it != end; ++it)
185+
{
186+
auto & modeOption = *it;
187+
if (modeOption.mode == mode)
188+
{
189+
*dataPtr = &modeOption;
190+
return Status::Success;
191+
}
192+
}
193+
ChipLogProgress(Zcl, "Cannot find the mode %u", mode);
194+
return Status::InvalidCommand;
195+
}
196+
197+
const ModeSelect::SupportedModesManager * ModeSelect::getSupportedModesManager()
198+
{
199+
return &StaticSupportedModesManager::getStaticSupportedModesManagerInstance();
200+
}
201+
202+
void StaticSupportedModesManager::FreeSupportedModes(EndpointId endpointId) const
203+
{
204+
if (epModeOptionsProviderList[endpointId].begin() != nullptr)
205+
{
206+
auto * begin = epModeOptionsProviderList[endpointId].begin();
207+
auto * end = epModeOptionsProviderList[endpointId].end();
208+
for (auto * it = begin; it != end; ++it)
209+
{
210+
auto & modeOption = *it;
211+
delete[] modeOption.label.data();
212+
delete[] modeOption.semanticTags.data();
213+
}
214+
delete[] begin;
215+
}
216+
epModeOptionsProviderList[endpointId] = ModeOptionsProvider();
217+
}
218+
219+
void StaticSupportedModesManager::CleanUp(EndpointId endpointId) const
220+
{
221+
ChipLogError(Zcl, "Supported mode data is in incorrect format");
222+
FreeSupportedModes(endpointId);
223+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
*
3+
* Copyright (c) 2023 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+
#pragma once
20+
21+
#include <app/clusters/mode-select-server/supported-modes-manager.h>
22+
23+
namespace chip {
24+
namespace app {
25+
namespace Clusters {
26+
namespace ModeSelect {
27+
28+
class StaticSupportedModesManager : public chip::app::Clusters::ModeSelect::SupportedModesManager
29+
{
30+
private:
31+
using ModeOptionStructType = Structs::ModeOptionStruct::Type;
32+
using SemanticTag = Structs::SemanticTagStruct::Type;
33+
static int mSize;
34+
35+
static ModeOptionsProvider * epModeOptionsProviderList;
36+
37+
void FreeSupportedModes(EndpointId endpointId) const;
38+
39+
static const StaticSupportedModesManager instance;
40+
41+
public:
42+
// InitEndpointArray should be called only once in the application. Memory allocated to the
43+
// epModeOptionsProviderList will be needed for the lifetime of the program, so it's never deallocated.
44+
static CHIP_ERROR InitEndpointArray(int size);
45+
46+
// DeInitEndpointArray should be called only when application need to reallocate memory of
47+
// epModeOptionsProviderList ( Eg. Bridges ).
48+
static void DeInitEndpointArray()
49+
{
50+
delete[] epModeOptionsProviderList;
51+
epModeOptionsProviderList = nullptr;
52+
mSize = 0;
53+
}
54+
55+
SupportedModesManager::ModeOptionsProvider getModeOptionsProvider(EndpointId endpointId) const override;
56+
57+
Protocols::InteractionModel::Status getModeOptionByMode(EndpointId endpointId, uint8_t mode,
58+
const ModeOptionStructType ** dataPtr) const override;
59+
60+
void CleanUp(EndpointId endpointId) const;
61+
62+
StaticSupportedModesManager() {}
63+
64+
~StaticSupportedModesManager()
65+
{
66+
for (int i = 0; i < mSize; i++)
67+
{
68+
FreeSupportedModes(i);
69+
}
70+
}
71+
72+
static inline const StaticSupportedModesManager & getStaticSupportedModesManagerInstance() { return instance; }
73+
};
74+
75+
const SupportedModesManager * getSupportedModesManager();
76+
77+
} // namespace ModeSelect
78+
} // namespace Clusters
79+
} // namespace app
80+
} // namespace chip

0 commit comments

Comments
 (0)