Add extracted tools: CitrineOS, OpenOCPP, ShapeShifter
- CitrineOS core extracted (CSMS OCPP 2.0.1) - OpenOCPP extracted (firmware OCPP 1.6J/2.0.1) - ShapeShifter library installed (pip install -e) - ShapeShifter specification extracted - EVerest extracted TODO updated with progress
This commit is contained in:
235
tools/EVerest-main/modules/EVSE/Auth/Auth.cpp
Normal file
235
tools/EVerest-main/modules/EVSE/Auth/Auth.cpp
Normal file
@@ -0,0 +1,235 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// Copyright Pionix GmbH and Contributors to EVerest
|
||||
#include <everest/helpers/helpers.hpp>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "Auth.hpp"
|
||||
#include <everest/logging.hpp>
|
||||
|
||||
namespace module {
|
||||
|
||||
void Auth::init() {
|
||||
invoke_init(*p_main);
|
||||
invoke_init(*p_reservation);
|
||||
|
||||
this->auth_handler = std::make_unique<AuthHandler>(
|
||||
string_to_selection_algorithm(this->config.selection_algorithm), this->config.connection_timeout,
|
||||
this->config.plug_in_timeout_enabled, this->config.prioritize_authorization_over_stopping_transaction,
|
||||
this->config.ignore_connector_faults, this->info.id,
|
||||
(!this->r_kvs.empty() ? this->r_kvs.at(0).get() : nullptr));
|
||||
|
||||
for (const auto& token_provider : this->r_token_provider) {
|
||||
token_provider->subscribe_provided_token([this](ProvidedIdToken provided_token) {
|
||||
{
|
||||
auto state = this->event_state.handle();
|
||||
if (!state->started) {
|
||||
EVLOG_warning << "Auth not fully initialized. Discarding provided token";
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::thread t([this, provided_token]() { this->auth_handler->on_token(provided_token); });
|
||||
t.detach();
|
||||
});
|
||||
}
|
||||
for (const auto& token_validator : this->r_token_validator) {
|
||||
token_validator->subscribe_validate_result_update([this](ValidationResultUpdate validation_result_update) {
|
||||
{
|
||||
auto state = this->event_state.handle();
|
||||
if (!state->started) {
|
||||
EVLOG_warning << "Auth not fully initialized. Discarding validation result update";
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->auth_handler->handle_token_validation_result_update(validation_result_update);
|
||||
});
|
||||
}
|
||||
|
||||
// Subscribe to session events and errors in init() so we don't miss any events
|
||||
// Events received before ready() are queued.
|
||||
int32_t evse_index = 0;
|
||||
for (const auto& evse_manager : this->r_evse_manager) {
|
||||
const int32_t evse_idx = evse_index;
|
||||
|
||||
evse_manager->subscribe_session_event([this, evse_idx](SessionEvent session_event) {
|
||||
{
|
||||
auto state = this->event_state.handle();
|
||||
if (!state->started) {
|
||||
EVLOG_debug << "Auth not fully initialized, but received a session event on evse_index: "
|
||||
<< evse_idx << " that will be queued up: " << session_event.event;
|
||||
state->event_queue.emplace(evse_idx, session_event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->auth_handler->handle_session_event(this->auth_handler->get_evse_id_by_index(evse_idx), session_event);
|
||||
});
|
||||
|
||||
evse_manager->subscribe_error(
|
||||
"evse_manager/Inoperative",
|
||||
[this, evse_idx](const Everest::error::Error& error) {
|
||||
{
|
||||
auto state = this->event_state.handle();
|
||||
if (!state->started) {
|
||||
EVLOG_debug << "Auth not fully initialized, queuing permanent fault raised for evse_index: "
|
||||
<< evse_idx;
|
||||
state->event_queue.emplace(evse_idx, PermanentFaultRaised{1});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->auth_handler->handle_permanent_fault_raised(this->auth_handler->get_evse_id_by_index(evse_idx),
|
||||
1);
|
||||
},
|
||||
[this, evse_idx](const Everest::error::Error& error) {
|
||||
{
|
||||
auto state = this->event_state.handle();
|
||||
if (!state->started) {
|
||||
EVLOG_debug << "Auth not fully initialized, queuing permanent fault cleared for evse_index: "
|
||||
<< evse_idx;
|
||||
state->event_queue.emplace(evse_idx, PermanentFaultCleared{1});
|
||||
return;
|
||||
}
|
||||
}
|
||||
this->auth_handler->handle_permanent_fault_cleared(this->auth_handler->get_evse_id_by_index(evse_idx),
|
||||
1);
|
||||
});
|
||||
|
||||
evse_index++;
|
||||
}
|
||||
}
|
||||
|
||||
void Auth::ready() {
|
||||
invoke_ready(*p_main);
|
||||
invoke_ready(*p_reservation);
|
||||
|
||||
int32_t evse_index = 0;
|
||||
for (const auto& evse_manager : this->r_evse_manager) {
|
||||
const int32_t evse_id = evse_manager->call_get_evse().id;
|
||||
std::vector<Connector> connectors;
|
||||
for (const auto& connector : evse_manager->call_get_evse().connectors) {
|
||||
connectors.push_back(
|
||||
Connector(connector.id, connector.type.value_or(types::evse_manager::ConnectorTypeEnum::Unknown)));
|
||||
}
|
||||
|
||||
this->auth_handler->init_evse(evse_id, evse_index, connectors);
|
||||
|
||||
evse_index++;
|
||||
}
|
||||
|
||||
this->auth_handler->register_publish_token_validation_status_callback(
|
||||
[this](const ProvidedIdToken& token, TokenValidationStatus status,
|
||||
const std::vector<MessageContent>& tariff_messages) {
|
||||
this->p_main->publish_token_validation_status({token, status, tariff_messages});
|
||||
});
|
||||
|
||||
this->auth_handler->register_notify_evse_callback(
|
||||
[this](const int evse_index, const ProvidedIdToken& provided_token, const ValidationResult& validation_result) {
|
||||
this->r_evse_manager.at(evse_index)->call_authorize_response(provided_token, validation_result);
|
||||
});
|
||||
this->auth_handler->register_withdraw_authorization_callback(
|
||||
[this](const int32_t evse_index) { this->r_evse_manager.at(evse_index)->call_withdraw_authorization(); });
|
||||
this->auth_handler->register_validate_token_callback([this](const ProvidedIdToken& provided_token) {
|
||||
std::vector<ValidationResult> validation_results;
|
||||
for (const auto& token_validator : this->r_token_validator) {
|
||||
try {
|
||||
const auto result = token_validator->call_validate_token(provided_token);
|
||||
validation_results.push_back(result);
|
||||
// TODO: This is very broad catch, make it more narrow when the everest-framework error handling will be
|
||||
// established
|
||||
} catch (const std::exception& e) {
|
||||
EVLOG_warning << "Exception during validating token: " << e.what();
|
||||
ValidationResult validation_result;
|
||||
validation_result.authorization_status = AuthorizationStatus::Unknown;
|
||||
validation_results.push_back(validation_result);
|
||||
}
|
||||
}
|
||||
return validation_results;
|
||||
});
|
||||
this->auth_handler->register_stop_transaction_callback(
|
||||
[this](const int32_t evse_index, const StopTransactionRequest& request) {
|
||||
this->r_evse_manager.at(evse_index)->call_stop_transaction(request);
|
||||
});
|
||||
this->auth_handler->register_reserved_callback(
|
||||
[this](const std::optional<int32_t> evse_id, const int32_t& reservation_id) {
|
||||
// Only call the evse manager to store the reservation if it is done for a specific evse.
|
||||
if (evse_id.has_value()) {
|
||||
EVLOG_info << "Call reserved callback for evse id " << evse_id.value();
|
||||
|
||||
if (!this->r_evse_manager.at(evse_id.value() - 1)->call_reserve(reservation_id)) {
|
||||
EVLOG_warning << "EVSE manager does not allow placing a reservation for evse id " << evse_id.value()
|
||||
<< ": cancelling reservation.";
|
||||
this->auth_handler->handle_cancel_reservation(reservation_id);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ReservationUpdateStatus status;
|
||||
status.reservation_id = reservation_id;
|
||||
status.reservation_status = Reservation_status::Placed;
|
||||
this->p_reservation->publish_reservation_update(status);
|
||||
return true;
|
||||
});
|
||||
this->auth_handler->register_reservation_cancelled_callback(
|
||||
[this](const std::optional<int32_t> evse_id, const int32_t reservation_id, const ReservationEndReason reason,
|
||||
const bool send_reservation_update) {
|
||||
// Only call the evse manager to cancel the reservation if it was for a specific evse
|
||||
if (evse_id.has_value() && evse_id.value() > 0) {
|
||||
EVLOG_debug << "Call evse manager to cancel the reservation with evse id " << evse_id.value();
|
||||
this->r_evse_manager.at(evse_id.value() - 1)->call_cancel_reservation();
|
||||
}
|
||||
|
||||
if (send_reservation_update) {
|
||||
ReservationUpdateStatus status;
|
||||
status.reservation_id = reservation_id;
|
||||
if (reason == ReservationEndReason::Expired) {
|
||||
status.reservation_status = Reservation_status::Expired;
|
||||
} else if (reason == ReservationEndReason::Cancelled) {
|
||||
status.reservation_status = Reservation_status::Removed;
|
||||
} else {
|
||||
// On reservation used: do not publish a reservation update!!
|
||||
return;
|
||||
}
|
||||
this->p_reservation->publish_reservation_update(status);
|
||||
}
|
||||
});
|
||||
|
||||
// Process any events that were queued during init before we were ready
|
||||
{
|
||||
auto state = this->event_state.handle();
|
||||
while (!state->event_queue.empty()) {
|
||||
auto queued_event = state->event_queue.front();
|
||||
state->event_queue.pop();
|
||||
const int32_t evse_id = this->auth_handler->get_evse_id_by_index(queued_event.evse_index);
|
||||
if (std::holds_alternative<SessionEvent>(queued_event.data)) {
|
||||
const auto& session_event = std::get<SessionEvent>(queued_event.data);
|
||||
EVLOG_debug << "Processing queued session event for evse_id: " << evse_id
|
||||
<< ", event: " << session_event.event;
|
||||
this->auth_handler->handle_session_event(evse_id, session_event);
|
||||
} else if (std::holds_alternative<PermanentFaultRaised>(queued_event.data)) {
|
||||
const auto& fault = std::get<PermanentFaultRaised>(queued_event.data);
|
||||
EVLOG_debug << "Processing queued permanent fault raised for evse_id: " << evse_id;
|
||||
this->auth_handler->handle_permanent_fault_raised(evse_id, fault.connector_id);
|
||||
} else if (std::holds_alternative<PermanentFaultCleared>(queued_event.data)) {
|
||||
const auto& fault = std::get<PermanentFaultCleared>(queued_event.data);
|
||||
EVLOG_debug << "Processing queued permanent fault cleared for evse_id: " << evse_id;
|
||||
this->auth_handler->handle_permanent_fault_cleared(evse_id, fault.connector_id);
|
||||
}
|
||||
}
|
||||
state->started = true;
|
||||
}
|
||||
|
||||
this->auth_handler->initialize();
|
||||
}
|
||||
|
||||
void Auth::set_connection_timeout(int& connection_timeout) {
|
||||
this->auth_handler->set_connection_timeout(connection_timeout);
|
||||
}
|
||||
|
||||
void Auth::set_master_pass_group_id(const std::string& master_pass_group_id) {
|
||||
this->auth_handler->set_master_pass_group_id(master_pass_group_id);
|
||||
}
|
||||
|
||||
WithdrawAuthorizationResult Auth::handle_withdraw_authorization(const WithdrawAuthorizationRequest& request) {
|
||||
return this->auth_handler->handle_withdraw_authorization(request);
|
||||
}
|
||||
|
||||
} // namespace module
|
||||
Reference in New Issue
Block a user