From 690a85528be3e3537a42ef07b07fbb6c465818da Mon Sep 17 00:00:00 2001 From: Habbus <44402940+Habbus@users.noreply.github.com> Date: Wed, 18 Oct 2023 16:56:39 +0200 Subject: [PATCH 1/6] Fix cancelreservation by passing connectorpointer by value instead of a reference to a temporary --- src/chargepoint/reservation/ReservationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chargepoint/reservation/ReservationManager.cpp b/src/chargepoint/reservation/ReservationManager.cpp index 9d730677..ac80ff51 100644 --- a/src/chargepoint/reservation/ReservationManager.cpp +++ b/src/chargepoint/reservation/ReservationManager.cpp @@ -296,7 +296,7 @@ bool ReservationManager::handleMessage(const ocpp::messages::CancelReservationRe if ((connector->status == ChargePointStatus::Reserved) && (connector->reservation_id == request.reservationId)) { // Cancel reservation - m_worker_pool.run([this, &connector] { endReservation(connector->id, true); }); + m_worker_pool.run([this, connector] { endReservation(connector->id, true); }); // Prepare response response.status = CancelReservationStatus::Accepted; From a0b0d6c11bd28e13dc05f09732477ca8136b6dc3 Mon Sep 17 00:00:00 2001 From: Habbus <44402940+Habbus@users.noreply.github.com> Date: Wed, 18 Oct 2023 18:22:39 +0200 Subject: [PATCH 2/6] Update src/chargepoint/reservation/ReservationManager.cpp Only capture the connector_id itself instead of a pointer to the complete connector struct Co-authored-by: c-jimenez <18682655+c-jimenez@users.noreply.github.com> --- src/chargepoint/reservation/ReservationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chargepoint/reservation/ReservationManager.cpp b/src/chargepoint/reservation/ReservationManager.cpp index ac80ff51..c6108cc4 100644 --- a/src/chargepoint/reservation/ReservationManager.cpp +++ b/src/chargepoint/reservation/ReservationManager.cpp @@ -296,7 +296,7 @@ bool ReservationManager::handleMessage(const ocpp::messages::CancelReservationRe if ((connector->status == ChargePointStatus::Reserved) && (connector->reservation_id == request.reservationId)) { // Cancel reservation - m_worker_pool.run([this, connector] { endReservation(connector->id, true); }); + m_worker_pool.run([this, connector_id = connector->id] { endReservation(connector_id, true); }); // Prepare response response.status = CancelReservationStatus::Accepted; From 20996481953628f87a37c28bc5ff9034de604a84 Mon Sep 17 00:00:00 2001 From: c-jimenez <18682655+c-jimenez@users.noreply.github.com> Date: Sat, 11 Nov 2023 10:52:09 +0100 Subject: [PATCH 3/6] [examples] Fix segfault on disconnect in central system examples --- .../DefaultCentralSystemEventsHandler.cpp | 38 ++++++++++++++++--- .../DefaultCentralSystemEventsHandler.h | 34 +++++++++++++---- examples/iso15118_centralsystem/main.cpp | 10 ++--- examples/quick_start_centralsystem/main.cpp | 3 +- 4 files changed, 65 insertions(+), 20 deletions(-) diff --git a/examples/common/DefaultCentralSystemEventsHandler.cpp b/examples/common/DefaultCentralSystemEventsHandler.cpp index 4b5d2210..ef2bd71e 100644 --- a/examples/common/DefaultCentralSystemEventsHandler.cpp +++ b/examples/common/DefaultCentralSystemEventsHandler.cpp @@ -45,7 +45,8 @@ using namespace ocpp::x509; DefaultCentralSystemEventsHandler::DefaultCentralSystemEventsHandler(std::filesystem::path iso_v2g_root_ca, std::filesystem::path iso_mo_root_ca, bool set_pending_status) - : m_iso_v2g_root_ca(iso_v2g_root_ca), + : m_chargepoints_mutex(), + m_iso_v2g_root_ca(iso_v2g_root_ca), m_iso_mo_root_ca(iso_mo_root_ca), m_set_pending_status(set_pending_status), m_chargepoints(), @@ -83,6 +84,9 @@ bool DefaultCentralSystemEventsHandler::checkCredentials(const std::string& char void DefaultCentralSystemEventsHandler::chargePointConnected(std::shared_ptr chargepoint) { cout << "Charge point [" << chargepoint->identifier() << "] connected" << endl; + + std::lock_guard lock(m_chargepoints_mutex); + auto iter_chargepoint = m_chargepoints.find(chargepoint->identifier()); if (iter_chargepoint == m_chargepoints.end()) { @@ -103,6 +107,8 @@ void DefaultCentralSystemEventsHandler::removeChargePoint(const std::string& ide [this, identifier = identifier] { std::this_thread::sleep_for(std::chrono::milliseconds(50)); + + std::lock_guard lock(m_chargepoints_mutex); m_chargepoints.erase(identifier); m_pending_chargepoints.erase(identifier); m_accepted_chargepoints.erase(identifier); @@ -110,6 +116,29 @@ void DefaultCentralSystemEventsHandler::removeChargePoint(const std::string& ide t.detach(); } +/** @brief Indicate if a charge point must be accepted */ +bool DefaultCentralSystemEventsHandler::isAcceptedChargePoint(const std::string& identifier) +{ + std::lock_guard lock(m_chargepoints_mutex); + return (m_accepted_chargepoints.find(identifier) != m_accepted_chargepoints.end()); +} + +/** @brief Add a charge point to the pending list */ +void DefaultCentralSystemEventsHandler::addPendingChargePoint( + std::shared_ptr chargepoint) +{ + std::lock_guard lock(m_chargepoints_mutex); + m_pending_chargepoints[chargepoint->identifier()] = chargepoint; +} + +/** @brief Add a charge point to the accepted list */ +void DefaultCentralSystemEventsHandler::addAcceptedChargePoint( + std::shared_ptr chargepoint) +{ + std::lock_guard lock(m_chargepoints_mutex); + m_accepted_chargepoints[chargepoint->identifier()] = chargepoint; +} + /** @brief Constructor */ DefaultCentralSystemEventsHandler::ChargePointRequestHandler::ChargePointRequestHandler( DefaultCentralSystemEventsHandler& event_handler, std::shared_ptr& chargepoint) @@ -170,12 +199,9 @@ ocpp::types::RegistrationStatus DefaultCentralSystemEventsHandler::ChargePointRe ocpp::types::RegistrationStatus ret = RegistrationStatus::Accepted; if (m_event_handler.setPendingEnabled()) { - auto accepted_chargepoint = m_event_handler.acceptedChargePoints(); - auto iter_accepted = accepted_chargepoint.find(m_chargepoint->identifier()); - if (iter_accepted == accepted_chargepoint.end()) + if (!m_event_handler.isAcceptedChargePoint(m_chargepoint->identifier())) { - m_event_handler.pendingChargePoints()[m_chargepoint->identifier()] = m_chargepoint; - + m_event_handler.addPendingChargePoint(m_chargepoint); ret = RegistrationStatus::Pending; } } diff --git a/examples/common/DefaultCentralSystemEventsHandler.h b/examples/common/DefaultCentralSystemEventsHandler.h index 7e86c02b..e0eccea7 100644 --- a/examples/common/DefaultCentralSystemEventsHandler.h +++ b/examples/common/DefaultCentralSystemEventsHandler.h @@ -30,6 +30,7 @@ SOFTWARE. #include #include +#include /** @brief Default central system event handlers implementation for the examples */ class DefaultCentralSystemEventsHandler : public ocpp::centralsystem::ICentralSystemEventsHandler @@ -237,19 +238,25 @@ class DefaultCentralSystemEventsHandler : public ocpp::centralsystem::ICentralSy std::string m_generated_certificate; }; - /** @brief Get the list of the connected charge points */ - std::map>& chargePoints() { return m_chargepoints; } + /** @brief Get the number connected charge points */ + size_t chargePointsCount() + { + std::lock_guard lock(m_chargepoints_mutex); + return m_chargepoints.size(); + } - /** @brief Get the list of the pending charge points */ - std::map>& pendingChargePoints() + /** @brief Get the list of the connected charge points */ + std::map> chargePoints() { - return m_pending_chargepoints; + std::lock_guard lock(m_chargepoints_mutex); + return m_chargepoints; } - /** @brief Get the list of the accepted charge points */ - std::map>& acceptedChargePoints() + /** @brief Get the list of the pending charge points */ + std::map> pendingChargePoints() { - return m_accepted_chargepoints; + std::lock_guard lock(m_chargepoints_mutex); + return m_pending_chargepoints; } /** @brief Path to the V2G root CA */ @@ -263,7 +270,18 @@ class DefaultCentralSystemEventsHandler : public ocpp::centralsystem::ICentralSy /** @brief Remove a charge point from the connected charge points */ void removeChargePoint(const std::string& identifier); + /** @brief Indicate if a charge point must be accepted */ + bool isAcceptedChargePoint(const std::string& identifier); + + /** @brief Add a charge point to the pending list */ + void addPendingChargePoint(std::shared_ptr chargepoint); + + /** @brief Add a charge point to the accepted list */ + void addAcceptedChargePoint(std::shared_ptr chargepoint); + protected: + /** @brief Mutex for charge point list */ + std::mutex m_chargepoints_mutex; /** @brief Path to the V2G root CA */ std::filesystem::path m_iso_v2g_root_ca; /** @brief Path to the MO root CA */ diff --git a/examples/iso15118_centralsystem/main.cpp b/examples/iso15118_centralsystem/main.cpp index c0ea294e..e22761e1 100644 --- a/examples/iso15118_centralsystem/main.cpp +++ b/examples/iso15118_centralsystem/main.cpp @@ -148,11 +148,11 @@ int main(int argc, char* argv[]) while (true) { // For each pending charge point - for (auto& iter_chargepoint : event_handler.pendingChargePoints()) + auto pending_chargepoints = event_handler.pendingChargePoints(); + for (auto& iter_chargepoint : pending_chargepoints) { - auto chargepoint = iter_chargepoint.second; - auto iter_accepted = event_handler.acceptedChargePoints().find(chargepoint->identifier()); - if (iter_accepted == event_handler.acceptedChargePoints().end()) + auto chargepoint = iter_chargepoint.second; + if (!event_handler.isAcceptedChargePoint(chargepoint->identifier())) { std::cout << "---------------------------------------------" << std::endl; std::cout << "Pending Charge point : " << chargepoint->identifier() << std::endl; @@ -239,7 +239,7 @@ int main(int argc, char* argv[]) } // Accept charge point - event_handler.acceptedChargePoints()[chargepoint->identifier()] = chargepoint; + event_handler.addAcceptedChargePoint(chargepoint); // Trigger a boot notification to force it to update its registration status chargepoint->triggerMessage(MessageTrigger::BootNotification, Optional()); diff --git a/examples/quick_start_centralsystem/main.cpp b/examples/quick_start_centralsystem/main.cpp index b1cdcbb0..1ffd1525 100644 --- a/examples/quick_start_centralsystem/main.cpp +++ b/examples/quick_start_centralsystem/main.cpp @@ -118,7 +118,8 @@ int main(int argc, char* argv[]) std::this_thread::sleep_for(std::chrono::seconds(1)); // For each connected charge point - for (auto& iter_chargepoint : event_handler.chargePoints()) + auto connected_chargepoints = event_handler.chargePoints(); + for (auto& iter_chargepoint : connected_chargepoints) { { auto chargepoint = iter_chargepoint.second->proxy(); From 094bf82d226ce73fecfe2da21f0dae281ec7d026 Mon Sep 17 00:00:00 2001 From: Habbus <44402940+Habbus@users.noreply.github.com> Date: Mon, 13 Nov 2023 10:45:07 +0100 Subject: [PATCH 4/6] Update TransactionManager.cpp, reject connectorid 0 on remotestart --- src/chargepoint/transaction/TransactionManager.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/chargepoint/transaction/TransactionManager.cpp b/src/chargepoint/transaction/TransactionManager.cpp index a4e662e8..7975bea2 100644 --- a/src/chargepoint/transaction/TransactionManager.cpp +++ b/src/chargepoint/transaction/TransactionManager.cpp @@ -299,7 +299,7 @@ bool TransactionManager::handleMessage(const ocpp::messages::RemoteStartTransact } } } - else + else if (!request.connectorId.isSet()) { // The user application will determine which connector to use authorized = m_events_handler.remoteStartTransactionRequested(Connectors::CONNECTOR_ID_CHARGE_POINT, request.idTag.str()); @@ -309,6 +309,12 @@ bool TransactionManager::handleMessage(const ocpp::messages::RemoteStartTransact authorized = m_smart_charging_manager.installTxProfile(Connectors::CONNECTOR_ID_CHARGE_POINT, request.chargingProfile); } } + else + { + // Connector id is set but equal to CONNECTOR_ID_CHARGE_POINT + // This is not allowed by the ocpp1.6 standard + authorized = false; + } // Response if (authorized) From 87c36151f35c07e4b7a817e11ae8d85c62190548 Mon Sep 17 00:00:00 2001 From: c-jimenez <18682655+c-jimenez@users.noreply.github.com> Date: Sat, 11 Nov 2023 11:09:06 +0100 Subject: [PATCH 5/6] =?UTF-8?q?[cmake]=C2=A0Add=20optionto=20no=20build=20?= =?UTF-8?q?libwebocket=20along=20Open=20OCPP=20library=20and=20use=20the?= =?UTF-8?q?=20one=20provided=20by=20the=20compiler=20SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3rdparty/CMakeLists.txt | 33 ++++++++++++++++++--------------- CMakeLists.txt | 6 ++++++ CMakeLists_Options.txt | 3 +++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index d3e66ff9..8624745a 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -14,19 +14,22 @@ target_include_directories(doctest INTERFACE doctest/doctest) # SQLite 3 add_subdirectory(sqlite3) -# Use default flags for the libwebsockets library -if (NOT MSVC) -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT} -O0 -g3 -ggdb3") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} -O0 -g3 -ggdb3") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT} -O2 -DNDEBUG") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT} -O2 -DNDEBUG") -else() -set(DISABLED_WARNING_LWS "/WX- /wd4191 /wd4996") -set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT} ${DISABLED_WARNING_LWS}") -set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} ${DISABLED_WARNING_LWS}") -set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT} ${DISABLED_WARNING_LWS}") -set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT} ${DISABLED_WARNING_LWS}") -endif() +# libwebsockets +if(${BUILD_LWS_LIBRARY}) + # Use default flags for the libwebsockets library + if (NOT MSVC) + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT} -O0 -g3 -ggdb3") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} -O0 -g3 -ggdb3") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT} -O2 -DNDEBUG") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT} -O2 -DNDEBUG") + else() + set(DISABLED_WARNING_LWS "/WX- /wd4191 /wd4996") + set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG_INIT} ${DISABLED_WARNING_LWS}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG_INIT} ${DISABLED_WARNING_LWS}") + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE_INIT} ${DISABLED_WARNING_LWS}") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE_INIT} ${DISABLED_WARNING_LWS}") + endif() -set(LWS_WITH_NETLINK OFF) -add_subdirectory(libwebsockets) + set(LWS_WITH_NETLINK OFF) + add_subdirectory(libwebsockets) +endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index d60a8350..e2ab8c62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,12 @@ add_subdirectory(3rdparty) # OpenSSL is mandatory find_package(OpenSSL REQUIRED COMPONENTS SSL Crypto) +# libwesockets is mandatory if not built along the Open OCPP library +if(NOT ${BUILD_LWS_LIBRARY}) + find_package(PkgConfig) + pkg_check_modules(LIB_WEBSOCKETS REQUIRED libwebsockets) +endif() + # Tests if(${BUILD_UNIT_TESTS}) enable_testing() diff --git a/CMakeLists_Options.txt b/CMakeLists_Options.txt index 4675f0b5..5bfa5a3d 100644 --- a/CMakeLists_Options.txt +++ b/CMakeLists_Options.txt @@ -22,3 +22,6 @@ option(BUILD_UNIT_TESTS "Build unit tests" ON) # Examples option(BUILD_EXAMPLES "Build examples" ON) + +# Build the libwebsocket library along with the Open OCPP library +option(BUILD_LWS_LIBRARY "Build libwebsocket library" ON) \ No newline at end of file From 62c8a06c8bdd81f42e16ca576ea412271ce3c473 Mon Sep 17 00:00:00 2001 From: c-jimenez <18682655+c-jimenez@users.noreply.github.com> Date: Mon, 13 Nov 2023 14:10:25 +0100 Subject: [PATCH 6/6] =?UTF-8?q?[version]=C2=A0Update=20version=20number=20?= =?UTF-8?q?=3D>=201.4.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e2ab8c62..5ad86a80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_minimum_required(VERSION 3.13) project(OpenOCPP DESCRIPTION "Open Source C++ implementation of the OCPP 1.6 protocol" - VERSION 1.4.0 + VERSION 1.4.1 ) # Definitions for Version.h file