Add water heater to energy management app (#34886)

* Refactored file location for chip-energy-management-app. Updated esp32 and linux build files.

* Updated some all-clusters-app build and CMakeLists (linux, esp32, psoc6)

* Updated remaining build and CMakefiles with new folders.

* Fixed unit tests BUILD.gn

* Restyled by gn

* Missed Ameba .cmake

* Missed all-clusters-minimal-app/esp32/main/CMakeLists.txt

* Added basic hooks to ESP32 to allow EVSE or Water Heater app

* Added initial WaterHeaterMain.cpp - needs rework

* Configure runner command to use --application <dem|eevse|whm> option

* Unify the WHM and EEVSE/DEM apps

* Restyled by whitespace

* Restyled by clang-format

* Restyled by gn

* Rename application names

* Get ESP32 energy management app building with water-heater. Move water heater files from all-clusters-app to examples/energy-management-app/energy-management-common/water-heater

* Get WHM triggers working

* Get energy tests passing

* Add some more build infrastructure to set the DEM feature map

* Address review comments from James and fix some CI tests

* Restyled by clang-format

* Restyled by gn

* Undo changes to Objects.py

* Address review from James and fix forecast subscription issues

* Address review from James

* Added ENERGY_REPORTING_TRIGGERS option to ESP32 and updated ESP32 README.md

* Guard against a EVSE and WHM app being simultaneously defined

* Updated Linux README.md to highlight --application and --featureSet args.

* Fixed mis-spell

* Removed duplicate WaterHeaterMode::Shutdown()

* Fixed missing free of WaterHeaterMode and made a call to both EvseMain shutdown and WaterHeaterMain shutdown regardless of application mode.

* Restyled by whitespace

* Restyled by clang-format

* Applied code review comments, attempt to fix clang build failure with type in loop.

* Restyled by whitespace

* Restyled by clang-format

* Get DEM and EEM tests passing when running combined app in WHM mode

* Restyled by clang-format

* Ensure absMinPower and absMaxPower are set

* Fix CI build error

* Restyled by whitespace

* Restyled by clang-format

* Fix power levels so they fit within absMinPower and absMaxPower

* Fix definition of CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER

---------

Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: pcoleman <pcoleman@geotogether.com>
Co-authored-by: PeterC1965 <101805108+PeterC1965@users.noreply.github.com>
diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt
index 9dfd4ff..66448c1 100644
--- a/examples/all-clusters-app/esp32/main/CMakeLists.txt
+++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt
@@ -22,6 +22,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/include"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
@@ -36,6 +37,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/src"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/providers"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn
index baac520..5c61b4d 100644
--- a/examples/all-clusters-app/linux/BUILD.gn
+++ b/examples/all-clusters-app/linux/BUILD.gn
@@ -29,10 +29,6 @@
 
 source_set("chip-all-clusters-common") {
   sources = [
-    "${chip_root}/examples/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp",
-    "${chip_root}/examples/all-clusters-app/all-clusters-common/src/WhmInstance.cpp",
-    "${chip_root}/examples/all-clusters-app/all-clusters-common/src/WhmMain.cpp",
-    "${chip_root}/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp",
@@ -62,7 +58,6 @@
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
     "${chip_root}/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp",
-    "${chip_root}/examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp",
     "${chip_root}/examples/all-clusters-app/linux/diagnostic-logs-provider-delegate-impl.cpp",
     "${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/DeviceEnergyManagementDelegateImpl.cpp",
@@ -75,6 +70,11 @@
     "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/src/EnergyEvseTargetsStore.cpp",
     "${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/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",
+    "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp",
+    "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp",
     "${chip_root}/examples/thermostat/thermostat-common/src/thermostat-delegate-impl.cpp",
     "AllClustersCommandDelegate.cpp",
     "AllClustersCommandDelegate.h",
@@ -102,6 +102,7 @@
     "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include",
     "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include",
     "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include",
+    "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/include",
     "${chip_root}/examples/thermostat/thermostat-common/include",
   ]
 
diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp
index badda7f..42df91b 100644
--- a/examples/all-clusters-app/linux/main-common.cpp
+++ b/examples/all-clusters-app/linux/main-common.cpp
@@ -285,7 +285,6 @@
     Clusters::WaterHeaterMode::Shutdown();
 
     Clusters::WaterHeaterManagement::WhmApplicationShutdown();
-    Clusters::WaterHeaterMode::Shutdown();
 
     if (sChipNamedPipeCommands.Stop() != CHIP_NO_ERROR)
     {
diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmMain.h b/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h
similarity index 72%
copy from examples/all-clusters-app/all-clusters-common/include/WhmMain.h
copy to examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h
index 21dc9d8..ac5cc50 100644
--- a/examples/all-clusters-app/all-clusters-common/include/WhmMain.h
+++ b/examples/energy-management-app/energy-management-common/device-energy-management/include/DEMDelegate.h
@@ -18,15 +18,6 @@
 
 #pragma once
 
-namespace chip {
-namespace app {
-namespace Clusters {
-namespace WaterHeaterManagement {
+#include <DeviceEnergyManagementDelegateImpl.h>
 
-void WhmApplicationInit();
-void WhmApplicationShutdown();
-
-} // namespace WaterHeaterManagement
-} // namespace Clusters
-} // namespace app
-} // namespace chip
+chip::app::Clusters::DeviceEnergyManagement::DeviceEnergyManagementDelegate * GetDEMDelegate();
diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp
index 469b781..ff545ec 100644
--- a/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp
+++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/DEMTestEventTriggers.cpp
@@ -16,6 +16,7 @@
  *    limitations under the License.
  */
 
+#include <DEMDelegate.h>
 #include <DeviceEnergyManagementDelegateImpl.h>
 #include <EVSEManufacturerImpl.h>
 #include <app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h>
@@ -41,16 +42,6 @@
 static chip::app::DataModel::Nullable<chip::app::Clusters::DeviceEnergyManagement::Structs::PowerAdjustCapabilityStruct::Type>
     sPowerAdjustmentCapability;
 
-DeviceEnergyManagementDelegate * GetDEMDelegate()
-{
-    EVSEManufacturer * mn = GetEvseManufacturer();
-    VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null");
-    DeviceEnergyManagementDelegate * dg = mn->GetDEMDelegate();
-    VerifyOrDieWithMsg(dg != nullptr, AppServer, "DEM Delegate is null");
-
-    return dg;
-}
-
 CHIP_ERROR ConfigureForecast(uint16_t numSlots)
 {
     uint32_t chipEpoch = 0;
@@ -92,9 +83,9 @@
 
     if (GetDEMDelegate()->HasFeature(DeviceEnergyManagement::Feature::kPowerForecastReporting))
     {
-        sSlots[0].nominalPower.SetValue(1500);
-        sSlots[0].minPower.SetValue(1000);
-        sSlots[0].maxPower.SetValue(2000);
+        sSlots[0].nominalPower.SetValue(2500000);
+        sSlots[0].minPower.SetValue(1200000);
+        sSlots[0].maxPower.SetValue(7600000);
     }
 
     sSlots[0].nominalEnergy.SetValue(2000);
@@ -119,9 +110,9 @@
 
         if (GetDEMDelegate()->HasFeature(DeviceEnergyManagement::Feature::kPowerForecastReporting))
         {
-            sSlots[slotNo].nominalPower.SetValue(2 * sSlots[slotNo - 1].nominalPower.Value());
-            sSlots[slotNo].minPower.SetValue(2 * sSlots[slotNo - 1].minPower.Value());
-            sSlots[slotNo].maxPower.SetValue(2 * sSlots[slotNo - 1].maxPower.Value());
+            sSlots[slotNo].nominalPower.SetValue(sSlots[slotNo - 1].nominalPower.Value());
+            sSlots[slotNo].minPower.SetValue(sSlots[slotNo - 1].minPower.Value());
+            sSlots[slotNo].maxPower.SetValue(sSlots[slotNo - 1].maxPower.Value());
 
             sSlots[slotNo].nominalEnergy.SetValue(2 * sSlots[slotNo - 1].nominalEnergy.Value());
         }
@@ -134,10 +125,7 @@
 
     sForecastStruct.slots = DataModel::List<const DeviceEnergyManagement::Structs::SlotStruct::Type>(sSlots, numSlots);
 
-    EVSEManufacturer * mn = GetEvseManufacturer();
-    mn->GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct));
-    mn->GetDEMDelegate()->SetAbsMinPower(1000);
-    mn->GetDEMDelegate()->SetAbsMaxPower(256 * 2000 * 1000);
+    GetDEMDelegate()->SetForecast(DataModel::MakeNullable(sForecastStruct));
 
     return CHIP_NO_ERROR;
 }
diff --git a/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp
index 273bc9e..161ea2f 100644
--- a/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp
+++ b/examples/energy-management-app/energy-management-common/device-energy-management/src/DeviceEnergyManagementDelegateImpl.cpp
@@ -377,10 +377,14 @@
             mForecast.Value().startTime            = savedStartTime;
             mForecast.Value().endTime              = savedEndTime;
 
+            MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
+
             return Status::Failure;
         }
     }
 
