From 1c550b0124f74e9389ef7a5de9cf71632b4594cb Mon Sep 17 00:00:00 2001 From: jamesharrow <93921463+jamesharrow@users.noreply.github.com> Date: Thu, 29 Feb 2024 03:39:50 +0000 Subject: [PATCH] Turned on PowerSource and PowerTopology clusters in EnergyManagementApp for SVE DUTs (#32329) * Turned on PowerSource on EP0 with WIRED mandated attributes, and PowerTopology on EP1 * Added code into EvseMain to initialise the PowerTopology cluster on EP1 * Changed ClusterRevision of PowerTopology to 2, enabled SerialNumber in BasicInfo. Added Initialization of PowerSource attributes. * Added missing PowerTopologyDelegate.h & .cpp * Added power-source and power-topology to ESP32 CMakeList.txt * Updated PowerTopology to include an Instance, and also added to EvseManufacturer class. Called PowerSource->SetEndpointList() * Restyled by whitespace --------- Co-authored-by: Restyled.io --- .../energy-management-app.matter | 307 +++++++++++++++ .../energy-management-app.zap | 351 +++++++++++++++++- .../include/EVSEManufacturerImpl.h | 21 +- .../include/PowerTopologyDelegate.h | 66 ++++ .../src/EVSEManufacturerImpl.cpp | 42 +++ .../src/EnergyEvseMain.cpp | 87 ++++- .../src/PowerTopologyDelegate.cpp | 43 +++ .../esp32/main/CMakeLists.txt | 2 + examples/energy-management-app/linux/BUILD.gn | 1 + .../linux/include/CHIPProjectAppConfig.h | 8 + 10 files changed, 925 insertions(+), 3 deletions(-) create mode 100644 examples/energy-management-app/energy-management-common/include/PowerTopologyDelegate.h create mode 100644 examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp 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 1cedefb6c1e43c..ea4e5db21a0b18 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 @@ -343,6 +343,265 @@ cluster UnitLocalization = 45 { readonly attribute int16u clusterRevision = 65533; } +/** This cluster is used to describe the configuration and capabilities of a physical power source that provides power to the Node. */ +cluster PowerSource = 47 { + revision 1; // NOTE: Default/not specifically set + + enum BatApprovedChemistryEnum : enum16 { + kUnspecified = 0; + kAlkaline = 1; + kLithiumCarbonFluoride = 2; + kLithiumChromiumOxide = 3; + kLithiumCopperOxide = 4; + kLithiumIronDisulfide = 5; + kLithiumManganeseDioxide = 6; + kLithiumThionylChloride = 7; + kMagnesium = 8; + kMercuryOxide = 9; + kNickelOxyhydride = 10; + kSilverOxide = 11; + kZincAir = 12; + kZincCarbon = 13; + kZincChloride = 14; + kZincManganeseDioxide = 15; + kLeadAcid = 16; + kLithiumCobaltOxide = 17; + kLithiumIon = 18; + kLithiumIonPolymer = 19; + kLithiumIronPhosphate = 20; + kLithiumSulfur = 21; + kLithiumTitanate = 22; + kNickelCadmium = 23; + kNickelHydrogen = 24; + kNickelIron = 25; + kNickelMetalHydride = 26; + kNickelZinc = 27; + kSilverZinc = 28; + kSodiumIon = 29; + kSodiumSulfur = 30; + kZincBromide = 31; + kZincCerium = 32; + } + + enum BatChargeFaultEnum : enum8 { + kUnspecified = 0; + kAmbientTooHot = 1; + kAmbientTooCold = 2; + kBatteryTooHot = 3; + kBatteryTooCold = 4; + kBatteryAbsent = 5; + kBatteryOverVoltage = 6; + kBatteryUnderVoltage = 7; + kChargerOverVoltage = 8; + kChargerUnderVoltage = 9; + kSafetyTimeout = 10; + } + + enum BatChargeLevelEnum : enum8 { + kOK = 0; + kWarning = 1; + kCritical = 2; + } + + enum BatChargeStateEnum : enum8 { + kUnknown = 0; + kIsCharging = 1; + kIsAtFullCharge = 2; + kIsNotCharging = 3; + } + + enum BatCommonDesignationEnum : enum16 { + kUnspecified = 0; + kAAA = 1; + kAA = 2; + kC = 3; + kD = 4; + k4v5 = 5; + k6v0 = 6; + k9v0 = 7; + k12AA = 8; + kAAAA = 9; + kA = 10; + kB = 11; + kF = 12; + kN = 13; + kNo6 = 14; + kSubC = 15; + kA23 = 16; + kA27 = 17; + kBA5800 = 18; + kDuplex = 19; + k4SR44 = 20; + k523 = 21; + k531 = 22; + k15v0 = 23; + k22v5 = 24; + k30v0 = 25; + k45v0 = 26; + k67v5 = 27; + kJ = 28; + kCR123A = 29; + kCR2 = 30; + k2CR5 = 31; + kCRP2 = 32; + kCRV3 = 33; + kSR41 = 34; + kSR43 = 35; + kSR44 = 36; + kSR45 = 37; + kSR48 = 38; + kSR54 = 39; + kSR55 = 40; + kSR57 = 41; + kSR58 = 42; + kSR59 = 43; + kSR60 = 44; + kSR63 = 45; + kSR64 = 46; + kSR65 = 47; + kSR66 = 48; + kSR67 = 49; + kSR68 = 50; + kSR69 = 51; + kSR516 = 52; + kSR731 = 53; + kSR712 = 54; + kLR932 = 55; + kA5 = 56; + kA10 = 57; + kA13 = 58; + kA312 = 59; + kA675 = 60; + kAC41E = 61; + k10180 = 62; + k10280 = 63; + k10440 = 64; + k14250 = 65; + k14430 = 66; + k14500 = 67; + k14650 = 68; + k15270 = 69; + k16340 = 70; + kRCR123A = 71; + k17500 = 72; + k17670 = 73; + k18350 = 74; + k18500 = 75; + k18650 = 76; + k19670 = 77; + k25500 = 78; + k26650 = 79; + k32600 = 80; + } + + enum BatFaultEnum : enum8 { + kUnspecified = 0; + kOverTemp = 1; + kUnderTemp = 2; + } + + enum BatReplaceabilityEnum : enum8 { + kUnspecified = 0; + kNotReplaceable = 1; + kUserReplaceable = 2; + kFactoryReplaceable = 3; + } + + enum PowerSourceStatusEnum : enum8 { + kUnspecified = 0; + kActive = 1; + kStandby = 2; + kUnavailable = 3; + } + + enum WiredCurrentTypeEnum : enum8 { + kAC = 0; + kDC = 1; + } + + enum WiredFaultEnum : enum8 { + kUnspecified = 0; + kOverVoltage = 1; + kUnderVoltage = 2; + } + + bitmap Feature : bitmap32 { + kWired = 0x1; + kBattery = 0x2; + kRechargeable = 0x4; + kReplaceable = 0x8; + } + + struct BatChargeFaultChangeType { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + struct BatFaultChangeType { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + struct WiredFaultChangeType { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event WiredFaultChange = 0 { + WiredFaultEnum current[] = 0; + WiredFaultEnum previous[] = 1; + } + + info event BatFaultChange = 1 { + BatFaultEnum current[] = 0; + BatFaultEnum previous[] = 1; + } + + info event BatChargeFaultChange = 2 { + BatChargeFaultEnum current[] = 0; + BatChargeFaultEnum previous[] = 1; + } + + readonly attribute PowerSourceStatusEnum status = 0; + readonly attribute int8u order = 1; + readonly attribute char_string<60> description = 2; + readonly attribute optional nullable int32u wiredAssessedInputVoltage = 3; + readonly attribute optional nullable int16u wiredAssessedInputFrequency = 4; + readonly attribute optional WiredCurrentTypeEnum wiredCurrentType = 5; + readonly attribute optional nullable int32u wiredAssessedCurrent = 6; + readonly attribute optional int32u wiredNominalVoltage = 7; + readonly attribute optional int32u wiredMaximumCurrent = 8; + readonly attribute optional boolean wiredPresent = 9; + readonly attribute optional WiredFaultEnum activeWiredFaults[] = 10; + readonly attribute optional nullable int32u batVoltage = 11; + readonly attribute optional nullable int8u batPercentRemaining = 12; + readonly attribute optional nullable int32u batTimeRemaining = 13; + readonly attribute optional BatChargeLevelEnum batChargeLevel = 14; + readonly attribute optional boolean batReplacementNeeded = 15; + readonly attribute optional BatReplaceabilityEnum batReplaceability = 16; + readonly attribute optional boolean batPresent = 17; + readonly attribute optional BatFaultEnum activeBatFaults[] = 18; + readonly attribute optional char_string<60> batReplacementDescription = 19; + readonly attribute optional BatCommonDesignationEnum batCommonDesignation = 20; + readonly attribute optional char_string<20> batANSIDesignation = 21; + readonly attribute optional char_string<20> batIECDesignation = 22; + readonly attribute optional BatApprovedChemistryEnum batApprovedChemistry = 23; + readonly attribute optional int32u batCapacity = 24; + readonly attribute optional int8u batQuantity = 25; + readonly attribute optional BatChargeStateEnum batChargeState = 26; + readonly attribute optional nullable int32u batTimeToFullCharge = 27; + readonly attribute optional boolean batFunctionalWhileCharging = 28; + readonly attribute optional nullable int32u batChargingCurrent = 29; + readonly attribute optional BatChargeFaultEnum activeBatChargeFaults[] = 30; + readonly attribute endpoint_no endpointList[] = 31; + 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; +} + /** This cluster is used to manage global aspects of the Commissioning flow. */ cluster GeneralCommissioning = 48 { revision 1; // NOTE: Default/not specifically set @@ -1557,6 +1816,27 @@ provisional cluster EnergyEvse = 153 { timed command ClearTargets(): DefaultSuccess = 7; } +/** The Power Topology Cluster provides a mechanism for expressing how power is flowing between endpoints. */ +provisional cluster PowerTopology = 156 { + revision 1; + + bitmap Feature : bitmap32 { + kNodeTopology = 0x1; + kTreeTopology = 0x2; + kSetTopology = 0x4; + kDynamicPowerFlow = 0x8; + } + + readonly attribute optional endpoint_no availableEndpoints[] = 0; + readonly attribute optional endpoint_no activeEndpoints[] = 1; + 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; +} + /** Attributes and commands for selecting a mode from a list of supported options. */ provisional cluster EnergyEvseMode = 157 { revision 1; @@ -1701,6 +1981,7 @@ endpoint 0 { callback attribute hardwareVersionString; callback attribute softwareVersion; callback attribute softwareVersionString; + callback attribute serialNumber; callback attribute capabilityMinima; callback attribute specificationVersion; callback attribute maxPathsPerInvoke; @@ -1742,6 +2023,22 @@ endpoint 0 { ram attribute clusterRevision default = 1; } + server cluster PowerSource { + ram attribute status; + ram attribute order; + ram attribute description; + ram attribute wiredCurrentType; + ram attribute wiredNominalVoltage; + ram attribute wiredMaximumCurrent; + callback attribute endpointList; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 0; + ram attribute clusterRevision default = 2; + } + server cluster GeneralCommissioning { ram attribute breadcrumb default = 0x0000000000000000; callback attribute basicCommissioningInfo; @@ -1860,6 +2157,7 @@ endpoint 0 { } } endpoint 1 { + device type ma_electricalsensor = 1296, version 1; device type energy_evse = 1292, version 1; @@ -2006,6 +2304,15 @@ endpoint 1 { handle command ClearTargets; } + server cluster PowerTopology { + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + callback attribute featureMap; + ram attribute clusterRevision default = 1; + } + server cluster EnergyEvseMode { callback attribute supportedModes; callback attribute currentMode; 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 88514f105c37f1..2f3745ed979e98 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 @@ -600,6 +600,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "SerialNumber", + "code": 15, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "External", + "singleton": 1, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "CapabilityMinima", "code": 19, @@ -1112,6 +1128,224 @@ } ] }, + { + "name": "Power Source", + "code": 47, + "mfgCode": null, + "define": "POWER_SOURCE_CLUSTER", + "side": "server", + "enabled": 1, + "attributes": [ + { + "name": "Status", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "PowerSourceStatusEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Order", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "Description", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "char_string", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredCurrentType", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "WiredCurrentTypeEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredNominalVoltage", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "WiredMaximumCurrent", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "int32u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "EndpointList", + "code": 31, + "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": "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": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "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": "2", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "General Commissioning", "code": 48, @@ -2471,13 +2705,21 @@ "profileId": 259, "label": "Energy EVSE", "name": "Energy EVSE" + }, + { + "code": 1296, + "profileId": 259, + "label": "MA-electricalsensor", + "name": "MA-electricalsensor" } ], "deviceVersions": [ + 1, 1 ], "deviceIdentifiers": [ - 1292 + 1292, + 1296 ], "deviceTypeName": "Energy EVSE", "deviceTypeCode": 1292, @@ -4259,6 +4501,113 @@ } ] }, + { + "name": "Power Topology", + "code": 156, + "mfgCode": null, + "define": "POWER_TOPOLOGY_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "attributes": [ + { + "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": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ] + }, { "name": "Energy EVSE Mode", "code": 157, diff --git a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h index fcae38dcafd2b5..23994e7f5d9454 100644 --- a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h +++ b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h @@ -21,6 +21,7 @@ #include #include #include +#include using chip::Protocols::InteractionModel::Status; namespace chip { @@ -36,13 +37,16 @@ class EVSEManufacturer { public: EVSEManufacturer(EnergyEvseManager * aEvseInstance, - ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * aEPMInstance) + ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * aEPMInstance, + PowerTopology::PowerTopologyInstance * aPTInstance) { mEvseInstance = aEvseInstance; mEPMInstance = aEPMInstance; + mPTInstance = aPTInstance; } EnergyEvseManager * GetEvseInstance() { return mEvseInstance; } ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * GetEPMInstance() { return mEPMInstance; } + PowerTopology::PowerTopologyInstance * GetPTInstance() { return mPTInstance; } EnergyEvseDelegate * GetEvseDelegate() { @@ -62,6 +66,15 @@ class EVSEManufacturer return nullptr; } + PowerTopology::PowerTopologyDelegate * GetPTDelegate() + { + if (mPTInstance) + { + return mPTInstance->GetDelegate(); + } + return nullptr; + } + /** * @brief Called at start up to apply hardware settings */ @@ -82,6 +95,11 @@ class EVSEManufacturer */ CHIP_ERROR InitializePowerMeasurementCluster(); + /** + * @brief Allows a client application to initialise the PowerSource cluster + */ + CHIP_ERROR InitializePowerSourceCluster(); + /** * @brief Allows a client application to send in power readings into the system * @@ -153,6 +171,7 @@ class EVSEManufacturer private: EnergyEvseManager * mEvseInstance; ElectricalPowerMeasurement::ElectricalPowerMeasurementInstance * mEPMInstance; + PowerTopology::PowerTopologyInstance * mPTInstance; int64_t mLastChargingEnergyMeter = 0; int64_t mLastDischargingEnergyMeter = 0; diff --git a/examples/energy-management-app/energy-management-common/include/PowerTopologyDelegate.h b/examples/energy-management-app/energy-management-common/include/PowerTopologyDelegate.h new file mode 100644 index 00000000000000..7e3336e772f940 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/PowerTopologyDelegate.h @@ -0,0 +1,66 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include + +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace PowerTopology { + +class PowerTopologyDelegate : public Delegate +{ +public: + ~PowerTopologyDelegate() = default; + + CHIP_ERROR GetAvailableEndpointAtIndex(size_t index, EndpointId & endpointId) override; + CHIP_ERROR GetActiveEndpointAtIndex(size_t index, EndpointId & endpointId) override; +}; + +class PowerTopologyInstance : public Instance +{ +public: + PowerTopologyInstance(EndpointId aEndpointId, PowerTopologyDelegate & aDelegate, Feature aFeature, + OptionalAttributes aOptionalAttributes) : + PowerTopology::Instance(aEndpointId, aDelegate, aFeature, aOptionalAttributes) + { + mDelegate = &aDelegate; + } + + // Delete copy constructor and assignment operator. + PowerTopologyInstance(const PowerTopologyInstance &) = delete; + PowerTopologyInstance(const PowerTopologyInstance &&) = delete; + PowerTopologyInstance & operator=(const PowerTopologyInstance &) = delete; + + CHIP_ERROR Init(); + void Shutdown(); + + PowerTopologyDelegate * GetDelegate() { return mDelegate; }; + +private: + PowerTopologyDelegate * mDelegate; +}; + +} // namespace PowerTopology +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp index cb7a7a44991e16..d9848bcbc53515 100644 --- a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp @@ -18,11 +18,16 @@ #include #include + #include #include #include +#include #include +#include +#include + using namespace chip; using namespace chip::app; using namespace chip::app::DataModel; @@ -31,6 +36,10 @@ using namespace chip::app::Clusters::EnergyEvse; using namespace chip::app::Clusters::ElectricalPowerMeasurement; using namespace chip::app::Clusters::ElectricalEnergyMeasurement; using namespace chip::app::Clusters::ElectricalEnergyMeasurement::Structs; +using namespace chip::app::Clusters::PowerSource; +using namespace chip::app::Clusters::PowerSource::Attributes; + +using Protocols::InteractionModel::Status; CHIP_ERROR EVSEManufacturer::Init() { @@ -48,6 +57,7 @@ CHIP_ERROR EVSEManufacturer::Init() ReturnErrorOnFailure(InitializePowerMeasurementCluster()); + ReturnErrorOnFailure(InitializePowerSourceCluster()); /* * This is an example implementation for manufacturers to consider * @@ -110,6 +120,38 @@ CHIP_ERROR EVSEManufacturer::InitializePowerMeasurementCluster() return CHIP_NO_ERROR; } +/** + * @brief Allows a client application to initialise the PowerSource cluster + */ +CHIP_ERROR EVSEManufacturer::InitializePowerSourceCluster() +{ + Protocols::InteractionModel::Status status; + + status = PowerSource::Attributes::Status::Set(EndpointId(0) /*RootNode*/, PowerSourceStatusEnum::kActive); + VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); + status = + PowerSource::Attributes::FeatureMap::Set(EndpointId(0 /*RootNode*/), static_cast(PowerSource::Feature::kWired)); + VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); + status = PowerSource::Attributes::WiredNominalVoltage::Set(EndpointId(0 /*RootNode*/), 230'000); // 230V in mv + VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); + status = PowerSource::Attributes::WiredMaximumCurrent::Set(EndpointId(0 /*RootNode*/), 32'000); // 32A in mA + VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); + + status = PowerSource::Attributes::WiredCurrentType::Set(EndpointId(0 /*RootNode*/), PowerSource::WiredCurrentTypeEnum::kAc); + VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); + status = PowerSource::Attributes::Description::Set(EndpointId(0 /*RootNode*/), CharSpan::fromCharString("Primary Mains Power")); + VerifyOrReturnError(status == Protocols::InteractionModel::Status::Success, CHIP_ERROR_INTERNAL); + + chip::EndpointId endpointArray[] = { 1 /* EVSE Endpoint */ }; + Span endpointList = Span(endpointArray); + + // Note per API - we do not need to maintain the span after the SetEndpointList has been called + // since it takes a copy (see power-source-server.cpp) + PowerSourceServer::Instance().SetEndpointList(0 /* Root Node */, endpointList); + + return CHIP_NO_ERROR; +} + /** * @brief Allows a client application to send in power readings into the system * diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp index 9beff80e8dc22a..6eeaaf8369c38c 100644 --- a/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -42,6 +44,7 @@ using namespace chip::app::Clusters::EnergyEvse; using namespace chip::app::Clusters::DeviceEnergyManagement; using namespace chip::app::Clusters::ElectricalPowerMeasurement; using namespace chip::app::Clusters::ElectricalEnergyMeasurement; +using namespace chip::app::Clusters::PowerTopology; static std::unique_ptr gEvseDelegate; static std::unique_ptr gEvseInstance; @@ -53,6 +56,9 @@ static std::unique_ptr gEPMInstance; // Electrical Energy Measurement cluster uses ember to initialise static std::unique_ptr gEEMAttrAccess; +static std::unique_ptr gPTDelegate; +static std::unique_ptr gPTInstance; + EVSEManufacturer * EnergyEvse::GetEvseManufacturer() { return gEvseManufacturer.get(); @@ -197,6 +203,74 @@ CHIP_ERROR EnergyEvseShutdown() return CHIP_NO_ERROR; } +/* + * @brief Creates a Delegate and Instance for PowerTopology clusters + * + * The Instance is a container around the Delegate, so + * create the Delegate first, then wrap it in the Instance + * Then call the Instance->Init() to register the attribute and command handlers + */ +CHIP_ERROR PowerTopologyInit() +{ + CHIP_ERROR err; + + if (gPTDelegate || gPTInstance) + { + ChipLogError(AppServer, "PowerTopology Instance or Delegate already exist."); + return CHIP_ERROR_INCORRECT_STATE; + } + + gPTDelegate = std::make_unique(); + if (!gPTDelegate) + { + ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Delegate"); + return CHIP_ERROR_NO_MEMORY; + } + + gPTInstance = + std::make_unique(EndpointId(ENERGY_EVSE_ENDPOINT), *gPTDelegate, + BitMask(PowerTopology::Feature::kNodeTopology), + BitMask(0)); + + if (!gPTInstance) + { + ChipLogError(AppServer, "Failed to allocate memory for PowerTopology Instance"); + gPTDelegate.reset(); + return CHIP_ERROR_NO_MEMORY; + } + + err = gPTInstance->Init(); /* Register Attribute & Command handlers */ + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Init failed on gPTInstance"); + gPTInstance.reset(); + gPTDelegate.reset(); + return err; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR PowerTopologyShutdown() +{ + /* Do this in the order Instance first, then delegate + * Ensure we call the Instance->Shutdown to free attribute & command handlers first + */ + if (gPTInstance) + { + /* deregister attribute & command handlers */ + gPTInstance->Shutdown(); + gPTInstance.reset(); + } + + if (gPTDelegate) + { + gPTDelegate.reset(); + } + + return CHIP_NO_ERROR; +} + /* * @brief Creates a Delegate and Instance for Electrical Power/Energy Measurement clusters * @@ -301,7 +375,7 @@ CHIP_ERROR EVSEManufacturerInit() } /* Now create EVSEManufacturer */ - gEvseManufacturer = std::make_unique(gEvseInstance.get(), gEPMInstance.get()); + gEvseManufacturer = std::make_unique(gEvseInstance.get(), gEPMInstance.get(), gPTInstance.get()); if (!gEvseManufacturer) { ChipLogError(AppServer, "Failed to allocate memory for EvseManufacturer"); @@ -352,6 +426,16 @@ void EvseApplicationInit() return; } + if (PowerTopologyInit() != CHIP_NO_ERROR) + { + EVSEManufacturerShutdown(); + DeviceEnergyManagementShutdown(); + EnergyEvseShutdown(); + EnergyMeterShutdown(); + return; + } + + /* Do this last so that the instances for other clusters can be wrapped inside */ if (EVSEManufacturerInit() != CHIP_NO_ERROR) { DeviceEnergyManagementShutdown(); @@ -367,6 +451,7 @@ void EvseApplicationShutdown() /* Shutdown in reverse order that they were created */ EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */ + PowerTopologyShutdown(); /* Free the PowerTopology */ EnergyMeterShutdown(); /* Free the Energy Meter */ EnergyEvseShutdown(); /* Free the EnergyEvse */ DeviceEnergyManagementShutdown(); /* Free the DEM */ diff --git a/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp b/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp new file mode 100644 index 00000000000000..9f72d58cbc4983 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp @@ -0,0 +1,43 @@ +/* + * + * 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 + +using namespace chip; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::PowerTopology; + +CHIP_ERROR PowerTopologyDelegate::GetAvailableEndpointAtIndex(size_t index, EndpointId & endpointId) +{ + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; +} + +CHIP_ERROR PowerTopologyDelegate::GetActiveEndpointAtIndex(size_t index, EndpointId & endpointId) +{ + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; +} + +CHIP_ERROR PowerTopologyInstance::Init() +{ + return Instance::Init(); +} + +void PowerTopologyInstance::Shutdown() +{ + Instance::Shutdown(); +} diff --git a/examples/energy-management-app/esp32/main/CMakeLists.txt b/examples/energy-management-app/esp32/main/CMakeLists.txt index ddaff6b83e02f0..0c038632b4feab 100644 --- a/examples/energy-management-app/esp32/main/CMakeLists.txt +++ b/examples/energy-management-app/esp32/main/CMakeLists.txt @@ -55,7 +55,9 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/operational-credentials-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ota-requestor" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-source-configuration-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/power-topology-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/software-diagnostics-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/switch-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/thread-network-diagnostics-server" diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn index 99acf81baad1c9..4730c2c8ea82f3 100644 --- a/examples/energy-management-app/linux/BUILD.gn +++ b/examples/energy-management-app/linux/BUILD.gn @@ -43,6 +43,7 @@ executable("chip-energy-management-app") { "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseMain.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", + "${chip_root}/examples/energy-management-app/energy-management-common/src/PowerTopologyDelegate.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/src/device-energy-management-mode.cpp", "${chip_root}/examples/energy-management-app/energy-management-common/src/energy-evse-mode.cpp", "include/CHIPProjectAppConfig.h", diff --git a/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h b/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h index e091fa9cf7c91c..4a42f0a9c04c97 100644 --- a/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h +++ b/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h @@ -45,3 +45,11 @@ #define CHIP_DEVICE_ENABLE_PORT_PARAMS 1 #define CHIP_DEVICE_CONFIG_DEVICE_NAME "Test Energy Management" + +#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 1 +#endif + +#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "1.0" +#endif