Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

EVSE add Session and Event support, test event trigger support #31200

Merged
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
3f0cded
Beginnings of Session handling
jamesharrow Dec 27, 2023
2990233
Added beginnings of EVConnected,EVNotDetected,EnergyTransferStarted,E…
jamesharrow Dec 28, 2023
c703453
Added framework for EVSE Test Event triggers
jamesharrow Dec 29, 2023
bfc9bfb
Added EnergyEvseTestEventTrigger delegates
jamesharrow Dec 29, 2023
590e63f
Restyled by whitespace
restyled-commits Dec 29, 2023
451428e
Restyled by gn
restyled-commits Dec 29, 2023
22d2504
Added :energy-evse-test-event-trigger to public_deps to see if it res…
jamesharrow Dec 29, 2023
85c68ed
Restyled by gn
restyled-commits Dec 29, 2023
a897dec
Fixed Darwin compile error - do not use else after return
jamesharrow Dec 30, 2023
9ccf8e5
Refactored code so that the EvseManufacturer instance could be retrie…
jamesharrow Dec 31, 2023
57cde7a
Started adding TC_EEVSE_2_2.py
jamesharrow Dec 31, 2023
b775fed
Updated TC_EEVSE_2_2.py to support test events. Still needs to handle…
jamesharrow Jan 1, 2024
8075657
Refactored Handling of TestEvents to allow clear, and better error ha…
jamesharrow Jan 1, 2024
8631c07
Refactored state handling by decomposing into state machine events wh…
jamesharrow Jan 2, 2024
a5774de
Fixed step 6e caused by not setting the cable limit / maxHardwareCurr…
jamesharrow Jan 2, 2024
3f365af
Added comment to clarify purpose and definition of test eventtrigger …
jamesharrow Jan 4, 2024
2f49014
Fixed several bugs in test script
jamesharrow Jan 5, 2024
f2ce4cf
Made SetChargingEnabledUntil take a nullable type.
jamesharrow Jan 5, 2024
b16e1ff
Removed Reference to step 5c, and moved reading of SessionID to step 4b.
jamesharrow Jan 7, 2024
469f313
Fixed issue with not detecting 2nd plug in event, and session ID not …
jamesharrow Jan 7, 2024
fbc5c6e
Merge branch 'upstream-master' into EVSE_Add_PersistedAttributes_and_…
jamesharrow Jan 7, 2024
ec0a876
Restyled by isort
restyled-commits Jan 7, 2024
e008095
Made some attributes persisted per spec.
jamesharrow Jan 8, 2024
b24bb80
Fixed incorrect type - not picked up by all compilers.
jamesharrow Jan 8, 2024
4e16e53
Merge branch 'upstream-master' into EVSE_Add_PersistedAttributes_and_…
jamesharrow Jan 8, 2024
320b5e1
Added provisional handling for Faults
jamesharrow Jan 8, 2024
3a7ace4
Added new test event triggers to help test Fault and Diagnostics
jamesharrow Jan 9, 2024
309b8f6
Added TC_EEVSE_2_4
jamesharrow Jan 9, 2024
9b02ef8
Fix lint issue - unused datetime modules.
jamesharrow Jan 9, 2024
925a701
Added TC_EEVSE_2_5.py to support DiagnosticsCommand testing. Also cha…
jamesharrow Jan 10, 2024
684d6b5
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 11, 2024
bd83ba4
Created a helper EEVSE base class to avoid repetition in the differen…
jamesharrow Jan 11, 2024
514e18e
Restyled by isort
restyled-commits Jan 11, 2024
21cd6d7
Fixed Lint issues
jamesharrow Jan 11, 2024
9ab79d1
Revamped TC_EEVSE_2_5 to match spec behaviour (cannot start diagnosti…
jamesharrow Jan 11, 2024
2e774fe
Implemented timer to disable the EVSE automatically.
jamesharrow Jan 12, 2024
cafe1b4
Added documentation to cover concern about long-lived bytespan in ena…
jamesharrow Jan 12, 2024
02d9713
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 12, 2024
c52fe69
Fixed Lint and build issues on other platforms
jamesharrow Jan 12, 2024
f50ef1e
Restyled by isort
restyled-commits Jan 12, 2024
bd97562
Implemented some of the feedback on PR
jamesharrow Jan 12, 2024
895b552
Refactored HwSetState to use nested switch statements to be clear tha…
jamesharrow Jan 12, 2024
87fe6cc
Fixed error messages
jamesharrow Jan 12, 2024
6b12abe
Test scripts: Removed hardcoded endpoint 1 (use --endpoint 1 in args)…
jamesharrow Jan 12, 2024
303ca2a
Made enum class for callbacks and improved documentation comments bas…
jamesharrow Jan 12, 2024
34c077d
Fixed another python lint issue.
jamesharrow Jan 12, 2024
50793c3
Updated README.md with help on how to build for test event triggers, …
jamesharrow Jan 12, 2024
f629326
Tweaks to README.md to avoid Myst syntax highlighting issues.
jamesharrow Jan 13, 2024
4d2108b
Improved error logging around GetEpochTS()
jamesharrow Jan 13, 2024
1f16b6c
Made main use std::unique_ptr instead of using new/delete per PR comm…
jamesharrow Jan 13, 2024
13f16a8
Fixing MISSPELL issues in README.md
jamesharrow Jan 13, 2024
6ae3073
Merge branch 'upstream-master' into EVSE_Add_PersistedAttributes_and_…
jamesharrow Jan 13, 2024
a1b379e
Fixes #31061 Updated DEVICE_TYPE to 0x050C now this has been allocated
jamesharrow Jan 13, 2024
44c85a5
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 15, 2024
495d347
Small correction to description in test case.
jamesharrow Jan 15, 2024
8f51c0b
Merge branch 'upstream-master' into EVSE_Add_PersistedAttributes_and_…
jamesharrow Jan 15, 2024
ac40f61
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 16, 2024
138760c
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 16, 2024
69241b7
Update examples/energy-management-app/energy-management-common/includ…
jamesharrow Jan 16, 2024
4e2c4c4
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 16, 2024
0c2a8cd
Touched file to retrigger restyled job
jamesharrow Jan 16, 2024
ddb4edc
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 16, 2024
fa45472
Removed whitespace which was added to trigger restyled to rerun
jamesharrow Jan 16, 2024
0e378b0
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 16, 2024
b362c71
Merge branch 'master' into EVSE_Add_PersistedAttributes_and_Events
jamesharrow Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/.wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -519,8 +519,10 @@ EthyleneOxideConcentrationMeasurement
EvalCode
EvalCodeWithName
EvalFrameDefault
EV
EVB
evk
EVSE
exceptfds
ExchangeContext
exe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,42 @@ using namespace chip::app::Clusters::EnergyEvse;
* This is not specific to the EnergyEVSE cluster, but includes DeviceEnergyManagement
* and potential future clusters.
*/
enum EVSECallbackType

jamesharrow marked this conversation as resolved.
Show resolved Hide resolved
enum class EVSECallbackType : uint8_t
{
/*
* The State has changed (e.g. from Disabled to Charging, or vice-versa)
*/
StateChanged,
/*
* ChargeCurrent has changed
* ChargeCurrent has changed (e.g. maxChargingCurrent so requires an
update to advertise a different charging current to the EV)
*/
ChargeCurrentChanged,
/*
* Charging Preferences have changed
* The daily charging target time, SoC / Added Energy schedules have changed
* and may require the local optimiser to re-run.
*/
ChargingPreferencesChanged,
/*
* DeviceEnergyManagement has changed
* Energy Meter Reading requested from the hardware, e.g. so that the session
* information can be updated.
*/
EnergyMeterReadingRequested,
/*
* The associated DeviceEnergyManagement cluster has changed. This may mean
* that the start time, or power profile or power levels have been adjusted
*/
DeviceEnergyManagementChanged,
};

enum class ChargingDischargingType : uint8_t
{
kCharging,
kDischarging
};

struct EVSECbInfo
{
EVSECallbackType type;
Expand All @@ -68,6 +84,13 @@ struct EVSECbInfo
{
int64_t maximumChargeCurrent;
} ChargingCurrent;

/* for type = EnergyMeterReadingRequested */
struct
{
ChargingDischargingType meterType;
int64_t * energyMeterValuePtr;
} EnergyMeterReadingRequest;
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,50 @@ namespace EnergyEvse {
class EVSEManufacturer
{
public:
EVSEManufacturer(EnergyEvseManager * aInstance) { mInstance = aInstance; }
EnergyEvseManager * GetInstance() { return mInstance; }
EnergyEvseDelegate * GetDelegate()
{
if (mInstance)
{
return mInstance->GetDelegate();
}
return nullptr;
}

/**
* @brief Called at start up to apply hardware settings
*/
CHIP_ERROR Init(EnergyEvseManager * aInstance);
CHIP_ERROR Init();

/**
* @brief Called at shutdown
*/
CHIP_ERROR Shutdown(EnergyEvseManager * aInstance);
CHIP_ERROR Shutdown();

/**
* @brief Main Callback handler from delegate to user code
*/
static void ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_t arg);

private:
EnergyEvseManager * mInstance;

int64_t mLastChargingEnergyMeter = 0;
int64_t mLastDischargingEnergyMeter = 0;
andy31415 marked this conversation as resolved.
Show resolved Hide resolved
};

/** @brief Helper function to return the singleton EVSEManufacturer instance
*
* This is needed by the EVSEManufacturer class to support TestEventTriggers
* which are called outside of any class context. This allows the EVSEManufacturer
* class to return the relevant Delegate instance in which to invoke the test
* events on.
*
* This function is typically found in main.cpp or wherever the singleton is created.
*/
EVSEManufacturer * GetEvseManufacturer();

} // namespace EnergyEvse
} // namespace Clusters
} // namespace app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,68 @@ namespace app {
namespace Clusters {
namespace EnergyEvse {

/* Local state machine Events to allow simpler handling of state transitions */
enum EVSEStateMachineEvent
{
EVPluggedInEvent, /* EV has been plugged in */
EVNotDetectedEvent, /* EV has been unplugged or detected as not connected */
EVNoDemandEvent, /* EV has stopped asking for demand */
EVDemandEvent, /* EV has asked for demand*/
ChargingEnabledEvent, /* Charging has been enabled */
DischargingEnabledEvent, /* Discharging has been enabled */
DisabledEvent, /* EVSE has been disabled */
FaultRaised, /* Fault has been raised */
FaultCleared, /* Fault has been cleared */
};

/**
* Helper class to handle all of the session related info
*/
class EvseSession
{
public:
EvseSession(EndpointId aEndpoint) { mEndpointId = aEndpoint; }
/**
* @brief This function records the start time and provided energy meter values as part of the new session.
*
* @param chargingMeterValue - The current value of the energy meter (charging) in mWh
* @param dischargingMeterValue - The current value of the energy meter (discharging) in mWh
*/
void StartSession(int64_t chargingMeterValue, int64_t dischargingMeterValue);
andy31415 marked this conversation as resolved.
Show resolved Hide resolved

/**
* @brief This function updates the session Duration to allow read attributes to return latest values
*/
void RecalculateSessionDuration();

/**
* @brief This function updates the EnergyCharged meter value
*
* @param chargingMeterValue - The value of the energy meter (charging) in mWh
*/
void UpdateEnergyCharged(int64_t chargingMeterValue);

/**
* @brief This function updates the EnergyDischarged meter value
*
* @param dischargingMeterValue - The value of the energy meter (discharging) in mWh
*/
void UpdateEnergyDischarged(int64_t dischargingMeterValue);

/* Public members - represent attributes in the cluster */
DataModel::Nullable<uint32_t> mSessionID;
DataModel::Nullable<uint32_t> mSessionDuration;
DataModel::Nullable<int64_t> mSessionEnergyCharged;
DataModel::Nullable<int64_t> mSessionEnergyDischarged;

private:
EndpointId mEndpointId = 0;

uint32_t mStartTime = 0; // Epoch_s - 0 means it hasn't started yet
int64_t mSessionEnergyChargedAtStart = 0; // in mWh - 0 means it hasn't been set yet
int64_t mSessionEnergyDischargedAtStart = 0; // in mWh - 0 means it hasn't been set yet
};

/**
* The application delegate.
*/
Expand Down Expand Up @@ -74,15 +136,41 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
*/
Status HwRegisterEvseCallbackHandler(EVSECallbackFunc handler, intptr_t arg);

/**
* @brief Decides if a timer is needed based on EVSE state and sets a callback if needed
*
* In order to ensure the EVSE restarts charging (if enabled) after power loss
* this should be called after the EVSE is initialised
* (e.g. HwSetMaxHardwareCurrentLimit and HwSetCircuitCapacity have been called)
* and the persisted attributes have been loaded, and time has been synchronised.
*
* If time isn't sync'd yet it will call itself back periodically (if required)
* until time is sync'd.
*
* It is also called when a EnableCharging or EnableDischarging command
* is recv'd to schedule when the EVSE should be automatically disabled based
* on ChargingEnabledUntil / DischargingEnabledUntil expiring.
*/
Status ScheduleCheckOnEnabledTimeout();

// -----------------------------------------------------------------
// Internal API to allow an EVSE to change its internal state etc
Status HwSetMaxHardwareCurrentLimit(int64_t currentmA);
int64_t HwGetMaxHardwareCurrentLimit() { return mMaxHardwareCurrentLimit; }
Status HwSetCircuitCapacity(int64_t currentmA);
Status HwSetCableAssemblyLimit(int64_t currentmA);
int64_t HwGetCableAssemblyLimit() { return mCableAssemblyCurrentLimit; }
Status HwSetState(StateEnum state);
StateEnum HwGetState() { return mHwState; };
Status HwSetFault(FaultStateEnum fault);
Status HwSetRFID(ByteSpan uid);
Status HwSetVehicleID(const CharSpan & vehID);
Status HwDiagnosticsComplete();
Status SendEVConnectedEvent();
Status SendEVNotDetectedEvent();
Status SendEnergyTransferStartedEvent();
Status SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum reason);
Status SendFaultEvent(FaultStateEnum newFaultState);

// ------------------------------------------------------------------
// Get attribute methods
Expand All @@ -96,10 +184,10 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
CHIP_ERROR SetFaultState(FaultStateEnum);

DataModel::Nullable<uint32_t> GetChargingEnabledUntil() override;
CHIP_ERROR SetChargingEnabledUntil(uint32_t);
CHIP_ERROR SetChargingEnabledUntil(DataModel::Nullable<uint32_t>);

DataModel::Nullable<uint32_t> GetDischargingEnabledUntil() override;
CHIP_ERROR SetDischargingEnabledUntil(uint32_t);
CHIP_ERROR SetDischargingEnabledUntil(DataModel::Nullable<uint32_t>);

int64_t GetCircuitCapacity() override;
CHIP_ERROR SetCircuitCapacity(int64_t);
Expand Down Expand Up @@ -128,7 +216,7 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
DataModel::Nullable<Percent> GetNextChargeTargetSoC() override;

DataModel::Nullable<uint16_t> GetApproximateEVEfficiency() override;
CHIP_ERROR SetApproximateEVEfficiency(uint16_t) override;
CHIP_ERROR SetApproximateEVEfficiency(DataModel::Nullable<uint16_t>) override;

/* SOC attributes */
DataModel::Nullable<Percent> GetStateOfCharge() override;
Expand All @@ -143,10 +231,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate

private:
/* Constants */
static constexpr int DEFAULT_MIN_CHARGE_CURRENT = 6000; /* 6A */
static constexpr int DEFAULT_USER_MAXIMUM_CHARGE_CURRENT = kMaximumChargeCurrent; /* 80A */
static constexpr int DEFAULT_RANDOMIZATION_DELAY_WINDOW = 600; /* 600s */
static constexpr int kMaxVehicleIDBufSize = 32;
static constexpr int kDefaultMinChargeCurrent = 6000; /* 6A */
static constexpr int kDefaultUserMaximumChargeCurrent = kMaximumChargeCurrent; /* 80A */
static constexpr int kDefaultRandomizationDelayWindow = 600; /* 600s */
static constexpr int kMaxVehicleIDBufSize = 32;
static constexpr int kPeriodicCheckIntervalRealTimeClockNotSynced = 30;

/* private variables for controlling the hardware - these are not attributes */
int64_t mMaxHardwareCurrentLimit = 0; /* Hardware current limit in mA */
Expand All @@ -155,28 +244,54 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
int64_t mActualChargingCurrentLimit = 0;
StateEnum mHwState = StateEnum::kNotPluggedIn; /* Hardware state */

/* Variables to hold State and SupplyState in case a fault is raised */
StateEnum mStateBeforeFault = StateEnum::kUnknownEnumValue;
SupplyStateEnum mSupplyStateBeforeFault = SupplyStateEnum::kUnknownEnumValue;

/* Callback related */
EVSECallbackWrapper mCallbacks = { .handler = nullptr, .arg = 0 }; /* Wrapper to allow callbacks to be registered */
Status NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent);
Status NotifyApplicationStateChange();
Status GetEVSEEnergyMeterValue(ChargingDischargingType meterType, int64_t & aMeterValue);

