Skip to content

Commit

Permalink
Connector Lock build switch (#312)
Browse files Browse the repository at this point in the history
* add build flag MO_ENABLE_CONNECTOR_LOCK

* change default for MO_ENABLE_CONNECTOR_LOCK to 0

* update changelog
  • Loading branch information
matth-x authored Jun 9, 2024
1 parent 0f8a528 commit e1b4d22
Show file tree
Hide file tree
Showing 13 changed files with 91 additions and 24 deletions.
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

0 comments on commit e1b4d22

Please sign in to comment.