+    MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
+
     return Status::Success;
 }
 
@@ -457,10 +461,14 @@
     if (cause == AdjustmentCauseEnum::kLocalOptimization)
     {
         mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kLocalOptimization;
+
+        MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
     }
     else if (cause == AdjustmentCauseEnum::kGridOptimization)
     {
         mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kGridOptimization;
+
+        MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
     }
 
     return Status::Success;
@@ -606,6 +614,8 @@
             // The PauseRequest has effectively been cancelled so as a result the device should
             // go back to InternalOptimisation
             mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization;
+
+            MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
         }
 
         CHIP_ERROR err = CancelPauseRequestAndGenerateEvent(CauseEnum::kCancelled);
@@ -672,6 +682,8 @@
         }
 
         mForecast.Value().forecastID++;
+
+        MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
     }
 
     return status;
@@ -725,6 +737,8 @@
 
         mForecast.Value().forecastID++;
 
+        MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
+
         status = Status::Success;
     }
 
@@ -748,6 +762,8 @@
 
     mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization;
 
+    MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
+
     /* It is expected the mpDEMManufacturerDelegate will cancel the effects of any previous adjustment
      * request commands, and re-evaluate its forecast for intended operation ignoring those previous
      * requests.
@@ -980,6 +996,8 @@
             if ((mOptOutState == OptOutStateEnum::kOptOut) || (mOptOutState == OptOutStateEnum::kLocalOptOut))
             {
                 mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization;
+
+                MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
                 // Generate a new forecast with Internal Optimization
                 // TODO
             }
@@ -988,6 +1006,8 @@
             if ((mOptOutState == OptOutStateEnum::kOptOut) || (mOptOutState == OptOutStateEnum::kGridOptOut))
             {
                 mForecast.Value().forecastUpdateReason = ForecastUpdateReasonEnum::kInternalOptimization;
+
+                MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, Forecast::Id);
                 // Generate a new forecast with Internal Optimization
                 // TODO
             }
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 2e7e295..07dce51 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,5 +18,16 @@
 
 #pragma once
 
+#include <lib/core/CHIPError.h>
+
 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/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp
index 00ced85..359e7c8 100644
--- a/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp
+++ b/examples/energy-management-app/energy-management-common/energy-evse/src/EVSEManufacturerImpl.cpp
@@ -70,6 +70,10 @@
     /* For Device Energy Management we need the ESA to be Online and ready to accept commands */
     dem->SetESAState(ESAStateEnum::kOnline);
 
+    // Set the abs min and max power
+    dem->SetAbsMinPower(1200000); // 1.2KW
+    dem->SetAbsMaxPower(7600000); // 7.6KW
+
     /*
      * This is an example implementation for manufacturers to consider
      *
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 bd22c67..8e900c0 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
@@ -67,6 +67,13 @@
     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
  *
@@ -472,7 +479,7 @@
 
 void EvseApplicationShutdown()
 {
-    ChipLogDetail(AppServer, "Energy Management App: ApplicationShutdown()");
+    ChipLogDetail(AppServer, "Energy Management App (EVSE): ApplicationShutdown()");
 
     /* Shutdown in reverse order that they were created */
     EVSEManufacturerShutdown();       /* Free the EVSEManufacturer */
diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.matter b/examples/energy-management-app/energy-management-common/energy-management-app.matter
index e7fba7e..faf05b7 100644
--- a/examples/energy-management-app/energy-management-common/energy-management-app.matter
+++ b/examples/energy-management-app/energy-management-common/energy-management-app.matter
@@ -1737,6 +1737,67 @@
   readonly attribute int16u clusterRevision = 65533;
 }
 
+/** This cluster is used to allow clients to control the operation of a hot water heating appliance so that it can be used with energy management. */
+provisional cluster WaterHeaterManagement = 148 {
+  revision 2;
+
+  enum BoostStateEnum : enum8 {
+    kInactive = 0;
+    kActive = 1;
+  }
+
+  bitmap Feature : bitmap32 {
+    kEnergyManagement = 0x1;
+    kTankPercent = 0x2;
+  }
+
+  bitmap WaterHeaterHeatSourceBitmap : bitmap8 {
+    kImmersionElement1 = 0x1;
+    kImmersionElement2 = 0x2;
+    kHeatPump = 0x4;
+    kBoiler = 0x8;
+    kOther = 0x10;
+  }
+
+  struct WaterHeaterBoostInfoStruct {
+    elapsed_s duration = 0;
+    optional boolean oneShot = 1;
+    optional boolean emergencyBoost = 2;
+    optional temperature temporarySetpoint = 3;
+    optional percent targetPercentage = 4;
+    optional percent targetReheat = 5;
+  }
+
+  info event BoostStarted = 0 {
+    WaterHeaterBoostInfoStruct boostInfo = 0;
+  }
+
+  info event BoostEnded = 1 {
+  }
+
+  readonly attribute WaterHeaterHeatSourceBitmap heaterTypes = 0;
+  readonly attribute WaterHeaterHeatSourceBitmap heatDemand = 1;
+  readonly attribute optional int16u tankVolume = 2;
+  readonly attribute optional energy_mwh estimatedHeatRequired = 3;
+  readonly attribute optional percent tankPercentage = 4;
+  readonly attribute BoostStateEnum boostState = 5;
+  readonly attribute command_id generatedCommandList[] = 65528;
+  readonly attribute command_id acceptedCommandList[] = 65529;
+  readonly attribute event_id eventList[] = 65530;
+  readonly attribute attrib_id attributeList[] = 65531;
+  readonly attribute bitmap32 featureMap = 65532;
+  readonly attribute int16u clusterRevision = 65533;
+
+  request struct BoostRequest {
+    WaterHeaterBoostInfoStruct boostInfo = 0;
+  }
+
+  /** Allows a client to request that the water heater is put into a Boost state. */
+  command access(invoke: manage) Boost(BoostRequest): DefaultSuccess = 0;
+  /** Allows a client to cancel an ongoing Boost operation. */
+  command access(invoke: manage) CancelBoost(): DefaultSuccess = 1;
+}
+
 /** This cluster allows a client to manage the power draw of a device. An example of such a client could be an Energy Management System (EMS) which controls an Energy Smart Appliance (ESA). */
 provisional cluster DeviceEnergyManagement = 152 {
   revision 4;
@@ -2211,6 +2272,56 @@
 }
 
 /** Attributes and commands for selecting a mode from a list of supported options. */
