From 005edff81c2ee8bce8af9d738a9742864b228d31 Mon Sep 17 00:00:00 2001 From: Rohit Jadhav Date: Mon, 22 Jan 2024 10:41:11 +0530 Subject: [PATCH 1/4] [ESP32] Fix build failure and Add DeviceEnergyManagement clusters initialization --- .github/workflows/examples-esp32.yaml | 3 ++ .../esp32/main/CMakeLists.txt | 1 + .../energy-management-app/esp32/main/main.cpp | 48 +++++++++++++++---- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/.github/workflows/examples-esp32.yaml b/.github/workflows/examples-esp32.yaml index 47908d654006e9..2e5432dd4ec03f 100644 --- a/.github/workflows/examples-esp32.yaml +++ b/.github/workflows/examples-esp32.yaml @@ -165,3 +165,6 @@ jobs: - name: Build example Lighting App (external platform) run: scripts/examples/esp_example.sh lighting-app sdkconfig.ext_plat.defaults + + - name: Build example Energy Management App + run: scripts/examples/esp_example.sh energy-management-app sdkconfig.defaults diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index 1c7f2a5b782948..414163514b86e0 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-format-localization-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/barrier-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/device-energy-management-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/network-commissioning" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp index 77899a45b58d03..4da39d1e871502 100644 --- a/examples/energy-management-app/esp32/main/main.cpp +++ b/examples/energy-management-app/esp32/main/main.cpp @@ -16,6 +16,7 @@ */ #include "DeviceCallbacks.h" +#include #include #include #include @@ -74,9 +75,11 @@ using namespace ::chip::Credentials; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; -static EnergyEvseDelegate * gDelegate = nullptr; -static EnergyEvseManager * gInstance = nullptr; +static EnergyEvseDelegate * gEvseDelegate = nullptr; +static EnergyEvseManager * gEvseInstance = nullptr; static EVSEManufacturer * gEvseManufacturer = nullptr; +static DeviceEnergyManagementDelegate * gDEMDelegate = nullptr; +static DeviceEnergyManagementManager * gDEMInstance = nullptr; #if CONFIG_ENABLE_ESP_INSIGHTS_TRACE extern const char insights_auth_key_start[] asm("_binary_insights_auth_key_txt_start"); @@ -116,15 +119,40 @@ chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void) } // namespace +EVSEManufacturer * EnergyEvse::GetEvseManufacturer() +{ + return gEvseManufacturer; +} + void ApplicationInit() { - if ((gDelegate == nullptr) && (gInstance == nullptr) && (gEvseManufacturer == nullptr)) + if ((gDEMDelegate == nullptr) && (gDEMInstance == nullptr)) + { + gDEMDelegate = new DeviceEnergyManagementDelegate(); + if (gDEMDelegate != nullptr) + { + gDEMInstance = new DeviceEnergyManagementManager( + EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, + BitMask( + DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kPowerForecastReporting, + DeviceEnergyManagement::Feature::kStateForecastReporting, DeviceEnergyManagement::Feature::kStartTimeAdjustment, + DeviceEnergyManagement::Feature::kPausable, DeviceEnergyManagement::Feature::kForecastAdjustment, + DeviceEnergyManagement::Feature::kConstraintBasedAdjustment)); + gDEMInstance->Init(); /* Register Attribute & Command handlers */ + } + } + else + { + ChipLogError(AppServer, "DEM Instance or Delegate already exist.") + } + + if ((gEvseDelegate == nullptr) && (gEvseInstance == nullptr) && (gEvseManufacturer == nullptr)) { - gDelegate = new EnergyEvseDelegate(); - if (gDelegate != nullptr) + gEvseDelegate = new EnergyEvseDelegate(); + if (gEvseDelegate != nullptr) { - gInstance = new EnergyEvseManager( - EndpointId(ENERGY_EVSE_ENDPOINT), *gDelegate, + gEvseInstance = new EnergyEvseManager( + EndpointId(ENERGY_EVSE_ENDPOINT), *gEvseDelegate, BitMask(EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge, EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting, EnergyEvse::Feature::kV2x), @@ -132,7 +160,7 @@ void ApplicationInit() OptionalAttributes::kSupportsRandomizationWindow, OptionalAttributes::kSupportsApproximateEvEfficiency), BitMask(OptionalCommands::kSupportsStartDiagnostics)); - gInstance->Init(); /* Register Attribute & Command handlers */ + gEvseInstance->Init(); /* Register Attribute & Command handlers */ } } else @@ -142,8 +170,8 @@ void ApplicationInit() if (gEvseManufacturer == nullptr) { - gEvseManufacturer = new EVSEManufacturer(); - gEvseManufacturer->Init(gInstance); + gEvseManufacturer = new EVSEManufacturer(gEvseInstance); + gEvseManufacturer->Init(); } else { From 403e9db8f897dec54c1be8c72400196f0493b5fd Mon Sep 17 00:00:00 2001 From: Rohit Jadhav Date: Mon, 22 Jan 2024 15:12:44 +0530 Subject: [PATCH 2/4] Fix crash --- .../src/EnergyEvseManager.cpp | 7 ++++++- examples/energy-management-app/esp32/main/main.cpp | 14 ++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp index 710b13f9d342b8..24643885d54368 100644 --- a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp @@ -27,7 +27,12 @@ CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes() { SafeAttributePersistenceProvider * aProvider = GetSafeAttributePersistenceProvider(); - EndpointId aEndpointId = mDelegate->GetEndpointId(); + if (aProvider == nullptr) + { + ChipLogError(AppServer, "GetSafeAttributePersistenceProvider returned NULL"); + return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + EndpointId aEndpointId = mDelegate->GetEndpointId(); CHIP_ERROR err; // Restore ChargingEnabledUntil value diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp index 4da39d1e871502..ef9fb89986f902 100644 --- a/examples/energy-management-app/esp32/main/main.cpp +++ b/examples/energy-management-app/esp32/main/main.cpp @@ -75,11 +75,11 @@ using namespace ::chip::Credentials; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; -static EnergyEvseDelegate * gEvseDelegate = nullptr; -static EnergyEvseManager * gEvseInstance = nullptr; -static EVSEManufacturer * gEvseManufacturer = nullptr; -static DeviceEnergyManagementDelegate * gDEMDelegate = nullptr; -static DeviceEnergyManagementManager * gDEMInstance = nullptr; +static EnergyEvseDelegate * gEvseDelegate = nullptr; +static EnergyEvseManager * gEvseInstance = nullptr; +static EVSEManufacturer * gEvseManufacturer = nullptr; +static DeviceEnergyManagementDelegate * gDEMDelegate = nullptr; +static DeviceEnergyManagementManager * gDEMInstance = nullptr; #if CONFIG_ENABLE_ESP_INSIGHTS_TRACE extern const char insights_auth_key_start[] asm("_binary_insights_auth_key_txt_start"); @@ -181,7 +181,6 @@ void ApplicationInit() static void InitServer(intptr_t context) { - ApplicationInit(); // Print QR Code URL PrintOnboardingCodes(chip::RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE)); @@ -203,6 +202,9 @@ static void InitServer(intptr_t context) static Tracing::Insights::ESP32Backend backend; Tracing::Register(backend); #endif + + // Application code should always be initialised after the initialisation of server. + ApplicationInit(); } extern "C" void app_main() From 3d9c512029bb11f0abef6e518f33223cd30fc49e Mon Sep 17 00:00:00 2001 From: Rohit Jadhav Date: Mon, 22 Jan 2024 16:00:42 +0530 Subject: [PATCH 3/4] Support EVSE and Device Energy Management Mode --- examples/energy-management-app/esp32/main/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index 414163514b86e0..46f97d766dbfeb 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -64,6 +64,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/groups-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/group-key-mgmt-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-base-server" ) set(PRIV_REQUIRES_LIST chip QRCode bt led_strip app_update openthread driver nvs_flash spi_flash) From a4848d00239a7f36444054e60a83b25853ae9469 Mon Sep 17 00:00:00 2001 From: Rohit Jadhav Date: Tue, 23 Jan 2024 20:19:59 +0530 Subject: [PATCH 4/4] Sync esp32 with linux app --- .../energy-management-app/esp32/main/main.cpp | 260 +++++++++++++++--- 1 file changed, 216 insertions(+), 44 deletions(-) diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp index ef9fb89986f902..fd79e606afb6aa 100644 --- a/examples/energy-management-app/esp32/main/main.cpp +++ b/examples/energy-management-app/esp32/main/main.cpp @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include "esp_log.h" #include @@ -75,11 +77,11 @@ using namespace ::chip::Credentials; using namespace ::chip::DeviceManager; using namespace ::chip::DeviceLayer; -static EnergyEvseDelegate * gEvseDelegate = nullptr; -static EnergyEvseManager * gEvseInstance = nullptr; -static EVSEManufacturer * gEvseManufacturer = nullptr; -static DeviceEnergyManagementDelegate * gDEMDelegate = nullptr; -static DeviceEnergyManagementManager * gDEMInstance = nullptr; +static std::unique_ptr gEvseDelegate; +static std::unique_ptr gEvseInstance; +static std::unique_ptr gDEMDelegate; +static std::unique_ptr gDEMInstance; +static std::unique_ptr gEvseManufacturer; #if CONFIG_ENABLE_ESP_INSIGHTS_TRACE extern const char insights_auth_key_start[] asm("_binary_insights_auth_key_txt_start"); @@ -121,64 +123,234 @@ chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void) EVSEManufacturer * EnergyEvse::GetEvseManufacturer() { - return gEvseManufacturer; + return gEvseManufacturer.get(); } -void ApplicationInit() +/* + * @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) + { + ESP_LOGE(TAG, "DEM Instance or Delegate already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + gDEMDelegate = std::make_unique(); + if (!gDEMDelegate) + { + ESP_LOGE(TAG, "Failed to allocate memory for DeviceEnergyManagementDelegate"); + return CHIP_ERROR_NO_MEMORY; + } + + /* Manufacturer may optionally not support all features, commands & attributes */ + gDEMInstance = std::make_unique( + EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, + BitMask( + DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kPowerForecastReporting, + DeviceEnergyManagement::Feature::kStateForecastReporting, DeviceEnergyManagement::Feature::kStartTimeAdjustment, + DeviceEnergyManagement::Feature::kPausable, DeviceEnergyManagement::Feature::kForecastAdjustment, + DeviceEnergyManagement::Feature::kConstraintBasedAdjustment)); + + if (!gDEMInstance) + { + ESP_LOGE(TAG, "Failed to allocate memory for DeviceEnergyManagementManager"); + gDEMDelegate.reset(); + return CHIP_ERROR_NO_MEMORY; + } + + CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */ + if (err != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Init failed on gDEMInstance, err:%" CHIP_ERROR_FORMAT, err.Format()); + 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 + * + * 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 EnergyEvseInit() +{ + CHIP_ERROR err; + + if (gEvseDelegate || gEvseInstance) + { + ESP_LOGE(TAG, "EVSE Instance or Delegate already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + gEvseDelegate = std::make_unique(); + if (!gEvseDelegate) + { + ESP_LOGE(TAG, "Failed to allocate memory for EnergyEvseDelegate"); + return CHIP_ERROR_NO_MEMORY; + } + + /* Manufacturer may optionally not support all features, commands & attributes */ + gEvseInstance = std::make_unique( + EndpointId(ENERGY_EVSE_ENDPOINT), *gEvseDelegate, + BitMask(EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge, + EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting, + EnergyEvse::Feature::kV2x), + BitMask(EnergyEvse::OptionalAttributes::kSupportsUserMaximumChargingCurrent, + EnergyEvse::OptionalAttributes::kSupportsRandomizationWindow, + EnergyEvse::OptionalAttributes::kSupportsApproximateEvEfficiency), + BitMask(EnergyEvse::OptionalCommands::kSupportsStartDiagnostics)); + + if (!gEvseInstance) + { + ESP_LOGE(TAG, "Failed to allocate memory for EnergyEvseManager"); + gEvseDelegate.reset(); + return CHIP_ERROR_NO_MEMORY; + } + + err = gEvseInstance->Init(); /* Register Attribute & Command handlers */ + if (err != CHIP_NO_ERROR) + { + ESP_LOGE(TAG, "Init failed on gEvseInstance, err:%" CHIP_ERROR_FORMAT, err.Format()); + gEvseInstance.reset(); + gEvseDelegate.reset(); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR EnergyEvseShutdown() +{ + /* Do this in the order Instance first, then delegate + * Ensure we call the Instance->Shutdown to free attribute & command handlers first + */ + if (gEvseInstance) + { + /* deregister attribute & command handlers */ + gEvseInstance->Shutdown(); + gEvseInstance.reset(); + } + + if (gEvseDelegate) + { + gEvseDelegate.reset(); + } + + return CHIP_NO_ERROR; +} + +/* + * @brief Creates a EVSEManufacturer class to hold the EVSE & DEM 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 EVSEManufacturerInit() { - if ((gDEMDelegate == nullptr) && (gDEMInstance == nullptr)) + CHIP_ERROR err; + + if (gEvseManufacturer) + { + ESP_LOGE(TAG, "EvseManufacturer already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + /* Now create EVSEManufacturer */ + gEvseManufacturer = std::make_unique(gEvseInstance.get()); + if (!gEvseManufacturer) { - gDEMDelegate = new DeviceEnergyManagementDelegate(); - if (gDEMDelegate != nullptr) - { - gDEMInstance = new DeviceEnergyManagementManager( - EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, - BitMask( - DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kPowerForecastReporting, - DeviceEnergyManagement::Feature::kStateForecastReporting, DeviceEnergyManagement::Feature::kStartTimeAdjustment, - DeviceEnergyManagement::Feature::kPausable, DeviceEnergyManagement::Feature::kForecastAdjustment, - DeviceEnergyManagement::Feature::kConstraintBasedAdjustment)); - gDEMInstance->Init(); /* Register Attribute & Command handlers */ - } + ESP_LOGE(TAG, "Failed to allocate memory for EvseManufacturer"); + return CHIP_ERROR_NO_MEMORY; } - else + + /* Call Manufacturer specific init */ + err = gEvseManufacturer->Init(); + if (err != CHIP_NO_ERROR) { - ChipLogError(AppServer, "DEM Instance or Delegate already exist.") + ESP_LOGE(TAG, "Init failed on gEvseManufacturer, err:%" CHIP_ERROR_FORMAT, err.Format()); + gEvseManufacturer.reset(); + return err; } - if ((gEvseDelegate == nullptr) && (gEvseInstance == nullptr) && (gEvseManufacturer == nullptr)) + return CHIP_NO_ERROR; +} + +CHIP_ERROR EVSEManufacturerShutdown() +{ + if (gEvseManufacturer) { - gEvseDelegate = new EnergyEvseDelegate(); - if (gEvseDelegate != nullptr) - { - gEvseInstance = new EnergyEvseManager( - EndpointId(ENERGY_EVSE_ENDPOINT), *gEvseDelegate, - BitMask(EnergyEvse::Feature::kChargingPreferences, - EnergyEvse::Feature::kPlugAndCharge, EnergyEvse::Feature::kRfid, - EnergyEvse::Feature::kSoCReporting, EnergyEvse::Feature::kV2x), - BitMask(OptionalAttributes::kSupportsUserMaximumChargingCurrent, - OptionalAttributes::kSupportsRandomizationWindow, - OptionalAttributes::kSupportsApproximateEvEfficiency), - BitMask(OptionalCommands::kSupportsStartDiagnostics)); - gEvseInstance->Init(); /* Register Attribute & Command handlers */ - } + /* Shutdown the EVSEManufacturer */ + gEvseManufacturer->Shutdown(); + gEvseManufacturer.reset(); } - else + + return CHIP_NO_ERROR; +} + +void ApplicationInit() +{ + if (DeviceEnergyManagementInit() != CHIP_NO_ERROR) { - ChipLogError(AppServer, "EVSE Instance or Delegate already exist.") + return; } - if (gEvseManufacturer == nullptr) + if (EnergyEvseInit() != CHIP_NO_ERROR) { - gEvseManufacturer = new EVSEManufacturer(gEvseInstance); - gEvseManufacturer->Init(); + DeviceEnergyManagementShutdown(); + return; } - else + + if (EVSEManufacturerInit() != CHIP_NO_ERROR) { - ChipLogError(AppServer, "EVSEManufacturer already exists.") + DeviceEnergyManagementShutdown(); + EnergyEvseShutdown(); + return; } } +void ApplicationShutdown() +{ + ESP_LOGD(TAG, "Energy Management App: ApplicationShutdown()"); + + /* Shutdown in reverse order that they were created */ + EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */ + EnergyEvseShutdown(); /* Free the EnergyEvse */ + DeviceEnergyManagementShutdown(); /* Free the DEM */ + + Clusters::DeviceEnergyManagementMode::Shutdown(); + Clusters::EnergyEvseMode::Shutdown(); +} + static void InitServer(intptr_t context) { // Print QR Code URL