Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 82624dc

Browse files
committedSep 9, 2024
Valve: Disco ball - Attribute Setters for client
1 parent 6f3357b commit 82624dc

8 files changed

+362
-9
lines changed
 

‎src/app/chip_data_model.gni

+1
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,7 @@ template("chip_data_model") {
449449
"${_app_root}/clusters/${cluster}/valve-configuration-and-control-cluster-logic.cpp",
450450
"${_app_root}/clusters/${cluster}/valve-configuration-and-control-cluster-logic.h",
451451
"${_app_root}/clusters/${cluster}/valve-configuration-and-control-delegate.h",
452+
"${_app_root}/clusters/${cluster}/valve-configuration-and-control-matter-context.cpp",
452453
"${_app_root}/clusters/${cluster}/valve-configuration-and-control-matter-context.h",
453454
]
454455
cflags += [ "-Wno-unused-private-field" ]

‎src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster-logic.cpp

+43
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,15 @@ CHIP_ERROR ClusterLogic::Init(const ClusterConformance & conformance, const Clus
3434
}
3535
mConformance = conformance;
3636
mState = initialState;
37+
38+
// Overwrite default initial state with stored persisted values if set.
39+
uint32_t defaultOpenDuration;
40+
if (mMatterContext.GetDefaultOpenDuration(defaultOpenDuration) == CHIP_NO_ERROR)
41+
{
42+
mState.defaultOpenDuration.SetNonNull(defaultOpenDuration);
43+
}
44+
mMatterContext.GetDefaultOpenLevel(mState.defaultOpenLevel);
45+
3746
mInitialized = true;
3847
return CHIP_NO_ERROR;
3948
}
@@ -117,6 +126,40 @@ CHIP_ERROR ClusterLogic::GetLevelStep(uint8_t & levelStep)
117126
return CHIP_NO_ERROR;
118127
}
119128

129+
CHIP_ERROR ClusterLogic::SetDefaultOpenDuration(const DataModel::Nullable<ElapsedS> & defaultOpenDuration)
130+
{
131+
VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE);
132+
if (!defaultOpenDuration.IsNull() && defaultOpenDuration.Value() < 1)
133+
{
134+
return CHIP_ERROR_INVALID_ARGUMENT;
135+
}
136+
ReturnErrorOnFailure(mMatterContext.StoreDefaultOpenDuration(defaultOpenDuration));
137+
mState.defaultOpenDuration = defaultOpenDuration;
138+
return CHIP_NO_ERROR;
139+
}
140+
141+
CHIP_ERROR ClusterLogic::SetDefaultOpenLevel(const uint8_t defaultOpenLevel)
142+
{
143+
VerifyOrReturnError(mInitialized, CHIP_ERROR_INCORRECT_STATE);
144+
VerifyOrReturnError(mConformance.supportsDefaultOpenLevel, CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
145+
if (defaultOpenLevel < 1 || defaultOpenLevel > 100)
146+
{
147+
return CHIP_ERROR_INVALID_ARGUMENT;
148+
}
149+
ReturnErrorOnFailure(mMatterContext.StoreDefaultOpenLevel(defaultOpenLevel));
150+
mState.defaultOpenLevel = defaultOpenLevel;
151+
return CHIP_NO_ERROR;
152+
}
153+
154+
CHIP_ERROR ClusterLogic::SetValveFault(const ValveFaultBitmap valveFault)
155+
{
156+
return CHIP_ERROR_NOT_IMPLEMENTED;
157+
}
158+
CHIP_ERROR ClusterLogic::ClearValveFault(const ValveFaultBitmap valveFault)
159+
{
160+
return CHIP_ERROR_NOT_IMPLEMENTED;
161+
}
162+
120163
} // namespace ValveConfigurationAndControl
121164
} // namespace Clusters
122165
} // namespace app

‎src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster-logic.h