+cluster WaterHeaterMode = 158 {
+  revision 1;
+
+  enum ModeTag : enum16 {
+    kOff = 16384;
+    kManual = 16385;
+    kTimed = 16386;
+  }
+
+  bitmap Feature : bitmap32 {
+    kOnOff = 0x1;
+  }
+
+  struct ModeTagStruct {
+    optional vendor_id mfgCode = 0;
+    enum16 value = 1;
+  }
+
+  struct ModeOptionStruct {
+    char_string<64> label = 0;
+    int8u mode = 1;
+    ModeTagStruct modeTags[] = 2;
+  }
+
+  readonly attribute ModeOptionStruct supportedModes[] = 0;
+  readonly attribute int8u currentMode = 1;
+  attribute optional nullable int8u startUpMode = 2;
+  attribute optional nullable int8u onMode = 3;
+  readonly attribute command_id generatedCommandList[] = 65528;
+  readonly attribute command_id acceptedCommandList[] = 65529;
+  readonly attribute event_id eventList[] = 65530;
+  readonly attribute attrib_id attributeList[] = 65531;
+  readonly attribute bitmap32 featureMap = 65532;
+  readonly attribute int16u clusterRevision = 65533;
+
+  request struct ChangeToModeRequest {
+    int8u newMode = 0;
+  }
+
+  response struct ChangeToModeResponse = 1 {
+    enum8 status = 0;
+    optional char_string statusText = 1;
+  }
+
+  /** This command is used to change device modes.
+        On receipt of this command the device SHALL respond with a ChangeToModeResponse command. */
+  command ChangeToMode(ChangeToModeRequest): ChangeToModeResponse = 0;
+}
+
+/** Attributes and commands for selecting a mode from a list of supported options. */
 provisional cluster DeviceEnergyManagementMode = 159 {
   revision 1;
 
@@ -2557,6 +2668,24 @@
     ram      attribute clusterRevision default = 1;
   }
 
