Skip to content
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
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
with:
repository: matth-x/MicroOcppSimulator
path: MicroOcppSimulator
ref: feature/remote-api
ref: 20e8da7b76a3f5f3e50facab018a457ecdbcca59
submodules: 'recursive'
- name: Clean MicroOcpp submodule
run: |
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
- UnlockConnector port for OCPP 2.0.1 ([#371](https://github.com/matth-x/MicroOcpp/pull/371))
- More APIs ported to OCPP 2.0.1 ([#371](https://github.com/matth-x/MicroOcpp/pull/371))
- Support for AuthorizeRemoteTxRequests ([#373](https://github.com/matth-x/MicroOcpp/pull/373))
- Persistent Variable and Tx store for OCPP 2.0.1 ([#379](https://github.com/matth-x/MicroOcpp/pull/379))

### Removed

Expand Down
3 changes: 2 additions & 1 deletion src/MicroOcpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ void mocpp_initialize(Connection& connection, const char *bootNotificationCreden
model.setVariableService(std::unique_ptr<VariableService>(
new VariableService(*context, filesystem)));
model.setTransactionService(std::unique_ptr<TransactionService>(
new TransactionService(*context)));
new TransactionService(*context, filesystem, MO_NUM_EVSEID)));
model.setRemoteControlService(std::unique_ptr<RemoteControlService>(
new RemoteControlService(*context, MO_NUM_EVSEID)));
} else
Expand Down Expand Up @@ -852,6 +852,7 @@ void setEvReadyInput(std::function<bool()> evReadyInput, unsigned int connectorI
evse->setEvReadyInput(evReadyInput);
}
}
return;
}
#endif
auto connector = context->getModel().getConnector(connectorId);
Expand Down
8 changes: 5 additions & 3 deletions src/MicroOcpp/Model/Authorization/IdToken.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ IdToken::IdToken(const char *token, Type type, const char *memoryTag) : MemoryMa
MO_DBG_ERR("invalid token");
*idToken = '\0';
}
} else {
*idToken = '\0';
}
}

Expand Down Expand Up @@ -63,11 +65,11 @@ bool IdToken::parseCstr(const char *token, const char *typeCstr) {
}

const char *IdToken::get() const {
return *idToken ? idToken : nullptr;;
return idToken;
}

const char *IdToken::getTypeCstr() const {
const char *res = nullptr;
const char *res = "";
switch (type) {
case Type::UNDEFINED:
MO_DBG_ERR("internal error");
Expand Down Expand Up @@ -98,7 +100,7 @@ const char *IdToken::getTypeCstr() const {
break;
}

return res ? res : "";
return res;
}

bool IdToken::equals(const IdToken& other) {
Expand Down
2 changes: 0 additions & 2 deletions src/MicroOcpp/Model/ConnectorBase/Connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
#define MO_TXRECORD_SIZE 4 //no. of tx to hold on flash storage
#endif

#define MAX_TX_CNT 100000U //upper limit of txNr (internal usage). Must be at least 2*MO_TXRECORD_SIZE+1

#ifndef MO_REPORT_NOERROR
#define MO_REPORT_NOERROR 0
#endif
Expand Down
78 changes: 44 additions & 34 deletions src/MicroOcpp/Model/Metering/MeterValuesV201.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,46 @@ bool MeteringServiceEvse::existsMeasurand(const char *measurand, size_t len) {
return false;
}

namespace MicroOcpp {
namespace Ocpp201 {

bool validateSelectString(const char *csl, void *userPtr) {
auto mService = static_cast<MeteringService*>(userPtr);

bool isValid = true;
const char *l = csl; //the beginning of an entry of the comma-separated list
const char *r = l; //one place after the last character of the entry beginning with l
while (*l) {
if (*l == ',') {
l++;
continue;
}
r = l + 1;
while (*r != '\0' && *r != ',') {
r++;
}
bool found = false;
for (size_t evseId = 0; evseId < MO_NUM_EVSEID && mService->getEvse(evseId); evseId++) {
if (mService->getEvse(evseId)->existsMeasurand(l, (size_t) (r - l))) {
found = true;
break;
}
}
if (!found) {
isValid = false;
MO_DBG_WARN("could not find metering device for %.*s", (int) (r - l), l);
break;
}
l = r;
}
return isValid;
}

} //namespace Ocpp201
} //namespace MicroOcpp

using namespace MicroOcpp::Ocpp201;

MeteringService::MeteringService(Model& model, size_t numEvses) {

auto varService = model.getVariableService();
Expand All @@ -298,40 +338,10 @@ MeteringService::MeteringService(Model& model, size_t numEvses) {
varService->declareVariable<const char*>("SampledDataCtrlr", "TxEndedMeasurands", "");
varService->declareVariable<const char*>("AlignedDataCtrlr", "AlignedDataMeasurands", "");

std::function<bool(const char*)> validateSelectString = [this] (const char *csl) {
bool isValid = true;
const char *l = csl; //the beginning of an entry of the comma-separated list
const char *r = l; //one place after the last character of the entry beginning with l
while (*l) {
if (*l == ',') {
l++;
continue;
}
r = l + 1;
while (*r != '\0' && *r != ',') {
r++;
}
bool found = false;
for (size_t evseId = 0; evseId < MO_NUM_EVSEID && evses[evseId]; evseId++) {
if (evses[evseId]->existsMeasurand(l, (size_t) (r - l))) {
found = true;
break;
}
}
if (!found) {
isValid = false;
MO_DBG_WARN("could not find metering device for %.*s", (int) (r - l), l);
break;
}
l = r;
}
return isValid;
};

varService->registerValidator<const char*>("SampledDataCtrlr", "TxStartedMeasurands", validateSelectString);
varService->registerValidator<const char*>("SampledDataCtrlr", "TxUpdatedMeasurands", validateSelectString);
varService->registerValidator<const char*>("SampledDataCtrlr", "TxEndedMeasurands", validateSelectString);
varService->registerValidator<const char*>("AlignedDataCtrlr", "AlignedDataMeasurands", validateSelectString);
varService->registerValidator<const char*>("SampledDataCtrlr", "TxStartedMeasurands", validateSelectString, this);
varService->registerValidator<const char*>("SampledDataCtrlr", "TxUpdatedMeasurands", validateSelectString, this);
varService->registerValidator<const char*>("SampledDataCtrlr", "TxEndedMeasurands", validateSelectString, this);
varService->registerValidator<const char*>("AlignedDataCtrlr", "AlignedDataMeasurands", validateSelectString, this);

for (size_t evseId = 0; evseId < std::min(numEvses, (size_t)MO_NUM_EVSEID); evseId++) {
evses[evseId] = new MeteringServiceEvse(model, evseId);
Expand Down
29 changes: 20 additions & 9 deletions src/MicroOcpp/Model/RemoteControl/RemoteControlService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ UnlockStatus RemoteControlServiceEvse::unlockConnector() {
if (tx->started && !tx->stopped && tx->isAuthorized) {
return UnlockStatus_OngoingAuthorizedTransaction;
} else {
evse->abortTransaction(Ocpp201::Transaction::StopReason::Other,Ocpp201::TransactionEventTriggerReason::UnlockCommand);
evse->abortTransaction(Ocpp201::Transaction::StoppedReason::Other,Ocpp201::TransactionEventTriggerReason::UnlockCommand);
}
}
}
Expand Down Expand Up @@ -102,7 +102,7 @@ RemoteControlServiceEvse *RemoteControlService::getEvse(unsigned int evseId) {
return evses[evseId];
}

RequestStartStopStatus RemoteControlService::requestStartTransaction(unsigned int evseId, unsigned int remoteStartId, IdToken idToken, std::shared_ptr<Ocpp201::Transaction>& transactionOut) {
RequestStartStopStatus RemoteControlService::requestStartTransaction(unsigned int evseId, unsigned int remoteStartId, IdToken idToken, char *transactionIdOut, size_t transactionIdBufSize) {

TransactionService *txService = context.getModel().getTransactionService();
if (!txService) {
Expand All @@ -116,21 +116,32 @@ RequestStartStopStatus RemoteControlService::requestStartTransaction(unsigned in
return RequestStartStopStatus_Rejected;
}

transactionOut = evse->getTransaction();

if (!evse->beginAuthorization(idToken, authorizeRemoteStart->getBool())) {
MO_DBG_INFO("EVSE still occupied with pending tx");
if (auto tx = evse->getTransaction()) {
auto ret = snprintf(transactionIdOut, transactionIdBufSize, "%s", tx->transactionId);
if (ret < 0 || (size_t)ret >= transactionIdBufSize) {
MO_DBG_ERR("internal error");
return RequestStartStopStatus_Rejected;
}
}
return RequestStartStopStatus_Rejected;
}

auto tx = evse->getTransaction();
if (!tx) {
MO_DBG_ERR("internal error");
return RequestStartStopStatus_Rejected;
}

transactionOut = evse->getTransaction();
if (!transactionOut) {
auto ret = snprintf(transactionIdOut, transactionIdBufSize, "%s", tx->transactionId);
if (ret < 0 || (size_t)ret >= transactionIdBufSize) {
MO_DBG_ERR("internal error");
return RequestStartStopStatus_Rejected;
}

transactionOut->remoteStartId = remoteStartId;
transactionOut->notifyRemoteStartId = true;
tx->remoteStartId = remoteStartId;
tx->notifyRemoteStartId = true;

return RequestStartStopStatus_Accepted;
}
Expand All @@ -148,7 +159,7 @@ RequestStartStopStatus RemoteControlService::requestStopTransaction(const char *
for (unsigned int evseId = 0; evseId < MO_NUM_EVSEID; evseId++) {
if (auto evse = txService->getEvse(evseId)) {
if (evse->getTransaction() && !strcmp(evse->getTransaction()->transactionId, transactionId)) {
success = evse->abortTransaction(Ocpp201::Transaction::StopReason::Remote, Ocpp201::TransactionEventTriggerReason::RemoteStop);
success = evse->abortTransaction(Ocpp201::Transaction::StoppedReason::Remote, Ocpp201::TransactionEventTriggerReason::RemoteStop);
break;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/MicroOcpp/Model/RemoteControl/RemoteControlService.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class RemoteControlService : public MemoryManaged {

RemoteControlServiceEvse *getEvse(unsigned int evseId);

RequestStartStopStatus requestStartTransaction(unsigned int evseId, unsigned int remoteStartId, IdToken idToken, std::shared_ptr<Ocpp201::Transaction>& transactionOut); //ChargingProfile, GroupIdToken not supported yet
RequestStartStopStatus requestStartTransaction(unsigned int evseId, unsigned int remoteStartId, IdToken idToken, char *transactionIdOut, size_t transactionIdBufSize); //ChargingProfile, GroupIdToken not supported yet

RequestStartStopStatus requestStopTransaction(const char *transactionId);
};
Expand Down
4 changes: 2 additions & 2 deletions src/MicroOcpp/Model/Reset/ResetService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ ResetService::~ResetService() {

ResetService::Evse::Evse(Context& context, ResetService& resetService, unsigned int evseId) : context(context), resetService(resetService), evseId(evseId) {
auto varService = context.getModel().getVariableService();
varService->declareVariable<bool>(ComponentId("EVSE", evseId >= 1 ? evseId : -1), "AllowReset", true, MO_VARIABLE_FN, Variable::Mutability::ReadOnly);
varService->declareVariable<bool>(ComponentId("EVSE", evseId >= 1 ? evseId : -1), "AllowReset", true, Variable::Mutability::ReadOnly, false);
}

void ResetService::Evse::loop() {
Expand Down Expand Up @@ -303,7 +303,7 @@ ResetStatus ResetService::initiateReset(ResetType type, unsigned int evseId) {
if (tx->active) {
//Tx in progress. Check behavior
if (type == ResetType_Immediate) {
txService->getEvse(eId)->abortTransaction(Transaction::StopReason::ImmediateReset, TransactionEventTriggerReason::ResetCommand);
txService->getEvse(eId)->abortTransaction(Transaction::StoppedReason::ImmediateReset, TransactionEventTriggerReason::ResetCommand);
} else {
scheduled = true;
break;
Expand Down
Loading