/* Local State machine handling */
Status CheckFaultOrDiagnostic();
Status HandleStateMachineEvent(EVSEStateMachineEvent event);
Status HandleEVPluggedInEvent();
Status HandleEVNotDetectedEvent();
Status HandleEVNoDemandEvent();
Status HandleEVDemandEvent();
Status HandleChargingEnabledEvent();
Status HandleDischargingEnabledEvent();
Status HandleDisabledEvent();
Status HandleFaultRaised();
Status HandleFaultCleared();

/**
* @brief Helper function to work out the charge limit based on conditions and settings
*/
Status ComputeMaxChargeCurrentLimit();

/**
* @brief This checks if the charging or discharging needs to be disabled
*
* @params pointer to SystemLayer
* @params pointer to EnergyEvseDelegate
*/
static void EvseCheckTimerExpiry(System::Layer * systemLayer, void * delegate);

/* Attributes */
StateEnum mState = StateEnum::kNotPluggedIn;
SupplyStateEnum mSupplyState = SupplyStateEnum::kDisabled;
FaultStateEnum mFaultState = FaultStateEnum::kNoError;
DataModel::Nullable<uint32_t> mChargingEnabledUntil; // TODO Default to 0 to indicate disabled
DataModel::Nullable<uint32_t> mDischargingEnabledUntil; // TODO Default to 0 to indicate disabled
int64_t mCircuitCapacity = 0;
int64_t mMinimumChargeCurrent = DEFAULT_MIN_CHARGE_CURRENT;
int64_t mMinimumChargeCurrent = kDefaultMinChargeCurrent;
int64_t mMaximumChargeCurrent = 0;
int64_t mMaximumDischargeCurrent = 0;
int64_t mUserMaximumChargeCurrent = DEFAULT_USER_MAXIMUM_CHARGE_CURRENT; // TODO update spec
uint32_t mRandomizationDelayWindow = DEFAULT_RANDOMIZATION_DELAY_WINDOW;
int64_t mUserMaximumChargeCurrent = kDefaultUserMaximumChargeCurrent; // TODO update spec
uint32_t mRandomizationDelayWindow = kDefaultRandomizationDelayWindow;
/* PREF attributes */
uint8_t mNumberOfWeeklyTargets = 0;
uint8_t mNumberOfDailyTargets = 1;
Expand All @@ -193,11 +308,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
/* PNC attributes*/
DataModel::Nullable<CharSpan> mVehicleID;

/* Session SESS attributes */
DataModel::Nullable<uint32_t> mSessionID;
DataModel::Nullable<uint32_t> mSessionDuration;
DataModel::Nullable<int64_t> mSessionEnergyCharged;
DataModel::Nullable<int64_t> mSessionEnergyDischarged;
/* Session Object */
EvseSession mSession = EvseSession(mEndpointId);

/* Helper variable to hold meter val since last EnergyTransferStarted event */
int64_t mMeterValueAtEnergyTransferStart;
};

} // namespace EnergyEvse
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class EnergyEvseManager : public Instance
CHIP_ERROR Init();
void Shutdown();

CHIP_ERROR LoadPersistentAttributes();

EnergyEvseDelegate * GetDelegate() { return mDelegate; };

private:
Expand Down
Loading
Loading