Skip to content

Commit 80a9f1c

Browse files
committed
Refactoring of Energy Management App to move DEM, PowerTopology, EEM/EPM out of EVSE and into bespoke files.
1 parent d04a667 commit 80a9f1c

File tree

11 files changed

+160
-437
lines changed

11 files changed

+160
-437
lines changed

examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h

+7
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,12 @@
1919
#pragma once
2020

2121
#include <DeviceEnergyManagementDelegateImpl.h>
22+
#include <DeviceEnergyManagementManager.h>
2223

2324
chip::app::Clusters::DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate();
25+
// TODO investigate this why isn't in in DEM?
26+
extern std::unique_ptr<chip::app::Clusters::DeviceEnergyManagementManager> gDEMInstance;
27+
extern std::unique_ptr<chip::app::Clusters::DeviceEnergyManagement::DeviceEnergyManagementDelegate> gDEMDelegate;
28+
29+
CHIP_ERROR DeviceEnergyManagementInit();
30+
CHIP_ERROR DeviceEnergyManagementShutdown();

examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h

-11
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,5 @@
1818

1919
#pragma once
2020

21-
#include <lib/core/CHIPError.h>
22-
2321
void EvseApplicationInit();
2422
void EvseApplicationShutdown();
25-
26-
CHIP_ERROR DeviceEnergyManagementInit();
27-
CHIP_ERROR DeviceEnergyManagementShutdown();
28-
29-
CHIP_ERROR EnergyMeterInit();
30-
CHIP_ERROR EnergyMeterShutdown();
31-
32-
CHIP_ERROR PowerTopologyInit();
33-
CHIP_ERROR PowerTopologyShutdown();

examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp

+5-282
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include <PowerTopologyDelegate.h>
2626
#include <device-energy-management-modes.h>
2727
#include <energy-evse-modes.h>
28+
#include <EnergyReportingMain.h>
29+
#include <DEMDelegate.h>
2830

2931
#include <app-common/zap-generated/ids/Attributes.h>
3032
#include <app-common/zap-generated/ids/Clusters.h>
@@ -36,7 +38,7 @@
3638
#include <lib/support/logging/CHIPLogging.h>
3739
#include <platform/Linux/NetworkCommissioningDriver.h>
3840

39-
#define ENERGY_EVSE_ENDPOINT 1
41+
static constexpr int ENERGY_EVSE_ENDPOINT = 1;
4042

4143
using namespace chip;
4244
using namespace chip::app;
@@ -51,94 +53,16 @@ using namespace chip::app::Clusters::PowerTopology;
5153
static std::unique_ptr<EnergyEvseDelegate> gEvseDelegate;
5254
static std::unique_ptr<EvseTargetsDelegate> gEvseTargetsDelegate;
5355
static std::unique_ptr<EnergyEvseManager> gEvseInstance;
54-
static std::unique_ptr<DeviceEnergyManagementDelegate> gDEMDelegate;
55-
static std::unique_ptr<DeviceEnergyManagementManager> gDEMInstance;
56+
5657
static std::unique_ptr<EVSEManufacturer> gEvseManufacturer;
57-
static std::unique_ptr<ElectricalPowerMeasurementDelegate> gEPMDelegate;
58-
static std::unique_ptr<ElectricalPowerMeasurementInstance> gEPMInstance;
59-
// Electrical Energy Measurement cluster uses ember to initialise
60-
static std::unique_ptr<ElectricalEnergyMeasurementAttrAccess> gEEMAttrAccess;
6158

62-
static std::unique_ptr<PowerTopologyDelegate> gPTDelegate;
63-
static std::unique_ptr<PowerTopologyInstance> gPTInstance;
6459

6560
EVSEManufacturer * EnergyEvse::GetEvseManufacturer()
6661
{
6762
return gEvseManufacturer.get();
6863
}
6964

