From ce32d114547172f6aed35a08ff61f7376694030c Mon Sep 17 00:00:00 2001 From: jamesharrow <93921463+jamesharrow@users.noreply.github.com> Date: Wed, 20 Dec 2023 02:17:27 +0000 Subject: [PATCH] EVSE Delegate callbacks to user application (#30999) * Fix #30665 (EVSE) - Changed to use amperage_mA, energy_mWh - removed max on epoch_s - removed access for operate - removed side for events * Fix #30665 updates to try to get further with ZAP and autogen, but still fails with some parts of regen_all * Added ember-compatibility-functions.cpp which was missing. * Made all types all lowercase to resolve regen_all issues. * Fixed lint issue (trailing whitespace). * Fixes #30727 - Added initial EVSE cluster and Example Energy Managament app. * Tidied up old comments. * Restyled by whitespace * Restyled by gn * Restyled by prettier-markdown * Added copy of files to all-clusters-app linux BUILD.gn and did basic test with chip-tool * Fixed lint error (Remove PRId64) * Fix for Documentation Build and publish checker. * Updated all-clusters-app.zap after merge and regen_all * Added Cluster to ESP32 CMakeLists.txt * Fixed ESP32 compile error caused by %d * Added missing source files to each build variant * Restyled by gn * Fixed incorrect uint64_t in EnableCharging/EnableDischarging command * Fixed more issues seen on different platforms * Removed unused mEndpointId * Add source files to shell standalone BUILD.gn, More %d fixes for different platforms * Restyled by gn * Removed unused mMinimumChargingCurrentLimitFromCommand * Removed yet more unused variables * Fixed missing semi-colon. How did the other compilers not pick this up? * Capitalise function names * PR comment - Moved PluginServerInitCallback to sdk. Capitalised more function names in energy-management-app. * Restyled by whitespace * Fixes #30805 Updated energy-evse-cluster.xml * Fixes #30805 zap_regen_all commit. * Made Fault Event allow a nullable SessionID * Updates based on review (use kMaximumChargeCurrent instead of duplicate #define). Add HwSetVehicleID implementation * Added RFID Event support. Removed more unnecessary chip:: * Added Feature flags, optional commands and optional attributes. * Made command handling conditional based on features * Added Feature support to all-clusters-app * Restyled by clang-format * Fix to Darwin compile error - not checking strcmp return * Attempt to fix Darwin errors (return after else) * Updated based on latest upstream master * Removed unnecessary mInstance and used 'this' instead. * Regen_all after merge to master. * Fix review comment. * Ensure Init() returns a failure if there is one. Aligned to mode-base-server.cpp * Backed out Read attr check based on features. * Fixed EnumerateAcceptedCommands to handle Loop::Break condition. * Had missed StartDiagnostic as an optional command in InvokeCommand * Removed extra chip:: in attr types. * Updated HwSetVehicleID to copy the value from callee * Fixed potential buffer overrun in HwSetVehicleID. * Fixed simple to address comments raised by Andrei in PR 30857 * Fixed simple to address comments raised by Andrei in PR 30857 * Check Delegate is initialized before calling functions. * Check Delegate is initialized before calling functions. * Added callbacks into Application code * Restyled by whitespace * Ensured that mVehicleID free's any malloc'd CharSpan in destructor * Sync EnergyEvseDelegateImpl.cpp from Example Energy Management * Ensured that mVehicleID free's any malloc'd CharSpan in destructor * Sync EnergyEvseDelegateImpl.cpp from Example Energy Management * Sync'd changes from example energy management app, and commits from #30857 & #30727 * Added namespace to avoid global namespace error in header file. * Re-write of ApplicationInit to handle potential errors * Re-write of ApplicationInit to handle potential errors * Removed unnecessary void in function decl. * Open and saved in ZAP, then regen_all * Updated Energy-management-app.zap / .matter after change to general-diagnostics.xml change to MS. * Updated Energy-management-app.zap / .matter after change to general-diagnostics.xml change to MS. * Restyled by whitespace * Fixed types to be signed=true * Fixed 31032 - revert removal of side="server". Also turned on Events. * PR comment fix - remove Localization Config and Time Format Localization cluster * Removed EVSE commands from ZAP to avoid emberAf linker errors since these are handled in the IM Commands handler * Regen_all to update energy-management.matter file to remove commands that cause linker errors. * Minor changes to align all-clusters and energy-management common. * Apply suggestions from code review Co-authored-by: Boris Zbarsky * Addressed comment and replicated into example energy management copies. * Added documentation to EVSE Callbacks as to which struct in the union is used. * Added Energy EVSE and Device Energy Management to config-data.yml under CommandHandlerInterfaceOnlyClusters. Then turned on EVSE commands in ZAP. --------- Co-authored-by: Restyled.io Co-authored-by: Boris Zbarsky --- .../all-clusters-app.matter | 9 ++ .../all-clusters-common/all-clusters-app.zap | 66 +++++++++++++ .../include/EVSECallbacks.h | 84 ++++++++++++++++ .../include/EnergyEvseDelegateImpl.h | 12 ++- .../src/EnergyEvseDelegateImpl.cpp | 96 ++++++++++++++---- .../include/EVSECallbacks.h | 84 ++++++++++++++++ .../include/EVSEManufacturerImpl.h | 5 + .../include/EnergyEvseDelegateImpl.h | 12 ++- .../src/EVSEManufacturerImpl.cpp | 26 ++++- .../src/EnergyEvseDelegateImpl.cpp | 98 ++++++++++++++----- src/app/common/templates/config-data.yaml | 2 + .../app-common/zap-generated/callback.h | 84 ---------------- 12 files changed, 448 insertions(+), 130 deletions(-) create mode 100644 examples/all-clusters-app/all-clusters-common/include/EVSECallbacks.h create mode 100644 examples/energy-management-app/energy-management-common/include/EVSECallbacks.h diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index 45be7ed614d227..59090b662d6486 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -7354,6 +7354,15 @@ endpoint 1 { callback attribute attributeList; ram attribute featureMap default = 0; ram attribute clusterRevision default = 2; + + handle command GetTargetsResponse; + handle command Disable; + handle command EnableCharging; + handle command EnableDischarging; + handle command StartDiagnostics; + handle command SetTargets; + handle command GetTargets; + handle command ClearTargets; } server cluster WindowCovering { diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 0bba4b8871e6c2..6f35331ee14640 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -11737,6 +11737,72 @@ "side": "server", "enabled": 1, "apiMaturity": "provisional", + "commands": [ + { + "name": "GetTargetsResponse", + "code": 0, + "mfgCode": null, + "source": "server", + "isIncoming": 0, + "isEnabled": 1 + }, + { + "name": "Disable", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "EnableCharging", + "code": 2, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "EnableDischarging", + "code": 3, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "StartDiagnostics", + "code": 4, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "SetTargets", + "code": 5, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "GetTargets", + "code": 6, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "ClearTargets", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], "attributes": [ { "name": "State", diff --git a/examples/all-clusters-app/all-clusters-common/include/EVSECallbacks.h b/examples/all-clusters-app/all-clusters-common/include/EVSECallbacks.h new file mode 100644 index 00000000000000..5bdac2f8e853d6 --- /dev/null +++ b/examples/all-clusters-app/all-clusters-common/include/EVSECallbacks.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace chip { +namespace app { +namespace Clusters { + +using namespace chip::app::Clusters::EnergyEvse; + +/* This callbacks mechanism is intended to allow different delegates to + * dispatch notifications that something has changed. + * + * This is not specific to the EnergyEVSE cluster, but includes DeviceEnergyManagement + * and potential future clusters. + */ +enum EVSECallbackType +{ + /* + * The State has changed (e.g. from Disabled to Charging, or vice-versa) + */ + StateChanged, + /* + * ChargeCurrent has changed + */ + ChargeCurrentChanged, + /* + * Charging Preferences have changed + */ + ChargingPreferencesChanged, + /* + * DeviceEnergyManagement has changed + */ + DeviceEnergyManagementChanged, +}; + +struct EVSECbInfo +{ + EVSECallbackType type; + + union + { + /* for type = StateChanged */ + struct + { + StateEnum state; + SupplyStateEnum supplyState; + } StateChange; + + /* for type = ChargeCurrentChanged */ + struct + { + int64_t maximumChargeCurrent; + } ChargingCurrent; + }; +}; + +typedef void (*EVSECallbackFunc)(const EVSECbInfo * cb, intptr_t arg); + +struct EVSECallbackWrapper +{ + EVSECallbackFunc handler; + intptr_t arg; +}; + +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/all-clusters-common/include/EnergyEvseDelegateImpl.h b/examples/all-clusters-app/all-clusters-common/include/EnergyEvseDelegateImpl.h index 0a967e2472be8b..f3c003d081fc6e 100644 --- a/examples/all-clusters-app/all-clusters-common/include/EnergyEvseDelegateImpl.h +++ b/examples/all-clusters-app/all-clusters-common/include/EnergyEvseDelegateImpl.h @@ -19,6 +19,7 @@ #pragma once #include "app/clusters/energy-evse-server/energy-evse-server.h" +#include #include #include @@ -68,9 +69,13 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate */ Status StartDiagnostics() override; + /** + * @brief Called by EVSE Hardware to register a single callback handler + */ + Status HwRegisterEvseCallbackHandler(EVSECallbackFunc handler, intptr_t arg); + // ----------------------------------------------------------------- // Internal API to allow an EVSE to change its internal state etc - // TODO Status HwRegisterEvseHardwareCallback(Callback); Status HwSetMaxHardwareCurrentLimit(int64_t currentmA); Status HwSetCircuitCapacity(int64_t currentmA); Status HwSetCableAssemblyLimit(int64_t currentmA); @@ -150,6 +155,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate int64_t mActualChargingCurrentLimit = 0; StateEnum mHwState = StateEnum::kNotPluggedIn; /* Hardware state */ + /* Callback related */ + EVSECallbackWrapper mCallbacks = { .handler = nullptr, .arg = 0 }; /* Wrapper to allow callbacks to be registered */ + Status NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent); + Status NotifyApplicationStateChange(); + /** * @brief Helper function to work out the charge limit based on conditions and settings */ diff --git a/examples/all-clusters-app/all-clusters-common/src/EnergyEvseDelegateImpl.cpp b/examples/all-clusters-app/all-clusters-common/src/EnergyEvseDelegateImpl.cpp index 64d8b98bafc644..4cc83eaaf8a835 100644 --- a/examples/all-clusters-app/all-clusters-common/src/EnergyEvseDelegateImpl.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/EnergyEvseDelegateImpl.cpp @@ -83,6 +83,7 @@ Status EnergyEvseDelegate::Disable() /* update MaximumDischargeCurrent to 0 */ SetMaximumDischargeCurrent(0); + NotifyApplicationStateChange(); // TODO: Generate events return Status::Success; @@ -102,31 +103,31 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable & if (maximumChargeCurrent < kMinimumChargeCurrent || maximumChargeCurrent > kMaximumChargeCurrent) { - ChipLogError(NotSpecified, "Maximum Current outside limits"); + ChipLogError(AppServer, "Maximum Current outside limits"); return Status::ConstraintError; } if (minimumChargeCurrent < kMinimumChargeCurrent || minimumChargeCurrent > kMaximumChargeCurrent) { - ChipLogError(NotSpecified, "Maximum Current outside limits"); + ChipLogError(AppServer, "Maximum Current outside limits"); return Status::ConstraintError; } if (minimumChargeCurrent > maximumChargeCurrent) { - ChipLogError(NotSpecified, "Minium Current > Maximum Current!"); + ChipLogError(AppServer, "Minium Current > Maximum Current!"); return Status::ConstraintError; } if (chargingEnabledUntil.IsNull()) { /* Charging enabled indefinitely */ - ChipLogError(NotSpecified, "Charging enabled indefinitely"); + ChipLogError(AppServer, "Charging enabled indefinitely"); } else { /* check chargingEnabledUntil is in the future */ - ChipLogError(NotSpecified, "Charging enabled until: %lu", static_cast(chargingEnabledUntil.Value())); + ChipLogError(AppServer, "Charging enabled until: %lu", static_cast(chargingEnabledUntil.Value())); // TODO // if (checkChargingEnabled) } @@ -169,6 +170,8 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable & // TODO: Generate events + NotifyApplicationStateChange(); + return this->ComputeMaxChargeCurrentLimit(); } @@ -188,6 +191,8 @@ Status EnergyEvseDelegate::EnableDischarging(const DataModel::Nullable // TODO: Generate events + NotifyApplicationStateChange(); + return Status::Success; } @@ -199,25 +204,42 @@ Status EnergyEvseDelegate::StartDiagnostics() /* For EVSE manufacturers to customize */ ChipLogProgress(AppServer, "EnergyEvseDelegate::StartDiagnostics()"); - /* update SupplyState */ + /* update SupplyState to indicate we are now in Diagnostics mode */ SetSupplyState(SupplyStateEnum::kDisabledDiagnostics); // TODO: Generate events + // TODO: Notify Application to implement Diagnostics + + NotifyApplicationStateChange(); + return Status::Success; } /* --------------------------------------------------------------------------- - * FUNCTIONS BELOW: - * - EVSE Hardware interface + * EVSE Hardware interface below + */ + +/** + * @brief Called by EVSE Hardware to register a callback handler mechanism * - * SetMaxHardwareCurrentLimit( currentmA ) - * SetCircuitCapacity( currentmA ) - * SetCableAssemblyLimit( currentmA ) - * SetState( EVSEStateEnum ) - * SetFault + * This is normally called at start-up. * + * @param EVSECallbackFunct - function pointer to call + * @param intptr_t - optional context to provide back to callback handler */ +Status EnergyEvseDelegate::HwRegisterEvseCallbackHandler(EVSECallbackFunc handler, intptr_t arg) +{ + if (mCallbacks.handler != nullptr) + { + ChipLogError(AppServer, "Callback handler already initialized"); + return Status::Failure; + } + mCallbacks.handler = handler; + mCallbacks.arg = arg; + + return Status::Success; +} /** * @brief Called by EVSE Hardware to notify the delegate of the maximum @@ -420,17 +442,18 @@ Status EnergyEvseDelegate::HwSetVehicleID(const CharSpan & newValue) /** * @brief Called to compute the safe charging current limit + * + * mActualChargingCurrentLimit is the minimum of: + * - MaxHardwareCurrentLimit (of the hardware) + * - CircuitCapacity (set by the electrician - less than the hardware) + * - CableAssemblyLimit (detected when the cable is inserted) + * - MaximumChargeCurrent (from charging command) + * - UserMaximumChargeCurrent (could dynamically change) + * */ Status EnergyEvseDelegate::ComputeMaxChargeCurrentLimit() { int64_t oldValue; - /* mActualChargingCurrentLimit is the minimum of: - * - MaxHardwareCurrentLimit (of the hardware) - * - CircuitCapacity (set by the electrician - less than the hardware) - * - CableAssemblyLimit (detected when the cable is inserted) - * - MaximumChargeCurrent (from charging command) - * - UserMaximumChargeCurrent (could dynamically change) - */ oldValue = mActualChargingCurrentLimit; mActualChargingCurrentLimit = mMaxHardwareCurrentLimit; @@ -448,11 +471,42 @@ Status EnergyEvseDelegate::ComputeMaxChargeCurrentLimit() MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, MaximumChargeCurrent::Id); /* Call the EV Charger hardware current limit callback */ - // TODO + NotifyApplicationCurrentLimitChange(mMaximumChargeCurrent); } return Status::Success; } +Status EnergyEvseDelegate::NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent) +{ + EVSECbInfo cbInfo; + + cbInfo.type = EVSECallbackType::ChargeCurrentChanged; + cbInfo.ChargingCurrent.maximumChargeCurrent = maximumChargeCurrent; + + if (mCallbacks.handler != nullptr) + { + mCallbacks.handler(&cbInfo, mCallbacks.arg); + } + + return Status::Success; +} + +Status EnergyEvseDelegate::NotifyApplicationStateChange() +{ + EVSECbInfo cbInfo; + + cbInfo.type = EVSECallbackType::StateChanged; + cbInfo.StateChange.state = mState; + cbInfo.StateChange.supplyState = mSupplyState; + + if (mCallbacks.handler != nullptr) + { + mCallbacks.handler(&cbInfo, mCallbacks.arg); + } + + return Status::Success; +} + /** * Attribute methods */ diff --git a/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h b/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h new file mode 100644 index 00000000000000..5bdac2f8e853d6 --- /dev/null +++ b/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h @@ -0,0 +1,84 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +namespace chip { +namespace app { +namespace Clusters { + +using namespace chip::app::Clusters::EnergyEvse; + +/* This callbacks mechanism is intended to allow different delegates to + * dispatch notifications that something has changed. + * + * This is not specific to the EnergyEVSE cluster, but includes DeviceEnergyManagement + * and potential future clusters. + */ +enum EVSECallbackType +{ + /* + * The State has changed (e.g. from Disabled to Charging, or vice-versa) + */ + StateChanged, + /* + * ChargeCurrent has changed + */ + ChargeCurrentChanged, + /* + * Charging Preferences have changed + */ + ChargingPreferencesChanged, + /* + * DeviceEnergyManagement has changed + */ + DeviceEnergyManagementChanged, +}; + +struct EVSECbInfo +{ + EVSECallbackType type; + + union + { + /* for type = StateChanged */ + struct + { + StateEnum state; + SupplyStateEnum supplyState; + } StateChange; + + /* for type = ChargeCurrentChanged */ + struct + { + int64_t maximumChargeCurrent; + } ChargingCurrent; + }; +}; + +typedef void (*EVSECallbackFunc)(const EVSECbInfo * cb, intptr_t arg); + +struct EVSECallbackWrapper +{ + EVSECallbackFunc handler; + intptr_t arg; +}; + +} // namespace Clusters +} // namespace app +} // namespace chip 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 34e9027e626ad5..4ff45e925674aa 100644 --- a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h +++ b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h @@ -43,6 +43,11 @@ class EVSEManufacturer */ CHIP_ERROR Shutdown(EnergyEvseManager * aInstance); + /** + * @brief Main Callback handler from delegate to user code + */ + static void ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_t arg); + private: }; diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h b/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h index 0a967e2472be8b..f3c003d081fc6e 100644 --- a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h +++ b/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h @@ -19,6 +19,7 @@ #pragma once #include "app/clusters/energy-evse-server/energy-evse-server.h" +#include #include #include @@ -68,9 +69,13 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate */ Status StartDiagnostics() override; + /** + * @brief Called by EVSE Hardware to register a single callback handler + */ + Status HwRegisterEvseCallbackHandler(EVSECallbackFunc handler, intptr_t arg); + // ----------------------------------------------------------------- // Internal API to allow an EVSE to change its internal state etc - // TODO Status HwRegisterEvseHardwareCallback(Callback); Status HwSetMaxHardwareCurrentLimit(int64_t currentmA); Status HwSetCircuitCapacity(int64_t currentmA); Status HwSetCableAssemblyLimit(int64_t currentmA); @@ -150,6 +155,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate int64_t mActualChargingCurrentLimit = 0; StateEnum mHwState = StateEnum::kNotPluggedIn; /* Hardware state */ + /* Callback related */ + EVSECallbackWrapper mCallbacks = { .handler = nullptr, .arg = 0 }; /* Wrapper to allow callbacks to be registered */ + Status NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent); + Status NotifyApplicationStateChange(); + /** * @brief Helper function to work out the charge limit based on conditions and settings */ 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 e5ad19306ea239..8daf1781103831 100644 --- a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp @@ -35,7 +35,7 @@ CHIP_ERROR EVSEManufacturer::Init(EnergyEvseManager * aInstance) return CHIP_ERROR_UNINITIALIZED; } - // TODO EnergyEvseManager::GetInstance()->GetDelegate()->RegisterCallbacks(); + dg->HwRegisterEvseCallbackHandler(ApplicationCallbackHandler, reinterpret_cast(nullptr)); /* Set the EVSE Hardware Maximum current limit */ // For Manufacturer to specify the hardware capability in mA @@ -67,3 +67,27 @@ CHIP_ERROR EVSEManufacturer::Shutdown(EnergyEvseManager * aInstance) return CHIP_NO_ERROR; } + +/** + * @brief Main Callback handler - to be implemented by Manufacturer + * + * @param EVSECbInfo describes the type of call back, and a union of structs + * which contain relevant info for the specific callback type + * + * @param arg - optional pointer to some context information (see register function) + */ +void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_t arg) +{ + switch (cb->type) + { + case EVSECallbackType::StateChanged: + ChipLogProgress(AppServer, "EVSE callback - state changed"); + break; + case EVSECallbackType::ChargeCurrentChanged: + ChipLogProgress(AppServer, "EVSE callback - maxChargeCurrent changed to %ld", + static_cast(cb->ChargingCurrent.maximumChargeCurrent)); + break; + default: + ChipLogError(AppServer, "Unhandler EVSE Callback type %d", static_cast(cb->type)); + } +} diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp index 7ad16c3737dacb..4cc83eaaf8a835 100644 --- a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp @@ -48,7 +48,7 @@ Status EnergyEvseDelegate::Disable() { ChipLogProgress(AppServer, "EnergyEvseDelegate::Disable()"); - /* update State */ + /* Update State */ switch (mHwState) { case StateEnum::kNotPluggedIn: @@ -83,6 +83,7 @@ Status EnergyEvseDelegate::Disable() /* update MaximumDischargeCurrent to 0 */ SetMaximumDischargeCurrent(0); + NotifyApplicationStateChange(); // TODO: Generate events return Status::Success; @@ -102,31 +103,31 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable & if (maximumChargeCurrent < kMinimumChargeCurrent || maximumChargeCurrent > kMaximumChargeCurrent) { - ChipLogError(NotSpecified, "Maximum Current outside limits"); + ChipLogError(AppServer, "Maximum Current outside limits"); return Status::ConstraintError; } if (minimumChargeCurrent < kMinimumChargeCurrent || minimumChargeCurrent > kMaximumChargeCurrent) { - ChipLogError(NotSpecified, "Maximum Current outside limits"); + ChipLogError(AppServer, "Maximum Current outside limits"); return Status::ConstraintError; } if (minimumChargeCurrent > maximumChargeCurrent) { - ChipLogError(NotSpecified, "Minium Current > Maximum Current!"); + ChipLogError(AppServer, "Minium Current > Maximum Current!"); return Status::ConstraintError; } if (chargingEnabledUntil.IsNull()) { /* Charging enabled indefinitely */ - ChipLogError(NotSpecified, "Charging enabled indefinitely"); + ChipLogError(AppServer, "Charging enabled indefinitely"); } else { /* check chargingEnabledUntil is in the future */ - ChipLogError(NotSpecified, "Charging enabled until: %lu", static_cast(chargingEnabledUntil.Value())); + ChipLogError(AppServer, "Charging enabled until: %lu", static_cast(chargingEnabledUntil.Value())); // TODO // if (checkChargingEnabled) } @@ -169,6 +170,8 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable & // TODO: Generate events + NotifyApplicationStateChange(); + return this->ComputeMaxChargeCurrentLimit(); } @@ -188,6 +191,8 @@ Status EnergyEvseDelegate::EnableDischarging(const DataModel::Nullable // TODO: Generate events + NotifyApplicationStateChange(); + return Status::Success; } @@ -199,25 +204,42 @@ Status EnergyEvseDelegate::StartDiagnostics() /* For EVSE manufacturers to customize */ ChipLogProgress(AppServer, "EnergyEvseDelegate::StartDiagnostics()"); - /* update SupplyState */ + /* update SupplyState to indicate we are now in Diagnostics mode */ SetSupplyState(SupplyStateEnum::kDisabledDiagnostics); // TODO: Generate events + // TODO: Notify Application to implement Diagnostics + + NotifyApplicationStateChange(); + return Status::Success; } /* --------------------------------------------------------------------------- - * FUNCTIONS BELOW: - * - EVSE Hardware interface + * EVSE Hardware interface below + */ + +/** + * @brief Called by EVSE Hardware to register a callback handler mechanism * - * SetMaxHardwareCurrentLimit( currentmA ) - * SetCircuitCapacity( currentmA ) - * SetCableAssemblyLimit( currentmA ) - * SetState( EVSEStateEnum ) - * SetFault + * This is normally called at start-up. * + * @param EVSECallbackFunct - function pointer to call + * @param intptr_t - optional context to provide back to callback handler */ +Status EnergyEvseDelegate::HwRegisterEvseCallbackHandler(EVSECallbackFunc handler, intptr_t arg) +{ + if (mCallbacks.handler != nullptr) + { + ChipLogError(AppServer, "Callback handler already initialized"); + return Status::Failure; + } + mCallbacks.handler = handler; + mCallbacks.arg = arg; + + return Status::Success; +} /** * @brief Called by EVSE Hardware to notify the delegate of the maximum @@ -420,17 +442,18 @@ Status EnergyEvseDelegate::HwSetVehicleID(const CharSpan & newValue) /** * @brief Called to compute the safe charging current limit + * + * mActualChargingCurrentLimit is the minimum of: + * - MaxHardwareCurrentLimit (of the hardware) + * - CircuitCapacity (set by the electrician - less than the hardware) + * - CableAssemblyLimit (detected when the cable is inserted) + * - MaximumChargeCurrent (from charging command) + * - UserMaximumChargeCurrent (could dynamically change) + * */ Status EnergyEvseDelegate::ComputeMaxChargeCurrentLimit() { int64_t oldValue; - /* mActualChargingCurrentLimit is the minimum of: - * - MaxHardwareCurrentLimit (of the hardware) - * - CircuitCapacity (set by the electrician - less than the hardware) - * - CableAssemblyLimit (detected when the cable is inserted) - * - MaximumChargeCurrent (from charging command) - * - UserMaximumChargeCurrent (could dynamically change) - */ oldValue = mActualChargingCurrentLimit; mActualChargingCurrentLimit = mMaxHardwareCurrentLimit; @@ -448,11 +471,42 @@ Status EnergyEvseDelegate::ComputeMaxChargeCurrentLimit() MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, MaximumChargeCurrent::Id); /* Call the EV Charger hardware current limit callback */ - // TODO + NotifyApplicationCurrentLimitChange(mMaximumChargeCurrent); } return Status::Success; } +Status EnergyEvseDelegate::NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent) +{ + EVSECbInfo cbInfo; + + cbInfo.type = EVSECallbackType::ChargeCurrentChanged; + cbInfo.ChargingCurrent.maximumChargeCurrent = maximumChargeCurrent; + + if (mCallbacks.handler != nullptr) + { + mCallbacks.handler(&cbInfo, mCallbacks.arg); + } + + return Status::Success; +} + +Status EnergyEvseDelegate::NotifyApplicationStateChange() +{ + EVSECbInfo cbInfo; + + cbInfo.type = EVSECallbackType::StateChanged; + cbInfo.StateChange.state = mState; + cbInfo.StateChange.supplyState = mSupplyState; + + if (mCallbacks.handler != nullptr) + { + mCallbacks.handler(&cbInfo, mCallbacks.arg); + } + + return Status::Success; +} + /** * Attribute methods */ diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index 9d3e094ffb046c..577e04ab04a856 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -37,6 +37,8 @@ CommandHandlerInterfaceOnlyClusters: - RVC Operational State - Sample MEI - Microwave Oven Control + - Energy EVSE + - Device Energy Management # We need a more configurable way of deciding which clusters have which init functions.... # See https://github.com/project-chip/connectedhomeip/issues/4369 diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index c37f234ce8a751..439ed6b63ab082 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -10237,90 +10237,6 @@ bool emberAfDemandResponseLoadControlClusterRemoveLoadControlEventRequestCallbac bool emberAfDemandResponseLoadControlClusterClearLoadControlEventsRequestCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::DemandResponseLoadControl::Commands::ClearLoadControlEventsRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster PowerAdjustRequest Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterPowerAdjustRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::PowerAdjustRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster CancelPowerAdjustRequest Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterCancelPowerAdjustRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::CancelPowerAdjustRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster StartTimeAdjustRequest Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterStartTimeAdjustRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::StartTimeAdjustRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster PauseRequest Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterPauseRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::PauseRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster ResumeRequest Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterResumeRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::ResumeRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster ModifyForecastRequest Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterModifyForecastRequestCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::ModifyForecastRequest::DecodableType & commandData); -/** - * @brief Device Energy Management Cluster RequestConstraintBasedForecast Command callback (from client) - */ -bool emberAfDeviceEnergyManagementClusterRequestConstraintBasedForecastCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DeviceEnergyManagement::Commands::RequestConstraintBasedForecast::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster Disable Command callback (from client) - */ -bool emberAfEnergyEvseClusterDisableCallback(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::Disable::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster EnableCharging Command callback (from client) - */ -bool emberAfEnergyEvseClusterEnableChargingCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::EnableCharging::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster EnableDischarging Command callback (from client) - */ -bool emberAfEnergyEvseClusterEnableDischargingCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::EnableDischarging::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster StartDiagnostics Command callback (from client) - */ -bool emberAfEnergyEvseClusterStartDiagnosticsCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::StartDiagnostics::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster SetTargets Command callback (from client) - */ -bool emberAfEnergyEvseClusterSetTargetsCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::SetTargets::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster GetTargets Command callback (from client) - */ -bool emberAfEnergyEvseClusterGetTargetsCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::GetTargets::DecodableType & commandData); -/** - * @brief Energy EVSE Cluster ClearTargets Command callback (from client) - */ -bool emberAfEnergyEvseClusterClearTargetsCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::EnergyEvse::Commands::ClearTargets::DecodableType & commandData); /** * @brief Door Lock Cluster LockDoor Command callback (from client) */