Skip to content

Commit 53d3b3a

Browse files
authored
[QPG] lighting-app: Persist level and color (project-chip#31601)
Use DeferredAttributePersistenceProvider to save CurrentX, CurrentY and CurrentLevel attributes. Restore them on startup.
1 parent a386c83 commit 53d3b3a

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

examples/lighting-app/qpg/src/AppTask.cpp

+23
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include <app/util/attribute-storage.h>
4444
#include <lib/support/TypeTraits.h>
4545

46+
#include <app/DeferredAttributePersistenceProvider.h>
4647
#include <credentials/DeviceAttestationCredsProvider.h>
4748
#include <credentials/examples/DeviceAttestationCredsExample.h>
4849

@@ -72,6 +73,7 @@ using namespace ::chip::DeviceLayer;
7273
static uint8_t countdown = 0;
7374

7475
namespace {
76+
constexpr EndpointId kLightEndpointId = 1;
7577
TaskHandle_t sAppTaskHandle;
7678
QueueHandle_t sAppEventQueue;
7779

@@ -93,6 +95,25 @@ StaticTask_t appTaskStruct;
9395
Clusters::Identify::EffectIdentifierEnum sIdentifyEffect = Clusters::Identify::EffectIdentifierEnum::kStopEffect;
9496
chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
9597

98+
// Define a custom attribute persister which makes actual write of the attribute value
99+
// to the non-volatile storage only when it has remained constant for 5 seconds. This is to reduce
100+
// the flash wearout when the attribute changes frequently as a result of commands.
101+
// DeferredAttribute object describes a deferred attribute, but also holds a buffer with a value to
102+
// be written, so it must live so long as the DeferredAttributePersistenceProvider object.
103+
//
104+
DeferredAttribute gPersisters[] = { DeferredAttribute(ConcreteAttributePath(kLightEndpointId, Clusters::ColorControl::Id,
105+
Clusters::ColorControl::Attributes::CurrentX::Id)),
106+
DeferredAttribute(ConcreteAttributePath(kLightEndpointId, Clusters::ColorControl::Id,
107+
Clusters::ColorControl::Attributes::CurrentY::Id)),
108+
DeferredAttribute(ConcreteAttributePath(kLightEndpointId, Clusters::LevelControl::Id,
109+
Clusters::LevelControl::Attributes::CurrentLevel::Id))
110+
111+
};
112+
113+
DeferredAttributePersistenceProvider gDeferredAttributePersister(Server::GetInstance().GetDefaultAttributePersister(),
114+
Span<DeferredAttribute>(gPersisters, 3),
115+
System::Clock::Milliseconds32(5000));
116+
96117
/**********************************************************
97118
* Identify Callbacks
98119
*********************************************************/
@@ -250,6 +271,8 @@ void AppTask::InitServer(intptr_t arg)
250271

251272
chip::Server::GetInstance().Init(initParams);
252273

274+
app::SetAttributePersistenceProvider(&gDeferredAttributePersister);
275+
253276
#if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
254277
chip::app::DnssdServer::Instance().SetExtendedDiscoveryTimeoutSecs(extDiscTimeoutSecs);
255278
#endif

examples/lighting-app/qpg/src/ZclCallbacks.cpp

+29-1
Original file line numberDiff line numberDiff line change
@@ -160,13 +160,41 @@ void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath &
160160
*/
161161
void emberAfOnOffClusterInitCallback(EndpointId endpoint)
162162
{
163+
uint8_t levelValue;
164+
XyColor_t xy;
163165
bool onOffValue = false;
166+
app::DataModel::Nullable<uint8_t> currentLevel;
167+
EmberAfStatus status;
164168

165-
EmberAfStatus status = OnOff::Attributes::OnOff::Get(1, &onOffValue);
169+
status = OnOff::Attributes::OnOff::Get(1, &onOffValue);
166170

167171
if (status == EMBER_ZCL_STATUS_SUCCESS)
168172
{
169173
LightingMgr().InitiateAction(onOffValue ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION, 0, 1,
170174
(uint8_t *) onOffValue);
171175
}
176+
177+
/* restore values saved by DeferredAttributePersistenceProvider */
178+
status = LevelControl::Attributes::CurrentLevel::Get(endpoint, currentLevel);
179+
if (status != EMBER_ZCL_STATUS_SUCCESS || currentLevel.IsNull())
180+
{
181+
return;
182+
}
183+
184+
levelValue = currentLevel.Value();
185+
186+
status = ColorControl::Attributes::CurrentY::Get(endpoint, &xy.y);
187+
if (status != EMBER_ZCL_STATUS_SUCCESS)
188+
{
189+
return;
190+
}
191+
status = ColorControl::Attributes::CurrentX::Get(endpoint, &xy.x);
192+
if (status != EMBER_ZCL_STATUS_SUCCESS)
193+
{
194+
return;
195+
}
196+
ChipLogProgress(Zcl, "restore level: %u", levelValue);
197+
LightingMgr().InitiateAction(LightingManager::LEVEL_ACTION, 0, 1, &levelValue);
198+
ChipLogProgress(Zcl, "restore XY color: %u|%u", xy.x, xy.y);
199+
LightingMgr().InitiateAction(LightingManager::COLOR_ACTION_XY, 0, sizeof(xy), (uint8_t *) &xy);
172200
}

examples/lighting-app/qpg/zap/light.matter

+2-2
Original file line numberDiff line numberDiff line change
@@ -2330,8 +2330,8 @@ endpoint 1 {
23302330
ram attribute currentHue default = 0x00;
23312331
ram attribute currentSaturation default = 0x00;
23322332
ram attribute remainingTime default = 0x0000;
2333-
ram attribute currentX default = 0x616B;
2334-
ram attribute currentY default = 0x607D;
2333+
persist attribute currentX default = 0x616B;
2334+
persist attribute currentY default = 0x607D;
23352335
ram attribute colorTemperatureMireds default = 0x00FA;
23362336
ram attribute colorMode default = 0x01;
23372337
ram attribute options default = 0x00;

examples/lighting-app/qpg/zap/light.zap

+3-3
Original file line numberDiff line numberDiff line change
@@ -5310,7 +5310,7 @@
53105310
"side": "server",
53115311
"type": "int16u",
53125312
"included": 1,
5313-
"storageOption": "RAM",
5313+
"storageOption": "NVM",
53145314
"singleton": 0,
53155315
"bounded": 0,
53165316
"defaultValue": "0x616B",
@@ -5326,7 +5326,7 @@
53265326
"side": "server",
53275327
"type": "int16u",
53285328
"included": 1,
5329-
"storageOption": "RAM",
5329+
"storageOption": "NVM",
53305330
"singleton": 0,
53315331
"bounded": 0,
53325332
"defaultValue": "0x607D",
@@ -5980,4 +5980,4 @@
59805980
"networkId": 0
59815981
}
59825982
]
5983-
}
5983+
}

0 commit comments

Comments
 (0)