blob: d3508ad80b51005f80c6f9be6025b412d742a0c0 [file]
/**
*
* Copyright (c) 2025 Project CHIP Authors
* All rights reserved.
*
* 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.
*/
/**
* @file CommodityTariffServer.h
* @brief Header for Matter Commodity Tariff Cluster implementation
*
* This file contains the implementation of the Matter Commodity Tariff Cluster,
* including attribute management, data structures, and server-side handling.
*/
#pragma once
#include "CommodityTariffAttrsDataMgmt.h"
#include <app/AttributeAccessInterface.h>
#include <app/CommandHandlerInterface.h>
#include <app/ConcreteAttributePath.h>
#include <app/InteractionModelEngine.h>
#include <app/reporting/reporting.h>
#include <array>
#include <cstdint>
#include <functional>
namespace chip {
namespace app {
namespace Clusters {
namespace CommodityTariff {
/**
* @class Delegate
* @brief Core tariff data management and processing class
*
* This class provides:
* - Storage for both primary and current attributes
* - Tariff update processing pipeline
* - Attribute access methods
* - Data validation and change management
*/
class Delegate
{
public:
virtual ~Delegate() = default;
void SetEndpointId(EndpointId aEndpoint) { mEndpointId = aEndpoint; }
/**
* @brief Set the current feature map for this tariff instance
* @param aFeature The current feature map value
*/
void SetFeatures(BitMask<Feature> aFeature) { mFeature = aFeature; }
bool HasFeature(Feature aFeature) { return mFeature.Has(aFeature); }
void SetTariffUpdCb(std::function<void(bool, const AttributeId *, size_t)> cb) { mTariffDataUpdatedCb = cb; }
// Attribute accessors - manually defined for each attribute
DataModel::Nullable<Globals::TariffUnitEnum> & GetTariffUnit() { return mTariffUnit_MgmtObj.GetValue(); }
DataModel::Nullable<uint32_t> & GetStartDate() { return mStartDate_MgmtObj.GetValue(); }
DataModel::Nullable<int16_t> & GetDefaultRandomizationOffset() { return mDefaultRandomizationOffset_MgmtObj.GetValue(); }
DataModel::Nullable<DayEntryRandomizationTypeEnum> & GetDefaultRandomizationType()
{
return mDefaultRandomizationType_MgmtObj.GetValue();
}
DataModel::Nullable<Structs::TariffInformationStruct::Type> & GetTariffInfo() { return mTariffInfo_MgmtObj.GetValue(); }
DataModel::Nullable<DataModel::List<Structs::DayEntryStruct::Type>> & GetDayEntries() { return mDayEntries_MgmtObj.GetValue(); }
DataModel::Nullable<DataModel::List<Structs::DayPatternStruct::Type>> & GetDayPatterns()
{
return mDayPatterns_MgmtObj.GetValue();
}
DataModel::Nullable<DataModel::List<Structs::TariffComponentStruct::Type>> & GetTariffComponents()
{
return mTariffComponents_MgmtObj.GetValue();
}
DataModel::Nullable<DataModel::List<Structs::TariffPeriodStruct::Type>> & GetTariffPeriods()
{
return mTariffPeriods_MgmtObj.GetValue();
}
DataModel::Nullable<DataModel::List<Structs::DayStruct::Type>> & GetIndividualDays()
{
return mIndividualDays_MgmtObj.GetValue();
}
DataModel::Nullable<DataModel::List<Structs::CalendarPeriodStruct::Type>> & GetCalendarPeriods()
{
return mCalendarPeriods_MgmtObj.GetValue();
}
enum CommodityTariffAttrTypeEnum
{
kTariffUnit,
kStartDate,
kDefaultRandomizationOffset,
kDefaultRandomizationType,
kTariffInfo,
kDayEntries,
kDayPatterns,
kTariffComponents,
kTariffPeriods,
kIndividualDays,
kCalendarPeriods,
kAttrMax
};
/**
* @brief Get the management object for a given attribute type enum
* @param aType The attribute type enum to retrieve
* @return Reference to the corresponding management object
*/
CommodityTariffAttrsDataMgmt::CTC_BaseDataClassBase & GetMgmtObj(CommodityTariffAttrTypeEnum aType);
private:
// Primary attribute storage and management
TariffUnitDataClass mTariffUnit_MgmtObj{};
StartDateDataClass mStartDate_MgmtObj{};
DefaultRandomizationOffsetDataClass mDefaultRandomizationOffset_MgmtObj{};
DefaultRandomizationTypeDataClass mDefaultRandomizationType_MgmtObj{};
TariffInfoDataClass mTariffInfo_MgmtObj{};
DayEntriesDataClass mDayEntries_MgmtObj{};
DayPatternsDataClass mDayPatterns_MgmtObj{};
TariffComponentsDataClass mTariffComponents_MgmtObj{};
TariffPeriodsDataClass mTariffPeriods_MgmtObj{};
IndividualDaysDataClass mIndividualDays_MgmtObj{};
CalendarPeriodsDataClass mCalendarPeriods_MgmtObj{};
protected:
EndpointId mEndpointId = 0; ///< Associated Matter endpoint ID
BitMask<Feature> mFeature;
std::function<void(bool, const AttributeId *, size_t)> mTariffDataUpdatedCb;
bool DelayedTariffUpdateIsActive = false;
};
/**
* @class CommodityTariffServer
* @brief Matter server implementation for the Commodity Tariff cluster
*
* This class handles:
* - Attribute access interface
* - Command handling
* - Cluster feature management
*/
class Instance : public AttributeAccessInterface, public CommandHandlerInterface
{
public:
/**
* @brief Construct a new Commodity Tariff Server instance
* @param aEndpointId The Matter endpoint ID
* @param aProvider The data provider delegate
* @param aFeature Bitmask of supported features
*/
Instance(EndpointId aEndpointId, Delegate & aDelegate, Feature aFeature) :
AttributeAccessInterface(MakeOptional(aEndpointId), Id), CommandHandlerInterface(MakeOptional(aEndpointId), Id),
mDelegate(aDelegate), mFeature(aFeature)
{
/* set the base class delegates endpointId */
mDelegate.SetEndpointId(aEndpointId);
mEndpointId = aEndpointId;
mDelegate.SetTariffUpdCb([this](bool is_erased, const AttributeId * updatedAttrIds, size_t count) {
this->TariffDataUpdatedCb(is_erased, updatedAttrIds, count);
});
mDelegate.SetFeatures(aFeature);
}
~Instance() { Shutdown(); }
CHIP_ERROR Init();
void Shutdown();
bool HasFeature(Feature aFeature) const;
void AttributeUpdCb(AttributeId aAttrId)
{
ChipLogProgress(NotSpecified, "EGW-CTC: The value for attribute (Id %" PRIu32 ") updated", aAttrId);
MatterReportingAttributeChangeCallback(mEndpointId, CommodityTariff::Id, aAttrId);
}
void TariffTimeAttrsSync();
/**
* @struct CurrentTariffAttrsCtx
* @brief Context for current tariff attributes
*/
struct CurrentTariffAttrsCtx
{
Delegate * mTariffProvider;
EndpointId mEndpointId;
};
private:
Delegate & mDelegate;
BitMask<Feature> mFeature;
EndpointId mEndpointId;
// Current attributes storage
DataModel::Nullable<Structs::DayStruct::Type> mCurrentDay;
DataModel::Nullable<Structs::DayStruct::Type> mNextDay;
DataModel::Nullable<Structs::DayEntryStruct::Type> mCurrentDayEntry;
DataModel::Nullable<Structs::DayEntryStruct::Type> mNextDayEntry;
DataModel::Nullable<uint32_t> mCurrentDayEntryDate;
DataModel::Nullable<uint32_t> mNextDayEntryDate;
TariffComponentsDataClass mCurrentTariffComponents_MgmtObj{};
TariffComponentsDataClass mNextTariffComponents_MgmtObj{};
// Attribute accessors
DataModel::Nullable<Structs::DayStruct::Type> & GetCurrentDay() { return mCurrentDay; }
DataModel::Nullable<Structs::DayStruct::Type> & GetNextDay() { return mNextDay; }
DataModel::Nullable<Structs::DayEntryStruct::Type> & GetCurrentDayEntry() { return mCurrentDayEntry; }
DataModel::Nullable<Structs::DayEntryStruct::Type> & GetNextDayEntry() { return mNextDayEntry; }
DataModel::Nullable<uint32_t> & GetCurrentDayEntryDate() { return mCurrentDayEntryDate; }
DataModel::Nullable<uint32_t> & GetNextDayEntryDate() { return mNextDayEntryDate; }
template <typename T>
CHIP_ERROR SetValue(T & currValue, T & newValue, uint32_t attrId);
CHIP_ERROR SetCurrentDay(DataModel::Nullable<Structs::DayStruct::Type> & newValue)
{
return SetValue(mCurrentDay, newValue, Attributes::CurrentDay::Id);
}
CHIP_ERROR SetNextDay(DataModel::Nullable<Structs::DayStruct::Type> & newValue)
{
return SetValue(mNextDay, newValue, Attributes::NextDay::Id);
}
CHIP_ERROR SetCurrentDayEntry(DataModel::Nullable<Structs::DayEntryStruct::Type> & newValue)
{
return SetValue(mCurrentDayEntry, newValue, Attributes::CurrentDayEntry::Id);
}
CHIP_ERROR SetNextDayEntry(DataModel::Nullable<Structs::DayEntryStruct::Type> & newValue)
{
return SetValue(mNextDayEntry, newValue, Attributes::NextDayEntry::Id);
}
CHIP_ERROR SetCurrentDayEntryDate(DataModel::Nullable<uint32_t> & newValue)
{
return SetValue(mCurrentDayEntryDate, newValue, Attributes::CurrentDayEntryDate::Id);
}
CHIP_ERROR SetNextDayEntryDate(DataModel::Nullable<uint32_t> & newValue)
{
return SetValue(mNextDayEntryDate, newValue, Attributes::NextDayEntryDate::Id);
}
DataModel::Nullable<DataModel::List<Structs::TariffComponentStruct::Type>> & GetCurrentTariffComponents()
{
return mCurrentTariffComponents_MgmtObj.GetValue();
}
DataModel::Nullable<DataModel::List<Structs::TariffComponentStruct::Type>> & GetNextTariffComponents()
{
return mNextTariffComponents_MgmtObj.GetValue();
}
CurrentTariffAttrsCtx mServerTariffAttrsCtx;
void TariffDataUpdatedCb(bool is_erased, const AttributeId * aUpdatedAttrIds, size_t aCount);
void ResetCurrentAttributes();
// AttributeAccessInterface implementation
CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override;
// CommandHandlerInterface implementation
void InvokeCommand(HandlerContext & handlerContext) override;
// Command handlers
void HandleGetDayEntry(HandlerContext & ctx, const Commands::GetDayEntry::DecodableType & commandData);
void HandleGetTariffComponent(HandlerContext & ctx, const Commands::GetTariffComponent::DecodableType & commandData);
// Current attrs (time depended) update methods
void InitCurrentAttrs();
CHIP_ERROR UpdateCurrentAttrs();
CHIP_ERROR UpdateDayInformation(uint32_t now);
CHIP_ERROR UpdateDayEntryInformation(uint32_t now);
void DeinitCurrentAttrs();
};
} // namespace CommodityTariff
} // namespace Clusters
} // namespace app
} // namespace chip