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

Feature/327 use case h01 reservation #854

Merged
merged 31 commits into from
Nov 26, 2024

Conversation

maaikez
Copy link
Contributor

@maaikez maaikez commented Oct 31, 2024

Describe your changes

Changes to implement reservations for ocpp 2.0.1.

Issue ticket number and link

Checklist before requesting a review

@maaikez maaikez linked an issue Oct 31, 2024 that may be closed by this pull request
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@maaikez maaikez marked this pull request as ready for review November 4, 2024 12:54
/// \param connector_type The connector type.
/// \return std::nullopt if connector type is given, but does not exist. Otherwise the connector status.
///
std::optional<ConnectorStatusEnum> get_available_connector_or_status(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.

Purely looking at this function from the header it is a bit confusing. I think you are just checking if an evse has a connector available and optionally only check for a specific connector type?

If so, I would rename and change the documentation a bit. The connector_type argument is then a sort of optional filter.

Copy link
Contributor Author

@maaikez maaikez Nov 5, 2024

Choose a reason for hiding this comment

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

Ok I changed it a bit, can you take a look if that's better (have to commit still).

I am not sure about the function name as it will just return 'Available' if possible and otherwise the status of one of the connectors. Which is hard to catch in a function name ;).

Moved it to the evse class by the way, as your other comment suggested.

Copy link
Contributor

@Pietfried Pietfried Nov 11, 2024

Choose a reason for hiding this comment

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

This also looks a little bit confusing to me. Looking at how this function is used internally, it looks like bool is_connector_available(const int32_t evse_id, std::optional<ConnectorEnum> connector_type) provides everything you need. This would search for an available connector at the given evse_id using the given connector_type filter. Apart from that it looks like we need a function bool does_connector_exist(const int32_t evse_id, const ConnectorEnum connector_type) to check if the given connector_type belongs to any evse. I will mark the places in charge_point.cpp where I think these function shall be used. It looks like you never need the actual ConnectorStatus so a bool should be sufficient

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, can you (@marcemmers , @Pietfried ) take a look if this is what you mean and if it is more readable now?

Copy link
Contributor

@marcemmers marcemmers Nov 14, 2024

Choose a reason for hiding this comment

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

Maybe get_connector_status can be a bit more explicit when it does not find an available connector. Instead of returning the state of one of the connectors I would return the first or the last connectorId or at least a defined connector status.

Other than that it looks fine for me.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It does return the status of the last found connector with the given connector type. But if no connector with that type is found, it returns a nullopt. Should that be changed? Because then there is a status returned of a connector that does not even exist?

I changed the function a bit by the way, if the connector type is unknown, it is also included in the search.

Copy link
Contributor

@marcemmers marcemmers Nov 14, 2024

Choose a reason for hiding this comment

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

Ah sorry, I meant this part If there is no 'Available' connector, it will return the status of one of the connectors. which makes it seem like it just picks a connector to return the status for.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok changed to If there is no 'Available' connector, it will return the status of the last found connector with the given connector type.

@@ -151,5 +151,14 @@ struct Callbacks {
std::optional<std::function<void(const RunningCost& running_cost, const uint32_t number_of_decimals,
std::optional<std::string> currency_code)>>
set_running_cost_callback;

/// \brief Callback function is called when a reservation request is received from the CSMS
std::optional<std::function<ReserveNowStatusEnum(
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason why you don't just forward the request like we do with the other callbacks? Saves a bunch of arguments ;)

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 kept it quite the same as in OCPP 1.6. I don't know why the choice there was to do it this way. Better change it then?

Copy link
Contributor

Choose a reason for hiding this comment

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

I would prefer to keep the interface for the 2.0.1 implementation consistent over certain functionality shared between 1.6 and 2.0.1 so yeah I would change it. Just my 2 cents ofcourse.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well it is consistent with 1.6.

@Pietfried do you have a preference?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Talked to Piet, I will change it to the Reservation type (give me some time :)).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done!

return std::nullopt;
}

bool type_found = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

I would move the implementation of this to the Evse class, minus the evse_id argument ofcourse.