+  server cluster WaterHeaterManagement {
+    callback attribute heaterTypes;
+    callback attribute heatDemand;
+    callback attribute tankVolume;
+    callback attribute estimatedHeatRequired;
+    callback attribute tankPercentage;
+    callback attribute boostState;
+    callback attribute generatedCommandList;
+    callback attribute acceptedCommandList;
+    callback attribute eventList;
+    callback attribute attributeList;
+    callback attribute featureMap;
+    callback attribute clusterRevision;
+
+    handle command Boost;
+    handle command CancelBoost;
+  }
+
   server cluster DeviceEnergyManagement {
     emits event PowerAdjustStart;
     emits event PowerAdjustEnd;
@@ -2640,8 +2769,20 @@
   server cluster EnergyEvseMode {
     callback attribute supportedModes;
     callback attribute currentMode;
-    ram      attribute startUpMode;
-    ram      attribute onMode;
+    callback attribute generatedCommandList;
+    callback attribute acceptedCommandList;
+    callback attribute eventList;
+    callback attribute attributeList;
+    callback attribute featureMap;
+    ram      attribute clusterRevision default = 1;
+
+    handle command ChangeToMode;
+    handle command ChangeToModeResponse;
+  }
+
+  server cluster WaterHeaterMode {
+    callback attribute supportedModes;
+    callback attribute currentMode;
     callback attribute generatedCommandList;
     callback attribute acceptedCommandList;
     callback attribute eventList;
@@ -2656,8 +2797,6 @@
   server cluster DeviceEnergyManagementMode {
     callback attribute supportedModes;
     callback attribute currentMode;
-    ram      attribute startUpMode;
-    ram      attribute onMode;
     callback attribute generatedCommandList;
     callback attribute acceptedCommandList;
     callback attribute eventList;
diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.zap b/examples/energy-management-app/energy-management-common/energy-management-app.zap
index 566588a..1a312c9 100644
--- a/examples/energy-management-app/energy-management-common/energy-management-app.zap
+++ b/examples/energy-management-app/energy-management-common/energy-management-app.zap
@@ -3697,6 +3697,227 @@
           ]
         },
         {
+          "name": "Water Heater Management",
+          "code": 148,
+          "mfgCode": null,
+          "define": "WATER_HEATER_MANAGEMENT_CLUSTER",
+          "side": "server",
+          "enabled": 1,
+          "apiMaturity": "provisional",
+          "commands": [
+            {
+              "name": "Boost",
+              "code": 0,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "CancelBoost",
+              "code": 1,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            }
+          ],
+          "attributes": [
+            {
+              "name": "HeaterTypes",
+              "code": 0,
+              "mfgCode": null,
+              "side": "server",
+              "type": "WaterHeaterHeatSourceBitmap",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "HeatDemand",
+              "code": 1,
+              "mfgCode": null,
+              "side": "server",
+              "type": "WaterHeaterHeatSourceBitmap",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "TankVolume",
+              "code": 2,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EstimatedHeatRequired",
+              "code": 3,
+              "mfgCode": null,
+              "side": "server",
+              "type": "energy_mwh",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "TankPercentage",
+              "code": 4,
+              "mfgCode": null,
+              "side": "server",
+              "type": "percent",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "BoostState",
+              "code": 5,
+              "mfgCode": null,
+              "side": "server",
+              "type": "BoostStateEnum",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "GeneratedCommandList",
+              "code": 65528,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AcceptedCommandList",
+              "code": 65529,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AttributeList",
+              "code": 65531,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "FeatureMap",
+              "code": 65532,
+              "mfgCode": null,
+              "side": "server",
+              "type": "bitmap32",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "ClusterRevision",
+              "code": 65533,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            }
+          ]
+        },
+        {
           "name": "Device Energy Management",
           "code": 152,
           "mfgCode": null,
@@ -4680,32 +4901,156 @@
               "reportableChange": 0
             },
             {
-              "name": "StartUpMode",
-              "code": 2,
+              "name": "GeneratedCommandList",
+              "code": 65528,
               "mfgCode": null,
               "side": "server",
-              "type": "int8u",
+              "type": "array",
               "included": 1,
-              "storageOption": "RAM",
+              "storageOption": "External",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "",
+              "defaultValue": null,
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
               "reportableChange": 0
             },
             {
-              "name": "OnMode",
-              "code": 3,
+              "name": "AcceptedCommandList",
+              "code": 65529,
               "mfgCode": null,
               "side": "server",
-              "type": "int8u",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "EventList",
+              "code": 65530,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "AttributeList",
+              "code": 65531,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "FeatureMap",
+              "code": 65532,
+              "mfgCode": null,
+              "side": "server",
+              "type": "bitmap32",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "ClusterRevision",
+              "code": 65533,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int16u",
               "included": 1,
               "storageOption": "RAM",
               "singleton": 0,
               "bounded": 0,
-              "defaultValue": "",
+              "defaultValue": "1",
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            }
+          ]
+        },
+        {
+          "name": "Water Heater Mode",
+          "code": 158,
+          "mfgCode": null,
+          "define": "WATER_HEATER_MODE_CLUSTER",
+          "side": "server",
+          "enabled": 1,
+          "commands": [
+            {
+              "name": "ChangeToMode",
+              "code": 0,
+              "mfgCode": null,
+              "source": "client",
+              "isIncoming": 1,
+              "isEnabled": 1
+            },
+            {
+              "name": "ChangeToModeResponse",
+              "code": 1,
+              "mfgCode": null,
+              "source": "server",
+              "isIncoming": 0,
+              "isEnabled": 1
+            }
+          ],
+          "attributes": [
+            {
+              "name": "SupportedModes",
+              "code": 0,
+              "mfgCode": null,
+              "side": "server",
+              "type": "array",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
+              "reportable": 1,
+              "minInterval": 1,
+              "maxInterval": 65534,
+              "reportableChange": 0
+            },
+            {
+              "name": "CurrentMode",
+              "code": 1,
+              "mfgCode": null,
+              "side": "server",
+              "type": "int8u",
+              "included": 1,
+              "storageOption": "External",
+              "singleton": 0,
+              "bounded": 0,
+              "defaultValue": null,
               "reportable": 1,
               "minInterval": 1,
               "maxInterval": 65534,
@@ -4869,38 +5214,6 @@
               "reportableChange": 0
             },
             {
-              "name": "StartUpMode",
-              "code": 2,
-              "mfgCode": null,
-              "side": "server",
-              "type": "int8u",
-              "included": 1,
-              "storageOption": "RAM",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": "",
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
-              "name": "OnMode",
-              "code": 3,
-              "mfgCode": null,
-              "side": "server",
-              "type": "int8u",
-              "included": 1,
-              "storageOption": "RAM",
-              "singleton": 0,
-              "bounded": 0,
-              "defaultValue": "",
-              "reportable": 1,
-              "minInterval": 1,
-              "maxInterval": 65534,
-              "reportableChange": 0
-            },
-            {
               "name": "GeneratedCommandList",
               "code": 65528,
               "mfgCode": null,
diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmMain.h b/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h
similarity index 92%
rename from examples/all-clusters-app/all-clusters-common/include/WhmMain.h
rename to examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h
index 21dc9d8..819ff9e 100644
--- a/examples/all-clusters-app/all-clusters-common/include/WhmMain.h
+++ b/examples/energy-management-app/energy-management-common/water-heater/include/WaterHeaterMain.h
@@ -23,8 +23,8 @@
 namespace Clusters {
 namespace WaterHeaterManagement {
 
-void WhmApplicationInit();
-void WhmApplicationShutdown();
+void FullWhmApplicationInit();
+void FullWhmApplicationShutdown();
 
 } // namespace WaterHeaterManagement
 } // namespace Clusters
diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmDelegate.h b/examples/energy-management-app/energy-management-common/water-heater/include/WhmDelegate.h
similarity index 100%
rename from examples/all-clusters-app/all-clusters-common/include/WhmDelegate.h
rename to examples/energy-management-app/energy-management-common/water-heater/include/WhmDelegate.h
diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmInstance.h b/examples/energy-management-app/energy-management-common/water-heater/include/WhmInstance.h
similarity index 100%
rename from examples/all-clusters-app/all-clusters-common/include/WhmInstance.h
rename to examples/energy-management-app/energy-management-common/water-heater/include/WhmInstance.h
diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmMain.h b/examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h
similarity index 89%
copy from examples/all-clusters-app/all-clusters-common/include/WhmMain.h
copy to examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h
index 21dc9d8..34f04d8 100644
--- a/examples/all-clusters-app/all-clusters-common/include/WhmMain.h
+++ b/examples/energy-management-app/energy-management-common/water-heater/include/WhmMain.h
@@ -18,13 +18,15 @@
 
 #pragma once
 
+#include <lib/core/CHIPError.h>
+
 namespace chip {
 namespace app {
 namespace Clusters {
 namespace WaterHeaterManagement {
 
-void WhmApplicationInit();
-void WhmApplicationShutdown();
+CHIP_ERROR WhmApplicationInit();
+CHIP_ERROR WhmApplicationShutdown();
 
 } // namespace WaterHeaterManagement
 } // namespace Clusters
diff --git a/examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h b/examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h
similarity index 94%
rename from examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h
rename to examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h
index b56aa24..3a48b46 100644
--- a/examples/all-clusters-app/all-clusters-common/include/WhmManufacturer.h
+++ b/examples/energy-management-app/energy-management-common/water-heater/include/WhmManufacturer.h
@@ -18,6 +18,7 @@
 
 #pragma once
 
+#include <DEMManufacturerDelegate.h>
 #include <WhmDelegate.h>
 #include <WhmInstance.h>
 
@@ -32,7 +33,7 @@
  * Helps with handling the test triggers.
  */
 
-class WhmManufacturer
+class WhmManufacturer : public DeviceEnergyManagement::DEMManufacturerDelegate
 {
 public:
     WhmManufacturer(WaterHeaterManagementInstance * whmInstance) { mWhmInstance = whmInstance; }
@@ -139,6 +140,13 @@
      */
     void BoostCommandFinished();
 
+    /* Implement the DEMManufacturerDelegate interface */
+
+    /**
+     * @brief The PowerAdjustEnd event needs to report the approximate energy used by the ESA during the session.
+     */
+    int64_t GetApproxEnergyDuringSession() override;
+
 private:
     WaterHeaterManagementInstance * mWhmInstance;
 };
diff --git a/examples/all-clusters-app/all-clusters-common/include/water-heater-mode.h b/examples/energy-management-app/energy-management-common/water-heater/include/water-heater-mode.h
similarity index 100%
rename from examples/all-clusters-app/all-clusters-common/include/water-heater-mode.h
rename to examples/energy-management-app/energy-management-common/water-heater/include/water-heater-mode.h
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
new file mode 100644
index 0000000..0dcfb81
--- /dev/null
+++ b/examples/energy-management-app/energy-management-common/water-heater/src/WaterHeaterMain.cpp
@@ -0,0 +1,100 @@
+/*
+ *
+ *    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 <DeviceEnergyManagementDelegateImpl.h>
+#include <DeviceEnergyManagementManager.h>
+#include <ElectricalPowerMeasurementDelegate.h>
+#include <PowerTopologyDelegate.h>
+#include <WhmManufacturer.h>
+#include <device-energy-management-modes.h>
+#include <water-heater-mode.h>
+
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <app/clusters/electrical-energy-measurement-server/electrical-energy-measurement-server.h>
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <app/clusters/power-topology-server/power-topology-server.h>
+#include <app/server/Server.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/Linux/NetworkCommissioningDriver.h>
+
+#include <DEMDelegate.h>
+#include <EnergyEvseMain.h>
+#include <WhmMain.h>
+
+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/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp
similarity index 100%
rename from examples/all-clusters-app/all-clusters-common/src/WhmDelegateImpl.cpp
rename to examples/energy-management-app/energy-management-common/water-heater/src/WhmDelegateImpl.cpp
diff --git a/examples/all-clusters-app/all-clusters-common/src/WhmInstance.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmInstance.cpp
similarity index 100%
rename from examples/all-clusters-app/all-clusters-common/src/WhmInstance.cpp
rename to examples/energy-management-app/energy-management-common/water-heater/src/WhmInstance.cpp
diff --git a/examples/all-clusters-app/all-clusters-common/src/WhmMain.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp
similarity index 95%
rename from examples/all-clusters-app/all-clusters-common/src/WhmMain.cpp
rename to examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp
index ea59fef..038e332 100644
--- a/examples/all-clusters-app/all-clusters-common/src/WhmMain.cpp
+++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmMain.cpp
@@ -167,25 +167,22 @@
     return CHIP_NO_ERROR;
 }
 
-void WhmApplicationInit()
+CHIP_ERROR WhmApplicationInit()
 {
-    if (WhmInit() != CHIP_NO_ERROR)
-    {
-        return;
-    }
+    ReturnErrorOnFailure(WhmInit());
 
     /* Do this last so that the instances for other clusters can be wrapped inside */
-    if (WhmManufacturerInit() != CHIP_NO_ERROR)
-    {
-        WhmShutdown();
-        return;
-    }
+    ReturnErrorOnFailure(WhmManufacturerInit());
+
+    return CHIP_NO_ERROR;
 }
 
-void WhmApplicationShutdown()
+CHIP_ERROR WhmApplicationShutdown()
 {
     /* Shutdown in reverse order that they were created */
     WhmManufacturerShutdown();
+
+    return WhmShutdown();
 }
 
 } // namespace WaterHeaterManagement
diff --git a/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp
similarity index 97%
rename from examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp
rename to examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp
index 8865501..af01f36 100644
--- a/examples/all-clusters-app/all-clusters-common/src/WhmManufacturer.cpp
+++ b/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp
@@ -160,6 +160,12 @@
     return wg;
 }
 
+// The PowerAdjustEnd event needs to report the approximate energy used by the ESA during the session.
+int64_t WhmManufacturer::GetApproxEnergyDuringSession()
+{
+    return 300;
+}
+
 void SetTestEventTrigger_BasicInstallationTestEvent()
 {
     WaterHeaterManagementDelegate * dg = GetWhmDelegate();
diff --git a/examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp b/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp
similarity index 100%
rename from examples/all-clusters-app/all-clusters-common/src/water-heater-mode.cpp
rename to examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp
diff --git a/examples/energy-management-app/esp32/README.md b/examples/energy-management-app/esp32/README.md
index c2fb2bc..8e0d127 100644
--- a/examples/energy-management-app/esp32/README.md
+++ b/examples/energy-management-app/esp32/README.md
@@ -1,7 +1,8 @@
 # Matter ESP32 Energy Management Example
 
-This example demonstrates the Matter Electric Vehicle Supply Equipment
-application on ESP platforms.
+This example demonstrates the Matter Electric Vehicle Supply Equipment and Water
+Heater example application along with several other energy management clusters
+on ESP platforms.
 
 Please
 [setup ESP-IDF and CHIP Environment](../../../docs/guides/esp32/setup_idf_chip.md)
@@ -35,6 +36,41 @@
 
 ---
 
+### Build time configuration
+
+-   Application mode: By default the example app will run the EVSE example,
+    however this can be changed using the `idy.py menuconfig` command and
+    searching for:
+
+        ENABLE_EXAMPLE_WATER_HEATER_DEVICE
+        ENABLE_EXAMPLE_EVSE_DEVICE
+
+-   Test Event Trigger support: By default the EVSE, Water Heater, Device Energy
+    Management (DEM), Energy Reporting test event triggers are enabled in the
+    build. To turn these off run `idf.py menuconfig` and search for the
+    following config entries:
+
+        ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
+        ENABLE_ENERGY_EVSE_TRIGGER
+        ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
+        ENABLE_ENERGY_REPORTING_TRIGGER
+
+-   Device Energy Management feature support: Depending on the capabilities of
+    the device it may support Power Forecast Reporting `PFR` or State Forecast
+    Reporting `SFR`. However it is not allowed to support both of these at once.
+
+    By default `PFR` is enabled in the build. To change this run
+    `idf.py menuconfig` and search for the following config entries:
+
+        DEM_SUPPORT_STATE_FORECAST_REPORTING
+        DEM_SUPPORT_POWER_FORECAST_REPORTING
+
+    Note only one of these can be enabled to meet Matter specification
+    conformance.
+
+    When running in test events, some test cases (e.g. TC_DEM_2.7 and
+    TC_DEM_2.8) depend on the correct setting to be used in the binary DUT.
+
 ### Cluster Control
 
 -   After successful commissioning, use the Energy Electric Vehicle Supply
@@ -47,3 +83,6 @@
 ```
         $ ./out/debug/chip-tool energyevse enable-charging 0xFFFFFFFF 6000 32000 <NODE ID> 1 --timedInteractionTimeoutMs <Time>
 ```
+
+-   More examples using chip-repl are demonstrated in
+    [Energy Management Linux](../linux/README.md)
diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt
index 03b8234..56940fb 100644
--- a/examples/energy-management-app/esp32/main/CMakeLists.txt
+++ b/examples/energy-management-app/esp32/main/CMakeLists.txt
@@ -23,6 +23,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/include"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/esp32/main/include"
                       "${CMAKE_CURRENT_LIST_DIR}/include"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32"
@@ -36,6 +37,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/device-energy-management/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-evse/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/energy-reporting/src"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/energy-management-app/energy-management-common/water-heater/src"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/ota"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/common"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/examples/platform/esp32/time"
@@ -76,6 +78,7 @@
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/mode-base-server"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-energy-measurement-server"
                       "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/electrical-power-measurement-server"
+                      "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/water-heater-management-server"
 )
 
 
diff --git a/examples/energy-management-app/esp32/main/Kconfig.projbuild b/examples/energy-management-app/esp32/main/Kconfig.projbuild
index d994865..94efe6c 100644
--- a/examples/energy-management-app/esp32/main/Kconfig.projbuild
+++ b/examples/energy-management-app/esp32/main/Kconfig.projbuild
@@ -185,3 +185,56 @@
             about available pin numbers for UART.
 
 endmenu
+
+
+menu "Energy Management Example App Configuration"
+
+    config ENABLE_EXAMPLE_EVSE_DEVICE
+        bool "Enable EVSE device on EP1"
+        default "y"
+        help
+            To use Energy Management App as EVSE device and compile dependent files.
+
+    config ENABLE_EXAMPLE_WATER_HEATER_DEVICE
+        bool "Enable Water Heater device on EP1"
+        default "n"
+        help
+            To use Energy Management App as Water Heater device and compile dependent files.
+
+    config CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
+        bool "Enable DEM triggers"
+        default "n"
+        help
+            Enable test triggers used by the Device Energy Management tests
+
+    config CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
+        bool "Enable EVSE triggers"
+        default "n"
+        help
+            Enable test triggers used by the Evse tests
+
+    config CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
+        bool "Enable Water Heater triggers"
+        default "n"
+        help
+            Enable test triggers used by the Water Heater Management tests
+
+    config CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
+        bool "Enable Electrical Power & Energy Measurement triggers"
+        default "n"
+        help
+            Enable test triggers used by the Energy Reporting (EEM / EPM) tests       
+
+    config DEM_SUPPORT_STATE_FORECAST_REPORTING
+        bool "State forecast reporting is supported"
+        default "n"
+        help
+            Ensure kStateForecastReporting (SFR) is set in the DeviceEnergyManagement::Feature attribute. Note cannot set SFR and PFR.
+
+    config DEM_SUPPORT_POWER_FORECAST_REPORTING
+        bool "Power forecast reporting is supported"
+        default "y"
+        help
+            Ensure kPowerForecastReporting (PFR) is set in the DeviceEnergyManagement::Feature attribute. Note cannot set PFR and SFR.
+
+endmenu
diff --git a/examples/energy-management-app/esp32/main/main.cpp b/examples/energy-management-app/esp32/main/main.cpp
index 136817a..3362388 100644
--- a/examples/energy-management-app/esp32/main/main.cpp
+++ b/examples/energy-management-app/esp32/main/main.cpp
@@ -16,7 +16,14 @@
  */
 
 #include "DeviceCallbacks.h"
+
+#if CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
 #include <EnergyEvseMain.h>
+#endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
+
+#if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE
+#include <WaterHeaterMain.h>
+#endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
 
 #include "esp_log.h"
 #include <common/CHIPDeviceManager.h>
@@ -72,6 +79,7 @@
 using namespace ::chip::Credentials;
 using namespace ::chip::DeviceManager;
 using namespace ::chip::DeviceLayer;
+using namespace chip::app::Clusters::WaterHeaterManagement;
 
 #if CONFIG_ENABLE_ESP_INSIGHTS_TRACE
 extern const char insights_auth_key_start[] asm("_binary_insights_auth_key_txt_start");
@@ -117,9 +125,21 @@
 namespace DeviceEnergyManagement {
 
 // Keep track of the parsed featureMap option
+#if defined(CONFIG_DEM_SUPPORT_POWER_FORECAST_REPORTING) && defined(CONFIG_DEM_SUPPORT_STATE_FORECAST_REPORTING)
+#error Cannot define CONFIG_DEM_SUPPORT_POWER_FORECAST_REPORTING and CONFIG_DEM_SUPPORT_STATE_FORECAST_REPORTING
+#endif
+
+#ifdef CONFIG_DEM_SUPPORT_POWER_FORECAST_REPORTING
 static chip::BitMask<Feature> sFeatureMap(Feature::kPowerAdjustment, Feature::kPowerForecastReporting,
-                                          Feature::kStateForecastReporting, Feature::kStartTimeAdjustment, Feature::kPausable,
-                                          Feature::kForecastAdjustment, Feature::kConstraintBasedAdjustment);
+                                          Feature::kStartTimeAdjustment, Feature::kPausable, Feature::kForecastAdjustment,
+                                          Feature::kConstraintBasedAdjustment);
+#elif CONFIG_DEM_SUPPORT_STATE_FORECAST_REPORTING
+static chip::BitMask<Feature> sFeatureMap(Feature::kPowerAdjustment, Feature::kStateForecastReporting,
+                                          Feature::kStartTimeAdjustment, Feature::kPausable, Feature::kForecastAdjustment,
+                                          Feature::kConstraintBasedAdjustment);
+#else
+static chip::BitMask<Feature> sFeatureMap(Feature::kPowerAdjustment);
+#endif
 
 chip::BitMask<Feature> GetFeatureMapFromCmdLine()
 {
@@ -131,16 +151,34 @@
 } // namespace app
 } // namespace chip
 
+// Check we are not trying to build in both app types simultaneously
+#if defined(CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE) && defined(CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE)
+#error Cannot define CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE and CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE
+#endif
+
 void ApplicationInit()
 {
     ESP_LOGD(TAG, "Energy Management App: ApplicationInit()");
+#if CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
     EvseApplicationInit();
+#endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
+
+#if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE
+    FullWhmApplicationInit();
+#endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE
 }
 
 void ApplicationShutdown()
 {
     ESP_LOGD(TAG, "Energy Management App: ApplicationShutdown()");
+
+#if CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
     EvseApplicationShutdown();
+#endif // CONFIG_ENABLE_EXAMPLE_EVSE_DEVICE
+
+#if CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE
+    FullWhmApplicationShutdown();
+#endif // CONFIG_ENABLE_EXAMPLE_WATER_HEATER_DEVICE
 }
 
 static void InitServer(intptr_t context)
diff --git a/examples/energy-management-app/esp32/sdkconfig.defaults b/examples/energy-management-app/esp32/sdkconfig.defaults
index c78a875..5bcdc33 100644
--- a/examples/energy-management-app/esp32/sdkconfig.defaults
+++ b/examples/energy-management-app/esp32/sdkconfig.defaults
@@ -67,3 +67,21 @@
 
 # Enable sntp time sync
 CONFIG_ENABLE_SNTP_TIME_SYNC=y
+
+# Enable EVSE device on EP1
+CONFIG_CHIP_DEVICE_CONFIG_ENABLE_EVSE=y
+
+# Enable test triggers used by the Device Energy Management tests
+CONFIG_CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER=y
+
+# Enable test triggers used by the Evse tests
+CONFIG_CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER=y
+
+# Enable test triggers used by the Water Heater Management tests
+CONFIG_CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER=y
+
+# Enable test triggers used by the Electrical Reporting tests
+CONFIG_CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER=y
+
+# Ensure kPowerForecastReporting (PFR) is set in the DeviceEnergyManagement::Feature attribute. Note cannot set PFR and SFR.
+CONFIG_DEM_SUPPORT_POWER_FORECAST_REPORTING=y
diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn
index d2633c6..a9d41a1 100644
--- a/examples/energy-management-app/linux/BUILD.gn
+++ b/examples/energy-management-app/linux/BUILD.gn
@@ -51,6 +51,12 @@
     "${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/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",
+    "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/WhmManufacturer.cpp",
+    "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/src/water-heater-mode.cpp",
     "include/CHIPProjectAppConfig.h",
     "main.cpp",
   ]
