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

Connector Lock build switch #312

Merged
merged 3 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Changed

- Change `MicroOcpp::ChargePointStatus` into C-style enum ([#309](https://github.com/matth-x/MicroOcpp/pull/309))
- Connector lock disabled by default per `MO_ENABLE_CONNECTOR_LOCK` ([#312](https://github.com/matth-x/MicroOcpp/pull/312))

### Added

Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ target_compile_definitions(mo_unit_tests PUBLIC
MO_ChargingScheduleMaxPeriods=4
MO_MaxChargingProfilesInstalled=3
MO_ENABLE_CERT_MGMT=1
MO_ENABLE_CONNECTOR_LOCK=1
)

target_compile_options(mo_unit_tests PUBLIC
Expand Down
2 changes: 2 additions & 0 deletions src/MicroOcpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ void setTxNotificationOutput(std::function<void(MicroOcpp::Transaction*,MicroOcp
connector->setTxNotificationOutput(notificationOutput);
}

#if MO_ENABLE_CONNECTOR_LOCK
void setOnUnlockConnectorInOut(std::function<UnlockConnectorResult()> onUnlockConnectorInOut, unsigned int connectorId) {
if (!context) {
MO_DBG_ERR("OCPP uninitialized"); //need to call mocpp_initialize before
Expand All @@ -886,6 +887,7 @@ void setOnUnlockConnectorInOut(std::function<UnlockConnectorResult()> onUnlockCo
}
connector->setOnUnlockConnector(onUnlockConnectorInOut);
}
#endif //MO_ENABLE_CONNECTOR_LOCK

bool isOperative(unsigned int connectorId) {
if (!context) {
Expand Down
4 changes: 3 additions & 1 deletion src/MicroOcpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,15 +309,17 @@ void setStopTxReadyInput(std::function<bool()> stopTxReady, unsigned int connect

void setTxNotificationOutput(std::function<void(MicroOcpp::Transaction*,MicroOcpp::TxNotification)> notificationOutput, unsigned int connectorId = 1); //called when transaction state changes (see TxNotification for possible events). Transaction can be null

#if MO_ENABLE_CONNECTOR_LOCK
/*
* Set an InputOutput (reads and sets information at the same time) for forcing to unlock the
* connector. Called as part of the OCPP operation "UnlockConnector"
* Return values:
* - UnlockConnectorResult_Pending if action needs more time to complete (MO will call this cb again later or eventually timeout)
* - UnlockConnectorResult_Pending if action needs more time to complete (MO will call this cb again later or eventually time out)
* - UnlockConnectorResult_Unlocked if successful
* - UnlockConnectorResult_UnlockFailed if not successful (e.g. lock stuck)
*/
void setOnUnlockConnectorInOut(std::function<UnlockConnectorResult()> onUnlockConnectorInOut, unsigned int connectorId = 1);
#endif //MO_ENABLE_CONNECTOR_LOCK

/*
* Access further information about the internal state of the library
Expand Down
11 changes: 9 additions & 2 deletions src/MicroOcpp/Model/ConnectorBase/Connector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ Connector::Connector(Context& context, int connectorId)

snprintf(availabilityBoolKey, sizeof(availabilityBoolKey), MO_CONFIG_EXT_PREFIX "AVAIL_CONN_%d", connectorId);
availabilityBool = declareConfiguration<bool>(availabilityBoolKey, true, MO_KEYVALUE_FN, false, false, false);


#if MO_ENABLE_CONNECTOR_LOCK
declareConfiguration<bool>("UnlockConnectorOnEVSideDisconnect", true); //read-write
#else
declareConfiguration<bool>("UnlockConnectorOnEVSideDisconnect", false, CONFIGURATION_VOLATILE, true); //read-only because there is no connector lock
#endif //MO_ENABLE_CONNECTOR_LOCK

connectionTimeOutInt = declareConfiguration<int>("ConnectionTimeOut", 30);
minimumStatusDurationInt = declareConfiguration<int>("MinimumStatusDuration", 0);
stopTransactionOnInvalidIdBool = declareConfiguration<bool>("StopTransactionOnInvalidId", true);
stopTransactionOnEVSideDisconnectBool = declareConfiguration<bool>("StopTransactionOnEVSideDisconnect", true);
declareConfiguration<bool>("UnlockConnectorOnEVSideDisconnect", true, CONFIGURATION_VOLATILE, true);
localPreAuthorizeBool = declareConfiguration<bool>("LocalPreAuthorize", false);
localAuthorizeOfflineBool = declareConfiguration<bool>("LocalAuthorizeOffline", true);
allowOfflineTxForUnknownIdBool = MicroOcpp::declareConfiguration<bool>("AllowOfflineTxForUnknownId", false);
Expand Down Expand Up @@ -945,13 +950,15 @@ void Connector::addErrorDataInput(std::function<ErrorData ()> errorDataInput) {
this->trackErrorDataInputs.push_back(false);
}

#if MO_ENABLE_CONNECTOR_LOCK
void Connector::setOnUnlockConnector(std::function<UnlockConnectorResult()> unlockConnector) {
this->onUnlockConnector = unlockConnector;
}

std::function<UnlockConnectorResult()> Connector::getOnUnlockConnector() {
return this->onUnlockConnector;
}
#endif //MO_ENABLE_CONNECTOR_LOCK

void Connector::setStartTxReadyInput(std::function<bool()> startTxReady) {
this->startTxReadyInput = startTxReady;
Expand Down
4 changes: 4 additions & 0 deletions src/MicroOcpp/Model/ConnectorBase/Connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ class Connector {
ChargePointStatus reportedStatus = ChargePointStatus_UNDEFINED;
unsigned long t_statusTransition = 0;

#if MO_ENABLE_CONNECTOR_LOCK
std::function<UnlockConnectorResult()> onUnlockConnector;
#endif //MO_ENABLE_CONNECTOR_LOCK

std::function<bool()> startTxReadyInput; //the StartTx request will be delayed while this Input is false
std::function<bool()> stopTxReadyInput; //the StopTx request will be delayed while this Input is false
Expand Down Expand Up @@ -118,8 +120,10 @@ class Connector {

bool ocppPermitsCharge();

#if MO_ENABLE_CONNECTOR_LOCK
void setOnUnlockConnector(std::function<UnlockConnectorResult()> unlockConnector);
std::function<UnlockConnectorResult()> getOnUnlockConnector();
#endif //MO_ENABLE_CONNECTOR_LOCK

void setStartTxReadyInput(std::function<bool()> startTxReady);
void setStopTxReadyInput(std::function<bool()> stopTxReady);
Expand Down
8 changes: 8 additions & 0 deletions src/MicroOcpp/Model/ConnectorBase/UnlockConnectorResult.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@

#include <stdint.h>

// Connector-lock related behavior (i.e. if UnlockConnectorOnEVSideDisconnect is RW; enable HW binding for UnlockConnector)
#ifndef MO_ENABLE_CONNECTOR_LOCK
#define MO_ENABLE_CONNECTOR_LOCK 0
#endif

#if MO_ENABLE_CONNECTOR_LOCK

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
Expand All @@ -25,4 +32,5 @@ typedef enum {
}
#endif // __cplusplus

#endif // MO_ENABLE_CONNECTOR_LOCK
#endif // MO_UNLOCKCONNECTORRESULT_H
54 changes: 33 additions & 21 deletions src/MicroOcpp/Operations/UnlockConnector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,53 @@ void UnlockConnector::processReq(JsonObject payload) {
return;
}

unlockConnector = connector->getOnUnlockConnector();
#if MO_ENABLE_CONNECTOR_LOCK
{
unlockConnector = connector->getOnUnlockConnector();

if (!unlockConnector) {
// NotSupported
return;
}
if (!unlockConnector) {
// NotSupported
return;
}

connector->endTransaction(nullptr, "UnlockCommand");
connector->updateTxNotification(TxNotification::RemoteStop);
connector->endTransaction(nullptr, "UnlockCommand");
connector->updateTxNotification(TxNotification::RemoteStop);

cbUnlockResult = unlockConnector();
cbUnlockResult = unlockConnector();

timerStart = mocpp_tick_ms();
timerStart = mocpp_tick_ms();
}
#endif //MO_ENABLE_CONNECTOR_LOCK
}

std::unique_ptr<DynamicJsonDocument> UnlockConnector::createConf() {
if (unlockConnector && mocpp_tick_ms() - timerStart < MO_UNLOCK_TIMEOUT) {
//do poll and if more time is needed, delay creation of conf msg

if (cbUnlockResult == UnlockConnectorResult_Pending) {
cbUnlockResult = unlockConnector();
const char *status = "NotSupported";

#if MO_ENABLE_CONNECTOR_LOCK
if (unlockConnector) {

if (mocpp_tick_ms() - timerStart < MO_UNLOCK_TIMEOUT) {
//do poll and if more time is needed, delay creation of conf msg

if (cbUnlockResult == UnlockConnectorResult_Pending) {
return nullptr; //no result yet - delay confirmation response
cbUnlockResult = unlockConnector();
if (cbUnlockResult == UnlockConnectorResult_Pending) {
return nullptr; //no result yet - delay confirmation response
}
}
}

if (cbUnlockResult == UnlockConnectorResult_Unlocked) {
status = "Unlocked";
} else {
status = "UnlockFailed";
}
}
#endif //MO_ENABLE_CONNECTOR_LOCK

auto doc = std::unique_ptr<DynamicJsonDocument>(new DynamicJsonDocument(JSON_OBJECT_SIZE(1)));
JsonObject payload = doc->to<JsonObject>();
if (!unlockConnector) {
payload["status"] = "NotSupported";
} else if (cbUnlockResult == UnlockConnectorResult_Unlocked) {
payload["status"] = "Unlocked";
} else {
payload["status"] = "UnlockFailed";
}
payload["status"] = status;
return doc;
}
3 changes: 3 additions & 0 deletions src/MicroOcpp/Operations/UnlockConnector.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,12 @@ namespace Ocpp16 {
class UnlockConnector : public Operation {
private:
Model& model;

#if MO_ENABLE_CONNECTOR_LOCK
std::function<UnlockConnectorResult ()> unlockConnector;
UnlockConnectorResult cbUnlockResult;
unsigned long timerStart = 0; //for timeout
#endif //MO_ENABLE_CONNECTOR_LOCK

const char *errorCode = nullptr;
public:
Expand Down
5 changes: 5 additions & 0 deletions src/MicroOcpp_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,15 @@ MicroOcpp::OnReceiveErrorListener adaptFn(OnCallError fn) {
};
}

#if MO_ENABLE_CONNECTOR_LOCK
std::function<UnlockConnectorResult()> adaptFn(PollUnlockResult fn) {
return [fn] () {return fn();};
}

std::function<UnlockConnectorResult()> adaptFn(unsigned int connectorId, PollUnlockResult_m fn) {
return [fn, connectorId] () {return fn(connectorId);};
}
#endif //MO_ENABLE_CONNECTOR_LOCK

void ocpp_beginTransaction(const char *idTag) {
beginTransaction(idTag);
Expand Down Expand Up @@ -281,12 +283,15 @@ void ocpp_addMeterValueInput_m(unsigned int connectorId, MeterValueInput *meterV
addMeterValueInput(std::move(svs), connectorId);
}


#if MO_ENABLE_CONNECTOR_LOCK
void ocpp_setOnUnlockConnectorInOut(PollUnlockResult onUnlockConnectorInOut) {
setOnUnlockConnectorInOut(adaptFn(onUnlockConnectorInOut));
}
void ocpp_setOnUnlockConnectorInOut_m(unsigned int connectorId, PollUnlockResult_m onUnlockConnectorInOut) {
setOnUnlockConnectorInOut(adaptFn(connectorId, onUnlockConnectorInOut), connectorId);
}
#endif //MO_ENABLE_CONNECTOR_LOCK

void ocpp_setStartTxReadyInput(InputBool startTxReady) {
setStartTxReadyInput(adaptFn(startTxReady));
Expand Down
5 changes: 5 additions & 0 deletions src/MicroOcpp_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ typedef void (*OutputFloat)(float limit);
typedef void (*OutputFloat_m)(unsigned int connectorId, float limit);
typedef void (*OutputSmartCharging)(float power, float current, int nphases);
typedef void (*OutputSmartCharging_m)(unsigned int connectorId, float power, float current, int nphases);

#if MO_ENABLE_CONNECTOR_LOCK
typedef UnlockConnectorResult (*PollUnlockResult)();
typedef UnlockConnectorResult (*PollUnlockResult_m)(unsigned int connectorId);
#endif //MO_ENABLE_CONNECTOR_LOCK


#ifdef __cplusplus
Expand Down Expand Up @@ -156,8 +159,10 @@ void ocpp_setStopTxReadyInput_m(unsigned int connectorId, InputBool_m stopTxRead
void ocpp_setTxNotificationOutput(void (*notificationOutput)(OCPP_Transaction*, enum OCPP_TxNotification));
void ocpp_setTxNotificationOutput_m(unsigned int connectorId, void (*notificationOutput)(unsigned int, OCPP_Transaction*, enum OCPP_TxNotification));

#if MO_ENABLE_CONNECTOR_LOCK
void ocpp_setOnUnlockConnectorInOut(PollUnlockResult onUnlockConnectorInOut);
void ocpp_setOnUnlockConnectorInOut_m(unsigned int connectorId, PollUnlockResult_m onUnlockConnectorInOut);
#endif //MO_ENABLE_CONNECTOR_LOCK

/*
* Access further information about the internal state of the library
Expand Down
9 changes: 9 additions & 0 deletions tests/Api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,10 @@ TEST_CASE( "C++ API test" ) {
setStartTxReadyInput([c = &checkpoints[ncheck++]] () -> bool {*c = true; return true;});
setStopTxReadyInput([c = &checkpoints[ncheck++]] () -> bool {*c = true; return true;});
setTxNotificationOutput([c = &checkpoints[ncheck++]] (MicroOcpp::Transaction*, MicroOcpp::TxNotification) {*c = true;});

#if MO_ENABLE_CONNECTOR_LOCK
setOnUnlockConnectorInOut([c = &checkpoints[ncheck++]] () -> UnlockConnectorResult {*c = true; return UnlockConnectorResult_Unlocked;});
#endif //MO_ENABLE_CONNECTOR_LOCK

setOnResetNotify([c = &checkpoints[ncheck++]] (bool) -> bool {*c = true; return true;});
setOnResetExecute([c = &checkpoints[ncheck++]] (bool) {*c = true;});
Expand Down Expand Up @@ -248,8 +251,14 @@ TEST_CASE( "C API test" ) {
ocpp_setStopTxReadyInput_m(2, [] (unsigned int) -> bool {checkpointsc[23] = true; return true;}); ncheckc++;
ocpp_setTxNotificationOutput([] (OCPP_Transaction*, OCPP_TxNotification) {checkpointsc[24] = true;}); ncheckc++;
ocpp_setTxNotificationOutput_m(2, [] (unsigned int, OCPP_Transaction*, OCPP_TxNotification) {checkpointsc[25] = true;}); ncheckc++;

#if MO_ENABLE_CONNECTOR_LOCK
ocpp_setOnUnlockConnectorInOut([] () -> UnlockConnectorResult {checkpointsc[26] = true; return UnlockConnectorResult_Unlocked;}); ncheckc++;
ocpp_setOnUnlockConnectorInOut_m(2, [] (unsigned int) -> UnlockConnectorResult {checkpointsc[27] = true; return UnlockConnectorResult_Unlocked;}); ncheckc++;
#else
checkpointsc[26] = true;
checkpointsc[27] = true;
#endif //MO_ENABLE_CONNECTOR_LOCK

ocpp_setOnResetNotify([] (bool) -> bool {checkpointsc[28] = true; return true;}); ncheckc++;
ocpp_setOnResetExecute([] (bool) {checkpointsc[29] = true;}); ncheckc++;
Expand Down
8 changes: 8 additions & 0 deletions tests/ChargingSessions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,8 @@ TEST_CASE( "Charging sessions" ) {
REQUIRE( checkProcessed );
REQUIRE( isTransactionRunning() ); // NotSupported doesn't lead to transaction stop

#if MO_ENABLE_CONNECTOR_LOCK

setOnUnlockConnectorInOut([] () -> UnlockConnectorResult {
// connector lock fails
return UnlockConnectorResult_UnlockFailed;
Expand Down Expand Up @@ -754,6 +756,12 @@ TEST_CASE( "Charging sessions" ) {
mtime += MO_UNLOCK_TIMEOUT; // increment clock so that MO_UNLOCK_TIMEOUT expires
loop();
REQUIRE( checkProcessed );

#else
endTransaction();
loop();
#endif //MO_ENABLE_CONNECTOR_LOCK

}

SECTION("TxStartPoint - PowerPathClosed") {
Expand Down
Loading