From ede5b2d4f5268e9567601ef7ed5840e99cd2d581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piet=20G=C3=B6mpel?= <37657534+Pietfried@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:38:23 +0100 Subject: [PATCH] After a plug in timeout, a replug is required in order to get authorization and start a transaction at this EVSE. The Auth module now marks an EVSE where a plug in time out occured in order to not select it for a later authorization request (#976) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Piet Gömpel --- modules/Auth/include/Connector.hpp | 9 ++++++++- modules/Auth/lib/AuthHandler.cpp | 5 +++-- modules/Auth/lib/Connector.cpp | 4 ++++ modules/Auth/tests/auth_tests.cpp | 26 ++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 3 deletions(-) diff --git a/modules/Auth/include/Connector.hpp b/modules/Auth/include/Connector.hpp index 907520a09..f53bff281 100644 --- a/modules/Auth/include/Connector.hpp +++ b/modules/Auth/include/Connector.hpp @@ -66,7 +66,12 @@ struct EVSEContext { } EVSEContext(int evse_id, int evse_index, const std::vector& 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; @@ -78,6 +83,8 @@ struct EVSEContext { std::vector connectors; Everest::SteadyTimer timeout_timer; 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(); diff --git a/modules/Auth/lib/AuthHandler.cpp b/modules/Auth/lib/AuthHandler.cpp index 39a9cca32..bffd1f1e6 100644 --- a/modules/Auth/lib/AuthHandler.cpp +++ b/modules/Auth/lib/AuthHandler.cpp @@ -657,11 +657,11 @@ void AuthHandler::handle_session_event(const int evse_id, const SessionEvent& ev [this, evse_id]() { std::lock_guard lk(this->event_mutex); - EVLOG_info << "Plug In timeout for evse#" << evse_id; + EVLOG_info << "Plug In timeout for evse#" << evse_id << ". Replug required for this EVSE"; this->withdraw_authorization_callback(this->evses.at(evse_id)->evse_index); this->plug_in_queue.remove_if([evse_id](int value) { return value == evse_id; }); - this->evses.at(evse_id)->plugged_in = false; + this->evses.at(evse_id)->plug_in_timeout = true; }, std::chrono::seconds(this->connection_timeout)); } @@ -680,6 +680,7 @@ void AuthHandler::handle_session_event(const int evse_id, const SessionEvent& ev break; case SessionEventEnum::SessionFinished: { this->evses.at(evse_id)->plugged_in = false; + this->evses.at(evse_id)->plug_in_timeout = false; this->evses.at(evse_id)->identifier.reset(); this->submit_event_for_connector(evse_id, connector_id, ConnectorEvent::SESSION_FINISHED); this->evses.at(evse_id)->timeout_timer.stop(); diff --git a/modules/Auth/lib/Connector.cpp b/modules/Auth/lib/Connector.cpp index 2bceff9f0..d3c841fb8 100644 --- a/modules/Auth/lib/Connector.cpp +++ b/modules/Auth/lib/Connector.cpp @@ -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) { diff --git a/modules/Auth/tests/auth_tests.cpp b/modules/Auth/tests/auth_tests.cpp index 90bcae086..d4d7c0502 100644 --- a/modules/Auth/tests/auth_tests.cpp +++ b/modules/Auth/tests/auth_tests.cpp @@ -1541,4 +1541,30 @@ TEST_F(AuthTest, test_token_timed_out) { std::this_thread::sleep_for(std::chrono::seconds(CONNECTION_TIMEOUT + 1)); } +/// \brief Test that in case of a plug in timeout, no authorization is given to the EVSE afterwards +TEST_F(AuthTest, test_plug_in_time_out) { + const SessionEvent session_event = get_session_started_event(types::evse_manager::StartSessionReason::EVConnected); + this->auth_handler->handle_session_event(1, session_event); + + std::vector connectors{1}; + ProvidedIdToken provided_token = get_provided_token(VALID_TOKEN_1, connectors); + + std::this_thread::sleep_for(std::chrono::seconds(CONNECTION_TIMEOUT)); + + EXPECT_CALL(mock_publish_token_validation_status_callback, + Call(Field(&ProvidedIdToken::id_token, provided_token.id_token), TokenValidationStatus::Processing)); + EXPECT_CALL(mock_publish_token_validation_status_callback, + Call(Field(&ProvidedIdToken::id_token, provided_token.id_token), TokenValidationStatus::Rejected)); + + // no connector should be available since the plug-in event has timed out + TokenHandlingResult result; + std::thread t1([this, provided_token, &result]() { result = this->auth_handler->on_token(provided_token); }); + t1.join(); + + ASSERT_TRUE(result == TokenHandlingResult::NO_CONNECTOR_AVAILABLE); + + ASSERT_FALSE(this->auth_receiver->get_authorization(0)); + ASSERT_FALSE(this->auth_receiver->get_authorization(1)); +} + } // namespace module