@@ -75,6 +81,8 @@
     "${chip_root}/examples/energy-management-app/energy-management-common/device-energy-management/include",
     "${chip_root}/examples/energy-management-app/energy-management-common/energy-evse/include",
     "${chip_root}/examples/energy-management-app/energy-management-common/energy-reporting/include",
+    "${chip_root}/examples/energy-management-app/energy-management-common/water-heater/include",
+    "${chip_root}/examples/all-clusters-app/all-clusters-common/include",
   ]
 
   if (chip_enable_pw_rpc) {
diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md
index c9d1dee..89b165c 100644
--- a/examples/energy-management-app/linux/README.md
+++ b/examples/energy-management-app/linux/README.md
@@ -16,7 +16,6 @@
     -   [Building](#building)
     -   [Commandline arguments](#commandline-arguments)
     -   [Running the Complete Example on Raspberry Pi 4](#running-the-complete-example-on-raspberry-pi-4)
-    -   [Running RPC Console](#running-rpc-console)
     -   [Device Tracing](#device-tracing)
     -   [Python Test Cases](#python-test-cases)
         -   [Running the test cases:](#running-the-test-cases)
@@ -74,6 +73,19 @@
     `hciconfig` command, for example, `--ble-device 1` means using `hci1`
     interface. Default: `0`.
 
+-   `--application <evse | water-heater>`
+
+    Emulate either an EVSE or Water Heater example.
+
+-   `--featureSet <feature map for Device Energy Management e.g. 0x7a>`
+
+    Sets the run-time FeatureMap value for the Device Energy Management cluster.
+    This allows the DEM cluster to support `PFR` or `SFR` so that the full range
+    of TC_DEM_2.x test cases can be exercised with this application.
+
+    See the test-runner headers in the respective test script in
+    src/python_testing/TC_DEM_2.x.py which have recommended values to use.
+
 ## Running the Complete Example on Raspberry Pi 4
 
 > If you want to test Echo protocol, please enable Echo handler
@@ -124,20 +136,6 @@
         -   Test the device using ChipDeviceController on your laptop /
             workstation etc.
 
-## Running RPC Console
-
--   As part of building the example with RPCs enabled the chip_rpc python
-    interactive console is installed into your venv. The python wheel files are
-    also created in the output folder: out/debug/chip_rpc_console_wheels. To
-    install the wheel files without rebuilding:
-    `pip3 install out/debug/chip_rpc_console_wheels/*.whl`
-
--   To use the chip-rpc console after it has been installed run:
-    `chip-console -s localhost:33000 -o /<YourFolder>/pw_log.out`
-
--   Then you can Get and Set the Energy Management using the RPCs:
-    `rpcs.chip.rpc.EnergyManagement.Get()`
-
 ## Device Tracing
 
 Device tracing is available to analyze the device performance. To turn on
@@ -185,7 +183,7 @@
 Once the application is built you also need to tell it at runtime what the
 chosen enable key is using the `--enable-key` command line option.
 
-          $ ./chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f
+          $ ./chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f --application evse
 
 ### Running the test cases:
 
@@ -194,7 +192,7 @@
 Start the chip-energy-management-app:
 
 ```bash
-rm -f evse.bin; out/debug/chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f --KVS evse.bin --featureSet $featureSet
+rm -f evse.bin; out/debug/chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f --KVS evse.bin --featureSet $featureSet --application evse
 ```
 
 where the \$featureSet depends on the test being run:
@@ -262,7 +260,7 @@
 -   Step 1: Launch the example app
 
 ```bash
-    $ ./chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f
+    $ ./chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f --application evse
 ```
 
 -   Step 2: Launch CHIP-REPL
diff --git a/examples/energy-management-app/linux/args.gni b/examples/energy-management-app/linux/args.gni
index 1f196e6..f3c90f1 100644
--- a/examples/energy-management-app/linux/args.gni
+++ b/examples/energy-management-app/linux/args.gni
@@ -32,3 +32,4 @@
 chip_enable_energy_evse_trigger = true
 chip_enable_energy_reporting_trigger = true
 chip_enable_device_energy_management_trigger = true
+chip_enable_water_heater_management_trigger = true
diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp
index cdc2c4e..7a63125 100644
--- a/examples/energy-management-app/linux/main.cpp
+++ b/examples/energy-management-app/linux/main.cpp
@@ -18,6 +18,7 @@
 
 #include <AppMain.h>
 #include <EnergyEvseMain.h>
+#include <WaterHeaterMain.h>
 #include <app-common/zap-generated/cluster-objects.h>
 #include <lib/support/BitMask.h>
 
@@ -26,28 +27,36 @@
 using namespace chip::app::Clusters;
 using namespace chip::app::Clusters::DeviceEnergyManagement;
 using namespace chip::app::Clusters::DeviceEnergyManagement::Attributes;
+using namespace chip::app::Clusters::WaterHeaterManagement;
 
 // Parse a hex (prefixed by 0x) or decimal (no-prefix) string
 static uint32_t ParseNumber(const char * pString);
 
 // Parses the --featureMap option
-static bool FeatureMapOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier,
-                                    const char * aName, const char * aValue);
+static bool EnergyAppOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier,
+                                   const char * aName, const char * aValue);
 
-constexpr uint16_t kOptionFeatureMap = 'f';
+constexpr uint16_t kOptionApplication = 0xffd0;
+constexpr uint16_t kOptionFeatureMap  = 0xffd1;
+
+constexpr const char * kEvseApp = "evse";
+constexpr const char * kWhmApp  = "water-heater";
+
+constexpr const char * kValidApps[] = { kEvseApp, kWhmApp };
 
 // Define the chip::ArgParser command line structures for extending the command line to support the
-// -f/--featureMap option
-static chip::ArgParser::OptionDef sFeatureMapOptionDefs[] = {
-    { "featureSet", chip::ArgParser::kArgumentRequired, kOptionFeatureMap }, { nullptr }
+// energy apps
+static chip::ArgParser::OptionDef sEnergyAppOptionDefs[] = {
+    { "application", chip::ArgParser::kArgumentRequired, kOptionApplication },
+    { "featureSet", chip::ArgParser::kArgumentRequired, kOptionFeatureMap },
+    { nullptr }
 };
 
-static chip::ArgParser::OptionSet sCmdLineOptions = {
-    FeatureMapOptionHandler,   // handler function
-    sFeatureMapOptionDefs,     // array of option definitions
-    "GENERAL OPTIONS",         // help group
-    "-f, --featureSet <value>" // option help text
-};
+static chip::ArgParser::OptionSet sCmdLineOptions = { EnergyAppOptionHandler, // handler function
+                                                      sEnergyAppOptionDefs,   // array of option definitions
+                                                      "PROGRAM OPTIONS",      // help group
+                                                      "-a, --application <evse|water-heater>\n"
+                                                      "-f, --featureSet <value>\n" };
 
 namespace chip {
 namespace app {
@@ -59,6 +68,9 @@
                                           Feature::kStateForecastReporting, Feature::kStartTimeAdjustment, Feature::kPausable,
                                           Feature::kForecastAdjustment, Feature::kConstraintBasedAdjustment);
 
+// Make EVSE the default app
+static const char * spApp = kEvseApp;
+
 chip::BitMask<Feature> GetFeatureMapFromCmdLine()
 {
     return sFeatureMap;
@@ -87,22 +99,55 @@
 void ApplicationInit()
 {
     ChipLogDetail(AppServer, "Energy Management App: ApplicationInit()");
-    EvseApplicationInit();
+    if (strcmp(spApp, kEvseApp) == 0)
+    {
+        EvseApplicationInit();
+    }
+    else if (strcmp(spApp, kWhmApp) == 0)
+    {
+        FullWhmApplicationInit();
+    }
+    else
+    {
+        ChipLogError(Support, "Unexpected application %s", spApp);
+    }
 }
 
 void ApplicationShutdown()
 {
     ChipLogDetail(AppServer, "Energy Management App: ApplicationShutdown()");
+
     EvseApplicationShutdown();
+    FullWhmApplicationShutdown();
 }
 
-static bool FeatureMapOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier,
-                                    const char * aName, const char * aValue)
+static bool EnergyAppOptionHandler(const char * aProgram, chip::ArgParser::OptionSet * aOptions, int aIdentifier,
+                                   const char * aName, const char * aValue)
 {
     bool retval = true;
 
     switch (aIdentifier)
     {
+    case kOptionApplication:
+        spApp = nullptr;
+        for (size_t idx = 0; idx < (sizeof(kValidApps) / sizeof(kValidApps[0])); idx++)
+        {
+            if (strcmp(kValidApps[idx], aValue) == 0)
+            {
+                spApp = kValidApps[idx];
+                break;
+            }
+        }
+
+        if (spApp != nullptr)
+        {
+            ChipLogDetail(Support, "Running application %s", spApp);
+        }
+        else
+        {
+            retval = false;
+        }
+        break;
     case kOptionFeatureMap:
         sFeatureMap = BitMask<chip::app::Clusters::DeviceEnergyManagement::Feature>(ParseNumber(aValue));
         ChipLogDetail(Support, "Using FeatureMap 0x%04x", sFeatureMap.Raw());
diff --git a/examples/platform/esp32/common/Esp32AppServer.cpp b/examples/platform/esp32/common/Esp32AppServer.cpp
index f0e75cf..37dd7f4 100644
--- a/examples/platform/esp32/common/Esp32AppServer.cpp
+++ b/examples/platform/esp32/common/Esp32AppServer.cpp
@@ -22,10 +22,24 @@
 #include <app/TestEventTriggerDelegate.h>
 #include <app/clusters/network-commissioning/network-commissioning.h>
 #include <app/clusters/ota-requestor/OTATestEventTriggerHandler.h>
+#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
 #include <app/server/Dnssd.h>
 #include <app/server/Server.h>
 #include <platform/ESP32/NetworkCommissioningDriver.h>
 
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
+#include <app/clusters/energy-evse-server/EnergyEvseTestEventTriggerHandler.h>
+#endif
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
+#include <app/clusters/electrical-energy-measurement-server/EnergyReportingTestEventTriggerHandler.h>
+#endif
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
+#include <app/clusters/water-heater-management-server/WaterHeaterManagementTestEventTriggerHandler.h>
+#endif
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
+#include <app/clusters/device-energy-management-server/DeviceEnergyManagementTestEventTriggerHandler.h>
+#endif
+
 #if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
 #if CONFIG_BT_ENABLED
 #include "esp_bt.h"
@@ -124,6 +138,24 @@
     }
     static SimpleTestEventTriggerDelegate sTestEventTriggerDelegate{};
     VerifyOrDie(sTestEventTriggerDelegate.Init(ByteSpan(sTestEventTriggerEnableKey)) == CHIP_NO_ERROR);
+
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_ENERGY_EVSE_TRIGGER
+    static EnergyEvseTestEventTriggerHandler sEnergyEvseTestEventTriggerHandler;
+    sTestEventTriggerDelegate.AddHandler(&sEnergyEvseTestEventTriggerHandler);
+#endif
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_ENERGY_REPORTING_TRIGGER
+    static EnergyReportingTestEventTriggerHandler sEnergyReportingTestEventTriggerHandler;
+    sTestEventTriggerDelegate.AddHandler(&sEnergyReportingTestEventTriggerHandler);
+#endif
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_WATER_HEATER_MANAGEMENT_TRIGGER
+    static WaterHeaterManagementTestEventTriggerHandler sWaterHeaterManagementTestEventTriggerHandler;
+    sTestEventTriggerDelegate.AddHandler(&sWaterHeaterManagementTestEventTriggerHandler);
+#endif
+#if CONFIG_CHIP_DEVICE_CONFIG_ENABLE_DEVICE_ENERGY_MANAGEMENT_TRIGGER
+    static DeviceEnergyManagementTestEventTriggerHandler sDeviceEnergyManagementTestEventTriggerHandler;
+    sTestEventTriggerDelegate.AddHandler(&sDeviceEnergyManagementTestEventTriggerHandler);
+#endif
+
 #if CONFIG_ENABLE_OTA_REQUESTOR
     static OTATestEventTriggerHandler sOtaTestEventTriggerHandler{};
     VerifyOrDie(sTestEventTriggerDelegate.AddHandler(&sOtaTestEventTriggerHandler) == CHIP_NO_ERROR);
diff --git a/src/python_testing/TC_DEM_2_2.py b/src/python_testing/TC_DEM_2_2.py
index 0c32992..ae4f370 100644
--- a/src/python_testing/TC_DEM_2_2.py
+++ b/src/python_testing/TC_DEM_2_2.py
@@ -23,7 +23,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x01
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x01 --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_3.py b/src/python_testing/TC_DEM_2_3.py
index 6bdd81c..8174c7b 100644
--- a/src/python_testing/TC_DEM_2_3.py
+++ b/src/python_testing/TC_DEM_2_3.py
@@ -22,7 +22,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_4.py b/src/python_testing/TC_DEM_2_4.py
index 390889f..6041dcf 100644
--- a/src/python_testing/TC_DEM_2_4.py
+++ b/src/python_testing/TC_DEM_2_4.py
@@ -22,7 +22,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_5.py b/src/python_testing/TC_DEM_2_5.py
index 85d3cd7..a822e7f 100644
--- a/src/python_testing/TC_DEM_2_5.py
+++ b/src/python_testing/TC_DEM_2_5.py
@@ -23,7 +23,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_6.py b/src/python_testing/TC_DEM_2_6.py
index 7390436..12bf060 100644
--- a/src/python_testing/TC_DEM_2_6.py
+++ b/src/python_testing/TC_DEM_2_6.py
@@ -23,7 +23,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7c
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7c --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_7.py b/src/python_testing/TC_DEM_2_7.py
index fa7dba1..46f0377 100644
--- a/src/python_testing/TC_DEM_2_7.py
+++ b/src/python_testing/TC_DEM_2_7.py
@@ -23,7 +23,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7a --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_8.py b/src/python_testing/TC_DEM_2_8.py
index 773648c..12200eb 100644
--- a/src/python_testing/TC_DEM_2_8.py
+++ b/src/python_testing/TC_DEM_2_8.py
@@ -23,7 +23,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7c
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7c --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_DEM_2_9.py b/src/python_testing/TC_DEM_2_9.py
index 8e60b69..de51b7a 100644
--- a/src/python_testing/TC_DEM_2_9.py
+++ b/src/python_testing/TC_DEM_2_9.py
@@ -23,7 +23,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7e
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x7e --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EEVSE_2_2.py b/src/python_testing/TC_EEVSE_2_2.py
index 833375e..a0e226b 100644
--- a/src/python_testing/TC_EEVSE_2_2.py
+++ b/src/python_testing/TC_EEVSE_2_2.py
@@ -22,7 +22,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EEVSE_2_3.py b/src/python_testing/TC_EEVSE_2_3.py
index 9ff68ee..27507a4 100644
--- a/src/python_testing/TC_EEVSE_2_3.py
+++ b/src/python_testing/TC_EEVSE_2_3.py
@@ -22,7 +22,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EEVSE_2_4.py b/src/python_testing/TC_EEVSE_2_4.py
index 3b2db65..33eb143 100644
--- a/src/python_testing/TC_EEVSE_2_4.py
+++ b/src/python_testing/TC_EEVSE_2_4.py
@@ -22,7 +22,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EEVSE_2_5.py b/src/python_testing/TC_EEVSE_2_5.py
index 89ee987..ecd88b4 100644
--- a/src/python_testing/TC_EEVSE_2_5.py
+++ b/src/python_testing/TC_EEVSE_2_5.py
@@ -22,7 +22,7 @@
 # test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EWATERHTR_2_1.py b/src/python_testing/TC_EWATERHTR_2_1.py
index 176ecf2..055b592 100644
--- a/src/python_testing/TC_EWATERHTR_2_1.py
+++ b/src/python_testing/TC_EWATERHTR_2_1.py
@@ -20,10 +20,10 @@
 #
 # === BEGIN CI TEST ARGUMENTS ===
 # test-runner-runs: run1
-# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
+# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x03 --application water-heater
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto --int-arg PIXIT.EWATERHTR.EM:1 PIXIT.EWATERHTR.TP:2
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EWATERHTR_2_2.py b/src/python_testing/TC_EWATERHTR_2_2.py
index 9eafd35..5fd40e4 100644
--- a/src/python_testing/TC_EWATERHTR_2_2.py
+++ b/src/python_testing/TC_EWATERHTR_2_2.py
@@ -20,10 +20,10 @@
 #
 # === BEGIN CI TEST ARGUMENTS ===
 # test-runner-runs: run1
-# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
+# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x00 --application water-heater
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_EWATERHTR_2_3.py b/src/python_testing/TC_EWATERHTR_2_3.py
index 41500bd..d2bc97d 100644
--- a/src/python_testing/TC_EWATERHTR_2_3.py
+++ b/src/python_testing/TC_EWATERHTR_2_3.py
@@ -19,10 +19,10 @@
 #
 # === BEGIN CI TEST ARGUMENTS ===
 # test-runner-runs: run1
-# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
+# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --featureSet 0x03 --application water-heater
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_WHM_1_2.py b/src/python_testing/TC_WHM_1_2.py
index aaa8d30..b872767 100644
--- a/src/python_testing/TC_WHM_1_2.py
+++ b/src/python_testing/TC_WHM_1_2.py
@@ -17,10 +17,10 @@
 
 # === BEGIN CI TEST ARGUMENTS ===
 # test-runner-runs: run1
-# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
+# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --enable-key 000102030405060708090a0b0c0d0e0f --application water-heater
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===
 
diff --git a/src/python_testing/TC_WHM_2_1.py b/src/python_testing/TC_WHM_2_1.py
index 0d39d23..3ed5787 100644
--- a/src/python_testing/TC_WHM_2_1.py
+++ b/src/python_testing/TC_WHM_2_1.py
@@ -20,10 +20,10 @@
 #
 # === BEGIN CI TEST ARGUMENTS ===
 # test-runner-runs: run1
-# test-runner-run/run1/app: ${ALL_CLUSTERS_APP}
+# test-runner-run/run1/app: ${ENERGY_MANAGEMENT_APP}
 # test-runner-run/run1/factoryreset: True
 # test-runner-run/run1/quiet: True
-# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json
+# test-runner-run/run1/app-args: --discriminator 1234 --KVS kvs1 --trace-to json:${TRACE_APP}.json --application evse
 # test-runner-run/run1/script-args: --storage-path admin_storage.json --commissioning-method on-network --discriminator 1234 --passcode 20202021 --endpoint 1 --trace-to json:${TRACE_TEST_JSON}.json --trace-to perfetto:${TRACE_TEST_PERFETTO}.perfetto
 # === END CI TEST ARGUMENTS ===