diff --git a/CHANGELOG.md b/CHANGELOG.md index e4e7f7b7..06410a8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - Variables (non-persistent), UCs B05 - B07 ([#247](https://github.com/matth-x/MicroOcpp/pull/247), [#284](https://github.com/matth-x/MicroOcpp/pull/284)) - Transactions (preview only), UCs E01 - E12 ([#247](https://github.com/matth-x/MicroOcpp/pull/247)) - StatusNotification compatibility ([#247](https://github.com/matth-x/MicroOcpp/pull/247)) + - ChangeAvailability compatibility ([#285](https://github.com/matth-x/MicroOcpp/pull/285)) ### Fixed diff --git a/src/MicroOcpp.cpp b/src/MicroOcpp.cpp index 6eb15c53..b3eb5857 100644 --- a/src/MicroOcpp.cpp +++ b/src/MicroOcpp.cpp @@ -515,6 +515,19 @@ bool ocppPermitsCharge(unsigned int connectorId) { MO_DBG_WARN("OCPP uninitialized"); return false; } +#if MO_ENABLE_V201 + if (context->getVersion().major == 2) { + TransactionService::Evse *evse = nullptr; + if (auto txService = context->getModel().getTransactionService()) { + evse = txService->getEvse(connectorId); + } + if (!evse) { + MO_DBG_ERR("could not find EVSE"); + return false; + } + return evse->ocppPermitsCharge(); + } +#endif auto connector = context->getModel().getConnector(connectorId); if (!connector) { MO_DBG_ERR("could not find connector"); diff --git a/src/MicroOcpp/Model/ConnectorBase/Connector.cpp b/src/MicroOcpp/Model/ConnectorBase/Connector.cpp index 67ce4284..1f7564db 100644 --- a/src/MicroOcpp/Model/ConnectorBase/Connector.cpp +++ b/src/MicroOcpp/Model/ConnectorBase/Connector.cpp @@ -22,6 +22,7 @@ #include <MicroOcpp/Model/Reservation/ReservationService.h> #include <MicroOcpp/Model/Authorization/AuthorizationService.h> #include <MicroOcpp/Model/ConnectorBase/EvseId.h> +#include <MicroOcpp/Model/Transactions/TransactionService.h> #include <MicroOcpp/Core/SimpleRequestFactory.h> #include <MicroOcpp/Core/Connection.h> @@ -871,6 +872,28 @@ bool Connector::isOperative() { } } + #if MO_ENABLE_V201 + if (model.getVersion().major == 2 && model.getTransactionService()) { + auto txService = model.getTransactionService(); + + if (connectorId == 0) { + for (unsigned int cId = 1; cId < model.getNumConnectors(); cId++) { + if (txService->getEvse(cId)->getTransaction() && + txService->getEvse(cId)->getTransaction()->started && + !txService->getEvse(cId)->getTransaction()->stopped) { + return true; + } + } + } else { + if (txService->getEvse(connectorId)->getTransaction() && + txService->getEvse(connectorId)->getTransaction()->started && + !txService->getEvse(connectorId)->getTransaction()->stopped) { + return true; + } + } + } + #endif //MO_ENABLE_V201 + return availabilityVolatile && availabilityBool->getBool(); } diff --git a/src/MicroOcpp/Model/Transactions/TransactionService.cpp b/src/MicroOcpp/Model/Transactions/TransactionService.cpp index 8a5048c9..62520f3f 100644 --- a/src/MicroOcpp/Model/Transactions/TransactionService.cpp +++ b/src/MicroOcpp/Model/Transactions/TransactionService.cpp @@ -417,6 +417,12 @@ const std::shared_ptr<MicroOcpp::Ocpp201::Transaction>& TransactionService::Evse return transaction; } +bool TransactionService::Evse::ocppPermitsCharge() { + return transaction && + transaction->active && + transaction->isAuthorized; +} + bool TransactionService::isTxStartPoint(TxStartStopPoint check) { for (auto& v : txStartPointParsed) { if (v == check) { diff --git a/src/MicroOcpp/Model/Transactions/TransactionService.h b/src/MicroOcpp/Model/Transactions/TransactionService.h index 1112101c..0f0b78bd 100644 --- a/src/MicroOcpp/Model/Transactions/TransactionService.h +++ b/src/MicroOcpp/Model/Transactions/TransactionService.h @@ -59,6 +59,8 @@ class TransactionService { bool abortTransaction(Ocpp201::Transaction::StopReason stopReason = Ocpp201::Transaction::StopReason::Other, Ocpp201::TransactionEventTriggerReason stopTrigger = Ocpp201::TransactionEventTriggerReason::AbnormalCondition); const std::shared_ptr<Ocpp201::Transaction>& getTransaction(); + + bool ocppPermitsCharge(); }; friend Evse; diff --git a/src/MicroOcpp/Operations/ChangeAvailability.cpp b/src/MicroOcpp/Operations/ChangeAvailability.cpp index ae66235d..517bdabb 100644 --- a/src/MicroOcpp/Operations/ChangeAvailability.cpp +++ b/src/MicroOcpp/Operations/ChangeAvailability.cpp @@ -1,10 +1,11 @@ // matth-x/MicroOcpp -// Copyright Matthias Akstaller 2019 - 2023 +// Copyright Matthias Akstaller 2019 - 2024 // MIT License #include <MicroOcpp/Operations/ChangeAvailability.h> #include <MicroOcpp/Model/Model.h> #include <MicroOcpp/Model/ConnectorBase/Connector.h> +#include <MicroOcpp/Version.h> #include <functional> @@ -19,19 +20,40 @@ const char* ChangeAvailability::getOperationType(){ } void ChangeAvailability::processReq(JsonObject payload) { - int connectorIdRaw = payload["connectorId"] | -1; - if (connectorIdRaw < 0) { - errorCode = "FormationViolation"; - return; + + unsigned int connectorId = 0; + const char *type = "_Undefined"; + + #if MO_ENABLE_V201 + if (model.getVersion().major == 2) { + //OCPP 2.0.1 + int connectorIdRaw = payload["evse"]["id"] | 0; + if (connectorIdRaw < 0) { + errorCode = "FormationViolation"; + return; + } + + connectorId = (unsigned int)connectorIdRaw; + type = payload["operationalStatus"] | type; + } else + #endif //MO_ENABLE_V201 + { + //OCPP 1.6 + int connectorIdRaw = payload["connectorId"] | -1; + if (connectorIdRaw < 0) { + errorCode = "FormationViolation"; + return; + } + + connectorId = (unsigned int)connectorIdRaw; + type = payload["type"] | type; } - unsigned int connectorId = (unsigned int) connectorIdRaw; if (connectorId >= model.getNumConnectors()) { errorCode = "PropertyConstraintViolation"; return; } - const char *type = payload["type"] | "INVALID"; bool available = false; if (!strcmp(type, "Operative")) {