blob: 66d4388df6d565e0c17ba66c9d91f667a4118169 [file] [log] [blame]
#pragma once
#include <app/ConcreteAttributePath.h>
#include "DataModel.h"
// This is the interface to the attribute implementation that permits retrieval of metadata about
// the attribute as well as set/get the underlying value.
class AttributeInterface
{
public:
virtual ~AttributeInterface() = default;
// Get the ID of this attribute. Shortcut for GetMetadata().attributeId
virtual chip::AttributeId GetId() = 0;
// Get the metadata of this attribute, suitable for advertising.
virtual const EmberAfAttributeMetadata & GetMetadata() = 0;
virtual chip::CharSpan GetName() = 0;
// List attribes should override these to get list write notifications.
virtual void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) {}
virtual void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) {}
// Write a single value to the attribute.
virtual CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) = 0;
// Read the contents of the attribute.
virtual CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) = 0;
};
// This is the base type for implementing an attribute
template <typename Type>
struct Attribute : public AttributeInterface
{
Attribute(chip::CharSpan name, chip::AttributeId id, EmberAfAttributeMask mask, EmberAfAttributeType type, size_t size,
Type value = Type()) :
mMetadata(EmberAfAttributeMetadata{ id, type, (uint16_t) size, mask, ZAP_EMPTY_DEFAULT() }),
mData(value), mName(name)
{}
chip::AttributeId GetId() override { return mMetadata.attributeId; }
const EmberAfAttributeMetadata & GetMetadata() override { return mMetadata; }
chip::CharSpan GetName() override { return mName; }
CHIP_ERROR Write(const chip::app::ConcreteDataAttributePath & aPath, chip::app::AttributeValueDecoder & aDecoder) override
{
return chip::app::DataModel::Decode(aPath, aDecoder, mData);
}
CHIP_ERROR Read(const chip::app::ConcreteReadAttributePath & aPath, chip::app::AttributeValueEncoder & aEncoder) override
{
return chip::app::DataModel::Encode(aPath, aEncoder, mData);
}
void operator=(const Type & value) { mData = value; }
const Type & Peek() const { return mData; }
protected:
EmberAfAttributeMetadata mMetadata;
Type mData;
chip::CharSpan mName;
};
// This specialization handles list writes and reverts if the write fails.
template <typename Type>
struct ListAttribute : public Attribute<Type>
{
using Attribute<Type>::Attribute;
void ListWriteBegin(const chip::app::ConcreteAttributePath & aPath) override { mBackup = this->mData; }
void ListWriteEnd(const chip::app::ConcreteAttributePath & aPath, bool aWriteWasSuccessful) override
{
if (aWriteWasSuccessful)
{
mBackup = Type();
}
else
{
this->mData = std::move(mBackup);
}
}
Type mBackup;
};