From 1827348549d877019ec46322934e07cebfaae172 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Tue, 12 Apr 2022 14:13:15 -0700 Subject: [PATCH] [Darwin] Implement DeviceInfoProviderImpl with persistent storage (#17136) * [Darwin] Implement DeviceInfoProviderImpl with persistent storage * Use storage delegate instead of PersistedStorage * Update src/platform/Darwin/DeviceInfoProviderImpl.cpp Co-authored-by: Boris Zbarsky * Update src/platform/Darwin/DeviceInfoProviderImpl.cpp Co-authored-by: Boris Zbarsky * Update src/platform/Darwin/DeviceInfoProviderImpl.cpp Co-authored-by: Boris Zbarsky * Update src/platform/Darwin/DeviceInfoProviderImpl.cpp Co-authored-by: Boris Zbarsky * Update src/include/platform/DeviceInfoProvider.h Co-authored-by: Boris Zbarsky * Address review comments Co-authored-by: Boris Zbarsky --- .github/workflows/tests.yaml | 2 +- src/app/server/Server.cpp | 8 + .../templates/tests/CHIPClustersTests.zapt | 6 + .../Framework/CHIP/templates/tests/tests.js | 1 + .../Framework/CHIPTests/CHIPClustersTests.m | 150 +++++++ src/include/platform/DeviceInfoProvider.h | 10 + src/platform/Darwin/BUILD.gn | 2 + .../Darwin/DeviceInfoProviderImpl.cpp | 365 ++++++++++++++++++ src/platform/Darwin/DeviceInfoProviderImpl.h | 106 +++++ src/platform/Darwin/PlatformManagerImpl.cpp | 2 + src/platform/DeviceInfoProvider.cpp | 6 + 11 files changed, 657 insertions(+), 1 deletion(-) create mode 100644 src/platform/Darwin/DeviceInfoProviderImpl.cpp create mode 100644 src/platform/Darwin/DeviceInfoProviderImpl.h diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index c077be1a86f976..8f31319e5f76a7 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -189,7 +189,7 @@ jobs: ./scripts/run_in_build_env.sh \ "./scripts/tests/run_test_suite.py \ --chip-tool ./out/darwin-x64-chip-tool${CHIP_TOOL_VARIANT}-${BUILD_VARIANT}/chip-tool \ - --target-skip-glob '{TestGroupMessaging,TestUserLabelCluster}' \ + --target-skip-glob '{TestGroupMessaging}' \ run \ --iterations 1 \ --all-clusters-app ./out/darwin-x64-all-clusters-${BUILD_VARIANT}/chip-all-clusters-app \ diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 2bbed884ed6c49..80062e5c83e1b3 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -97,6 +98,7 @@ static ::chip::app::CircularEventBuffer sLoggingBuffer[CHIP_NUM_EVENT_LOGGING_BU CHIP_ERROR Server::Init(const ServerInitParams & initParams) { CASESessionManagerConfig caseSessionManagerConfig; + DeviceLayer::DeviceInfoProvider * deviceInfoprovider = nullptr; mOperationalServicePort = initParams.operationalServicePort; mUserDirectedCommissioningPort = initParams.userDirectedCommissioningPort; @@ -134,6 +136,12 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) mGroupsProvider = initParams.groupDataProvider; SetGroupDataProvider(mGroupsProvider); + deviceInfoprovider = DeviceLayer::GetDeviceInfoProvider(); + if (deviceInfoprovider) + { + deviceInfoprovider->SetStorageDelegate(mDeviceStorage); + } + err = mAccessControl.Init(initParams.accessDelegate, sDeviceTypeResolver); SuccessOrExit(err); Access::SetAccessControl(mAccessControl); diff --git a/src/darwin/Framework/CHIP/templates/tests/CHIPClustersTests.zapt b/src/darwin/Framework/CHIP/templates/tests/CHIPClustersTests.zapt index 99f74ce72bb1f4..8facb0ae519f76 100644 --- a/src/darwin/Framework/CHIP/templates/tests/CHIPClustersTests.zapt +++ b/src/darwin/Framework/CHIP/templates/tests/CHIPClustersTests.zapt @@ -50,6 +50,12 @@ void UserPrompt(XCTestExpectation * expectation, dispatch_queue_t queue, NSStrin [expectation fulfill]; } +// Stub for reboot target device. +void Reboot(XCTestExpectation * expectation, dispatch_queue_t queue, uint16_t discriminator) +{ + [expectation fulfill]; +} + void WaitForCommissionee(XCTestExpectation * expectation, dispatch_queue_t queue, uint64_t deviceId) { CHIPDeviceController * controller = [CHIPDeviceController sharedController]; diff --git a/src/darwin/Framework/CHIP/templates/tests/tests.js b/src/darwin/Framework/CHIP/templates/tests/tests.js index 4b60175369b9c6..6633e0649bb7f5 100644 --- a/src/darwin/Framework/CHIP/templates/tests/tests.js +++ b/src/darwin/Framework/CHIP/templates/tests/tests.js @@ -278,6 +278,7 @@ function getTests() 'TestLogCommands', 'TestOperationalCredentialsCluster', 'TestBinding', + 'TestUserLabelCluster', ]; const SoftwareDiagnostics = [ diff --git a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m index bf58094c83c81c..633f734ab26575 100644 --- a/src/darwin/Framework/CHIPTests/CHIPClustersTests.m +++ b/src/darwin/Framework/CHIPTests/CHIPClustersTests.m @@ -66,6 +66,9 @@ void Log(XCTestExpectation * expectation, dispatch_queue_t queue, NSString * mes // Stub for User Prompts for XCTests to run. void UserPrompt(XCTestExpectation * expectation, dispatch_queue_t queue, NSString * message) { [expectation fulfill]; } +// Stub for reboot target device. +void Reboot(XCTestExpectation * expectation, dispatch_queue_t queue, uint16_t discriminator) { [expectation fulfill]; } + void WaitForCommissionee(XCTestExpectation * expectation, dispatch_queue_t queue, uint64_t deviceId) { CHIPDeviceController * controller = [CHIPDeviceController sharedController]; @@ -49706,6 +49709,153 @@ - (void)testSendClusterTestBinding_000008_ReadAttribute [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; } +- (void)testSendClusterTestUserLabelCluster_000000_WaitForCommissionee +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Wait for the commissioned device to be retrieved"]; + + dispatch_queue_t queue = dispatch_get_main_queue(); + WaitForCommissionee(expectation, queue, 305414945); + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestUserLabelCluster_000001_WriteAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Clear User Label List"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestUserLabel * cluster = [[CHIPTestUserLabel alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + id labelListArgument; + { + NSMutableArray * temp_0 = [[NSMutableArray alloc] init]; + labelListArgument = temp_0; + } + [cluster writeAttributeLabelListWithValue:labelListArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Clear User Label List Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestUserLabelCluster_000002_ReadAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Read User Label List"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestUserLabel * cluster = [[CHIPTestUserLabel alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeLabelListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Read User Label List Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + + { + id actualValue = value; + XCTAssertEqual([actualValue count], 0); + } + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestUserLabelCluster_000003_WriteAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Write User Label List"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestUserLabel * cluster = [[CHIPTestUserLabel alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + id labelListArgument; + { + NSMutableArray * temp_0 = [[NSMutableArray alloc] init]; + temp_0[0] = [[CHIPUserLabelClusterLabelStruct alloc] init]; + ((CHIPUserLabelClusterLabelStruct *) temp_0[0]).label = @"room"; + ((CHIPUserLabelClusterLabelStruct *) temp_0[0]).value = @"bedroom 2"; + + temp_0[1] = [[CHIPUserLabelClusterLabelStruct alloc] init]; + ((CHIPUserLabelClusterLabelStruct *) temp_0[1]).label = @"orientation"; + ((CHIPUserLabelClusterLabelStruct *) temp_0[1]).value = @"North"; + + temp_0[2] = [[CHIPUserLabelClusterLabelStruct alloc] init]; + ((CHIPUserLabelClusterLabelStruct *) temp_0[2]).label = @"floor"; + ((CHIPUserLabelClusterLabelStruct *) temp_0[2]).value = @"5"; + + temp_0[3] = [[CHIPUserLabelClusterLabelStruct alloc] init]; + ((CHIPUserLabelClusterLabelStruct *) temp_0[3]).label = @"direction"; + ((CHIPUserLabelClusterLabelStruct *) temp_0[3]).value = @"up"; + + labelListArgument = temp_0; + } + [cluster writeAttributeLabelListWithValue:labelListArgument + completionHandler:^(NSError * _Nullable err) { + NSLog(@"Write User Label List Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestUserLabelCluster_000004_Reboot +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Reboot target device"]; + + dispatch_queue_t queue = dispatch_get_main_queue(); + Reboot(expectation, queue, 3840); + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestUserLabelCluster_000005_WaitForCommissionee +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Wait for the commissioned device to be retrieved"]; + + dispatch_queue_t queue = dispatch_get_main_queue(); + WaitForCommissionee(expectation, queue, 305414945); + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} +- (void)testSendClusterTestUserLabelCluster_000006_ReadAttribute +{ + XCTestExpectation * expectation = [self expectationWithDescription:@"Verify"]; + + CHIPDevice * device = GetConnectedDevice(); + dispatch_queue_t queue = dispatch_get_main_queue(); + CHIPTestUserLabel * cluster = [[CHIPTestUserLabel alloc] initWithDevice:device endpoint:0 queue:queue]; + XCTAssertNotNil(cluster); + + [cluster readAttributeLabelListWithCompletionHandler:^(NSArray * _Nullable value, NSError * _Nullable err) { + NSLog(@"Verify Error: %@", err); + + XCTAssertEqual([CHIPErrorTestUtils errorToZCLErrorCode:err], 0); + + { + id actualValue = value; + XCTAssertEqual([actualValue count], 4); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[0]).label isEqualToString:@"room"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[0]).value isEqualToString:@"bedroom 2"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[1]).label isEqualToString:@"orientation"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[1]).value isEqualToString:@"North"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[2]).label isEqualToString:@"floor"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[2]).value isEqualToString:@"5"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[3]).label isEqualToString:@"direction"]); + XCTAssertTrue([((CHIPUserLabelClusterLabelStruct *) actualValue[3]).value isEqualToString:@"up"]); + } + + [expectation fulfill]; + }]; + + [self waitForExpectationsWithTimeout:kTimeoutInSeconds handler:nil]; +} + - (void)testSendClusterTest_TC_SWDIAG_1_1_000000_WaitForCommissionee { XCTestExpectation * expectation = [self expectationWithDescription:@"Wait for the commissioned device to be retrieved"]; diff --git a/src/include/platform/DeviceInfoProvider.h b/src/include/platform/DeviceInfoProvider.h index eb1b26e1053c14..7299d2013fc52a 100644 --- a/src/include/platform/DeviceInfoProvider.h +++ b/src/include/platform/DeviceInfoProvider.h @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace chip { @@ -81,6 +82,13 @@ class DeviceInfoProvider DeviceInfoProvider(const DeviceInfoProvider &) = delete; DeviceInfoProvider & operator=(const DeviceInfoProvider &) = delete; + /** + * @brief Set the storage implementation used for non-volatile storage of device information data. + * + * @param storage Pointer to storage instance to set. Cannot be nullptr, will assert. + */ + void SetStorageDelegate(PersistentStorageDelegate * storage); + CHIP_ERROR SetUserLabelList(EndpointId endpoint, const AttributeList & labelList); CHIP_ERROR AppendUserLabel(EndpointId endpoint, const UserLabelType & label); @@ -112,6 +120,8 @@ class DeviceInfoProvider virtual SupportedCalendarTypesIterator * IterateSupportedCalendarTypes() = 0; protected: + PersistentStorageDelegate * mStorage = nullptr; + /** * @brief Set the UserLabel at the specified index of the UserLabelList on a given endpoint * diff --git a/src/platform/Darwin/BUILD.gn b/src/platform/Darwin/BUILD.gn index 707f7f79183db9..5aa6668ce00460 100644 --- a/src/platform/Darwin/BUILD.gn +++ b/src/platform/Darwin/BUILD.gn @@ -47,6 +47,8 @@ static_library("Darwin") { "ConfigurationManagerImpl.h", "ConnectivityManagerImpl.cpp", "ConnectivityManagerImpl.h", + "DeviceInfoProviderImpl.cpp", + "DeviceInfoProviderImpl.h", "DiagnosticDataProviderImpl.cpp", "DiagnosticDataProviderImpl.h", "DnssdImpl.cpp", diff --git a/src/platform/Darwin/DeviceInfoProviderImpl.cpp b/src/platform/Darwin/DeviceInfoProviderImpl.cpp new file mode 100644 index 00000000000000..3ea2236809eb31 --- /dev/null +++ b/src/platform/Darwin/DeviceInfoProviderImpl.cpp @@ -0,0 +1,365 @@ +/* + * + * Copyright (c) 2022 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 +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace chip { +namespace DeviceLayer { + +namespace { +constexpr TLV::Tag kLabelNameTag = TLV::ContextTag(0); +constexpr TLV::Tag kLabelValueTag = TLV::ContextTag(1); +} // anonymous namespace + +DeviceInfoProviderImpl & DeviceInfoProviderImpl::GetDefaultInstance() +{ + static DeviceInfoProviderImpl sInstance; + return sInstance; +} + +DeviceInfoProvider::FixedLabelIterator * DeviceInfoProviderImpl::IterateFixedLabel(EndpointId endpoint) +{ + return new FixedLabelIteratorImpl(endpoint); +} + +DeviceInfoProviderImpl::FixedLabelIteratorImpl::FixedLabelIteratorImpl(EndpointId endpoint) : mEndpoint(endpoint) +{ + mIndex = 0; +} + +size_t DeviceInfoProviderImpl::FixedLabelIteratorImpl::Count() +{ + // In Darwin Simulation, return the size of the hardcoded labelList on all endpoints. + return 4; +} + +bool DeviceInfoProviderImpl::FixedLabelIteratorImpl::Next(FixedLabelType & output) +{ + bool retval = true; + + // In Darwin Simulation, use the following hardcoded labelList on all endpoints. + CHIP_ERROR err = CHIP_NO_ERROR; + + const char * labelPtr = nullptr; + const char * valuePtr = nullptr; + + VerifyOrReturnError(mIndex < 4, false); + + ChipLogProgress(DeviceLayer, "Get the fixed label with index:%ld at endpoint:%d", mIndex, mEndpoint); + + switch (mIndex) + { + case 0: + labelPtr = "room"; + valuePtr = "bedroom 2"; + break; + case 1: + labelPtr = "orientation"; + valuePtr = "North"; + break; + case 2: + labelPtr = "floor"; + valuePtr = "2"; + break; + case 3: + labelPtr = "direction"; + valuePtr = "up"; + break; + default: + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + break; + } + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(std::strlen(labelPtr) <= kMaxLabelNameLength, false); + VerifyOrReturnError(std::strlen(valuePtr) <= kMaxLabelValueLength, false); + + Platform::CopyString(mFixedLabelNameBuf, kMaxLabelNameLength + 1, labelPtr); + Platform::CopyString(mFixedLabelValueBuf, kMaxLabelValueLength + 1, valuePtr); + + output.label = CharSpan::fromCharString(mFixedLabelNameBuf); + output.value = CharSpan::fromCharString(mFixedLabelValueBuf); + + mIndex++; + + retval = true; + } + else + { + retval = false; + } + + return retval; +} + +CHIP_ERROR DeviceInfoProviderImpl::SetUserLabelLength(EndpointId endpoint, size_t val) +{ + DefaultStorageKeyAllocator keyAlloc; + + return mStorage->SyncSetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, static_cast(sizeof(val))); +} + +CHIP_ERROR DeviceInfoProviderImpl::GetUserLabelLength(EndpointId endpoint, size_t & val) +{ + DefaultStorageKeyAllocator keyAlloc; + uint16_t len = static_cast(sizeof(val)); + + return mStorage->SyncGetKeyValue(keyAlloc.UserLabelLengthKey(endpoint), &val, len); +} + +CHIP_ERROR DeviceInfoProviderImpl::SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) +{ + DefaultStorageKeyAllocator keyAlloc; + uint8_t buf[UserLabelTLVMaxSize()]; + TLV::TLVWriter writer; + writer.Init(buf); + + TLV::TLVType outerType; + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerType)); + ReturnErrorOnFailure(writer.PutString(kLabelNameTag, userLabel.label)); + ReturnErrorOnFailure(writer.PutString(kLabelValueTag, userLabel.value)); + ReturnErrorOnFailure(writer.EndContainer(outerType)); + + return mStorage->SyncSetKeyValue(keyAlloc.UserLabelIndexKey(endpoint, index), buf, + static_cast(writer.GetLengthWritten())); +} + +DeviceInfoProvider::UserLabelIterator * DeviceInfoProviderImpl::IterateUserLabel(EndpointId endpoint) +{ + return new UserLabelIteratorImpl(*this, endpoint); +} + +DeviceInfoProviderImpl::UserLabelIteratorImpl::UserLabelIteratorImpl(DeviceInfoProviderImpl & provider, EndpointId endpoint) : + mProvider(provider), mEndpoint(endpoint) +{ + size_t total = 0; + + ReturnOnFailure(mProvider.GetUserLabelLength(mEndpoint, total)); + mTotal = total; + mIndex = 0; +} + +bool DeviceInfoProviderImpl::UserLabelIteratorImpl::Next(UserLabelType & output) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrReturnError(mIndex < mTotal, false); + + DefaultStorageKeyAllocator keyAlloc; + uint8_t buf[UserLabelTLVMaxSize()]; + uint16_t len = static_cast(UserLabelTLVMaxSize()); + + err = mProvider.mStorage->SyncGetKeyValue(keyAlloc.UserLabelIndexKey(mEndpoint, mIndex), buf, len); + VerifyOrReturnError(err == CHIP_NO_ERROR, false); + + TLV::ContiguousBufferTLVReader reader; + reader.Init(buf); + err = reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()); + VerifyOrReturnError(err == CHIP_NO_ERROR, false); + + TLV::TLVType containerType; + VerifyOrReturnError(reader.EnterContainer(containerType) == CHIP_NO_ERROR, false); + + chip::CharSpan label; + chip::CharSpan value; + + VerifyOrReturnError(reader.Next(kLabelNameTag) == CHIP_NO_ERROR, false); + VerifyOrReturnError(reader.Get(label) == CHIP_NO_ERROR, false); + + VerifyOrReturnError(reader.Next(kLabelValueTag) == CHIP_NO_ERROR, false); + VerifyOrReturnError(reader.Get(value) == CHIP_NO_ERROR, false); + + VerifyOrReturnError(reader.VerifyEndOfContainer() == CHIP_NO_ERROR, false); + VerifyOrReturnError(reader.ExitContainer(containerType) == CHIP_NO_ERROR, false); + + Platform::CopyString(mUserLabelNameBuf, label); + Platform::CopyString(mUserLabelValueBuf, value); + + output.label = CharSpan::fromCharString(mUserLabelNameBuf); + output.value = CharSpan::fromCharString(mUserLabelValueBuf); + + mIndex++; + + return true; +} + +DeviceInfoProvider::SupportedLocalesIterator * DeviceInfoProviderImpl::IterateSupportedLocales() +{ + return new SupportedLocalesIteratorImpl(); +} + +size_t DeviceInfoProviderImpl::SupportedLocalesIteratorImpl::Count() +{ + // In Darwin Simulation, return the size of the hardcoded list of Strings that are valid values for the ActiveLocale. + // {("en-US"), ("de-DE"), ("fr-FR"), ("en-GB"), ("es-ES"), ("zh-CN"), ("it-IT"), ("ja-JP")} + + return 8; +} + +bool DeviceInfoProviderImpl::SupportedLocalesIteratorImpl::Next(CharSpan & output) +{ + bool retval = true; + + // In Darwin simulation, return following hardcoded list of Strings that are valid values for the ActiveLocale. + CHIP_ERROR err = CHIP_NO_ERROR; + + const char * activeLocalePtr = nullptr; + + VerifyOrReturnError(mIndex < 8, false); + + switch (mIndex) + { + case 0: + activeLocalePtr = "en-US"; + break; + case 1: + activeLocalePtr = "de-DE"; + break; + case 2: + activeLocalePtr = "fr-FR"; + break; + case 3: + activeLocalePtr = "en-GB"; + break; + case 4: + activeLocalePtr = "es-ES"; + break; + case 5: + activeLocalePtr = "zh-CN"; + break; + case 6: + activeLocalePtr = "it-IT"; + break; + case 7: + activeLocalePtr = "ja-JP"; + break; + default: + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + break; + } + + if (err == CHIP_NO_ERROR) + { + VerifyOrReturnError(std::strlen(activeLocalePtr) <= kMaxActiveLocaleLength, false); + + Platform::CopyString(mActiveLocaleBuf, kMaxActiveLocaleLength + 1, activeLocalePtr); + + output = CharSpan::fromCharString(mActiveLocaleBuf); + + mIndex++; + + retval = true; + } + else + { + retval = false; + } + + return retval; +} + +DeviceInfoProvider::SupportedCalendarTypesIterator * DeviceInfoProviderImpl::IterateSupportedCalendarTypes() +{ + return new SupportedCalendarTypesIteratorImpl(); +} + +size_t DeviceInfoProviderImpl::SupportedCalendarTypesIteratorImpl::Count() +{ + // In Darwin Simulation, return the size of the hardcoded list of Strings that are valid values for the Calendar Types. + // {("kBuddhist"), ("kChinese"), ("kCoptic"), ("kEthiopian"), ("kGregorian"), ("kHebrew"), ("kIndian"), ("kJapanese"), + // ("kKorean"), ("kPersian"), ("kTaiwanese"), ("kIslamic")} + + return 12; +} + +bool DeviceInfoProviderImpl::SupportedCalendarTypesIteratorImpl::Next(CalendarType & output) +{ + bool retval = true; + + // In Darwin Simulation, return following hardcoded list of Strings that are valid values for the Calendar Types. + CHIP_ERROR err = CHIP_NO_ERROR; + + VerifyOrReturnError(mIndex < 12, false); + + switch (mIndex) + { + case 0: + output = app::Clusters::TimeFormatLocalization::CalendarType::kBuddhist; + break; + case 1: + output = app::Clusters::TimeFormatLocalization::CalendarType::kChinese; + break; + case 2: + output = app::Clusters::TimeFormatLocalization::CalendarType::kCoptic; + break; + case 3: + output = app::Clusters::TimeFormatLocalization::CalendarType::kEthiopian; + break; + case 4: + output = app::Clusters::TimeFormatLocalization::CalendarType::kGregorian; + break; + case 5: + output = app::Clusters::TimeFormatLocalization::CalendarType::kHebrew; + break; + case 6: + output = app::Clusters::TimeFormatLocalization::CalendarType::kIndian; + break; + case 7: + output = app::Clusters::TimeFormatLocalization::CalendarType::kJapanese; + break; + case 8: + output = app::Clusters::TimeFormatLocalization::CalendarType::kKorean; + break; + case 9: + output = app::Clusters::TimeFormatLocalization::CalendarType::kPersian; + break; + case 10: + output = app::Clusters::TimeFormatLocalization::CalendarType::kTaiwanese; + break; + case 11: + output = app::Clusters::TimeFormatLocalization::CalendarType::kIslamic; + break; + default: + err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND; + break; + } + + if (err == CHIP_NO_ERROR) + { + mIndex++; + retval = true; + } + else + { + retval = false; + } + + return retval; +} + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Darwin/DeviceInfoProviderImpl.h b/src/platform/Darwin/DeviceInfoProviderImpl.h new file mode 100644 index 00000000000000..6d7c6e0c0ecf35 --- /dev/null +++ b/src/platform/Darwin/DeviceInfoProviderImpl.h @@ -0,0 +1,106 @@ +/* + * + * Copyright (c) 2022 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 +#include + +namespace chip { +namespace DeviceLayer { + +class DeviceInfoProviderImpl : public DeviceInfoProvider +{ +public: + DeviceInfoProviderImpl() = default; + ~DeviceInfoProviderImpl() override {} + + // Iterators + FixedLabelIterator * IterateFixedLabel(EndpointId endpoint) override; + UserLabelIterator * IterateUserLabel(EndpointId endpoint) override; + SupportedLocalesIterator * IterateSupportedLocales() override; + SupportedCalendarTypesIterator * IterateSupportedCalendarTypes() override; + + static DeviceInfoProviderImpl & GetDefaultInstance(); + +protected: + class FixedLabelIteratorImpl : public FixedLabelIterator + { + public: + FixedLabelIteratorImpl(EndpointId endpoint); + size_t Count() override; + bool Next(FixedLabelType & output) override; + void Release() override { delete this; } + + private: + EndpointId mEndpoint = 0; + size_t mIndex = 0; + char mFixedLabelNameBuf[kMaxLabelNameLength + 1]; + char mFixedLabelValueBuf[kMaxLabelValueLength + 1]; + }; + + class UserLabelIteratorImpl : public UserLabelIterator + { + public: + UserLabelIteratorImpl(DeviceInfoProviderImpl & provider, EndpointId endpoint); + size_t Count() override { return mTotal; } + bool Next(UserLabelType & output) override; + void Release() override { delete this; } + + private: + DeviceInfoProviderImpl & mProvider; + EndpointId mEndpoint = 0; + size_t mIndex = 0; + size_t mTotal = 0; + char mUserLabelNameBuf[kMaxLabelNameLength + 1]; + char mUserLabelValueBuf[kMaxLabelValueLength + 1]; + }; + + class SupportedLocalesIteratorImpl : public SupportedLocalesIterator + { + public: + SupportedLocalesIteratorImpl() = default; + size_t Count() override; + bool Next(CharSpan & output) override; + void Release() override { delete this; } + + private: + size_t mIndex = 0; + char mActiveLocaleBuf[kMaxActiveLocaleLength + 1]; + }; + + class SupportedCalendarTypesIteratorImpl : public SupportedCalendarTypesIterator + { + public: + SupportedCalendarTypesIteratorImpl() = default; + size_t Count() override; + bool Next(CalendarType & output) override; + void Release() override { delete this; } + + private: + size_t mIndex = 0; + }; + + CHIP_ERROR SetUserLabelLength(EndpointId endpoint, size_t val) override; + CHIP_ERROR GetUserLabelLength(EndpointId endpoint, size_t & val) override; + CHIP_ERROR SetUserLabelAt(EndpointId endpoint, size_t index, const UserLabelType & userLabel) override; + +private: + static constexpr size_t UserLabelTLVMaxSize() { return TLV::EstimateStructOverhead(kMaxLabelNameLength, kMaxLabelValueLength); } +}; + +} // namespace DeviceLayer +} // namespace chip diff --git a/src/platform/Darwin/PlatformManagerImpl.cpp b/src/platform/Darwin/PlatformManagerImpl.cpp index c423b87f46ddf6..d39022c03a5132 100644 --- a/src/platform/Darwin/PlatformManagerImpl.cpp +++ b/src/platform/Darwin/PlatformManagerImpl.cpp @@ -24,6 +24,7 @@ #include +#include #include #include @@ -46,6 +47,7 @@ CHIP_ERROR PlatformManagerImpl::_InitChipStack() SuccessOrExit(err); SetConfigurationMgr(&ConfigurationManagerImpl::GetDefaultInstance()); SetDiagnosticDataProvider(&DiagnosticDataProviderImpl::GetDefaultInstance()); + SetDeviceInfoProvider(&DeviceInfoProviderImpl::GetDefaultInstance()); mRunLoopSem = dispatch_semaphore_create(0); diff --git a/src/platform/DeviceInfoProvider.cpp b/src/platform/DeviceInfoProvider.cpp index dd008137749a0a..6a4e88e70b6dab 100644 --- a/src/platform/DeviceInfoProvider.cpp +++ b/src/platform/DeviceInfoProvider.cpp @@ -64,6 +64,12 @@ CHIP_ERROR DeviceInfoProvider::AppendUserLabel(EndpointId endpoint, const UserLa return CHIP_NO_ERROR; } +void DeviceInfoProvider::SetStorageDelegate(PersistentStorageDelegate * storage) +{ + VerifyOrDie(storage != nullptr); + mStorage = storage; +} + /** * Instance getter for the global DeviceInfoProvider. *