Skip to content

Commit

Permalink
Add back the original Device info provider which reads from the nvs
Browse files Browse the repository at this point in the history
Add StaticESP32DeviceInfoProvider along with APIs to set data

Remove changes from example and add a guide along with usage
  • Loading branch information
shubhamdp committed Apr 18, 2024
1 parent 65f2f09 commit b6251a3
Show file tree
Hide file tree
Showing 11 changed files with 468 additions and 139 deletions.
1 change: 1 addition & 0 deletions docs/guides/esp32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ example on ESP32 series of SoCs
- [Matter OTA](ota.md)
- [Generating and Using ESP Secure Cert Partition](secure_cert_partition.md)
- [BLE Settings](ble_settings.md)
- [Providers](providers.md)
6 changes: 6 additions & 0 deletions docs/guides/esp32/factory_data.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ ESP32 specific implementation of `DeviceInstanceInfoProvider`.
[Component config → CHIP Device Layer → Commissioning options → Use ESP32 Device
Instance Info Provider]

Enable config option `CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER` to use ESP32
specific implementation of `DeviceInfoProvider`.

[Component config → CHIP Device Layer → Commissioning options → Use ESP32 Device
Info Provider]

ESP32 implementation reads factory data from nvs partition, chip-factory data
must be flashed into the configured nvs partition. Factory partition can be
configured using `CONFIG_CHIP_FACTORY_NAMESPACE_PARTITION_LABEL` option, default
Expand Down
76 changes: 76 additions & 0 deletions docs/guides/esp32/providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
## Providers Implemented for ESP32 Platform

The ESP32 platform has implemented several providers that can be used with data
stored in the factory or by setting fixed data.

Below are the providers that have been implemented:

