From 80a9f1cc0c567024307e167ea452b1fe8a4e0eb4 Mon Sep 17 00:00:00 2001 From: James Harrow Date: Tue, 17 Sep 2024 09:47:34 +0100 Subject: [PATCH] Refactoring of Energy Management App to move DEM, PowerTopology, EEM/EPM out of EVSE and into bespoke files. --- .../include/DEMDelegate.h | 7 + .../energy-evse/include/EnergyEvseMain.h | 11 - .../energy-evse/src/EnergyEvseMain.cpp | 287 +----------------- .../water-heater/include/WaterHeaterMain.h | 32 -- .../water-heater/include/WhmManufacturer.h | 49 ++- .../water-heater/src/WaterHeaterMain.cpp | 100 ------ .../water-heater/src/WhmMain.cpp | 58 +++- .../water-heater/src/WhmManufacturer.cpp | 37 +++ .../energy-management-app/esp32/main/main.cpp | 6 +- examples/energy-management-app/linux/BUILD.gn | 3 +- examples/energy-management-app/linux/main.cpp | 7 +- 11 files changed, 160 insertions(+), 437 deletions(-) delete mode 100644 examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h delete mode 100644 examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h b/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h index ac5cc5000e71b9..a64bca8df78f5f 100644 --- a/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h +++ b/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h @@ -19,5 +19,12 @@ #pragma once #include +#include chip::app::Clusters::DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate(); +// TODO investigate this why isn't in in DEM? +extern std::unique_ptr gDEMInstance; +extern std::unique_ptr gDEMDelegate; + +CHIP_ERROR DeviceEnergyManagementInit(); +CHIP_ERROR DeviceEnergyManagementShutdown(); \ No newline at end of file diff --git a/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h index 07dce510e9b38c..2e7e29537ef3b4 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h +++ b/examples/energy-management-app/energy-management-common/energy-evse/include/EnergyEvseMain.h @@ -18,16 +18,5 @@ #pragma once -#include - void EvseApplicationInit(); void EvseApplicationShutdown(); - -CHIP_ERROR DeviceEnergyManagementInit(); -CHIP_ERROR DeviceEnergyManagementShutdown(); - -CHIP_ERROR EnergyMeterInit(); -CHIP_ERROR EnergyMeterShutdown(); - -CHIP_ERROR PowerTopologyInit(); -CHIP_ERROR PowerTopologyShutdown(); diff --git a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp index 8e900c0948008a..77e73fd0b7b685 100644 --- a/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp +++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseMain.cpp @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include #include @@ -36,7 +38,7 @@ #include #include -#define ENERGY_EVSE_ENDPOINT 1 +static constexpr int ENERGY_EVSE_ENDPOINT = 1; using namespace chip; using namespace chip::app; @@ -51,94 +53,16 @@ using namespace chip::app::Clusters::PowerTopology; static std::unique_ptr gEvseDelegate; static std::unique_ptr gEvseTargetsDelegate; static std::unique_ptr gEvseInstance; -static std::unique_ptr gDEMDelegate; -static std::unique_ptr gDEMInstance; + static std::unique_ptr gEvseManufacturer; -static std::unique_ptr gEPMDelegate; -static std::unique_ptr gEPMInstance; -// Electrical Energy Measurement cluster uses ember to initialise -static std::unique_ptr gEEMAttrAccess; -static std::unique_ptr gPTDelegate; -static std::unique_ptr gPTInstance; EVSEManufacturer * EnergyEvse::GetEvseManufacturer() { return gEvseManufacturer.get(); } -DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate() -{ - VerifyOrDieWithMsg(gDEMDelegate.get() != nullptr, AppServer, "DEM Delegate is null"); - - return gDEMDelegate.get(); -} - -/* - * @brief Creates a Delegate and Instance for DEM - * - * The Instance is a container around the Delegate, so - * create the Delegate first, then wrap it in the Instance - * Then call the Instance->Init() to register the attribute and command handlers - */ -CHIP_ERROR DeviceEnergyManagementInit() -{ - if (gDEMDelegate || gDEMInstance) - { - ChipLogError(AppServer, "DEM Instance or Delegate already exist."); - return CHIP_ERROR_INCORRECT_STATE; - } - - gDEMDelegate = std::make_unique(); - if (!gDEMDelegate) - { - ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementDelegate"); - return CHIP_ERROR_NO_MEMORY; - } - - BitMask featureMap = GetFeatureMapFromCmdLine(); - - /* Manufacturer may optionally not support all features, commands & attributes */ - gDEMInstance = std::make_unique(EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, featureMap); - - if (!gDEMInstance) - { - ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementManager"); - gDEMDelegate.reset(); - return CHIP_ERROR_NO_MEMORY; - } - - gDEMDelegate->SetDeviceEnergyManagementInstance(*gDEMInstance); - - CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */ - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Init failed on gDEMInstance"); - gDEMInstance.reset(); - gDEMDelegate.reset(); - return err; - } - - return CHIP_NO_ERROR; -} -CHIP_ERROR DeviceEnergyManagementShutdown() -{ - /* Do this in the order Instance first, then delegate - * Ensure we call the Instance->Shutdown to free attribute & command handlers first - */ - if (gDEMInstance) - { - /* deregister attribute & command handlers */ - gDEMInstance->Shutdown(); - gDEMInstance.reset(); - } - if (gDEMDelegate) - { - gDEMDelegate.reset(); - } - return CHIP_NO_ERROR; -} /* * @brief Creates a Delegate and Instance for EVSE cluster @@ -232,160 +156,6 @@ CHIP_ERROR EnergyEvseShutdown() return CHIP_NO_ERROR; } -/* - * @brief Creates a Delegate and Instance for PowerTopology clusters - * - * The Instance is a container around the Delegate, so - * create the Delegate first, then wrap it in the Instance - * Then call the Instance->Init() to register the attribute and command handlers - */ -CHIP_ERROR PowerTopologyInit() -{ - CHIP_ERROR err; - - if (gPTDelegate || gPTInstance) - { - ChipLogError(AppServer, "PowerTopology Instance or Delegate already exist."); - return CHIP_ERROR_INCORRECT_STATE; - } - - gPTDelegate = std::make_unique(); - if (!gPTDelegate) - { - ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Delegate"); - return CHIP_ERROR_NO_MEMORY; - } - - gPTInstance = - std::make_unique(EndpointId(ENERGY_EVSE_ENDPOINT), *gPTDelegate, - BitMask(PowerTopology::Feature::kNodeTopology), - BitMask(0)); - - if (!gPTInstance) - { - ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Instance"); - gPTDelegate.reset(); - return CHIP_ERROR_NO_MEMORY; - } - - err = gPTInstance->Init(); /* Register Attribute & Command handlers */ - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Init failed on gPTInstance"); - gPTInstance.reset(); - gPTDelegate.reset(); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR PowerTopologyShutdown() -{ - /* Do this in the order Instance first, then delegate - * Ensure we call the Instance->Shutdown to free attribute & command handlers first - */ - if (gPTInstance) - { - /* deregister attribute & command handlers */ - gPTInstance->Shutdown(); - gPTInstance.reset(); - } - - if (gPTDelegate) - { - gPTDelegate.reset(); - } - - return CHIP_NO_ERROR; -} - -/* - * @brief Creates a Delegate and Instance for Electrical Power/Energy Measurement clusters - * - * The Instance is a container around the Delegate, so - * create the Delegate first, then wrap it in the Instance - * Then call the Instance->Init() to register the attribute and command handlers - */ -CHIP_ERROR EnergyMeterInit() -{ - CHIP_ERROR err; - - if (gEPMDelegate || gEPMInstance) - { - ChipLogError(AppServer, "EPM Instance or Delegate already exist."); - return CHIP_ERROR_INCORRECT_STATE; - } - - gEPMDelegate = std::make_unique(); - if (!gEPMDelegate) - { - ChipLogError(AppServer, "Failed to allocate memory for EPM Delegate"); - return CHIP_ERROR_NO_MEMORY; - } - - /* Manufacturer may optionally not support all features, commands & attributes */ - /* Turning on all optional features and attributes for test certification purposes */ - gEPMInstance = std::make_unique( - EndpointId(ENERGY_EVSE_ENDPOINT), *gEPMDelegate, - BitMask( - ElectricalPowerMeasurement::Feature::kDirectCurrent, ElectricalPowerMeasurement::Feature::kAlternatingCurrent, - ElectricalPowerMeasurement::Feature::kPolyphasePower, ElectricalPowerMeasurement::Feature::kHarmonics, - ElectricalPowerMeasurement::Feature::kPowerQuality), - BitMask( - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRanges, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeVoltage, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeActiveCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactiveCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeReactivePower, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeApparentPower, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSVoltage, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSCurrent, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeRMSPower, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeFrequency, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributePowerFactor, - ElectricalPowerMeasurement::OptionalAttributes::kOptionalAttributeNeutralCurrent)); - - if (!gEPMInstance) - { - ChipLogError(AppServer, "Failed to allocate memory for EPM Instance"); - gEPMDelegate.reset(); - return CHIP_ERROR_NO_MEMORY; - } - - err = gEPMInstance->Init(); /* Register Attribute & Command handlers */ - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Init failed on gEPMInstance"); - gEPMInstance.reset(); - gEPMDelegate.reset(); - return err; - } - - return CHIP_NO_ERROR; -} - -CHIP_ERROR EnergyMeterShutdown() -{ - /* Do this in the order Instance first, then delegate - * Ensure we call the Instance->Shutdown to free attribute & command handlers first - */ - if (gEPMInstance) - { - /* deregister attribute & command handlers */ - gEPMInstance->Shutdown(); - gEPMInstance.reset(); - } - - if (gEPMDelegate) - { - gEPMDelegate.reset(); - } - - return CHIP_NO_ERROR; -} - /* * @brief Creates a EVSEManufacturer class to hold the EVSE & DEM clusters * @@ -460,7 +230,6 @@ void EvseApplicationInit() if (PowerTopologyInit() != CHIP_NO_ERROR) { - EVSEManufacturerShutdown(); DeviceEnergyManagementShutdown(); EnergyEvseShutdown(); EnergyMeterShutdown(); @@ -473,6 +242,7 @@ void EvseApplicationInit() DeviceEnergyManagementShutdown(); EnergyEvseShutdown(); EnergyMeterShutdown(); + PowerTopologyShutdown(); return; } } @@ -491,50 +261,3 @@ void EvseApplicationShutdown() Clusters::DeviceEnergyManagementMode::Shutdown(); Clusters::EnergyEvseMode::Shutdown(); } - -void emberAfElectricalEnergyMeasurementClusterInitCallback(chip::EndpointId endpointId) -{ - VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1. - VerifyOrDie(!gEEMAttrAccess); - - gEEMAttrAccess = std::make_unique( - BitMask( - ElectricalEnergyMeasurement::Feature::kImportedEnergy, ElectricalEnergyMeasurement::Feature::kExportedEnergy, - ElectricalEnergyMeasurement::Feature::kCumulativeEnergy, ElectricalEnergyMeasurement::Feature::kPeriodicEnergy), - BitMask( - ElectricalEnergyMeasurement::OptionalAttributes::kOptionalAttributeCumulativeEnergyReset)); - - // Create an accuracy entry which is between +/-0.5 and +/- 5% across the range of all possible energy readings - ElectricalEnergyMeasurement::Structs::MeasurementAccuracyRangeStruct::Type energyAccuracyRanges[] = { - { .rangeMin = 0, - .rangeMax = 1'000'000'000'000'000, // 1 million Mwh - .percentMax = MakeOptional(static_cast(500)), - .percentMin = MakeOptional(static_cast(50)) } - }; - - ElectricalEnergyMeasurement::Structs::MeasurementAccuracyStruct::Type accuracy = { - .measurementType = MeasurementTypeEnum::kElectricalEnergy, - .measured = true, - .minMeasuredValue = 0, - .maxMeasuredValue = 1'000'000'000'000'000, // 1 million Mwh - .accuracyRanges = - DataModel::List(energyAccuracyRanges) - }; - - // Example of setting CumulativeEnergyReset structure - for now set these to 0 - // but the manufacturer may want to store these in non volatile storage for timestamp (based on epoch_s) - ElectricalEnergyMeasurement::Structs::CumulativeEnergyResetStruct::Type resetStruct = { - .importedResetTimestamp = MakeOptional(MakeNullable(static_cast(0))), - .exportedResetTimestamp = MakeOptional(MakeNullable(static_cast(0))), - .importedResetSystime = MakeOptional(MakeNullable(static_cast(0))), - .exportedResetSystime = MakeOptional(MakeNullable(static_cast(0))), - }; - - if (gEEMAttrAccess) - { - gEEMAttrAccess->Init(); - - SetMeasurementAccuracy(endpointId, accuracy); - SetCumulativeReset(endpointId, MakeOptional(resetStruct)); - } -} diff --git a/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h b/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h deleted file mode 100644 index 819ff9e4d160ca..00000000000000 --- a/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Copyright (c) 2024 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. - */ - -#pragma once - -namespace chip { -namespace app { -namespace Clusters { -namespace WaterHeaterManagement { - -void FullWhmApplicationInit(); -void FullWhmApplicationShutdown(); - -} // namespace WaterHeaterManagement -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h b/examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h index 3a48b467ee22c5..9f5235bdbdfab5 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h +++ b/examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h @@ -18,7 +18,11 @@ #pragma once +#include #include +#include +#include + #include #include @@ -36,7 +40,16 @@ namespace WaterHeaterManagement { class WhmManufacturer : public DeviceEnergyManagement::DEMManufacturerDelegate { public: - WhmManufacturer(WaterHeaterManagementInstance * whmInstance) { mWhmInstance = whmInstance; } + WhmManufacturer(WaterHeaterManagementInstance * whmInstance, + ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * aEPMInstance, + PowerTopology::PowerTopologyInstance * aPTInstance, + DeviceEnergyManagementManager * aDEMInstance) + { + mWhmInstance = whmInstance; + mEPMInstance = aEPMInstance; + mPTInstance = aPTInstance; + mDEMInstance = aDEMInstance; + } WaterHeaterManagementInstance * GetWhmInstance() { return mWhmInstance; } @@ -50,6 +63,33 @@ class WhmManufacturer : public DeviceEnergyManagement::DEMManufacturerDelegate return nullptr; } + ElectricalPowerMeasurement::ElectricalPowerMeasurementDelegate * GetEPMDelegate() + { + if (mEPMInstance) + { + return mEPMInstance->GetDelegate(); + } + return nullptr; + } + + PowerTopology::PowerTopologyDelegate * GetPTDelegate() + { + if (mPTInstance) + { + return mPTInstance->GetDelegate(); + } + return nullptr; + } + + DeviceEnergyManagementDelegate * GetDEMDelegate() + { + if (mDEMInstance) + { + return mDEMInstance->GetDelegate(); + } + return nullptr; + } + /** * @brief Called at start up to apply hardware settings */ @@ -140,6 +180,10 @@ class WhmManufacturer : public DeviceEnergyManagement::DEMManufacturerDelegate */ void BoostCommandFinished(); + + CHIP_ERROR SendPowerReading(EndpointId aEndpointId, Power_mW aActivePower_mW, + Voltage_mV aVoltage_mV, Amperage_mA aActiveCurrent_mA); + /* Implement the DEMManufacturerDelegate interface */ /** @@ -149,6 +193,9 @@ class WhmManufacturer : public DeviceEnergyManagement::DEMManufacturerDelegate private: WaterHeaterManagementInstance * mWhmInstance; + ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * mEPMInstance; + PowerTopology::PowerTopologyInstance * mPTInstance; + DeviceEnergyManagementManager * mDEMInstance; }; /** @brief Helper function to return the singleton WhmManufacturer instance diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp deleted file mode 100644 index 0dcfb81f59a8f0..00000000000000 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * - * Copyright (c) 2024 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. - */ - -#include "EnergyManagementAppCmdLineOptions.h" - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace chip { -namespace app { -namespace Clusters { -namespace WaterHeaterManagement { - -void FullWhmApplicationInit() -{ - ReturnOnFailure(WhmApplicationInit()); - - if (DeviceEnergyManagementInit() != CHIP_NO_ERROR) - { - WhmApplicationShutdown(); - return; - } - - if (EnergyMeterInit() != CHIP_NO_ERROR) - { - DeviceEnergyManagementShutdown(); - WhmApplicationShutdown(); - return; - } - - if (PowerTopologyInit() != CHIP_NO_ERROR) - { - EnergyMeterShutdown(); - DeviceEnergyManagementShutdown(); - WhmApplicationShutdown(); - return; - } - - /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ - - GetDEMDelegate()->SetESAState(ESAStateEnum::kOnline); - GetDEMDelegate()->SetDEMManufacturerDelegate(*GetWhmManufacturer()); - - // Set the abs min and max power - GetDEMDelegate()->SetAbsMinPower(1200000); // 1.2KW - GetDEMDelegate()->SetAbsMaxPower(7600000); // 7.6KW -} - -void FullWhmApplicationShutdown() -{ - ChipLogDetail(AppServer, "Energy Management App (WaterHeater): ApplicationShutdown()"); - - /* Shutdown in reverse order that they were created */ - PowerTopologyShutdown(); /* Free the PowerTopology */ - EnergyMeterShutdown(); /* Free the Energy Meter */ - DeviceEnergyManagementShutdown(); /* Free the DEM */ - WhmApplicationShutdown(); - - Clusters::DeviceEnergyManagementMode::Shutdown(); - Clusters::WaterHeaterMode::Shutdown(); -} - -} // namespace WaterHeaterManagement -} // namespace Clusters -} // namespace app -} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp index 038e332bd31aff..0e1ebb233de8b6 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp @@ -18,6 +18,10 @@ #include #include +#include +#include +#include +#include #include #include @@ -30,6 +34,10 @@ using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; using namespace chip::app::Clusters; +using namespace chip::app::Clusters::ElectricalPowerMeasurement; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement; +using namespace chip::app::Clusters::PowerTopology; +using namespace chip::app::Clusters::DeviceEnergyManagement; namespace chip { namespace app { @@ -133,7 +141,8 @@ CHIP_ERROR WhmManufacturerInit() } /* Now create WhmManufacturer */ - gWhmManufacturer = std::make_unique(gWhmInstance.get()); + gWhmManufacturer = std::make_unique(gWhmInstance.get(), gEPMInstance.get(), + gPTInstance.get(), gDEMInstance.get()); if (!gWhmManufacturer) { ChipLogError(AppServer, "Failed to allocate memory for WhmManufacturer"); @@ -169,20 +178,61 @@ CHIP_ERROR WhmManufacturerShutdown() CHIP_ERROR WhmApplicationInit() { - ReturnErrorOnFailure(WhmInit()); + ReturnErrorOnFailure(DeviceEnergyManagementInit()); + + CHIP_ERROR err = WhmInit(); + if (err != CHIP_NO_ERROR) + { + DeviceEnergyManagementShutdown(); + return err; + } + + err = EnergyMeterInit(); + if (err != CHIP_NO_ERROR) + { + DeviceEnergyManagementShutdown(); + WhmShutdown(); + return err; + } + + err = PowerTopologyInit(); + if( err != CHIP_NO_ERROR) + { + DeviceEnergyManagementShutdown(); + WhmShutdown(); + EnergyMeterShutdown(); + return err; + } /* Do this last so that the instances for other clusters can be wrapped inside */ - ReturnErrorOnFailure(WhmManufacturerInit()); + err = WhmManufacturerInit(); + if (err != CHIP_NO_ERROR) + { + DeviceEnergyManagementShutdown(); + WhmShutdown(); + EnergyMeterShutdown(); + PowerTopologyShutdown(); + return err; + } return CHIP_NO_ERROR; } CHIP_ERROR WhmApplicationShutdown() { + ChipLogDetail(AppServer, "Energy Management App (WaterHeater): ApplicationShutdown()"); + /* Shutdown in reverse order that they were created */ WhmManufacturerShutdown(); + PowerTopologyShutdown(); + EnergyMeterShutdown(); + WhmShutdown(); + DeviceEnergyManagementShutdown(); - return WhmShutdown(); + Clusters::DeviceEnergyManagementMode::Shutdown(); + Clusters::WaterHeaterMode::Shutdown(); + + return CHIP_NO_ERROR; } } // namespace WaterHeaterManagement diff --git a/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp index 446d684e41be64..3caf1fd1df75e1 100644 --- a/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp +++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp @@ -25,7 +25,10 @@ #include using namespace chip; +using namespace chip::app::DataModel; using namespace chip::app::Clusters::WaterHeaterManagement; +using namespace chip::app::Clusters::ElectricalPowerMeasurement; +using namespace chip::app::Clusters::ElectricalEnergyMeasurement; using Protocols::InteractionModel::Status; @@ -46,6 +49,14 @@ CHIP_ERROR WhmManufacturer::Init() dg->SetHeaterTypes(BitMask(WaterHeaterHeatSourceBitmap::kImmersionElement1)); dg->SetColdWaterTemperature(2000); + /* For Device Energy Management we need the ESA to be Online and ready to accept commands */ + GetDEMDelegate()->SetESAState(ESAStateEnum::kOnline); + GetDEMDelegate()->SetDEMManufacturerDelegate(*GetWhmManufacturer()); + + // Set the abs min and max power + GetDEMDelegate()->SetAbsMinPower(1000000); // 1.0KW + GetDEMDelegate()->SetAbsMaxPower(5400000); // 5.4KW + return CHIP_NO_ERROR; } @@ -151,6 +162,32 @@ WaterHeaterManagementDelegate * GetWhmDelegate() return wg; } + +/** + * @brief Allows a client application to send in power readings into the system + * + * @param[in] aEndpointId - Endpoint to send to EPM Cluster + * @param[in] aActivePower_mW - ActivePower measured in milli-watts + * @param[in] aVoltage_mV - Voltage measured in milli-volts + * @param[in] aActiveCurrent_mA - ActiveCurrent measured in milli-amps + */ +CHIP_ERROR WhmManufacturer::SendPowerReading(EndpointId aEndpointId, + Power_mW aActivePower_mW, + Voltage_mV aVoltage_mV, + Amperage_mA aActiveCurrent_mA) +{ + WhmManufacturer * mn = GetWhmManufacturer(); + VerifyOrReturnError(mn != nullptr, CHIP_ERROR_UNINITIALIZED); + + ElectricalPowerMeasurementDelegate * dg = mn->GetEPMDelegate(); + VerifyOrReturnError(dg != nullptr, CHIP_ERROR_UNINITIALIZED); + + dg->SetActivePower(MakeNullable(aActivePower_mW)); + dg->SetVoltage(MakeNullable(aVoltage_mV)); + dg->SetActiveCurrent(MakeNullable(aActiveCurrent_mA)); + + return CHIP_NO_ERROR; +} // The PowerAdjustEnd event needs to report the approximate energy used by the ESA during the session. int64_t WhmManufacturer::GetApproxEnergyDuringSession() { diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp index d235fa4291ac98..7d83ecfde94c5e 100644 --- a/examples/energy-management-app/esp32/main/main.cpp +++ b/examples/energy-management-app/esp32/main/main.cpp @@ -22,7 +22,7 @@ #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE -#include +#include #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #include "esp_log.h" @@ -164,7 +164,7 @@ void ApplicationInit() #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE - FullWhmApplicationInit(); + WhmApplicationInit(); #endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE } @@ -177,7 +177,7 @@ void ApplicationShutdown() #endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE #if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE - FullWhmApplicationShutdown(); + WhmApplicationShutdown(); #endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE } diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn index a9d41a1e76d033..fc5324ce47cf24 100644 --- a/examples/energy-management-app/linux/BUILD.gn +++ b/examples/energy-management-app/linux/BUILD.gn @@ -35,6 +35,7 @@ config("includes") { executable("chip-energy-management-app") { sources = [ "${chip_root}/examples/energy-management-app/energy-management-common/common/src/EnergyTimeUtils.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMDelegate.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementManager.cpp", @@ -49,9 +50,9 @@ executable("chip-energy-management-app") { "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/energy-evse-mode.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/ElectricalPowerMeasurementDelegate.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingEventTriggers.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/EnergyReportingMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/FakeReadings.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/src/PowerTopologyDelegate.cpp", - "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmInstance.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp", diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp index 7a6312538ada45..856a01cd424bfd 100644 --- a/examples/energy-management-app/linux/main.cpp +++ b/examples/energy-management-app/linux/main.cpp @@ -18,7 +18,8 @@ #include #include -#include +#include + #include #include @@ -105,7 +106,7 @@ void ApplicationInit() } else if (strcmp(spApp, kWhmApp) == 0) { - FullWhmApplicationInit(); + WhmApplicationInit(); } else { @@ -118,7 +119,7 @@ void ApplicationShutdown() ChipLogDetail(AppServer, "Energy Management App: ApplicationShutdown()"); EvseApplicationShutdown(); - FullWhmApplicationShutdown(); + WhmApplicationShutdown(); } static bool EnergyAppOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier,