Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ESP32] Fix build and crash and add DeviceManagementCluster, EVSE mode and DeviceManagementCluster mode. #31591

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/examples-esp32.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions examples/energy-management-app/esp32/main/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -63,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)
Expand Down
256 changes: 229 additions & 27 deletions examples/energy-management-app/esp32/main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@
*/

#include "DeviceCallbacks.h"
#include <DeviceEnergyManagementManager.h>
#include <EVSEManufacturerImpl.h>
#include <EnergyEvseManager.h>
#include <EnergyManagementManager.h>
#include <device-energy-management-modes.h>
#include <energy-evse-modes.h>

#include "esp_log.h"
#include <common/CHIPDeviceManager.h>
Expand Down Expand Up @@ -74,9 +77,11 @@ using namespace ::chip::Credentials;
using namespace ::chip::DeviceManager;
using namespace ::chip::DeviceLayer;

static EnergyEvseDelegate * gDelegate = nullptr;
static EnergyEvseManager * gInstance = nullptr;
static EVSEManufacturer * gEvseManufacturer = nullptr;
static std::unique_ptr<EnergyEvseDelegate> gEvseDelegate;
static std::unique_ptr<EnergyEvseManager> gEvseInstance;
static std::unique_ptr<DeviceEnergyManagementDelegate> gDEMDelegate;
static std::unique_ptr<DeviceEnergyManagementManager> gDEMInstance;
static std::unique_ptr<EVSEManufacturer> gEvseManufacturer;

#if CONFIG_ENABLE_ESP_INSIGHTS_TRACE
extern const char insights_auth_key_start[] asm("_binary_insights_auth_key_txt_start");
Expand Down Expand Up @@ -116,44 +121,238 @@ chip::Credentials::DeviceAttestationCredentialsProvider * get_dac_provider(void)

} // namespace

void ApplicationInit()
EVSEManufacturer * EnergyEvse::GetEvseManufacturer()
{
return gEvseManufacturer.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)
{
ESP_LOGE(TAG, "DEM Instance or Delegate already exist.");
return CHIP_ERROR_INCORRECT_STATE;
}

gDEMDelegate = std::make_unique<DeviceEnergyManagementDelegate>();
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<DeviceEnergyManagementManager>(
EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate,
BitMask<DeviceEnergyManagement::Feature, uint32_t>(
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()
{
if ((gDelegate == nullptr) && (gInstance == nullptr) && (gEvseManufacturer == nullptr))
/* Do this in the order Instance first, then delegate
* Ensure we call the Instance->Shutdown to free attribute & command handlers first
*/
if (gDEMInstance)
{
gDelegate = new EnergyEvseDelegate();
if (gDelegate != nullptr)
{
gInstance = new EnergyEvseManager(
EndpointId(ENERGY_EVSE_ENDPOINT), *gDelegate,
BitMask<EnergyEvse::Feature, uint32_t>(EnergyEvse::Feature::kChargingPreferences,
EnergyEvse::Feature::kPlugAndCharge, EnergyEvse::Feature::kRfid,
EnergyEvse::Feature::kSoCReporting, EnergyEvse::Feature::kV2x),
BitMask<OptionalAttributes, uint32_t>(OptionalAttributes::kSupportsUserMaximumChargingCurrent,
OptionalAttributes::kSupportsRandomizationWindow,
OptionalAttributes::kSupportsApproximateEvEfficiency),
BitMask<OptionalCommands, uint32_t>(OptionalCommands::kSupportsStartDiagnostics));
gInstance->Init(); /* Register Attribute & Command handlers */
}
/* deregister attribute & command handlers */
gDEMInstance->Shutdown();
gDEMInstance.reset();
}
else
if (gDEMDelegate)
{
ChipLogError(AppServer, "EVSE Instance or Delegate already exist.")
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 (gEvseManufacturer == nullptr)
if (gEvseDelegate || gEvseInstance)
{
gEvseManufacturer = new EVSEManufacturer();
gEvseManufacturer->Init(gInstance);
ESP_LOGE(TAG, "EVSE Instance or Delegate already exist.");
return CHIP_ERROR_INCORRECT_STATE;
}
else

gEvseDelegate = std::make_unique<EnergyEvseDelegate>();
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<EnergyEvseManager>(
EndpointId(ENERGY_EVSE_ENDPOINT), *gEvseDelegate,
BitMask<EnergyEvse::Feature, uint32_t>(EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge,
EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting,
EnergyEvse::Feature::kV2x),
BitMask<EnergyEvse::OptionalAttributes, uint32_t>(EnergyEvse::OptionalAttributes::kSupportsUserMaximumChargingCurrent,
EnergyEvse::OptionalAttributes::kSupportsRandomizationWindow,
EnergyEvse::OptionalAttributes::kSupportsApproximateEvEfficiency),
BitMask<EnergyEvse::OptionalCommands, uint32_t>(EnergyEvse::OptionalCommands::kSupportsStartDiagnostics));

if (!gEvseInstance)
{
ChipLogError(AppServer, "EVSEManufacturer already exists.")
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()
{
CHIP_ERROR err;

if (gEvseManufacturer)
{
ESP_LOGE(TAG, "EvseManufacturer already exist.");
return CHIP_ERROR_INCORRECT_STATE;
}

/* Now create EVSEManufacturer */
gEvseManufacturer = std::make_unique<EVSEManufacturer>(gEvseInstance.get());
if (!gEvseManufacturer)
{
ESP_LOGE(TAG, "Failed to allocate memory for EvseManufacturer");
return CHIP_ERROR_NO_MEMORY;
}

/* Call Manufacturer specific init */
err = gEvseManufacturer->Init();
if (err != CHIP_NO_ERROR)
{
ESP_LOGE(TAG, "Init failed on gEvseManufacturer, err:%" CHIP_ERROR_FORMAT, err.Format());
gEvseManufacturer.reset();
return err;
}

return CHIP_NO_ERROR;
}

CHIP_ERROR EVSEManufacturerShutdown()
{
if (gEvseManufacturer)
{
/* Shutdown the EVSEManufacturer */
gEvseManufacturer->Shutdown();
gEvseManufacturer.reset();
}

return CHIP_NO_ERROR;
}

void ApplicationInit()
{
if (DeviceEnergyManagementInit() != CHIP_NO_ERROR)
{
return;
}

if (EnergyEvseInit() != CHIP_NO_ERROR)
{
DeviceEnergyManagementShutdown();
return;
}

if (EVSEManufacturerInit() != CHIP_NO_ERROR)
{
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)
{
ApplicationInit();
// Print QR Code URL
PrintOnboardingCodes(chip::RendezvousInformationFlags(CONFIG_RENDEZVOUS_MODE));

Expand All @@ -175,6 +374,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()
Expand Down
Loading