From 1886e873d4d4ecffbdc93e68213161efc537bb54 Mon Sep 17 00:00:00 2001 From: Ivan Rogach Date: Mon, 30 Sep 2024 13:25:43 +0200 Subject: [PATCH 1/4] Add exception if format string for DateTime is invalid Signed-off-by: Ivan Rogach --- include/ocpp/common/types.hpp | 23 ++++++++++++++----- .../database/database_handler_common.cpp | 2 +- lib/ocpp/common/types.cpp | 13 +---------- lib/ocpp/v201/charge_point.cpp | 10 +++++--- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 6a4813329..f71119742 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -33,6 +33,23 @@ struct Message { virtual std::string get_type() const = 0; }; +/// \brief Exception used when DateTime class is initialized by invalid timepoint string. +class TimePointParseException : public std::exception { +public: + explicit TimePointParseException(const std::string& timepoint_str) : + msg{"Timepoint string parsing failed. Could not convert: \"" + timepoint_str + "\" into DateTime."} { + } + + ~TimePointParseException() noexcept override = default; + + const char* what() const noexcept override { + return msg.c_str(); + } + +private: + std::string msg; +}; + /// \brief Contains a DateTime implementation that can parse and create RFC 3339 compatible strings class DateTimeImpl { private: @@ -103,12 +120,6 @@ class DateTime : public DateTimeImpl { /// \brief Creates a new DateTime object from the given \p timepoint_str explicit DateTime(const std::string& timepoint_str); - - /// \brief Assignment operator= that converts a given string \p s into a DateTime - DateTime& operator=(const std::string& s); - - /// \brief Assignment operator= that converts a given char* \p c into a DateTime - DateTime& operator=(const char* c); }; /// \brief Base exception for when a conversion from string to enum or vice versa fails diff --git a/lib/ocpp/common/database/database_handler_common.cpp b/lib/ocpp/common/database/database_handler_common.cpp index b28d75a45..476c6df59 100644 --- a/lib/ocpp/common/database/database_handler_common.cpp +++ b/lib/ocpp/common/database/database_handler_common.cpp @@ -56,7 +56,7 @@ std::vector DatabaseHandlerCommon::get_message_queue_messa DBTransactionMessage control_message; control_message.message_attempts = message_attempts; - control_message.timestamp = message_timestamp; + control_message.timestamp = ocpp::DateTime(message_timestamp); control_message.message_type = message_type; control_message.unique_id = unique_id; control_message.json_message = json_message; diff --git a/lib/ocpp/common/types.cpp b/lib/ocpp/common/types.cpp index 743fbe1f0..656eca84b 100644 --- a/lib/ocpp/common/types.cpp +++ b/lib/ocpp/common/types.cpp @@ -16,16 +16,6 @@ DateTime::DateTime(std::chrono::time_point timepoint) : DateTim DateTime::DateTime(const std::string& timepoint_str) : DateTimeImpl(timepoint_str) { } -DateTime& DateTime::operator=(const std::string& s) { - this->from_rfc3339(s); - return *this; -} - -DateTime& DateTime::operator=(const char* c) { - this->from_rfc3339(std::string(c)); - return *this; -} - DateTimeImpl::DateTimeImpl() { this->timepoint = date::utc_clock::now(); } @@ -53,8 +43,7 @@ void DateTimeImpl::from_rfc3339(const std::string& timepoint_str) { in.seekg(0); in >> date::parse("%FT%T", this->timepoint); if (in.fail()) { - EVLOG_error << "Timepoint string parsing failed. Could not convert: \"" << timepoint_str - << "\" into DateTime."; + throw TimePointParseException(timepoint_str); } } } diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index b8a2f66ee..733d01c6c 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -1484,6 +1484,10 @@ void ChargePoint::message_callback(const std::string& message) { EVLOG_error << "EnumConversionException during handling of message: " << e.what(); auto call_error = CallError(enhanced_message.uniqueId, "FormationViolation", e.what(), json({})); this->send(call_error); + } catch (const TimePointParseException& e) { + EVLOG_error << "Exception during handling of message: " << e.what(); + auto call_error = CallError(enhanced_message.uniqueId, "FormationViolation", e.what(), json({})); + this->send(call_error); } catch (json::exception& e) { EVLOG_error << "JSON exception during handling of message: " << e.what(); if (json_message.is_array() and json_message.size() > MESSAGE_ID) { @@ -1991,9 +1995,9 @@ void ChargePoint::security_event_notification_req(const CiString<50>& event_type req.type = event_type; if (timestamp.has_value()) { - req.timestamp = timestamp.value().to_rfc3339(); + req.timestamp = timestamp.value(); } else { - req.timestamp = DateTime().to_rfc3339(); + req.timestamp = DateTime(); } req.techInfo = tech_info; this->logging->security(json(req).dump()); @@ -2165,7 +2169,7 @@ void ChargePoint::status_notification_req(const int32_t evse_id, const int32_t c StatusNotificationRequest req; req.connectorId = connector_id; req.evseId = evse_id; - req.timestamp = DateTime().to_rfc3339(); + req.timestamp = DateTime(); req.connectorStatus = status; ocpp::Call call(req, this->message_queue->createMessageId()); From 25deb7ce15c0f93d08d0c8b37e4af23a6d882617 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Sun, 6 Oct 2024 12:27:49 +0200 Subject: [PATCH 2/4] Handle TimePointParseException in OCPP 1.6 message callback Signed-off-by: Kai-Uwe Hermann --- lib/ocpp/v16/charge_point_impl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index 3599c4712..f3e6b7435 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -1230,6 +1230,9 @@ void ChargePointImpl::message_callback(const std::string& message) { EnhancedMessage enhanced_message; try { enhanced_message = this->message_queue->receive(message); + } catch (const TimePointParseException& e) { + EVLOG_error << "Exception during handling of message: " << e.what(); + this->send(CallError(enhanced_message.uniqueId, "FormationViolation", e.what(), json({}))); } catch (const json::exception& e) { EVLOG_error << "JSON exception during reception of message: " << e.what(); this->send(CallError(MessageId("-1"), "GenericError", e.what(), json({}))); From d6194077e02cb033decefce0658174dad1ded9e0 Mon Sep 17 00:00:00 2001 From: Kai-Uwe Hermann Date: Sun, 6 Oct 2024 12:28:40 +0200 Subject: [PATCH 3/4] Bump version to 0.18.0 Signed-off-by: Kai-Uwe Hermann --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e36796a6c..8e066c183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.14) project(ocpp - VERSION 0.17.1 + VERSION 0.18.0 DESCRIPTION "A C++ implementation of the Open Charge Point Protocol" LANGUAGES CXX ) From a96e3739d9ec54b1d501814bf09230abdde1ab41 Mon Sep 17 00:00:00 2001 From: Ivan Rogach Date: Wed, 9 Oct 2024 12:11:43 +0200 Subject: [PATCH 4/4] Remove defined destructor form the TimePointParseException class Signed-off-by: Ivan Rogach --- include/ocpp/common/types.hpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index f71119742..ce8555362 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -40,8 +40,6 @@ class TimePointParseException : public std::exception { msg{"Timepoint string parsing failed. Could not convert: \"" + timepoint_str + "\" into DateTime."} { } - ~TimePointParseException() noexcept override = default; - const char* what() const noexcept override { return msg.c_str(); }