From 4c30a7613a2f461953c6e2c6f98aec37c6a6a3f4 Mon Sep 17 00:00:00 2001 From: marcemmers <35759328+marcemmers@users.noreply.github.com> Date: Fri, 3 Nov 2023 11:26:43 +0100 Subject: [PATCH] Add message logging callback (#209) * Added a callback for all ocpp messages * Add calls to callback with direction * Move message logging into ocpp_logging class --------- Signed-off-by: Kai-Uwe Hermann Signed-off-by: Soumya Subramanya Signed-off-by: Marc Emmers Co-authored-by: Soumya Subramanya --- include/ocpp/common/ocpp_logging.hpp | 9 ++++++--- include/ocpp/common/types.hpp | 5 +++++ include/ocpp/v201/charge_point.hpp | 4 ++++ lib/ocpp/common/ocpp_logging.cpp | 23 +++++++++++++++++------ lib/ocpp/v16/charge_point_impl.cpp | 2 +- lib/ocpp/v201/charge_point.cpp | 11 +++++++---- 6 files changed, 40 insertions(+), 14 deletions(-) diff --git a/include/ocpp/common/ocpp_logging.hpp b/include/ocpp/common/ocpp_logging.hpp index 6e956caca..852c1cc6a 100644 --- a/include/ocpp/common/ocpp_logging.hpp +++ b/include/ocpp/common/ocpp_logging.hpp @@ -8,6 +8,7 @@ #include #include #include +#include #include namespace ocpp { @@ -33,6 +34,7 @@ class MessageLogging { std::ofstream output_file; std::ofstream html_log_file; std::mutex output_file_mutex; + std::function message_callback; std::map lookup_map; std::map> session_id_logging; @@ -42,9 +44,10 @@ class MessageLogging { public: /// \brief Creates a new Websocket object with the providede \p configuration - explicit MessageLogging(bool log_messages, const std::string& message_log_path, const std::string& output_file_name, - bool log_to_console, bool detailed_log_to_console, bool log_to_file, bool log_to_html, - bool session_logging); + explicit MessageLogging( + bool log_messages, const std::string& message_log_path, const std::string& output_file_name, + bool log_to_console, bool detailed_log_to_console, bool log_to_file, bool log_to_html, bool session_logging, + std::function message_callback); ~MessageLogging(); void charge_point(const std::string& message_type, const std::string& json_str); diff --git a/include/ocpp/common/types.hpp b/include/ocpp/common/types.hpp index 60f587493..fde8a3b31 100644 --- a/include/ocpp/common/types.hpp +++ b/include/ocpp/common/types.hpp @@ -586,6 +586,11 @@ inline const std::string INVALIDTLSVERSION = "InvalidTLSVersion"; inline const std::string INVALIDTLSCIPHERSUITE = "InvalidTLSCipherSuite"; } // namespace security_events +enum class MessageDirection { + CSMSToChargingStation, + ChargingStationToCSMS +}; + } // namespace ocpp #endif diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 030daa571..abfbe67e9 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -102,6 +102,10 @@ struct Callbacks { std::optional> configure_network_connection_profile_callback; std::optional> time_sync_callback; + + /// \brief callback to be called to congfigure ocpp message logging + std::optional> ocpp_messages_callback; + /// /// \brief callback function that can be used to react to a security event callback. This callback is /// called only if the SecurityEvent occured internally within libocpp diff --git a/lib/ocpp/common/ocpp_logging.cpp b/lib/ocpp/common/ocpp_logging.cpp index 30e0817e9..0da0d9d4d 100644 --- a/lib/ocpp/common/ocpp_logging.cpp +++ b/lib/ocpp/common/ocpp_logging.cpp @@ -12,9 +12,10 @@ using json = nlohmann::json; namespace ocpp { -MessageLogging::MessageLogging(bool log_messages, const std::string& message_log_path, - const std::string& output_file_name, bool log_to_console, bool detailed_log_to_console, - bool log_to_file, bool log_to_html, bool session_logging) : +MessageLogging::MessageLogging( + bool log_messages, const std::string& message_log_path, const std::string& output_file_name, bool log_to_console, + bool detailed_log_to_console, bool log_to_file, bool log_to_html, bool session_logging, + std::function message_callback) : log_messages(log_messages), message_log_path(message_log_path), output_file_name(output_file_name), @@ -22,12 +23,16 @@ MessageLogging::MessageLogging(bool log_messages, const std::string& message_log detailed_log_to_console(detailed_log_to_console), log_to_file(log_to_file), log_to_html(log_to_html), - session_logging(session_logging) { + session_logging(session_logging), + message_callback(message_callback) { if (this->log_messages) { if (this->log_to_console) { EVLOG_info << "Logging OCPP messages to console"; } + if (this->message_callback != nullptr) { + EVLOG_info << "Logging OCPP messages to callback"; + } if (this->log_to_file) { auto output_file_path = message_log_path + "/" + output_file_name + ".log"; EVLOG_info << "Logging OCPP messages to log file: " << output_file_path; @@ -82,6 +87,9 @@ MessageLogging::~MessageLogging() { } void MessageLogging::charge_point(const std::string& message_type, const std::string& json_str) { + if (this->message_callback != nullptr) { + this->message_callback(json_str, MessageDirection::ChargingStationToCSMS); + } auto formatted = format_message(message_type, json_str); log_output(0, formatted.message_type, formatted.message); if (this->session_logging) { @@ -92,6 +100,9 @@ void MessageLogging::charge_point(const std::string& message_type, const std::st } void MessageLogging::central_system(const std::string& message_type, const std::string& json_str) { + if (this->message_callback != nullptr) { + this->message_callback(json_str, MessageDirection::CSMSToChargingStation); + } auto formatted = format_message(message_type, json_str); log_output(1, formatted.message_type, formatted.message); if (this->session_logging) { @@ -190,8 +201,8 @@ FormattedMessageWithType MessageLogging::format_message(const std::string& messa } void MessageLogging::start_session_logging(const std::string& session_id, const std::string& log_path) { - this->session_id_logging[session_id] = - std::make_shared(true, log_path, "incomplete-ocpp", false, false, false, true, false); + this->session_id_logging[session_id] = std::make_shared( + true, log_path, "incomplete-ocpp", false, false, false, true, false, nullptr); } void MessageLogging::stop_session_logging(const std::string& session_id) { diff --git a/lib/ocpp/v16/charge_point_impl.cpp b/lib/ocpp/v16/charge_point_impl.cpp index ba155943c..9cce89b71 100644 --- a/lib/ocpp/v16/charge_point_impl.cpp +++ b/lib/ocpp/v16/charge_point_impl.cpp @@ -56,7 +56,7 @@ ChargePointImpl::ChargePointImpl(const std::string& config, const fs::path& shar this->logging = std::make_shared( this->configuration->getLogMessages(), this->message_log_path, DateTime().to_rfc3339(), log_to_console, - detailed_log_to_console, log_to_file, log_to_html, session_logging); + detailed_log_to_console, log_to_file, log_to_html, session_logging, nullptr); this->boot_notification_timer = std::make_unique(&this->io_service, [this]() { this->boot_notification(); }); diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index cf4a9ae1a..d2aa408c8 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -26,7 +26,8 @@ bool Callbacks::all_callbacks_valid() const { (!this->configure_network_connection_profile_callback.has_value() or this->configure_network_connection_profile_callback.value() != nullptr) and (!this->time_sync_callback.has_value() or this->time_sync_callback.value() != nullptr) and - (!this->boot_notification_callback.has_value() or this->boot_notification_callback.value() != nullptr); + (!this->boot_notification_callback.has_value() or this->boot_notification_callback.value() != nullptr) and + (!this->ocpp_messages_callback.has_value() or this->ocpp_messages_callback.value() != nullptr); } ChargePoint::ChargePoint(const std::map& evse_connector_structure, @@ -121,8 +122,10 @@ ChargePoint::ChargePoint(const std::map& evse_connector_struct this->database_handler->insert_availability(evse_id, connector_id, OperationalStatusEnum::Operative, false); } } - this->logging = std::make_shared(true, message_log_path, DateTime().to_rfc3339(), false, - false, false, true, true); + this->logging = + std::make_shared(true, message_log_path, DateTime().to_rfc3339(), false, false, false, + true, true, this->callbacks.ocpp_messages_callback.value_or(nullptr)); + this->message_queue = std::make_unique>( [this](json message) -> bool { return this->websocket->send(message.dump()); }, this->device_model->get_value(ControllerComponentVariables::MessageAttempts), @@ -2418,4 +2421,4 @@ void ChargePoint::handle_get_local_authorization_list_version_req(Call