Skip to content

Commit

Permalink
Merge branch 'main' into feat/fail_on_powermeter_errors
Browse files Browse the repository at this point in the history
  • Loading branch information
florinmihut authored Dec 18, 2024
2 parents 1f08b5a + d8db948 commit 8949f46
Show file tree
Hide file tree
Showing 11 changed files with 236 additions and 125 deletions.
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ libevse-security:
# OCPP
libocpp:
git: https://github.com/EVerest/libocpp.git
git_tag: e52ac969095804144af4896af1984cedaf45a3f8
git_tag: c66383782a32827920af80314165843deed63c98
cmake_condition: "EVEREST_DEPENDENCY_ENABLED_LIBOCPP"
# Josev
Josev:
Expand Down
8 changes: 1 addition & 7 deletions modules/Auth/include/AuthHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,10 @@ class AuthHandler {

std::map<int, std::unique_ptr<EVSEContext>> evses;

std::mutex timer_mutex;
std::list<int> plug_in_queue;
std::mutex plug_in_queue_mutex;
std::mutex plug_in_mutex;
std::set<std::string> tokens_in_process;
std::mutex token_in_process_mutex;
std::condition_variable cv;
std::recursive_mutex evse_mutex;
std::mutex event_mutex;

// callbacks
std::function<void(const int evse_index, const ProvidedIdToken& provided_token,
Expand Down Expand Up @@ -268,8 +264,6 @@ class AuthHandler {
*/
int select_evse(const std::vector<int>& selected_evses);

void lock_plug_in_mutex(const std::vector<int>& evse_ids);
void unlock_plug_in_mutex(const std::vector<int>& evse_ids);
int get_latest_plugin(const std::vector<int>& evse_ids);
void notify_evse(int evse_id, const ProvidedIdToken& provided_token, const ValidationResult& validation_result);
Identifier get_identifier(const ValidationResult& validation_result, const std::string& id_token,
Expand Down
11 changes: 8 additions & 3 deletions modules/Auth/include/Connector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ struct EVSEContext {
}

EVSEContext(int evse_id, int evse_index, const std::vector<Connector>& connectors) :
evse_id(evse_id), evse_index(evse_index), transaction_active(false), connectors(connectors), plugged_in(false) {
evse_id(evse_id),
evse_index(evse_index),
transaction_active(false),
connectors(connectors),
plugged_in(false),
plug_in_timeout(false) {
}

int32_t evse_id;
Expand All @@ -77,9 +82,9 @@ struct EVSEContext {
std::optional<Identifier> identifier = std::nullopt;
std::vector<Connector> connectors;
Everest::SteadyTimer timeout_timer;
std::mutex plug_in_mutex;
std::mutex event_mutex;
bool plugged_in;
bool plug_in_timeout; // indicates no authorization received within connection_timeout. Replug is required for this
// EVSE to get authorization and start a transaction

bool is_available();
bool is_unavailable();
Expand Down
12 changes: 4 additions & 8 deletions modules/Auth/include/ReservationHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class ReservationHandler {
private: // Members
/// \brief Map of EVSE's, with EVSE id as key and the EVSE struct as value.
std::map<int, std::unique_ptr<module::EVSEContext>>& evses;
/// \brief Recursive mutex for the evse map (shared with AuthHandler).
std::recursive_mutex& evse_mutex;
/// \brief Key value store id.
const std::string kvs_store_key_id;
/// \brief Key value store for storing reservations.
Expand All @@ -35,10 +33,8 @@ class ReservationHandler {
std::map<uint32_t, types::reservation::Reservation> evse_reservations;
/// \brief All reservations not bound to a specific EVSE.
std::vector<types::reservation::Reservation> global_reservations;
/// \brief Reservation mutex, for all reservation bound locks.
mutable std::recursive_mutex reservation_mutex;
/// \brief Timer mutex, for all timer bound locks (for `reservation_id_to_reservation_timeout_timer_map`)
mutable std::recursive_mutex timer_mutex;
/// \brief event mutex, for all timer bound locks (for `reservation_id_to_reservation_timeout_timer_map`)
mutable std::recursive_mutex event_mutex;
/// \brief Map with reservations and their timer.
///
/// Every reservation has a specific end time, which is stored in this map. Key is the reservation id. When the
Expand All @@ -64,8 +60,8 @@ class ReservationHandler {
///
/// \brief Constructor.
///
ReservationHandler(std::map<int, std::unique_ptr<module::EVSEContext>>& evses, std::recursive_mutex& evse_mutex,
const std::string& id, kvsIntf* store);
ReservationHandler(std::map<int, std::unique_ptr<module::EVSEContext>>& evses, const std::string& id,
kvsIntf* store);

///
/// \brief Destructor.
Expand Down
80 changes: 27 additions & 53 deletions modules/Auth/lib/AuthHandler.cpp

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions modules/Auth/lib/Connector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ std::string connector_state_to_string(const ConnectorState& state) {
} // namespace conversions

bool EVSEContext::is_available() {
if (this->plug_in_timeout) {
return false;
}

bool occupied = false;
bool available = false;
for (const auto& connector : this->connectors) {
Expand Down
60 changes: 19 additions & 41 deletions modules/Auth/lib/ReservationHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ static types::reservation::ReservationResult
connector_state_to_reservation_result(const ConnectorState connector_state);

ReservationHandler::ReservationHandler(std::map<int, std::unique_ptr<module::EVSEContext>>& evses,
std::recursive_mutex& evse_mutex, const std::string& id, kvsIntf* store) :
evses(evses), evse_mutex(evse_mutex), kvs_store_key_id("reservation_" + id), store(store) {
const std::string& id, kvsIntf* store) :
evses(evses), kvs_store_key_id("reservation_" + id), store(store) {
// Create this worker thread and io service etc here for the timer.
this->work = boost::make_shared<boost::asio::io_service::work>(this->io_service);
this->io_service_thread = std::thread([this]() { this->io_service.run(); });
Expand All @@ -29,6 +29,7 @@ ReservationHandler::~ReservationHandler() {
}

void ReservationHandler::load_reservations() {
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
if (this->store == nullptr) {
EVLOG_info << "Can not load reservations because the store is a nullptr.";
return;
Expand Down Expand Up @@ -68,6 +69,7 @@ void ReservationHandler::load_reservations() {
types::reservation::ReservationResult
ReservationHandler::make_reservation(const std::optional<uint32_t> evse_id,
const types::reservation::Reservation& reservation) {
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
if (date::utc_clock::now() > Everest::Date::from_rfc3339(reservation.expiry_time)) {
EVLOG_info << "Rejecting reservation because expire time is in the past.";
return types::reservation::ReservationResult::Rejected;
Expand All @@ -83,8 +85,6 @@ ReservationHandler::make_reservation(const std::optional<uint32_t> evse_id,
<< reservation_cancelled.second.value() << " because a reservation with the same id was made";
}

std::unique_lock<std::recursive_mutex> lock(reservation_mutex);

if (evse_id.has_value()) {
if (this->evse_reservations.count(evse_id.value()) > 0) {
// There already is a reservation for this evse.
Expand Down Expand Up @@ -179,13 +179,12 @@ ReservationHandler::make_reservation(const std::optional<uint32_t> evse_id,

void ReservationHandler::on_connector_state_changed(const ConnectorState connector_state, const uint32_t evse_id,
const uint32_t connector_id) {
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
if (connector_state == ConnectorState::AVAILABLE) {
// Nothing to cancel.
return;
}

std::unique_lock<std::recursive_mutex> lock(reservation_mutex);
std::unique_lock<std::recursive_mutex> lock2(evse_mutex);
if (this->evses.count(static_cast<int32_t>(evse_id)) == 0) {
EVLOG_warning << "on_connector_state_changed: evse " << evse_id << " does not exist. This should not happen.";
return;
Expand Down Expand Up @@ -219,7 +218,7 @@ void ReservationHandler::on_connector_state_changed(const ConnectorState connect
}

bool ReservationHandler::is_charging_possible(const uint32_t evse_id) {
std::unique_lock<std::recursive_mutex> lock(reservation_mutex);
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
if (this->evse_reservations.count(evse_id) > 0) {
return false;
}
Expand All @@ -239,6 +238,7 @@ bool ReservationHandler::is_charging_possible(const uint32_t evse_id) {
}

bool ReservationHandler::is_evse_reserved(const uint32_t evse_id) {
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
if (this->evse_reservations.count(evse_id) > 0) {
return true;
}
Expand All @@ -249,22 +249,17 @@ bool ReservationHandler::is_evse_reserved(const uint32_t evse_id) {
std::pair<bool, std::optional<uint32_t>>
ReservationHandler::cancel_reservation(const int reservation_id, const bool execute_callback,
const types::reservation::ReservationEndReason reason) {

std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
std::pair<bool, std::optional<uint32_t>> result;

std::unique_lock<std::recursive_mutex> lock(reservation_mutex);

bool reservation_cancelled = false;

{
std::unique_lock<std::recursive_mutex> lk(this->timer_mutex);
auto reservation_id_timer_it = this->reservation_id_to_reservation_timeout_timer_map.find(reservation_id);
if (reservation_id_timer_it != this->reservation_id_to_reservation_timeout_timer_map.end()) {
reservation_id_timer_it->second->stop();
this->reservation_id_to_reservation_timeout_timer_map.erase(reservation_id_timer_it);
reservation_cancelled = true;
result.first = true;
}
auto reservation_id_timer_it = this->reservation_id_to_reservation_timeout_timer_map.find(reservation_id);
if (reservation_id_timer_it != this->reservation_id_to_reservation_timeout_timer_map.end()) {
reservation_id_timer_it->second->stop();
this->reservation_id_to_reservation_timeout_timer_map.erase(reservation_id_timer_it);
reservation_cancelled = true;
result.first = true;
}

if (!reservation_cancelled) {
Expand Down Expand Up @@ -333,6 +328,7 @@ void ReservationHandler::register_reservation_cancelled_callback(
}

void ReservationHandler::on_reservation_used(const int32_t reservation_id) {
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
const std::pair<bool, std::optional<uint32_t>> cancelled =
this->cancel_reservation(reservation_id, false, types::reservation::ReservationEndReason::UsedToStartCharging);
if (cancelled.first) {
Expand All @@ -350,12 +346,11 @@ void ReservationHandler::on_reservation_used(const int32_t reservation_id) {
std::optional<int32_t> ReservationHandler::matches_reserved_identifier(const std::string& id_token,
const std::optional<uint32_t> evse_id,
std::optional<std::string> parent_id_token) {
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
EVLOG_debug << "Matches reserved identifier for evse id " << (evse_id.has_value() ? evse_id.value() : 9999)
<< " and id token " << everest::staging::helpers::redact(id_token) << " and parent id token "
<< (parent_id_token.has_value() ? everest::staging::helpers::redact(parent_id_token.value()) : "-");

std::lock_guard<std::recursive_mutex> lock(this->reservation_mutex);

// Return true if id tokens match or parent id tokens exists and match.
if (evse_id.has_value()) {
if (this->evse_reservations.count(evse_id.value())) {
Expand Down Expand Up @@ -389,8 +384,7 @@ std::optional<int32_t> ReservationHandler::matches_reserved_identifier(const std
}

bool ReservationHandler::has_reservation_parent_id(const std::optional<uint32_t> evse_id) {
std::lock_guard<std::recursive_mutex> lock(this->reservation_mutex);

std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
if (evse_id.has_value()) {
if (this->evses.count(evse_id.value()) == 0) {
// EVSE id does not exist.
Expand All @@ -413,8 +407,8 @@ bool ReservationHandler::has_reservation_parent_id(const std::optional<uint32_t>
}

ReservationEvseStatus ReservationHandler::check_number_global_reservations_match_number_available_evses() {
std::unique_lock<std::recursive_mutex> reservation_lock(this->event_mutex);
std::set<int32_t> available_evses;
std::unique_lock<std::recursive_mutex> lock(this->evse_mutex);
// Get all evse's that are not reserved or used.
for (const auto& evse : this->evses) {
if (get_evse_connector_state_reservation_result(static_cast<uint32_t>(evse.first), this->evse_reservations) ==
Expand All @@ -425,8 +419,6 @@ ReservationEvseStatus ReservationHandler::check_number_global_reservations_match
available_evses.insert(evse.first);
}
}

std::unique_lock<std::recursive_mutex> reservation_lock(this->reservation_mutex);
if (available_evses.size() == this->global_reservations.size()) {
// There are as many evses available as 'global' reservations, so all evse's are reserved. Set all available
// evse's to reserved.
Expand Down Expand Up @@ -474,7 +466,6 @@ bool ReservationHandler::has_evse_connector_type(const std::vector<Connector>& e

bool ReservationHandler::does_evse_connector_type_exist(
const types::evse_manager::ConnectorTypeEnum connector_type) const {
std::unique_lock<std::recursive_mutex> lock(evse_mutex);
for (const auto& [evse_id, evse] : evses) {
if (has_evse_connector_type(evse->connectors, connector_type)) {
return true;
Expand All @@ -493,24 +484,19 @@ types::reservation::ReservationResult ReservationHandler::get_evse_connector_sta
}

// Check if evse is available.
std::unique_lock<std::recursive_mutex> lock(evse_mutex);
if (evses[evse_id]->plugged_in) {
return connector_state_to_reservation_result(ConnectorState::OCCUPIED);
}

// If one connector is occupied, then the other connector can also not be used (one connector of an evse can be
// used at the same time).
std::unique_lock<std::mutex> lock_evse(evses[evse_id]->event_mutex);
for (const auto& connector : evses[evse_id]->connectors) {
if (connector.get_state() == ConnectorState::OCCUPIED ||
connector.get_state() == ConnectorState::FAULTED_OCCUPIED) {
return connector_state_to_reservation_result(connector.get_state());
}
}

lock.unlock();
lock_evse.unlock();

// If evse is reserved, it is not available.
if (evse_specific_reservations.count(evse_id) > 0) {
return types::reservation::ReservationResult::Occupied;
Expand All @@ -521,8 +507,6 @@ types::reservation::ReservationResult ReservationHandler::get_evse_connector_sta

types::reservation::ReservationResult ReservationHandler::get_connector_availability_reservation_result(
const uint32_t evse_id, const types::evse_manager::ConnectorTypeEnum connector_type) {
std::unique_lock<std::recursive_mutex> lock(evse_mutex);
std::unique_lock<std::mutex> lock_evse(evses[evse_id]->event_mutex);
if (evses.count(evse_id) == 0) {
EVLOG_warning << "Request if connector is available for evse id " << evse_id
<< ", but evse id does not exist. This should not happen.";
Expand Down Expand Up @@ -576,7 +560,6 @@ bool ReservationHandler::can_virtual_car_arrive(

bool is_possible = false;

std::unique_lock<std::recursive_mutex> lock(evse_mutex);
for (const auto& [evse_id, evse] : evses) {
// Check if there is a car already at this evse id.
if (std::find(used_evse_ids.begin(), used_evse_ids.end(), evse_id) != used_evse_ids.end()) {
Expand Down Expand Up @@ -635,7 +618,6 @@ bool ReservationHandler::is_reservation_possible(

const std::vector<std::vector<types::evse_manager::ConnectorTypeEnum>> orders = get_all_possible_orders(types);

std::unique_lock<std::recursive_mutex> lock(evse_mutex);
for (const auto& o : orders) {
if (!this->can_virtual_car_arrive({}, o, evse_specific_reservations)) {
return false;
Expand All @@ -647,7 +629,7 @@ bool ReservationHandler::is_reservation_possible(

void ReservationHandler::set_reservation_timer(const types::reservation::Reservation& reservation,
const std::optional<uint32_t> evse_id) {
std::lock_guard<std::recursive_mutex> lk(this->timer_mutex);
std::lock_guard<std::recursive_mutex> lk(this->event_mutex);
this->reservation_id_to_reservation_timeout_timer_map[reservation.reservation_id] =
std::make_unique<Everest::SteadyTimer>(&this->io_service);

Expand All @@ -668,7 +650,6 @@ void ReservationHandler::set_reservation_timer(const types::reservation::Reserva

std::vector<EVSEContext*> ReservationHandler::get_all_evses_with_connector_type(
const types::evse_manager::ConnectorTypeEnum connector_type) const {
std::unique_lock<std::recursive_mutex> lock(evse_mutex);
std::vector<EVSEContext*> result;
for (const auto& evse : this->evses) {
if (this->has_evse_connector_type(evse.second->connectors, connector_type)) {
Expand Down Expand Up @@ -711,7 +692,6 @@ types::reservation::ReservationResult ReservationHandler::get_reservation_evse_c

bool found_state = false;

std::unique_lock<std::recursive_mutex> lock(evse_mutex);
ConnectorState state = ConnectorState::UNAVAILABLE;

for (const auto& [evse_id, evse] : evses) {
Expand All @@ -733,7 +713,6 @@ types::reservation::ReservationResult ReservationHandler::get_reservation_evse_c

// Get all evse's with this specific connector type and check the connectors availability states.
for (const auto& evse : evses_with_connector_type) {
std::unique_lock<std::mutex> lock(evse->event_mutex);
for (const auto& connector : evse->connectors) {
if (connector.type != connector_type &&
connector.type != types::evse_manager::ConnectorTypeEnum::Unknown &&
Expand All @@ -752,7 +731,6 @@ types::reservation::ReservationResult ReservationHandler::get_reservation_evse_c
}

void ReservationHandler::check_reservations_and_cancel_if_not_possible() {
std::unique_lock<std::recursive_mutex> lock(reservation_mutex);

std::vector<int32_t> reservations_to_cancel;
std::map<uint32_t, types::reservation::Reservation> evse_specific_reservations;
Expand Down
Loading

0 comments on commit 8949f46

Please sign in to comment.