From 8884219b33a3b123e6ad4eed96c1e624cfef3c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piet=20G=C3=B6mpel?= Date: Mon, 23 Dec 2024 10:20:46 +0100 Subject: [PATCH 1/2] * Added internal variable SupportedOcppVersions that allows to specify the supported protocol versions in order of preference * Added member variable ocpp_version to ChargePoint to indicate the selected version * ConnectivityManager now uses the configured value to set up the WebsocketConnectionOptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Piet Gömpel --- .../standardized/InternalCtrlr.json | 21 ++++++++++++++++++- include/ocpp/v201/charge_point.hpp | 5 ++++- include/ocpp/v201/charge_point_callbacks.hpp | 3 ++- include/ocpp/v201/connectivity_manager.hpp | 5 +++-- .../ocpp/v201/ctrlr_component_variables.hpp | 1 + include/ocpp/v201/utils.hpp | 3 +++ lib/ocpp/v201/charge_point.cpp | 19 ++++++++++------- lib/ocpp/v201/connectivity_manager.cpp | 6 +++++- lib/ocpp/v201/ctrlr_component_variables.cpp | 5 +++++ lib/ocpp/v201/utils.cpp | 17 +++++++++++++++ 10 files changed, 71 insertions(+), 14 deletions(-) diff --git a/config/v201/component_config/standardized/InternalCtrlr.json b/config/v201/component_config/standardized/InternalCtrlr.json index f2ca627fc..9dd85b61d 100644 --- a/config/v201/component_config/standardized/InternalCtrlr.json +++ b/config/v201/component_config/standardized/InternalCtrlr.json @@ -818,6 +818,24 @@ "description": "If enabled we allow connections using security level 0. This does pose a security risk and is not allowed according to the OCPP spec", "default": false, "type": "boolean" + }, + "SupportedOcppVersions": { + "variable_name": "SupportedOcppVersions", + "characteristics": { + "supportsMonitoring": true, + "dataType": "SequenceList", + "valuesList": "v201,v21" + }, + "attributes": [ + { + "type": "Actual", + "mutability": "ReadOnly", + "value": "v21,v201" + } + ], + "description": "List of supported OCPP versions in order of preference", + "default": "v21,v201", + "type": "string" } }, "required": [ @@ -830,6 +848,7 @@ "NetworkConnectionProfiles", "NumberOfConnectors", "SupportedCiphers12", - "SupportedCiphers13" + "SupportedCiphers13", + "SupportedOcppVersions" ] } diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 6f6b94845..96b3d745c 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -420,6 +420,8 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa // states std::atomic registration_status; + std::atomic ocpp_version = + OcppProtocolVersion::Unknown; // version that is currently in use, selected by CSMS in websocket handshake FirmwareStatusEnum firmware_status; // The request ID in the last firmware update status received std::optional firmware_status_id; @@ -477,7 +479,8 @@ class ChargePoint : public ChargePointInterface, private ocpp::ChargingStationBa void scheduled_check_client_certificate_expiration(); void scheduled_check_v2g_certificate_expiration(); void websocket_connected_callback(const int configuration_slot, - const NetworkConnectionProfile& network_connection_profile); + const NetworkConnectionProfile& network_connection_profile, + const OcppProtocolVersion ocpp_version); void websocket_disconnected_callback(const int configuration_slot, const NetworkConnectionProfile& network_connection_profile); void websocket_connection_failed(ConnectionFailedReason reason); diff --git a/include/ocpp/v201/charge_point_callbacks.hpp b/include/ocpp/v201/charge_point_callbacks.hpp index 72be1a324..3c0266775 100644 --- a/include/ocpp/v201/charge_point_callbacks.hpp +++ b/include/ocpp/v201/charge_point_callbacks.hpp @@ -145,7 +145,8 @@ struct Callbacks { /// \brief Callback function is called when the websocket connection status changes std::optional> + const NetworkConnectionProfile& network_connection_profile, + const OcppProtocolVersion ocpp_version)>> connection_state_changed_callback; /// \brief Callback functions called for get / set / clear display messages diff --git a/include/ocpp/v201/connectivity_manager.hpp b/include/ocpp/v201/connectivity_manager.hpp index 6f1c28898..d4d64f9ca 100644 --- a/include/ocpp/v201/connectivity_manager.hpp +++ b/include/ocpp/v201/connectivity_manager.hpp @@ -15,8 +15,9 @@ namespace v201 { class DeviceModel; -using WebsocketConnectionCallback = std::function; +using WebsocketConnectionCallback = + std::function; using WebsocketConnectionFailedCallback = std::function; using ConfigureNetworkConnectionProfileCallback = std::function( const int32_t configuration_slot, const NetworkConnectionProfile& network_connection_profile)>; diff --git a/include/ocpp/v201/ctrlr_component_variables.hpp b/include/ocpp/v201/ctrlr_component_variables.hpp index 6ecddef25..761410ef1 100644 --- a/include/ocpp/v201/ctrlr_component_variables.hpp +++ b/include/ocpp/v201/ctrlr_component_variables.hpp @@ -87,6 +87,7 @@ extern const ComponentVariable MessageQueueSizeThreshold; extern const ComponentVariable MaxMessageSize; extern const ComponentVariable ResumeTransactionsOnBoot; extern const ComponentVariable AllowSecurityLevelZeroConnections; +extern const RequiredComponentVariable SupportedOcppVersions; extern const ComponentVariable AlignedDataCtrlrEnabled; extern const ComponentVariable AlignedDataCtrlrAvailable; extern const RequiredComponentVariable AlignedDataInterval; diff --git a/include/ocpp/v201/utils.hpp b/include/ocpp/v201/utils.hpp index 4a68a9cb5..60fc6cb40 100644 --- a/include/ocpp/v201/utils.hpp +++ b/include/ocpp/v201/utils.hpp @@ -76,6 +76,9 @@ bool is_critical(const std::string& security_event); /// \brief Converts the given \p csl of ChargingProfilePurpose strings into a std::set std::set get_purposes_to_ignore(const std::string& csl, const bool is_offline); +/// \brief Converts the given \p csl of OcppProtocolVersion strings into a std::vector +std::vector get_ocpp_protocol_versions(const std::string& csl); + } // namespace utils } // namespace v201 } // namespace ocpp diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index a4a6e5c10..7afdad922 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -1137,8 +1137,9 @@ void ChargePoint::initialize(const std::map& evse_connector_st std::bind(&ChargePoint::message_callback, this, std::placeholders::_1)); this->connectivity_manager->set_websocket_connected_callback( - [this](int configuration_slot, const NetworkConnectionProfile& network_connection_profile, auto) { - this->websocket_connected_callback(configuration_slot, network_connection_profile); + [this](int configuration_slot, const NetworkConnectionProfile& network_connection_profile, + const OcppProtocolVersion ocpp_version) { + this->websocket_connected_callback(configuration_slot, network_connection_profile, ocpp_version); }); this->connectivity_manager->set_websocket_disconnected_callback( [this](int configuration_slot, const NetworkConnectionProfile& network_connection_profile, auto) { @@ -3020,7 +3021,7 @@ void ChargePoint::handle_trigger_message(Call call) { return; } - auto send_evse_message = [&](std::function send) { + auto send_evse_message = [&](std::function send) { if (evse_ptr != nullptr) { send(msg.evse.value().id, *evse_ptr); } else { @@ -4170,9 +4171,10 @@ void ChargePoint::scheduled_check_v2g_certificate_expiration() { } void ChargePoint::websocket_connected_callback(const int configuration_slot, - const NetworkConnectionProfile& network_connection_profile) { + const NetworkConnectionProfile& network_connection_profile, + const OcppProtocolVersion ocpp_version) { this->message_queue->resume(this->message_queue_resume_delay); - + this->ocpp_version = ocpp_version; if (this->registration_status == RegistrationStatusEnum::Accepted) { this->connectivity_manager->confirm_successful_connection(); @@ -4203,7 +4205,8 @@ void ChargePoint::websocket_connected_callback(const int configuration_slot, this->skip_invalid_csms_certificate_notifications = false; if (this->callbacks.connection_state_changed_callback.has_value()) { - this->callbacks.connection_state_changed_callback.value()(true, configuration_slot, network_connection_profile); + this->callbacks.connection_state_changed_callback.value()(true, configuration_slot, network_connection_profile, + ocpp_version); } } @@ -4220,8 +4223,8 @@ void ChargePoint::websocket_disconnected_callback(const int configuration_slot, this->client_certificate_expiration_check_timer.stop(); this->v2g_certificate_expiration_check_timer.stop(); if (this->callbacks.connection_state_changed_callback.has_value()) { - this->callbacks.connection_state_changed_callback.value()(false, configuration_slot, - network_connection_profile); + this->callbacks.connection_state_changed_callback.value()(false, configuration_slot, network_connection_profile, + this->ocpp_version); } } diff --git a/lib/ocpp/v201/connectivity_manager.cpp b/lib/ocpp/v201/connectivity_manager.cpp index d41198d7d..1158a2b74 100644 --- a/lib/ocpp/v201/connectivity_manager.cpp +++ b/lib/ocpp/v201/connectivity_manager.cpp @@ -6,6 +6,7 @@ #include #include #include +#include namespace { const auto WEBSOCKET_INIT_DELAY = std::chrono::seconds(2); @@ -337,8 +338,11 @@ ConnectivityManager::get_ws_connection_options(const int32_t configuration_slot) this->device_model.get_value(ControllerComponentVariables::SecurityCtrlrIdentity), network_connection_profile.securityProfile); + std::vector ocpp_versions = utils::get_ocpp_protocol_versions( + this->device_model.get_value(ControllerComponentVariables::SupportedOcppVersions)); + WebsocketConnectionOptions connection_options{ - {OcppProtocolVersion::v201}, + ocpp_versions, uri, network_connection_profile.securityProfile, this->device_model.get_optional_value(ControllerComponentVariables::BasicAuthPassword), diff --git a/lib/ocpp/v201/ctrlr_component_variables.cpp b/lib/ocpp/v201/ctrlr_component_variables.cpp index 263e3d86f..43193274c 100644 --- a/lib/ocpp/v201/ctrlr_component_variables.cpp +++ b/lib/ocpp/v201/ctrlr_component_variables.cpp @@ -380,6 +380,11 @@ const ComponentVariable AllowSecurityLevelZeroConnections = { "AllowSecurityLevelZeroConnections", }), }; +const RequiredComponentVariable SupportedOcppVersions = { + ControllerComponents::InternalCtrlr, + std::nullopt, + std::optional({"SupportedOcppVersions"}), +}; const ComponentVariable AlignedDataCtrlrEnabled = { ControllerComponents::AlignedDataCtrlr, std::nullopt, diff --git a/lib/ocpp/v201/utils.cpp b/lib/ocpp/v201/utils.cpp index e9697e3f2..ebb0343e6 100644 --- a/lib/ocpp/v201/utils.cpp +++ b/lib/ocpp/v201/utils.cpp @@ -210,6 +210,23 @@ std::set get_purposes_to_ignore(const std::string& c return purposes_to_ignore; } +std::vector get_ocpp_protocol_versions(const std::string& csl) { + if (csl.empty()) { + return {}; + } + + std::vector ocpp_versions; + const auto ocpp_versions_str = ocpp::split_string(csl, ','); + for (const auto ocpp_version_str : ocpp_versions_str) { + try { + ocpp_versions.push_back(ocpp::conversions::string_to_ocpp_protocol_version(ocpp_version_str)); + } catch (std::out_of_range& e) { + EVLOG_warning << "Error while converting ocpp protocol version: " << ocpp_version_str; + } + } + return ocpp_versions; +} + } // namespace utils } // namespace v201 } // namespace ocpp From 2db789e1c4ac49d00ecae33134f8b58d0629bb31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piet=20G=C3=B6mpel?= Date: Sun, 29 Dec 2024 21:40:29 +0100 Subject: [PATCH 2/2] Fix supported ocpp versions in config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Piet Gömpel --- .../v201/component_config/standardized/InternalCtrlr.json | 6 +++--- lib/ocpp/v201/connectivity_manager.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/config/v201/component_config/standardized/InternalCtrlr.json b/config/v201/component_config/standardized/InternalCtrlr.json index 9dd85b61d..aa5d8eb06 100644 --- a/config/v201/component_config/standardized/InternalCtrlr.json +++ b/config/v201/component_config/standardized/InternalCtrlr.json @@ -824,17 +824,17 @@ "characteristics": { "supportsMonitoring": true, "dataType": "SequenceList", - "valuesList": "v201,v21" + "valuesList": "ocpp2.0.1,ocpp2.1" }, "attributes": [ { "type": "Actual", "mutability": "ReadOnly", - "value": "v21,v201" + "value": "ocpp2.1,ocpp2.0.1" } ], "description": "List of supported OCPP versions in order of preference", - "default": "v21,v201", + "default": "ocpp2.1,ocpp2.0.1", "type": "string" } }, diff --git a/lib/ocpp/v201/connectivity_manager.cpp b/lib/ocpp/v201/connectivity_manager.cpp index 1158a2b74..442cd5535 100644 --- a/lib/ocpp/v201/connectivity_manager.cpp +++ b/lib/ocpp/v201/connectivity_manager.cpp @@ -338,7 +338,7 @@ ConnectivityManager::get_ws_connection_options(const int32_t configuration_slot) this->device_model.get_value(ControllerComponentVariables::SecurityCtrlrIdentity), network_connection_profile.securityProfile); - std::vector ocpp_versions = utils::get_ocpp_protocol_versions( + const auto ocpp_versions = utils::get_ocpp_protocol_versions( this->device_model.get_value(ControllerComponentVariables::SupportedOcppVersions)); WebsocketConnectionOptions connection_options{