70-
DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate()
71-
{
72-
VerifyOrDieWithMsg(gDEMDelegate.get() != nullptr, AppServer, "DEM Delegate is null");
73-
74-
return gDEMDelegate.get();
75-
}
76-
77-
/*
78-
* @brief Creates a Delegate and Instance for DEM
79-
*
80-
* The Instance is a container around the Delegate, so
81-
* create the Delegate first, then wrap it in the Instance
82-
* Then call the Instance->Init() to register the attribute and command handlers
83-
*/
84-
CHIP_ERROR DeviceEnergyManagementInit()
85-
{
86-
if (gDEMDelegate || gDEMInstance)
87-
{
88-
ChipLogError(AppServer, "DEM Instance or Delegate already exist.");
89-
return CHIP_ERROR_INCORRECT_STATE;
90-
}
91-
92-
gDEMDelegate = std::make_unique<DeviceEnergyManagementDelegate>();
93-
if (!gDEMDelegate)
94-
{
95-
ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementDelegate");
96-
return CHIP_ERROR_NO_MEMORY;
97-
}
98-
99-
BitMask<DeviceEnergyManagement::Feature> featureMap = GetFeatureMapFromCmdLine();
100-
101-
/* Manufacturer may optionally not support all features, commands & attributes */
102-
gDEMInstance = std::make_unique<DeviceEnergyManagementManager>(EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, featureMap);
103-
104-
if (!gDEMInstance)
105-
{
106-
ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementManager");
107-
gDEMDelegate.reset();
108-
return CHIP_ERROR_NO_MEMORY;
109-
}
110-
111-
gDEMDelegate->SetDeviceEnergyManagementInstance(*gDEMInstance);
112-
113-
CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */
114-
if (err != CHIP_NO_ERROR)
115-
{
116-
ChipLogError(AppServer, "Init failed on gDEMInstance");
117-
gDEMInstance.reset();
118-
gDEMDelegate.reset();
119-
return err;
120-
}
121-
122-
return CHIP_NO_ERROR;
123-
}
12465

125-
CHIP_ERROR DeviceEnergyManagementShutdown()
126-
{
127-
/* Do this in the order Instance first, then delegate
128-
* Ensure we call the Instance->Shutdown to free attribute & command handlers first
129-
*/
130-
if (gDEMInstance)
131-
{
132-
/* deregister attribute & command handlers */
133-
gDEMInstance->Shutdown();
134-
gDEMInstance.reset();
135-
}
136-
if (gDEMDelegate)
137-
{
138-
gDEMDelegate.reset();
139-
}
140-
return CHIP_NO_ERROR;
141-
}
14266