- [Commissionable Data Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32FactoryDataProvider.h#L47)
This provider reads the discriminator and setup pincode related parameters
from the factory partition.
- [Device Attestation Credentials Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32FactoryDataProvider.h#L56)
This provider manages the attestation data.
- [Device Instance Info Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32FactoryDataProvider.h#L86)
This provider reads basic device information from the factory partition.
- [Device Info Provider](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32DeviceInfoProvider.h#L31)
This provider provides fixed labels, supported calendar types, and supported
locales from the factory partition.
- [Supported Modes](https://github.com/project-chip/connectedhomeip/blob/master/examples/platform/esp32/mode-support/static-supported-modes-manager.h#L28)
This provider offers the supported modes for the mode-select cluster.

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

### Device Info Provider

Currently, there are two implementations for this provider:

1. [Reads data stored in the factory partition](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/ESP32FactoryDataProvider.h#L56)
_(This will be deprecated in the future)_
2. [Provides APIs to set fixed data that gets read later](https://github.com/project-chip/connectedhomeip/blob/master/src/platform/ESP32/StaticESP32DeviceInfoProvider.h)

- New products should use the `StaticESP32DeviceInfoProvider`. Utilize the
`Set...()` APIs to set the fixed data.
- Existing products using the first implementation can continue to use it if
they do not wish to change the data.
- For products using the first implementation and wanting to change the fixed
data via OTA, they should switch to the second implementation in the OTA
image and use the `Set...()` APIs to set the fixed data.

#### Example:

```cpp
#include <platform/ESP32/StaticESP32FactoryDataProvider.h>

DeviceLayer::StaticESP32DeviceInfoProvider deviceInfoProvider;

// Define array for Supported Calendar Types
using namespace chip::app::Clusters::TimeFormatLocalization::CalendarTypeEnum;
CalendarTypeEnum supportedCalendarTypes[] = {
CalendarTypeEnum::kGregorian, CalendarTypeEnum::kCoptic,
CalendarTypeEnum::kEthiopian, CalendarTypeEnum::kChinese,
};

// Define array for Supported Locales
const char* supportedLocales[] = {
"en-US",
"en-EU",
};

// Define array for Fixed labels { EndpointId, Label, Value }
struct StaticESP32DeviceInfoProvider::FixedLabelEntry fixedLabels[] = {
{ 0, "Room", "Bedroom 2" },
{ 0, "Orientation", "North" },
{ 0, "Direction", "Up" },
};

Span<CalendarTypeEnum> sSupportedCalendarTypes(supportedCalendarTypes);
Span<const char*> sSupportedLocales(supportedLocales);
Span<StaticESP32DeviceInfoProvider::FixedLabelEntry> sFixedLabels(fixedLabels);

{
deviceInfoProvider.SetSupportedLocales(sSupportedLocales);
deviceInfoProvider.SetSupportedCalendarTypes(sSupportedCalendarTypes);
deviceInfoProvider.SetFixedLabels(sFixedLabels);
DeviceLayer::SetDeviceInfoProvider(&deviceInfoProvider);
}
```
31 changes: 0 additions & 31 deletions examples/lighting-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,31 +92,6 @@ DeviceLayer::ESP32FactoryDataProvider sFactoryDataProvider;

#if CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
DeviceLayer::ESP32DeviceInfoProvider gExampleDeviceInfoProvider;

using namespace app::Clusters::TimeFormatLocalization;
using CalendarType = app::Clusters::TimeFormatLocalization::CalendarTypeEnum;

CalendarType supportedCalendarTyppes[] = {
CalendarTypeEnum::kGregorian, CalendarTypeEnum::kCoptic, CalendarTypeEnum::kBuddhist,
CalendarTypeEnum::kEthiopian, CalendarTypeEnum::kChinese,
};

CharSpan supportedLocales[] = {
CharSpan::fromCharString("en-US"),
CharSpan::fromCharString("en-EU"),
CharSpan::fromCharString("en-IN"),
};

struct ESP32DeviceInfoProvider::FixedLabelEntry fixedLabels[] = {
{ 0, CharSpan::fromCharString("Room"), CharSpan::fromCharString("Bedroom 2") },
{ 0, CharSpan::fromCharString("Orientation"), CharSpan::fromCharString("North") },
{ 0, CharSpan::fromCharString("Direction"), CharSpan::fromCharString("Up") },
};

Span<CalendarType> sSupportedCalendarTypes(supportedCalendarTyppes);
Span<CharSpan> sSupportedLocales(supportedLocales);
Span<ESP32DeviceInfoProvider::FixedLabelEntry> sFixedLabels(fixedLabels);

#else
DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
Expand Down Expand Up @@ -217,12 +192,6 @@ extern "C" void app_main()
}
#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI

#ifdef CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER
gExampleDeviceInfoProvider.SetSupportedLocales(sSupportedLocales);
gExampleDeviceInfoProvider.SetSupportedCalendarTypes(sSupportedCalendarTypes);
gExampleDeviceInfoProvider.SetFixedLabels(sFixedLabels);
#endif // CONFIG_ENABLE_ESP32_DEVICE_INFO_PROVIDER

DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);

CHIPDeviceManager & deviceMgr = CHIPDeviceManager::GetInstance();
Expand Down
2 changes: 2 additions & 0 deletions src/platform/ESP32/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,8 @@ static_library("ESP32") {
sources += [
"ESP32DeviceInfoProvider.cpp",
"ESP32DeviceInfoProvider.h",
"StaticESP32DeviceInfoProvider.cpp",
"StaticESP32DeviceInfoProvider.h",
]
}

Expand Down
2 changes: 2 additions & 0 deletions src/platform/ESP32/ESP32Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ const ESP32Config::Key ESP32Config::kConfigKey_ProductId = { kConfig
const ESP32Config::Key ESP32Config::kConfigKey_ProductName = { kConfigNamespace_ChipFactory, "product-name" };
const ESP32Config::Key ESP32Config::kConfigKey_ProductLabel = { kConfigNamespace_ChipFactory, "product-label" };
const ESP32Config::Key ESP32Config::kConfigKey_ProductURL = { kConfigNamespace_ChipFactory, "product-url" };
const ESP32Config::Key ESP32Config::kConfigKey_SupportedCalTypes = { kConfigNamespace_ChipFactory, "cal-types" };
const ESP32Config::Key ESP32Config::kConfigKey_SupportedLocaleSize = { kConfigNamespace_ChipFactory, "locale-sz" };
const ESP32Config::Key ESP32Config::kConfigKey_RotatingDevIdUniqueId = { kConfigNamespace_ChipFactory, "rd-id-uid" };
const ESP32Config::Key ESP32Config::kConfigKey_LocationCapability = { kConfigNamespace_ChipFactory, "loc-capability" };

Expand Down
22 changes: 22 additions & 0 deletions src/platform/ESP32/ESP32Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,29 @@ inline bool ESP32Config::Key::operator==(const Key & other) const
class ESP32Config::KeyAllocator
{
public:
static CHIP_ERROR Locale(char * key, size_t size, uint16_t index)
{
VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
return snprintf(key, size, "locale/%x", index) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
}
static CHIP_ERROR FixedLabelCount(char * key, size_t size, uint16_t endpoint)
{
VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
return snprintf(key, size, "fl-sz/%x", endpoint) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
}
static CHIP_ERROR FixedLabelKey(char * key, size_t size, uint16_t endpoint, uint16_t index)
{
VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
return snprintf(key, size, "fl-k/%x/%x", endpoint, index) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
}
static CHIP_ERROR FixedLabelValue(char * key, size_t size, uint16_t endpoint, uint16_t index)
{
VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
return snprintf(key, size, "fl-v/%x/%x", endpoint, index) > 0 ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL;
}

// Supported modes

static CHIP_ERROR SupportedModesCount(char * key, size_t size, uint16_t endpoint)
{
VerifyOrReturnError(key, CHIP_ERROR_INVALID_ARGUMENT);
Expand Down
127 changes: 87 additions & 40 deletions src/platform/ESP32/ESP32DeviceInfoProvider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,46 +41,58 @@ ESP32DeviceInfoProvider & ESP32DeviceInfoProvider::GetDefaultInstance(void)

DeviceInfoProvider::FixedLabelIterator * ESP32DeviceInfoProvider::IterateFixedLabel(EndpointId endpoint)
{
return chip::Platform::New<FixedLabelIteratorImpl>(endpoint, mFixedLabels);
return chip::Platform::New<FixedLabelIteratorImpl>(endpoint);
}

ESP32DeviceInfoProvider::FixedLabelIteratorImpl::FixedLabelIteratorImpl(EndpointId endpoint, const Span<FixedLabelEntry> & labels) :
mEndpoint(endpoint), mLabels(labels)
ESP32DeviceInfoProvider::FixedLabelIteratorImpl::FixedLabelIteratorImpl(EndpointId endpoint) : mEndpoint(endpoint)
{
mIndex = 0;
}

size_t ESP32DeviceInfoProvider::FixedLabelIteratorImpl::Count()
{
size_t count = 0;
for (size_t i = 0; i < mLabels.size(); i++)
{
const FixedLabelEntry & entry = mLabels.data()[i];
char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
uint32_t count = 0;

if (entry.endpointId == mEndpoint)
{
count++;
}
}
VerifyOrReturnValue(ESP32Config::KeyAllocator::FixedLabelCount(keyBuf, sizeof(keyBuf), mEndpoint) == CHIP_NO_ERROR, 0);
ESP32Config::Key key(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
VerifyOrReturnValue(ESP32Config::ReadConfigValue(key, count) == CHIP_NO_ERROR, 0);
return count;
}

bool ESP32DeviceInfoProvider::FixedLabelIteratorImpl::Next(FixedLabelType & output)
{
ChipLogDetail(DeviceLayer, "Get the fixed label with index:%u at endpoint:%d", static_cast<unsigned>(mIndex), mEndpoint);

while (mIndex < mLabels.size())
{
const FixedLabelEntry & entry = mLabels.data()[mIndex++];
if (entry.endpointId == mEndpoint)
{
output.label = entry.label;
output.value = entry.value;
return true;
}
}
char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
size_t keyOutLen = 0;
size_t valueOutLen = 0;

memset(mFixedLabelNameBuf, 0, sizeof(mFixedLabelNameBuf));
memset(mFixedLabelValueBuf, 0, sizeof(mFixedLabelValueBuf));

VerifyOrReturnValue(
ESP32Config::KeyAllocator::FixedLabelKey(keyBuf, sizeof(keyBuf), mEndpoint, static_cast<uint16_t>(mIndex)) == CHIP_NO_ERROR,
false);
ESP32Config::Key keyKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
VerifyOrReturnValue(
ESP32Config::ReadConfigValueStr(keyKey, mFixedLabelNameBuf, sizeof(mFixedLabelNameBuf), keyOutLen) == CHIP_NO_ERROR, false);

VerifyOrReturnValue(ESP32Config::KeyAllocator::FixedLabelValue(keyBuf, sizeof(keyBuf), mEndpoint,
static_cast<uint16_t>(mIndex)) == CHIP_NO_ERROR,
false);
ESP32Config::Key valueKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(valueKey, mFixedLabelValueBuf, sizeof(mFixedLabelValueBuf), valueOutLen) ==
CHIP_NO_ERROR,
false);

output.label = CharSpan::fromCharString(mFixedLabelNameBuf);
output.value = CharSpan::fromCharString(mFixedLabelValueBuf);
ChipLogDetail(DeviceLayer, "Fixed label with index:%u at endpoint:%d, %s:%s", static_cast<unsigned>(mIndex), mEndpoint,
mFixedLabelNameBuf, mFixedLabelValueBuf);

return false;
mIndex++;
return true;
}

CHIP_ERROR ESP32DeviceInfoProvider::SetUserLabelLength(EndpointId endpoint, size_t val)
Expand Down Expand Up @@ -180,47 +192,82 @@ bool ESP32DeviceInfoProvider::UserLabelIteratorImpl::Next(UserLabelType & output

DeviceInfoProvider::SupportedLocalesIterator * ESP32DeviceInfoProvider::IterateSupportedLocales()
{
return chip::Platform::New<SupportedLocalesIteratorImpl>(mSupportedLocales);
}

ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::SupportedLocalesIteratorImpl(const Span<CharSpan> & locales)
{
mLocales = locales;
return chip::Platform::New<SupportedLocalesIteratorImpl>();
}

size_t ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::Count()
{
return mLocales.empty() ? 0 : mLocales.size();
uint32_t count = 0;
CHIP_ERROR err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_SupportedLocaleSize, count);
if (err != CHIP_NO_ERROR)
{
return 0;
}
return count;
}

bool ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::Next(CharSpan & output)
{
VerifyOrReturnValue(mIndex < mLocales.size(), false);
output = mLocales.data()[mIndex++];
char keyBuf[ESP32Config::kMaxConfigKeyNameLength];
size_t keyOutLen = 0;
memset(mLocaleBuf, 0, sizeof(mLocaleBuf));

VerifyOrReturnValue(ESP32Config::KeyAllocator::Locale(keyBuf, sizeof(keyBuf), static_cast<uint16_t>(mIndex)) == CHIP_NO_ERROR,
false);
ESP32Config::Key keyKey(ESP32Config::kConfigNamespace_ChipFactory, keyBuf);
VerifyOrReturnValue(ESP32Config::ReadConfigValueStr(keyKey, mLocaleBuf, sizeof(mLocaleBuf), keyOutLen) == CHIP_NO_ERROR, false);

output = CharSpan::fromCharString(mLocaleBuf);
mIndex++;
return true;
}

void ESP32DeviceInfoProvider::SupportedLocalesIteratorImpl::Release()
{
chip::Platform::Delete(this);
}

DeviceInfoProvider::SupportedCalendarTypesIterator * ESP32DeviceInfoProvider::IterateSupportedCalendarTypes()
{
return chip::Platform::New<SupportedCalendarTypesIteratorImpl>(mSupportedCalendarTypes);
return chip::Platform::New<SupportedCalendarTypesIteratorImpl>();
}

ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::SupportedCalendarTypesIteratorImpl(
const Span<CalendarType> & calendarTypes)
ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::SupportedCalendarTypesIteratorImpl()
{
mCalendarTypes = calendarTypes;
CHIP_ERROR err = ESP32Config::ReadConfigValue(ESP32Config::kConfigKey_SupportedCalTypes, mSupportedCalendarTypes);
if (err != CHIP_NO_ERROR)
{
ChipLogError(DeviceLayer, "Failed to read supported calendar types: %" CHIP_ERROR_FORMAT, err.Format());
}
}

size_t ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::Count()
{
return mCalendarTypes.empty() ? 0 : mCalendarTypes.size();
size_t count = 0;
for (uint8_t i = 0; i < to_underlying(app::Clusters::TimeFormatLocalization::CalendarTypeEnum::kUnknownEnumValue); i++)
{
if (mSupportedCalendarTypes & (1 << i))
{
count++;
}
}
ChipLogDetail(DeviceLayer, "Supported calendar types count:%u", count);
return count;
}

bool ESP32DeviceInfoProvider::SupportedCalendarTypesIteratorImpl::Next(CalendarType & output)
{
VerifyOrReturnValue(mIndex < mCalendarTypes.size(), false);
output = mCalendarTypes.data()[mIndex++];
return true;
while (mIndex < to_underlying(app::Clusters::TimeFormatLocalization::CalendarTypeEnum::kUnknownEnumValue))
{
if (mSupportedCalendarTypes & (1 << mIndex))
{
output = static_cast<CalendarType>(mIndex);
mIndex++;
return true;
}
mIndex++;
}
return false;
}

} // namespace DeviceLayer
Expand Down
Loading

0 comments on commit b6251a3

Please sign in to comment.