+27-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "valve-configuration-and-control-delegate.h"
2424
#include "valve-configuration-and-control-matter-context.h"
25+
#include <app/data-model/Nullable.h>
2526
#include <lib/core/CHIPError.h>
2627

2728
namespace chip {
@@ -79,7 +80,6 @@ class ClusterLogic
7980
{
8081
// TODO: remove these once the fields are used properly
8182
(void) mClusterDriver;
82-
(void) mMatterContext;
8383
}
8484

8585
// Validates the conformance and performs initialization.
@@ -105,6 +105,32 @@ class ClusterLogic
105105
CHIP_ERROR GetValveFault(BitMask<ValveFaultBitmap> & valveFault);
106106
CHIP_ERROR GetLevelStep(uint8_t & levelStep);
107107

108+
// All Set functions
109+
// Return CHIP_ERROR_INCORRECT_STATE if the class has not been initialized.
110+
// Return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE if the attribute is not supported by the conformance.
111+
// Return CHIP_ERROR_INVALID_ARGUMENT if the input value is out of range.
112+
// Returns CHIP_ERROR_PERSISTED_STORAGE_FAILED if the value could not not be stored in persistent storage.
113+
// Otherwise return CHIP_NO_ERROR and set the parameter value in the cluster state
114+
// Set functions are supplied for any values that can be set either internally by the device or externally
115+
// through a direct attribute write. Changes to attributes that happen as a side effect of cluster commands
116+
// are handled by the cluster command handlers.
117+
118+
// DefaultOpenDuration can be set by the client using attribute write
119+
CHIP_ERROR SetDefaultOpenDuration(const DataModel::Nullable<ElapsedS> & defaultOpenDuration);
120+
121+
// DefaultOpenLevel can be set by the client using attribute write
122+
CHIP_ERROR SetDefaultOpenLevel(const uint8_t defaultOpenLevel);
123+
124+
// ValveFault can be set internally by the device.
125+
// Use the Set function to add a specific valve fault and the clear function to clear it.
126+
// Q: Should we push these through the delegate?
127+
CHIP_ERROR SetValveFault(const ValveFaultBitmap valveFault);
128+
CHIP_ERROR ClearValveFault(const ValveFaultBitmap valveFault);
129+
130+
// Other ones that are set internally?
131+
// Current state
132+
// Current level
133+
108134
private:
109135
bool mInitialized = false;
110136

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
*
3+
* Copyright (c) 2024 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 "valve-configuration-and-control-matter-context.h"
20+
21+
#include <lib/support/DefaultStorageKeyAllocator.h>
22+
23+
namespace chip {
24+
namespace app {
25+
namespace Clusters {
26+
namespace ValveConfigurationAndControl {
27+
28+
CHIP_ERROR MatterContext::StoreDefaultOpenDuration(const DataModel::Nullable<uint32_t> & defaultOpenDuration)
29+
{
30+
31+
if (defaultOpenDuration.IsNull())
32+
{
33+
return mPersistentStorageDelegate.SyncDeleteKeyValue(
34+
DefaultStorageKeyAllocator::VCCDefaultOpenDuration(mEndpoint).KeyName());
35+
}
36+
uint32_t val = defaultOpenDuration.Value();
37+
return mPersistentStorageDelegate.SyncSetKeyValue(DefaultStorageKeyAllocator::VCCDefaultOpenDuration(mEndpoint).KeyName(), &val,
38+
sizeof(val));
39+
}
40+
41+
CHIP_ERROR MatterContext::GetDefaultOpenDuration(uint32_t & returnVal)
42+
{
43+
uint16_t size = static_cast<uint16_t>(sizeof(returnVal));
44+
return mPersistentStorageDelegate.SyncGetKeyValue(DefaultStorageKeyAllocator::VCCDefaultOpenDuration(mEndpoint).KeyName(),
45+
&returnVal, size);
46+
}
47+
48+
CHIP_ERROR MatterContext::StoreDefaultOpenLevel(const uint8_t defaultOpenLevel)
49+
{
50+
51+
return mPersistentStorageDelegate.SyncSetKeyValue(DefaultStorageKeyAllocator::VCCDefaultOpenLevel(mEndpoint).KeyName(),
52+
&defaultOpenLevel, sizeof(defaultOpenLevel));
53+
}
54+
55+
CHIP_ERROR MatterContext::GetDefaultOpenLevel(uint8_t & returnVal)
56+
{
57+
uint16_t size = static_cast<uint16_t>(sizeof(returnVal));
58+
return mPersistentStorageDelegate.SyncGetKeyValue(DefaultStorageKeyAllocator::VCCDefaultOpenLevel(mEndpoint).KeyName(),
59+
&returnVal, size);
60+
}
61+
62+
} // namespace ValveConfigurationAndControl
63+
} // namespace Clusters
64+
} // namespace app
65+
} // namespace chip

‎src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-matter-context.h

+19-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818

1919
#pragma once
2020

21+
#include <app/data-model/Nullable.h>
2122
#include <lib/core/CHIPError.h>
22-
// #include <src/lib/core/DataModelTypes.h>
23-
#include <app-common/zap-generated/cluster-enums.h>
23+
#include <lib/core/CHIPPersistentStorageDelegate.h>
24+
#include <lib/core/DataModelTypes.h>
2425

2526
namespace chip {
2627
namespace app {
@@ -35,10 +36,25 @@ class MatterContext
3536
public:
3637
// TODO: remove touch on mEndpoint once this is used. I am apparently unable to locate the proper place to turn this off in the
3738
// build file, so whatever, compiler, you win. I've touched it. You happy now?
38-
MatterContext(EndpointId endpoint) : mEndpoint(endpoint) { (void) mEndpoint; }
39+
MatterContext(EndpointId endpoint, PersistentStorageDelegate & persistentStorageDelegate) :
40+
mEndpoint(endpoint), mPersistentStorageDelegate(persistentStorageDelegate)
41+
{}
42+
43+
// All Set functions:
44+
// Return CHIP_ERROR_PERSISTED_STORAGE_FAILED if the value could not be stored.
45+
// Return CHIP_NO_ERROR if the value was successfully stored. Clear the storage on a NullNullable.
46+
CHIP_ERROR StoreDefaultOpenDuration(const DataModel::Nullable<uint32_t> & val);
47+
CHIP_ERROR StoreDefaultOpenLevel(const uint8_t val);
48+
49+
// All Get functions
50+
// Return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND if there is no value in storage.
51+
// Return CHIP_NO_ERROR and fill return value if the value is found.
52+
CHIP_ERROR GetDefaultOpenDuration(uint32_t & returnVal);
53+
CHIP_ERROR GetDefaultOpenLevel(uint8_t & returnVal);
3954

4055
private:
4156
EndpointId mEndpoint;
57+
PersistentStorageDelegate & mPersistentStorageDelegate;
4258
};
4359

4460
} // namespace ValveConfigurationAndControl

‎src/app/tests/BUILD.gn

+1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ source_set("valve-configuration-and-control-test-srcs") {
159159
"${chip_root}/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster-logic.cpp",
160160
"${chip_root}/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster-logic.h",
161161
"${chip_root}/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-delegate.h",
162+
"${chip_root}/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-matter-context.cpp",
162163
"${chip_root}/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-matter-context.h",
163164
]
164165
public_deps = [

‎src/app/tests/TestValveConfigurationAndControl.cpp

+199-5
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
* See the License for the specific language governing permissions and
1616
* limitations under the License.
1717
*/
18-
#include "lib/support/CHIPMem.h"
1918
#include <app-common/zap-generated/cluster-objects.h>
2019
#include <app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-cluster-logic.h>
2120
#include <app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-delegate.h>
2221
#include <app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-matter-context.h>
22+
#include <lib/support/CHIPMem.h>
23+
#include <lib/support/DefaultStorageKeyAllocator.h>
24+
#include <lib/support/TestPersistentStorageDelegate.h>
2325
#include <pw_unit_test/framework.h>
2426

2527
namespace chip {
@@ -115,7 +117,8 @@ TEST_F(TestValveConfigurationAndControlClusterLogic, TestConformanceValid)
115117
TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesAllFeatures)
116118
{
117119
TestDelegate delegate;
118-
MatterContext context = MatterContext(0);
120+
TestPersistentStorageDelegate storageDelegate;
121+
MatterContext context = MatterContext(0, storageDelegate);
119122
ClusterLogic logic = ClusterLogic(delegate, context);
120123

121124
// Everything on, all should return values
@@ -170,7 +173,8 @@ TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesAllFeature
170173
TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesNoFeatures)
171174
{
172175
TestDelegate delegate;
173-
MatterContext context = MatterContext(0);
176+
TestPersistentStorageDelegate storageDelegate;
177+
MatterContext context = MatterContext(0, storageDelegate);
174178
ClusterLogic logic = ClusterLogic(delegate, context);
175179

176180
// Everything on, all should return values
@@ -218,7 +222,8 @@ TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesNoFeatures
218222
TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesStartingState)
219223
{
220224
TestDelegate delegate;
221-
MatterContext context = MatterContext(0);
225+
TestPersistentStorageDelegate storageDelegate;
226+
MatterContext context = MatterContext(0, storageDelegate);
222227
ClusterLogic logic = ClusterLogic(delegate, context);
223228

224229
// Everything on, all should return values
@@ -286,7 +291,8 @@ TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesStartingSt
286291
TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesUninitialized)
287292
{
288293
TestDelegate delegate;
289-
MatterContext context = MatterContext(0);
294+
TestPersistentStorageDelegate storageDelegate;
295+
MatterContext context = MatterContext(0, storageDelegate);
290296
ClusterLogic logic = ClusterLogic(delegate, context);
291297

292298
DataModel::Nullable<ElapsedS> valElapsedSNullable;
@@ -310,6 +316,194 @@ TEST_F(TestValveConfigurationAndControlClusterLogic, TestGetAttributesUninitiali
310316
EXPECT_EQ(logic.GetLevelStep(val8), CHIP_ERROR_INCORRECT_STATE);
311317
}
312318

319+
TEST_F(TestValveConfigurationAndControlClusterLogic, TestSetDefaultOpenDuration)
320+
{
321+
TestDelegate delegate;
322+
TestPersistentStorageDelegate storageDelegate;
323+
EndpointId endpoint = 0;
324+
MatterContext context = MatterContext(endpoint, storageDelegate);
325+
ClusterLogic logic = ClusterLogic(delegate, context);
326+
327+
DataModel::Nullable<ElapsedS> valElapsedSNullable;
328+
329+
// Setting this value before initialization should fail
330+
auto testVal = DataModel::MakeNullable(static_cast<ElapsedS>(5u));
331+
EXPECT_EQ(logic.SetDefaultOpenDuration(testVal), CHIP_ERROR_INCORRECT_STATE);
332+
333+
ClusterConformance conformance = { .featureMap = to_underlying(Feature::kLevel) | to_underlying(Feature::kTimeSync),
334+
.supportsDefaultOpenLevel = true,
335+
.supportsValveFault = true,
336+
.supportsLevelStep = true };
337+
EXPECT_EQ(logic.Init(conformance), CHIP_NO_ERROR);
338+
339+
EXPECT_EQ(logic.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
340+
EXPECT_EQ(valElapsedSNullable, DataModel::NullNullable);
341+
342+
// Lowest possible value
343+
testVal = DataModel::MakeNullable(static_cast<ElapsedS>(1u));
344+
EXPECT_EQ(logic.SetDefaultOpenDuration(testVal), CHIP_NO_ERROR);
345+
346+
// Ensure the value is accessible via the API
347+
EXPECT_EQ(logic.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
348+
EXPECT_EQ(valElapsedSNullable, testVal);
349+
350+
// Ensure the value is persisted in the test storage
351+
StorageKeyName keyName = DefaultStorageKeyAllocator::VCCDefaultOpenDuration(endpoint);
352+
uint32_t persistedValue;
353+
uint16_t size = static_cast<uint16_t>(sizeof(persistedValue));
354+
EXPECT_TRUE(storageDelegate.HasKey(keyName.KeyName()));
355+
EXPECT_EQ(storageDelegate.SyncGetKeyValue(keyName.KeyName(), &persistedValue, size), CHIP_NO_ERROR);
356+
EXPECT_EQ(persistedValue, testVal.Value());
357+
// Test that this doesn't exist for other endpoints. Check 1.
358+
EXPECT_FALSE(storageDelegate.HasKey(DefaultStorageKeyAllocator::VCCDefaultOpenDuration(1).KeyName()));
359+
360+
testVal = DataModel::MakeNullable(static_cast<ElapsedS>(12u));
361+
EXPECT_EQ(logic.SetDefaultOpenDuration(testVal), CHIP_NO_ERROR);
362+
363+
EXPECT_EQ(logic.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
364+
EXPECT_EQ(valElapsedSNullable, testVal);
365+
366+
EXPECT_TRUE(storageDelegate.HasKey(keyName.KeyName()));
367+
EXPECT_EQ(storageDelegate.SyncGetKeyValue(keyName.KeyName(), &persistedValue, size), CHIP_NO_ERROR);
368+
EXPECT_EQ(persistedValue, testVal.Value());
369+
370+
auto outOfRangeVal = DataModel::MakeNullable(static_cast<ElapsedS>(0u));
371+
EXPECT_EQ(logic.SetDefaultOpenDuration(outOfRangeVal), CHIP_ERROR_INVALID_ARGUMENT);
372+
373+
// Ensure the value wasn't changed
374+
EXPECT_EQ(logic.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
375+
EXPECT_EQ(valElapsedSNullable, testVal);
376+
377+
EXPECT_TRUE(storageDelegate.HasKey(keyName.KeyName()));
378+
EXPECT_EQ(storageDelegate.SyncGetKeyValue(keyName.KeyName(), &persistedValue, size), CHIP_NO_ERROR);
379+
EXPECT_EQ(persistedValue, testVal.Value());
380+
381+
// Test that firing up a new logic cluster on the same endpoint loads the value from persisted storage
382+
ClusterLogic logic_same_endpoint = ClusterLogic(delegate, context);
383+
EXPECT_EQ(logic_same_endpoint.Init(conformance), CHIP_NO_ERROR);
384+
EXPECT_EQ(logic_same_endpoint.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
385+
EXPECT_EQ(valElapsedSNullable, testVal);
386+
387+
// Test that a new logic cluster on a different endpoint does not load the value
388+
MatterContext context_ep1 = MatterContext(1, storageDelegate);
389+
ClusterLogic logic_different_endpoint = ClusterLogic(delegate, context_ep1);
390+
EXPECT_EQ(logic_different_endpoint.Init(conformance), CHIP_NO_ERROR);
391+
EXPECT_EQ(logic_different_endpoint.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
392+
EXPECT_EQ(valElapsedSNullable, DataModel::NullNullable);
393+
394+
// Test setting back to null, this should clear the persisted value
395+
testVal = DataModel::NullNullable;
396+
EXPECT_EQ(logic.SetDefaultOpenDuration(testVal), CHIP_NO_ERROR);
397+
EXPECT_FALSE(storageDelegate.HasKey(keyName.KeyName()));
398+
399+
// Check that the value is not loaded when a new logic cluster is created
400+
ClusterLogic logic_same_endpoint_again = ClusterLogic(delegate, context);
401+
EXPECT_EQ(logic_same_endpoint_again.Init(conformance), CHIP_NO_ERROR);
402+
EXPECT_EQ(logic_same_endpoint_again.GetDefaultOpenDuration(valElapsedSNullable), CHIP_NO_ERROR);
403+
EXPECT_EQ(valElapsedSNullable, DataModel::NullNullable);
404+
405+
// Test that the calling function fails when write fails are on
406+
storageDelegate.SetRejectWrites(true);
407+
testVal.SetNonNull(12u);
408+
EXPECT_EQ(logic.SetDefaultOpenDuration(testVal), CHIP_ERROR_PERSISTED_STORAGE_FAILED);
409+
}
410+
411+
TEST_F(TestValveConfigurationAndControlClusterLogic, TestSetDefaultOpenLevel)
412+
{
413+
TestDelegate delegate;
414+
TestPersistentStorageDelegate storageDelegate;
415+
EndpointId endpoint = 0;
416+
MatterContext context = MatterContext(endpoint, storageDelegate);
417+
ClusterLogic logic = ClusterLogic(delegate, context);
418+
419+
uint8_t val8;
420+
421+
// Setting this value before initialization should fail
422+
uint8_t testVal = 5u;
423+
EXPECT_EQ(logic.SetDefaultOpenLevel(testVal), CHIP_ERROR_INCORRECT_STATE);
424+
425+
ClusterConformance conformance = { .featureMap = to_underlying(Feature::kLevel) | to_underlying(Feature::kTimeSync),
426+
.supportsDefaultOpenLevel = true,
427+
.supportsValveFault = true,
428+
.supportsLevelStep = true };
429+
EXPECT_EQ(logic.Init(conformance), CHIP_NO_ERROR);
430+
431+
EXPECT_EQ(logic.GetDefaultOpenLevel(val8), CHIP_NO_ERROR);
432+
EXPECT_EQ(val8, 100u);
433+
434+
// Lowest possible value
435+
testVal = 1u;
436+
EXPECT_EQ(logic.SetDefaultOpenLevel(testVal), CHIP_NO_ERROR);
437+
438+
// Ensure the value is accessible via the API
439+
EXPECT_EQ(logic.GetDefaultOpenLevel(val8), CHIP_NO_ERROR);
440+
EXPECT_EQ(val8, testVal);
441+
442+
// Ensure the value is persisted in the test storage
443+
StorageKeyName keyName = DefaultStorageKeyAllocator::VCCDefaultOpenLevel(endpoint);
444+
uint8_t persistedValue;
445+
uint16_t size = static_cast<uint16_t>(sizeof(persistedValue));
446+
EXPECT_TRUE(storageDelegate.HasKey(keyName.KeyName()));
447+
EXPECT_EQ(storageDelegate.SyncGetKeyValue(keyName.KeyName(), &persistedValue, size), CHIP_NO_ERROR);
448+
EXPECT_EQ(persistedValue, testVal);
449+
// Test that this doesn't exist for other endpoints. Check 1.
450+
EXPECT_FALSE(storageDelegate.HasKey(DefaultStorageKeyAllocator::VCCDefaultOpenLevel(1).KeyName()));
451+
452+
// Highest possible value
453+
testVal = 100u;
454+
EXPECT_EQ(logic.SetDefaultOpenLevel(testVal), CHIP_NO_ERROR);
455+
EXPECT_EQ(logic.GetDefaultOpenLevel(val8), CHIP_NO_ERROR);
456+
EXPECT_EQ(val8, testVal);
457+
458+
EXPECT_TRUE(storageDelegate.HasKey(keyName.KeyName()));
459+
EXPECT_EQ(storageDelegate.SyncGetKeyValue(keyName.KeyName(), &persistedValue, size), CHIP_NO_ERROR);
460+
EXPECT_EQ(persistedValue, testVal);
461+
462+
uint8_t outOfRangeVal = 0u;
463+
EXPECT_EQ(logic.SetDefaultOpenLevel(outOfRangeVal), CHIP_ERROR_INVALID_ARGUMENT);
464+
outOfRangeVal = 101u;
465+
EXPECT_EQ(logic.SetDefaultOpenLevel(outOfRangeVal), CHIP_ERROR_INVALID_ARGUMENT);
466+
467+
// Ensure the value wasn't changed
468+
EXPECT_EQ(logic.GetDefaultOpenLevel(val8), CHIP_NO_ERROR);
469+
EXPECT_EQ(val8, testVal);
470+
471+
EXPECT_TRUE(storageDelegate.HasKey(keyName.KeyName()));
472+
EXPECT_EQ(storageDelegate.SyncGetKeyValue(keyName.KeyName(), &persistedValue, size), CHIP_NO_ERROR);
473+
EXPECT_EQ(persistedValue, testVal);
474+
475+
// Set Non-default value
476+
testVal = 12u;
477+
EXPECT_EQ(logic.SetDefaultOpenLevel(testVal), CHIP_NO_ERROR);
478+
// Test that firing up a new logic cluster on the same endpoint loads the value from persisted storage
479+
ClusterLogic logic_same_endpoint = ClusterLogic(delegate, context);
480+
EXPECT_EQ(logic_same_endpoint.Init(conformance), CHIP_NO_ERROR);
481+
EXPECT_EQ(logic_same_endpoint.GetDefaultOpenLevel(val8), CHIP_NO_ERROR);
482+
EXPECT_EQ(val8, testVal);
483+
484+
// Test that a new logic cluster on a different endpoint does not load the value
485+
MatterContext context_ep1 = MatterContext(1, storageDelegate);
486+
ClusterLogic logic_different_endpoint = ClusterLogic(delegate, context_ep1);
487+
EXPECT_EQ(logic_different_endpoint.Init(conformance), CHIP_NO_ERROR);
488+
EXPECT_EQ(logic_different_endpoint.GetDefaultOpenLevel(val8), CHIP_NO_ERROR);
489+
EXPECT_EQ(val8, 100u);
490+
491+
// Test that the calling function fails when write fails are on
492+
storageDelegate.SetRejectWrites(true);
493+
testVal = 15u;
494+
EXPECT_EQ(logic.SetDefaultOpenLevel(testVal), CHIP_ERROR_PERSISTED_STORAGE_FAILED);
495+
storageDelegate.SetRejectWrites(false);
496+
497+
// Test that we get an error if this attribute is not supported
498+
ClusterLogic logic_no_level = ClusterLogic(delegate, context);
499+
ClusterConformance conformance_no_level = { .featureMap = to_underlying(Feature::kLevel) | to_underlying(Feature::kTimeSync),
500+
.supportsDefaultOpenLevel = false,
501+
.supportsValveFault = true,
502+
.supportsLevelStep = true };
503+
EXPECT_EQ(logic_no_level.Init(conformance_no_level), CHIP_NO_ERROR);
504+
EXPECT_EQ(logic_no_level.SetDefaultOpenLevel(testVal), CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
505+
}
506+
313507
} // namespace ValveConfigurationAndControl
314508
} // namespace Clusters
315509
} // namespace app

‎src/lib/support/DefaultStorageKeyAllocator.h

+7
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,13 @@ class DefaultStorageKeyAllocator
256256
// when new fabric is created, this list needs to be updated,
257257
// when client init DefaultICDClientStorage, this table needs to be loaded.
258258
static StorageKeyName ICDFabricList() { return StorageKeyName::FromConst("g/icdfl"); }
259+
260+
// Valve configuration and control
261+
static StorageKeyName VCCDefaultOpenDuration(EndpointId endpoint)
262+
{
263+
return StorageKeyName::Formatted("g/vcc/dod/%x", endpoint);
264+
}
265+
static StorageKeyName VCCDefaultOpenLevel(EndpointId endpoint) { return StorageKeyName::Formatted("g/vcc/dol/%x", endpoint); }
259266
};
260267

261268
} // namespace chip

0 commit comments

Comments
 (0)
Please sign in to comment.