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

Reservation changes for 2.0.1 #943

Open
wants to merge 63 commits into
base: main
Choose a base branch
from

Conversation

maaikez
Copy link
Contributor

@maaikez maaikez commented Oct 31, 2024

Describe your changes

Implement reservation changes for ocpp 2.0.1 (connector type, reservation for not specific evse)

OCTT tests:

OCPP 2.0.1

Passed:
TC_H_01_CS
TC_H_02_CS
TC_H_03_CS
TC_H_04_CS
TC_H_06_CS
TC_H_07_CS
TC_H_09_CS
TC_H_10_CS
TC_H_12_CS
TC_H_13_CS
TC_H_16_CS
TC_H_17_CS
TC_H_18_CS
TC_H_19_CS
TC_H_22_CS
TC_H_23_CS

Failed:
TC_B_24_CS: After reset, BootNotification should have reason 'RemoteReset', but is 'PowerUp'.
TC_H_08_CS: Did not receive expected status change to 'Available'.
TC_H_14_CS: Two 'global' reservations and 2 evse's, should set them both to 'reserved'.
TC_H_15_CS: Did not receive expected status change to 'Available'. ??? -> Reservation is 'Cancelled', there is no reservation status update sent.
TC_H_21_CS: When evse is set to Unavailable and a reservation is cancelled, evse should go to 'Unavailable' directly, but it first goes to 'Available'.
TC_H_24_CS: Received unexpected request message: ReservationStatusUpdateRequest (Waiting for StatusNotificationRequest; NotifyEventRequest) ????

OCPP 1.6

Passed:
TC_046_1_CS
TC_046_2_CS
TC_047_CS
TC_048_2_CS
TC_048_3_CS
TC_048_4_CS
TC_050_2_CS
TC_050_3_CS
TC_051_CS
TC_052_CS
TC_053_CS

Failed:
TC_049_CS: Test makes a reservation for connector id 0. Expects a StatusNotification.req with 'Reserved'. Is the test wrong or should we send a StatusNotification.req with connector id 0 and status reserved????

Issue ticket number and link

Checklist before requesting a review

  • I have performed a self-review of my code
  • I have made corresponding changes to the documentation
  • I read the contribution documentation and made sure that my changes meet its requirements

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…d added a request to check if there is a reservation for a specific token. Reservations are done on evse level, not on connector level. Further implementation of reservations.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…th tests. Some changes in connector availability.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
… connector type and evse's with different connector types.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…ed. If a reservation is made and there is already an existing one with the same reservation id, cancel that reservation. Add reservation timer.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…on. Fix bug with expired reservation.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…se state after submitting an event. Change set_evse_available to set_evse_state and the same for connector state.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…s with Auth tests.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
… evse index. Fix start reserved session with parent id for 'global' reservation. Change return value of cancel reservation callback so it returns true or false if a reservation could or could not be cancelled.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…ce. Add tests for storing and loading reservations.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@maaikez maaikez changed the title Feature/327 use case h01 reservation Reservation changes for 2.0.1 Oct 31, 2024
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
maaikez and others added 4 commits November 11, 2024 15:44
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
types/reservation.yaml Outdated Show resolved Hide resolved
*/
void init_connector(const int connector_id, const int evse_index);
void init_evse(const int evse_id, const int evse_index, const std::vector<Connector>& connectors);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you dont need the evse_index anymore in this function and also not in the Connector.hpp/cpp, which is good. So this can simply be

void init_evse(const int evse_id, const std::vector<Connector>& connectors);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is evse index always evse id - 1?
Or can evse id also be 5 while evse index is 1?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes you can make this assumption and add this requirement to the documentation in the index.rst with something like

The module connections of the evse_manager requirement must be connected in the correct order in the EVerest config file, i.e. the module representing the EVSE with evse id 1 must listed first, EVSE with evse id 2 second and so on.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added this to the Auth index.rst

