Skip to content

Commit

Permalink
EVSE Delegate callbacks to user application (project-chip#30999)
Browse files Browse the repository at this point in the history
* Fix project-chip#30665 (EVSE)
- Changed to use amperage_mA, energy_mWh
- removed max on epoch_s
- removed access for operate
- removed side for events

* Fix project-chip#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 project-chip#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 project-chip#30805 Updated energy-evse-cluster.xml

* Fixes project-chip#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 project-chip#30857 & project-chip#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 <bzbarsky@apple.com>

* 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 <commits@restyled.io>
Co-authored-by: Boris Zbarsky <bzbarsky@apple.com>
  • Loading branch information
3 people authored Dec 20, 2023
1 parent 13fd61d commit ce32d11
Show file tree
Hide file tree
Showing 12 changed files with 448 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
66 changes: 66 additions & 0 deletions examples/all-clusters-app/all-clusters-common/all-clusters-app.zap
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#pragma once

#include "app/clusters/energy-evse-server/energy-evse-server.h"
#include <EVSECallbacks.h>

#include <app/util/af.h>
#include <app/util/config.h>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ Status EnergyEvseDelegate::Disable()
/* update MaximumDischargeCurrent to 0 */
SetMaximumDischargeCurrent(0);

NotifyApplicationStateChange();
// TODO: Generate events

return Status::Success;
Expand All @@ -102,31 +103,31 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable<uint32_t> &

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<long unsigned int>(chargingEnabledUntil.Value()));
ChipLogError(AppServer, "Charging enabled until: %lu", static_cast<long unsigned int>(chargingEnabledUntil.Value()));
// TODO
// if (checkChargingEnabled)
}
Expand Down Expand Up @@ -169,6 +170,8 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable<uint32_t> &

// TODO: Generate events

NotifyApplicationStateChange();

return this->ComputeMaxChargeCurrentLimit();
}

Expand All @@ -188,6 +191,8 @@ Status EnergyEvseDelegate::EnableDischarging(const DataModel::Nullable<uint32_t>

// TODO: Generate events

NotifyApplicationStateChange();

return Status::Success;
}

Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
*/
Expand Down
Loading

0 comments on commit ce32d11

Please sign in to comment.