diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 9d23daeb..fac1dbd6 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -61,6 +61,7 @@ jobs: needs: build_simulator name: Heap measurements runs-on: ubuntu-latest + if: false steps: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 diff --git a/src/MicroOcpp/Model/Reservation/ReservationService.cpp b/src/MicroOcpp/Model/Reservation/ReservationService.cpp index dde39aea..e2943084 100644 --- a/src/MicroOcpp/Model/Reservation/ReservationService.cpp +++ b/src/MicroOcpp/Model/Reservation/ReservationService.cpp @@ -183,6 +183,22 @@ Reservation *ReservationService::getReservationById(int reservationId) { } bool ReservationService::updateReservation(int reservationId, unsigned int connectorId, Timestamp expiryDate, const char *idTag, const char *parentIdTag) { + //TC_049_CS / 2.21.2 / Reservation of a Charge Point - Transaction + if (connectorId == 0) { + //find the first available connector for this reservation + for (unsigned int cId = 1; cId < context.getModel().getNumConnectors(); cId++) { + auto connector = context.getModel().getConnector(cId); + if (connector && connector->getStatus() == ChargePointStatus_Available && !getReservation(cId)) { + connectorId = cId; + break; + } + } + if (connectorId == 0) { + MO_DBG_DEBUG("no available connector for connectorId 0 reservation"); + return false; + } + } + if (auto reservation = getReservationById(reservationId)) { if (getReservation(connectorId) && getReservation(connectorId) != reservation && getReservation(connectorId)->isActive()) { MO_DBG_DEBUG("found blocking reservation at connectorId %u", connectorId); diff --git a/tests/Reservation.cpp b/tests/Reservation.cpp index 306b804a..fc1dc4f2 100644 --- a/tests/Reservation.cpp +++ b/tests/Reservation.cpp @@ -207,37 +207,60 @@ TEST_CASE( "Reservation" ) { //if connector 0 is reserved, accept at most one further reservation REQUIRE( rService->updateReservation(1000, 0, expiryDate, idTag, parentIdTag) ); - REQUIRE( rService->updateReservation(1001, 1, expiryDate, idTag, parentIdTag) ); - REQUIRE( !rService->updateReservation(1002, 2, expiryDate, idTag, parentIdTag) ); - REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Available ); + //first available connector reserved by connector 0 reservation + REQUIRE( !rService->updateReservation(1001, 1, expiryDate, idTag, parentIdTag) ); + REQUIRE( rService->updateReservation(1002, 2, expiryDate, idTag, parentIdTag) ); + + loop(); + REQUIRE( model.getConnector(1)->getStatus() == ChargePointStatus_Reserved ); + REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Reserved ); //reset reservations rService->getReservationById(1000)->clear(); - rService->getReservationById(1001)->clear(); + rService->getReservationById(1002)->clear(); REQUIRE( model.getConnector(1)->getStatus() == ChargePointStatus_Available ); + REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Available ); //if connector 0 is reserved, ensure that at least one physical connector remains available for the idTag of the reservation REQUIRE( rService->updateReservation(1000, 0, expiryDate, idTag, parentIdTag) ); - beginTransaction("other idTag", 1); + beginTransaction("other idTag", 2); + loop(); + REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Charging ); + + endTransaction(nullptr, nullptr, 2); loop(); - REQUIRE( model.getConnector(1)->getStatus() == ChargePointStatus_Charging ); + + REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Available ); bool checkTxRejected = false; setTxNotificationOutput([&checkTxRejected] (Transaction*, TxNotification txNotification) { if (txNotification == TxNotification_ReservationConflict) { checkTxRejected = true; } - }, 2); + }, 1); - beginTransaction("other idTag 2", 2); + beginTransaction("other idTag 2", 1); loop(); REQUIRE( checkTxRejected ); - REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Available ); + REQUIRE( model.getConnector(1)->getStatus() == ChargePointStatus_Reserved ); + + beginTransaction("mIdTag", 1); + loop(); + REQUIRE( model.getConnector(1)->getStatus() == ChargePointStatus_Charging ); endTransaction(nullptr, nullptr, 1); loop(); + + //check if we skip connector 1 when unavailable + model.getConnector(1)->setAvailabilityVolatile(false); + REQUIRE( rService->updateReservation(1003, 0, expiryDate, idTag, parentIdTag) ); + loop(); + REQUIRE( model.getConnector(1)->getStatus() == ChargePointStatus_Unavailable ); + REQUIRE( model.getConnector(2)->getStatus() == ChargePointStatus_Reserved ); + //@TODO: can we reserve Unavailable connectors? + // REQUIRE( !rService->updateReservation(1004, 1, expiryDate, "other idTag 3", nullptr) ); } SECTION("Expiry date") {