modules/Auth/include/AuthHandler.hpp Outdated Show resolved Hide resolved
modules/Auth/lib/AuthHandler.cpp Outdated Show resolved Hide resolved
modules/Auth/include/ReservationHandler.hpp Outdated Show resolved Hide resolved
/// \param evse_id The EVSE id the connector belongs to.
/// \param connector_id The connector id.
///
void on_connector_state_changed(const ConnectorState connector_state, const uint32_t evse_id,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to pass the connector_state here since the ReservationManager has a reference the the evse map and can check the status internally

Copy link
Contributor Author

@maaikez maaikez Nov 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well I did that because if that connector is reserved, the reservation is just cancelled and we don't have to loop through all reservations to check if they can still be done. Do you think it's more readable when I remove it?

if (evse_id.has_value()) {
EVLOG_info << "Call reserved callback for evse id " << evse_id.value();

this->r_evse_manager.at(evse_id.value() - 1)->call_reserve(reservation_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The EvseManager shall stay autonoumus with the decision if a reservation can be made, so we should be able to handle the response at some point

Comment on lines 199 to 210
types::reservation::ReservationResult
get_evse_state(const uint32_t evse_id,
const std::map<uint32_t, types::reservation::Reservation>& evse_specific_reservations);

///
/// \brief Helper function to check if the connector of a specific EVSE is available.
/// \param evse_id The evse id the connector belongs to.
/// \param connector_type The connector type to check.
/// \return The `ReservationResult` to return fot his specific connector.
///
types::reservation::ReservationResult
is_connector_available(const uint32_t evse_id, const types::evse_manager::ConnectorTypeEnum connector_type);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These function signatures look confusing. get_evse_state and is_connector_available return a ReservationResult. I see that you are using the responses to return the value in make_reservation, but I think something more readable is possible here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I gave the function a slightly different name, is it more clear like this?

I also thought of a helper function converting a ConnectorState to a ReservationResult, maybe that makes it more clear? What do you think?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks better now 👍

@Pietfried Pietfried self-assigned this Nov 12, 2024
Copy link
Contributor

@SirVer SirVer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good for Bazel.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…king a reservation if the evse manager rejects the reservation. Make sure the evse manager can make the reservation if it is overwritten (same reservation id).

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
…in timed out (swipe of rfid but never a plugin of a connector)

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@@ -98,6 +98,10 @@ requires:
interface: display_message
min_connections: 0
max_connections: 1
reservation:
interface: reservation
min_connections: 1
Copy link
Contributor Author

@maaikez maaikez Nov 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Pietfried Is it ok that this is mandatory?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have discussed this with Cornelius and Kai , lets make it optional to allow compatability of older configs

Comment on lines 205 to 212
if (evse_reservations.count(evse_id) != 0 && evse_reservations[evse_id].connector_type.has_value() &&
(connector_it->type == evse_reservations[evse_id].connector_type.value() ||
connector_it->type == types::evse_manager::ConnectorTypeEnum::Unknown ||
evse_reservations[evse_id].connector_type.value() == types::evse_manager::ConnectorTypeEnum::Unknown)) {
cancel_reservation(evse_reservations[evse_id].reservation_id, true,
types::reservation::ReservationEndReason::Cancelled);
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I find that quite hard to read. Id prefer something like:

bool reservation_exists = evse_reservations.count(evse_id) != 0;
bool reserved_connector_specified = evse_reservations[evse_id].connector_type.has_value();
bool connector_type_matches = 
    connector_it->type == evse_reservations[evse_id].connector_type.value();
bool connector_type_unknown =
    connector_it->type == types::evse_manager::ConnectorTypeEnum::Unknown ||
    evse_reservations[evse_id].connector_type.value() == types::evse_manager::ConnectorTypeEnum::Unknown;

if (reservation_exists && reserved_connector_specified && (connector_type_matches || connector_type_unknown)) {
    cancel_reservation(evse_reservations[evse_id].reservation_id, 
                       true, 
                       types::reservation::ReservationEndReason::Cancelled);
    return;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I did this, but the order is important because of the optionals. I tried what happens if I keep those bools but it's a lot extra checks and I don't know if it will be more readable.

*/
void init_connector(const int connector_id, const int evse_index);
void init_evse(const int evse_id, const int evse_index, const std::vector<Connector>& connectors);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes you can make this assumption and add this requirement to the documentation in the index.rst with something like

The module connections of the evse_manager requirement must be connected in the correct order in the EVerest config file, i.e. the module representing the EVSE with evse id 1 must listed first, EVSE with evse id 2 second and so on.

Comment on lines 199 to 210
types::reservation::ReservationResult
get_evse_state(const uint32_t evse_id,
const std::map<uint32_t, types::reservation::Reservation>& evse_specific_reservations);

///
/// \brief Helper function to check if the connector of a specific EVSE is available.
/// \param evse_id The evse id the connector belongs to.
/// \param connector_type The connector type to check.
/// \return The `ReservationResult` to return fot his specific connector.
///
types::reservation::ReservationResult
is_connector_available(const uint32_t evse_id, const types::evse_manager::ConnectorTypeEnum connector_type);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks better now 👍

@Pietfried
Copy link
Contributor

Failed:
TC_B_24_CS: After reset, BootNotification should have reason 'RemoteReset', but is 'PowerUp'.

That is just a SIL issue, the system module doesnt remember the reset reason.

TC_H_08_CS: Did not receive expected status change to 'Available'.

Probably unrelated to this PR

TC_H_14_CS: Two 'global' reservations and 2 evse's, should set them both to 'reserved'.

TC_H_15_CS: Did not receive expected status change to 'Available'. ??? -> Reservation is 'Cancelled', there is no reservation status update sent.

We need to investigate.

TC_H_21_CS: When evse is set to Unavailable and a reservation is cancelled, evse should go to 'Unavailable' directly, but it first goes to 'Available'.

Probably unrelated to this PR

TC_H_24_CS: Received unexpected request message: ReservationStatusUpdateRequest (Waiting for StatusNotificationRequest; NotifyEventRequest) ????

Failed:
TC_049_CS: Test makes a reservation for connector id 0. Expects a StatusNotification.req with 'Reserved'. Is the test wrong or should we send a StatusNotification.req with connector id 0 and status reserved????

Great that all OCPP1.6 PASS ! TC_049_CS can fail in my view since we can configure ReserveConnectorZeroSupported to false, right?

@maaikez
Copy link
Contributor Author

maaikez commented Nov 14, 2024

Failed:
TC_B_24_CS: After reset, BootNotification should have reason 'RemoteReset', but is 'PowerUp'.

That is just a SIL issue, the system module doesnt remember the reset reason.

Yes all the identified issues were not for this pull request, only some we indeed need to investigate.

TC_H_08_CS: Did not receive expected status change to 'Available'.

Probably unrelated to this PR

I wonder if it is our bug of a bug in OCTT.

TC_H_15_CS: Did not receive expected status change to 'Available'. ???

We need to investigate.

Yep I also wonder here if it isn't an OCTT bug. Or some feature I don't understand (yet).

TC_H_21_CS: When evse is set to Unavailable and a reservation is cancelled, evse should go to 'Unavailable' directly, but it first goes to 'Available'.

Probably unrelated to this PR

Yes you'd already taken a look.

TC_H_24_CS: Received unexpected request message: ReservationStatusUpdateRequest (Waiting for StatusNotificationRequest; NotifyEventRequest) ????

We need to investigate this one as well.

Failed:
TC_049_CS: Test makes a reservation for connector id 0. Expects a StatusNotification.req with 'Reserved'. Is the test wrong or should we send a StatusNotification.req with connector id 0 and status reserved????

Great that all OCPP1.6 PASS ! TC_049_CS can fail in my view since we can configure ReserveConnectorZeroSupported to false, right?

All other tests pass except this one indeed.
Also for this one: I am not sure if this is indeed expected behaviour to have a status notification for connector 0.
We can indeed configure that to pass the test.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants