/* * 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 #include #include namespace chip { namespace app { class DeferredAttribute { public: explicit DeferredAttribute(const ConcreteAttributePath & path) : mPath(path) {} bool Matches(const ConcreteAttributePath & path) const { return mPath == path; } bool IsArmed() const { return static_cast(mValue); } System::Clock::Timestamp GetFlushTime() const { return mFlushTime; } CHIP_ERROR PrepareWrite(System::Clock::Timestamp flushTime, const ByteSpan & value); void Flush(AttributePersistenceProvider & persister); private: const ConcreteAttributePath mPath; System::Clock::Timestamp mFlushTime; Platform::ScopedMemoryBufferWithSize mValue; }; /** * Decorator class for the AttributePersistenceProvider implementation that * defers writes of selected attributes. * * This class is useful to increase the flash lifetime by reducing the number * of writes of fast-changing attributes, such as CurrentLevel attribute of the * LevelControl cluster. */ class DeferredAttributePersistenceProvider : public AttributePersistenceProvider { public: DeferredAttributePersistenceProvider(AttributePersistenceProvider & persister, const Span & deferredAttributes, System::Clock::Milliseconds32 writeDelay) : mPersister(persister), mDeferredAttributes(deferredAttributes), mWriteDelay(writeDelay) {} /* * If the written attribute is one of the deferred attributes specified in the constructor, * postpone the write operation by the configured delay. If this attribute changes within the * delay period, further postpone the operation so that the actual write happens once the * attribute has remained constant for the write delay period. * * For other attributes, immediately pass the write operation to the decorated persister. */ CHIP_ERROR WriteValue(const ConcreteAttributePath & aPath, const ByteSpan & aValue) override; CHIP_ERROR ReadValue(const ConcreteAttributePath & aPath, const EmberAfAttributeMetadata * aMetadata, MutableByteSpan & aValue) override; private: void FlushAndScheduleNext(); AttributePersistenceProvider & mPersister; const Span mDeferredAttributes; const System::Clock::Milliseconds32 mWriteDelay; }; } // namespace app } // namespace chip