.value_or(false)) {
// Reservation not available / implemented, return 'Rejected'.
// H01.FR.01
EVLOG_info << "Receiving a reservation request, but reservation is not implemented.";
Copy link
Contributor

Choose a reason for hiding this comment

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

if ReservationCtrlrEnabled is false it might be implemented, just not enabled.

Also, for most of these it would be nice if we can add the error to the call result as well for the CSMS to see what is actually happening.

.value_or(false)) {
// H01.FR.19
EVLOG_warning
<< "Trying to make a reservation, but no evse id was given while it should be sent in the request.";
Copy link
Contributor

Choose a reason for hiding this comment

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

  • when ReservationCtrlrNonEvseSpecific is disabled

ConnectorStatusEnum connector_status = ConnectorStatusEnum::Unavailable;

if (evse_id.has_value()) {
if (evse_id.value() < 0 || !evse_manager->does_evse_exist(evse_id.value())) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I see I missed some checks in the evse manager. The smaller than 0 check should definitely be there (also in the get_evse functions. Then evse_id.value() < 0 would not be necessary anymore


const std::optional<int32_t> evse_id = request.evseId;

ConnectorStatusEnum connector_status = ConnectorStatusEnum::Unavailable;
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 store this since you never use it anywhere

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is just shorter and better readable in my opinion.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure I follow. You set the connector_status value here and in other places, but you never read it except for in line 3407. Where you always set the value the line before so this variable could be limited to that if statement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah thought it was about evse_id.

You're right.

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@maaikez maaikez force-pushed the feature/327-use-case-h01-reservation branch from 2828d56 to 3823b1c Compare November 5, 2024 17:26
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@marcemmers marcemmers self-assigned this Nov 6, 2024
@maaikez maaikez force-pushed the feature/327-use-case-h01-reservation branch 2 times, most recently from 4259dc0 to dbdf07a Compare November 8, 2024 17:28
@maaikez maaikez force-pushed the feature/327-use-case-h01-reservation branch from dbdf07a to 045bdaf Compare November 8, 2024 17:44
// Function Block H: Reservations
void handle_reserve_now_request(Call<ReserveNowRequest> call);
void handle_cancel_reservation_callback(Call<CancelReservationRequest> call);
void send_reserve_now_rejected_response(const MessageId& unique_id, const std::string& status_info);
Copy link
Contributor

Choose a reason for hiding this comment

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

I see we haven't used this anywhere yet in ChargePoint but the status_info could be a string_view. You can change it if you want but it's fine either way.

}

// Check if there is a connector available for this evse id.
std::optional<ConnectorStatusEnum> status =
Copy link
Contributor

Choose a reason for hiding this comment

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

use does_connector_exist here.


bool status_found = false;
for (uint64_t i = 1; i <= number_of_evses; i++) {
std::optional<ConnectorStatusEnum> status = get_connector_status(i, request.connectorType);
Copy link
Contributor

Choose a reason for hiding this comment

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

use is_connector_available here

throw EvseOutOfRangeException(id);
}
return *this->evses.at(id - 1);
}

bool EvseManager::does_evse_exist(int32_t id) const {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The name of this function is a bit strange. In principle, evse id 0 does not exist so I added that check. But composite schedule relies on this that evse id 0 does exist. So maybe we should change the name or add an extra parameter here? @Pietfried ?

Copy link
Contributor

Choose a reason for hiding this comment

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

The fact that with smart charging profiles they (mis)use evse 0 should be covered in that part of the code I think. Now you can ask the EvseManager if evse 0 exists and it will say yes. Then please give me evse 0 and it will throw 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Exactly, that's strange isn't it?
So it's not for this pull request but shall I make a ticket maybe?

Copy link
Contributor

Choose a reason for hiding this comment

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

Well you could change this to be id > 0 && etc and then fix the issues in smart charging as well, should be a small fix. Or indeed in a different ticket if you prefer that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes I created a bug report, as the function is also called from another function and I think to be sure, we have to test smart charging if everything is still fine.

#868

return std::nullopt;
}

return conversions::string_to_connector_enum(connector_type.value());
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
return conversions::string_to_connector_enum(connector_type.value());
try {
return conversions::string_to_connector_enum(connector_type.value());
}
catch (const StringToEnumException& e) {
EVLOG_warning << "Could not convert to ConnectorEnum: " << connector_type.value();
return std::nullopt;
}

…n (needed for remote start).

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@maaikez maaikez force-pushed the feature/327-use-case-h01-reservation branch from c70ecec to 7840131 Compare November 22, 2024 15:32
@Pietfried
Copy link
Contributor

@maaikez we could also tick the Reservation functional block in the README.md as part of this PR :)

Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
Signed-off-by: Maaike Zijderveld, iolar <[email protected]>
@maaikez maaikez merged commit 173af8d into main Nov 26, 2024
8 checks passed
@maaikez maaikez deleted the feature/327-use-case-h01-reservation branch November 26, 2024 09:48
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.

Use Case H01: Reservation
3 participants