14367
/*
14468
* @brief Creates a Delegate and Instance for EVSE cluster
@@ -232,160 +156,6 @@ CHIP_ERROR EnergyEvseShutdown()
232156
return CHIP_NO_ERROR;
233157
}
234158

235-
/*
236-
* @brief Creates a Delegate and Instance for PowerTopology clusters
237-
*
238-
* The Instance is a container around the Delegate, so
239-
* create the Delegate first, then wrap it in the Instance
240-
* Then call the Instance->Init() to register the attribute and command handlers
241-
*/
242-
CHIP_ERROR PowerTopologyInit()
243-
{
244-
CHIP_ERROR err;
245-
246-
if (gPTDelegate || gPTInstance)
247-
{
248-
ChipLogError(AppServer, "PowerTopology Instance or Delegate already exist.");
249-
return CHIP_ERROR_INCORRECT_STATE;
250-
}
251-
252-
gPTDelegate = std::make_unique<PowerTopologyDelegate>();
253-
if (!gPTDelegate)
254-
{
255-
ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Delegate");
256-
return CHIP_ERROR_NO_MEMORY;
257-
}
258-
259-
gPTInstance =
260-
std::make_unique<PowerTopologyInstance>(EndpointId(ENERGY_EVSE_ENDPOINT), *gPTDelegate,
261-
BitMask<PowerTopology::Feature, uint32_t>(PowerTopology::Feature::kNodeTopology),
262-
BitMask<PowerTopology::OptionalAttributes, uint32_t>(0));
263-
264-
if (!gPTInstance)
265-
{
266-
ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Instance");
267-
gPTDelegate.reset();
268-
return CHIP_ERROR_NO_MEMORY;
269-
}
270-
271-
err = gPTInstance->Init(); /* Register Attribute & Command handlers */
272-
if (err != CHIP_NO_ERROR)
273-
{
274-
ChipLogError(AppServer, "Init failed on gPTInstance");
275-
gPTInstance.reset();
276-
gPTDelegate.reset();
277-
return err;
278-
}
279-
280-
return CHIP_NO_ERROR;
281-
}
282-
283-
CHIP_ERROR PowerTopologyShutdown()
284-
{
285-
/* Do this in the order Instance first, then delegate
286-
* Ensure we call the Instance->Shutdown to free attribute & command handlers first
287-
*/
288-
if (gPTInstance)
289-
{
290-
/* deregister attribute & command handlers */
291-
gPTInstance->Shutdown();
292-
gPTInstance.reset();
293-
}
294-
295-
if (gPTDelegate)
296-
{
297-
gPTDelegate.reset();
298-
}
299-
300-
return CHIP_NO_ERROR;
301-
}
302-
303-
/*
304-
* @brief Creates a Delegate and Instance for Electrical Power/Energy Measurement clusters
305-
*
306-
* The Instance is a container around the Delegate, so
307-
* create the Delegate first, then wrap it in the Instance
308-
* Then call the Instance->Init() to register the attribute and command handlers
309-
*/
310-
CHIP_ERROR EnergyMeterInit()
311-
{
312-
CHIP_ERROR err;
313-
314-
if (gEPMDelegate || gEPMInstance)
315-
{
316-
ChipLogError(AppServer, "EPM Instance or Delegate already exist.");
317-
return CHIP_ERROR_INCORRECT_STATE;
318-
}
319-
320-
gEPMDelegate = std::make_unique<ElectricalPowerMeasurementDelegate>();
321-
if (!gEPMDelegate)
322-
{
323-
ChipLogError(AppServer, "Failed to allocate memory for EPM Delegate");
324-
return CHIP_ERROR_NO_MEMORY;
325-
}
326-
327-
/* Manufacturer may optionally not support all features, commands & attributes */
328-
/* Turning on all optional features and attributes for test certification purposes */
329-
gEPMInstance = std::make_unique<ElectricalPowerMeasurementInstance>(
330-
EndpointId(ENERGY_EVSE_ENDPOINT), *gEPMDelegate,
331-
BitMask<ElectricalPowerMeasurement::Feature, uint32_t>(
332-
ElectricalPowerMeasurement::Feature::kDirectCurrent, ElectricalPowerMeasurement::Feature::kAlternatingCurrent,
333-
ElectricalPowerMeasurement::Feature::kPolyphasePower, ElectricalPowerMeasurement::Feature::kHarmonics,
334-
ElectricalPowerMeasurement::Feature::kPowerQuality),
335-
BitMask<ElectricalPowerMeasurement::OptionalAttributes, uint32_t>(
336-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRanges,
337-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeVoltage,
338-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeActiveCurrent,
339-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactiveCurrent,
340-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentCurrent,
341-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactivePower,
342-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentPower,
343-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSVoltage,
344-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSCurrent,
345-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSPower,
346-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeFrequency,
347-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributePowerFactor,
348-
ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeNeutralCurrent));
349-
350-
if (!gEPMInstance)
351-
{
352-
ChipLogError(AppServer, "Failed to allocate memory for EPM Instance");
353-
gEPMDelegate.reset();
354-
return CHIP_ERROR_NO_MEMORY;
355-
}
356-
357-
err = gEPMInstance->Init(); /* Register Attribute & Command handlers */
358-
if (err != CHIP_NO_ERROR)
359-
{
360-
ChipLogError(AppServer, "Init failed on gEPMInstance");
361-
gEPMInstance.reset();
362-
gEPMDelegate.reset();
363-
return err;
364-
}
365-
366-
return CHIP_NO_ERROR;
367-
}
368-
369-
CHIP_ERROR EnergyMeterShutdown()
370-
{
371-
/* Do this in the order Instance first, then delegate
372-
* Ensure we call the Instance->Shutdown to free attribute & command handlers first
373-
*/
374-
if (gEPMInstance)
375-
{
376-
/* deregister attribute & command handlers */
377-
gEPMInstance->Shutdown();
378-
gEPMInstance.reset();
379-
}
380-
381-
if (gEPMDelegate)
382-
{
383-
gEPMDelegate.reset();
384-
}
385-
386-
return CHIP_NO_ERROR;
387-
}
388-
389159
/*
390160
* @brief Creates a EVSEManufacturer class to hold the EVSE & DEM clusters
391161
*
@@ -460,7 +230,6 @@ void EvseApplicationInit()
460230

461231
if (PowerTopologyInit() != CHIP_NO_ERROR)
462232
{
463-
EVSEManufacturerShutdown();
464233
DeviceEnergyManagementShutdown();
465234
EnergyEvseShutdown();
466235
EnergyMeterShutdown();
@@ -473,6 +242,7 @@ void EvseApplicationInit()
473242
DeviceEnergyManagementShutdown();
474243
EnergyEvseShutdown();
475244
EnergyMeterShutdown();
245+
PowerTopologyShutdown();
476246
return;
477247
}
478248
}
@@ -491,50 +261,3 @@ void EvseApplicationShutdown()
491261
Clusters::DeviceEnergyManagementMode::Shutdown();
492262
Clusters::EnergyEvseMode::Shutdown();
493263
}
494-
495-
void emberAfElectricalEnergyMeasurementClusterInitCallback(chip::EndpointId endpointId)
496-
{
497-
VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1.
498-
VerifyOrDie(!gEEMAttrAccess);
499-
500-
gEEMAttrAccess = std::make_unique<ElectricalEnergyMeasurementAttrAccess>(
501-
BitMask<ElectricalEnergyMeasurement::Feature, uint32_t>(
502-
ElectricalEnergyMeasurement::Feature::kImportedEnergy, ElectricalEnergyMeasurement::Feature::kExportedEnergy,
503-
ElectricalEnergyMeasurement::Feature::kCumulativeEnergy, ElectricalEnergyMeasurement::Feature::kPeriodicEnergy),
504-
BitMask<ElectricalEnergyMeasurement::OptionalAttributes, uint32_t>(
505-
ElectricalEnergyMeasurement::OptionalAttributes::kOptionalAttributeCumulativeEnergyReset));
506-
507-
// Create an accuracy entry which is between +/-0.5 and +/- 5% across the range of all possible energy readings
508-
ElectricalEnergyMeasurement::Structs::MeasurementAccuracyRangeStruct::Type energyAccuracyRanges[] = {
509-
{ .rangeMin = 0,
510-
.rangeMax = 1'000'000'000'000'000, // 1 million Mwh
511-
.percentMax = MakeOptional(static_cast<chip::Percent100ths>(500)),
512-
.percentMin = MakeOptional(static_cast<chip::Percent100ths>(50)) }
513-
};
514-
515-
ElectricalEnergyMeasurement::Structs::MeasurementAccuracyStruct::Type accuracy = {
516-
.measurementType = MeasurementTypeEnum::kElectricalEnergy,
517-
.measured = true,
518-
.minMeasuredValue = 0,
519-
.maxMeasuredValue = 1'000'000'000'000'000, // 1 million Mwh
520-
.accuracyRanges =
521-
DataModel::List<const ElectricalEnergyMeasurement::Structs::MeasurementAccuracyRangeStruct::Type>(energyAccuracyRanges)
522-
};
523-
524-
// Example of setting CumulativeEnergyReset structure - for now set these to 0
525-
// but the manufacturer may want to store these in non volatile storage for timestamp (based on epoch_s)
526-
ElectricalEnergyMeasurement::Structs::CumulativeEnergyResetStruct::Type resetStruct = {
527-
.importedResetTimestamp = MakeOptional(MakeNullable(static_cast<uint32_t>(0))),
528-
.exportedResetTimestamp = MakeOptional(MakeNullable(static_cast<uint32_t>(0))),
529-
.importedResetSystime = MakeOptional(MakeNullable(static_cast<uint64_t>(0))),
530-
.exportedResetSystime = MakeOptional(MakeNullable(static_cast<uint64_t>(0))),
531-
};
532-
533-
if (gEEMAttrAccess)
534-
{
535-
gEEMAttrAccess->Init();
536-
537-
SetMeasurementAccuracy(endpointId, accuracy);
538-
SetCumulativeReset(endpointId, MakeOptional(resetStruct));
539-
}
540-
}

0 commit comments

Comments
 (0)