Skip to content

Commit

Permalink
OCPP: Handle ocpp::DateTime TimePointParseException (#892)
Browse files Browse the repository at this point in the history
* Add warning when optional DisplayMessage timestamps could not be converted
* Add function to convert a datetime string to OCPP DateTime

If this is not possible it will return the current DateTime

* Use to_ocpp_datetime_or_now for session event timestamps

---------

Signed-off-by: Kai-Uwe Hermann <[email protected]>
Signed-off-by: Piet Gömpel <[email protected]>
Signed-off-by: Piet Gömpel <[email protected]>
Co-authored-by: Piet Gömpel <[email protected]>
Co-authored-by: Piet Gömpel <[email protected]>
  • Loading branch information
3 people authored Oct 16, 2024
1 parent 15a511b commit 06038e4
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 19 deletions.
2 changes: 1 addition & 1 deletion dependencies.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ libevse-security:
# OCPP
libocpp:
git: https://github.com/EVerest/libocpp.git
git_tag: v0.17.2
git_tag: 5c7f10cdfd9aa70db80ccf43ace250e3322be00c
cmake_condition: "EVEREST_DEPENDENCY_ENABLED_LIBOCPP"
# Josev
Josev:
Expand Down
24 changes: 22 additions & 2 deletions lib/staging/ocpp/ocpp_conversions.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "ocpp_conversions.hpp"

#include <everest/logging.hpp>

#include "generated/types/display_message.hpp"

namespace ocpp_conversions {
Expand Down Expand Up @@ -185,8 +187,16 @@ ocpp::DisplayMessage to_ocpp_display_message(const types::display_message::Displ
m.state = to_ocpp_201_display_message_state(display_message.state.value());
}

m.timestamp_from = display_message.timestamp_from;
m.timestamp_to = display_message.timestamp_to;
try {
if (display_message.timestamp_from.has_value()) {
m.timestamp_from = ocpp::DateTime(display_message.timestamp_from.value());
}
if (display_message.timestamp_to.has_value()) {
m.timestamp_to = ocpp::DateTime(display_message.timestamp_to.value());
}
} catch (const ocpp::TimePointParseException& e) {
EVLOG_warning << "Could not parse timestamp when converting DisplayMessage: " << e.what();
}

return m;
}
Expand Down Expand Up @@ -347,4 +357,14 @@ types::session_cost::SessionCost create_session_cost(const ocpp::RunningCost& ru

return cost;
}

ocpp::DateTime to_ocpp_datetime_or_now(const std::string& datetime_string) {
std::optional<ocpp::DateTime> timestamp;
try {
return ocpp::DateTime(datetime_string);
} catch (const ocpp::TimePointParseException& e) {
EVLOG_warning << "Could not parse datetime string: " << e.what() << ". Using current DateTime instead";
}
return ocpp::DateTime();
}
} // namespace ocpp_conversions
5 changes: 5 additions & 0 deletions lib/staging/ocpp/ocpp_conversions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,9 @@ create_charging_price_component(const double& price, const uint32_t& number_of_d
types::session_cost::SessionCost create_session_cost(const ocpp::RunningCost& running_cost,
const uint32_t number_of_decimals,
std::optional<types::money::CurrencyCode> currency_code);

/// \brief Convert given \p datetime_string in RFC3339 format to a OCPP DateTime. If this is not possible return the
/// current datetime
ocpp::DateTime to_ocpp_datetime_or_now(const std::string& datetime_string);

}; // namespace ocpp_conversions
4 changes: 2 additions & 2 deletions modules/OCPP/OCPP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void OCPP::process_session_event(int32_t evse_id, const types::evse_manager::Ses
<< "Received TransactionStarted";
const auto transaction_started = session_event.transaction_started.value();

const auto timestamp = ocpp::DateTime(session_event.timestamp);
const auto timestamp = ocpp_conversions::to_ocpp_datetime_or_now(session_event.timestamp);
const auto energy_Wh_import = transaction_started.meter_value.energy_Wh_import.total;
const auto session_id = session_event.uuid;
const auto id_token = transaction_started.id_tag.id_token.value;
Expand Down Expand Up @@ -177,7 +177,7 @@ void OCPP::process_session_event(int32_t evse_id, const types::evse_manager::Ses
<< "Received TransactionFinished";

const auto transaction_finished = session_event.transaction_finished.value();
const auto timestamp = ocpp::DateTime(session_event.timestamp);
const auto timestamp = ocpp_conversions::to_ocpp_datetime_or_now(session_event.timestamp);
const auto energy_Wh_import = transaction_finished.meter_value.energy_Wh_import.total;
const auto signed_meter_value = transaction_finished.signed_meter_value;

Expand Down
2 changes: 1 addition & 1 deletion modules/OCPP/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ ocpp::v16::BootReasonEnum to_ocpp_boot_reason_enum(const types::system::BootReas

ocpp::Powermeter to_ocpp_power_meter(const types::powermeter::Powermeter& powermeter) {
ocpp::Powermeter ocpp_powermeter;
ocpp_powermeter.timestamp = powermeter.timestamp;
ocpp_powermeter.timestamp = ocpp_conversions::to_ocpp_datetime_or_now(powermeter.timestamp);
ocpp_powermeter.energy_Wh_import = {powermeter.energy_Wh_import.total, powermeter.energy_Wh_import.L1,
powermeter.energy_Wh_import.L2, powermeter.energy_Wh_import.L3};

Expand Down
8 changes: 3 additions & 5 deletions modules/OCPP/ocpp_generic/ocppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include "ocppImpl.hpp"
#include "ocpp/v16/messages/ChangeAvailability.hpp"

#include <ocpp_conversions.hpp>

namespace module {
namespace ocpp_generic {

Expand Down Expand Up @@ -124,11 +126,7 @@ bool ocppImpl::handle_restart() {
void ocppImpl::handle_security_event(types::ocpp::SecurityEvent& event) {
std::optional<ocpp::DateTime> timestamp;
if (event.timestamp.has_value()) {
try {
timestamp = ocpp::DateTime(event.timestamp.value());
} catch (...) {
EVLOG_warning << "Timestamp in security event could not be parsed, using current datetime.";
}
timestamp = ocpp_conversions::to_ocpp_datetime_or_now(event.timestamp.value());
}
this->mod->charge_point->on_security_event(event.type, event.info, event.critical, timestamp);
}
Expand Down
4 changes: 2 additions & 2 deletions modules/OCPP201/OCPP201.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -904,7 +904,7 @@ void OCPP201::process_tx_event_effect(const int32_t evse_id, const TxEventEffect
if (transaction_data == nullptr) {
throw std::runtime_error("Could not start transaction because no tranasaction data is present");
}
transaction_data->timestamp = ocpp::DateTime(session_event.timestamp);
transaction_data->timestamp = ocpp_conversions::to_ocpp_datetime_or_now(session_event.timestamp);

if (tx_event_effect == TxEventEffect::START_TRANSACTION) {
transaction_data->started = true;
Expand Down Expand Up @@ -959,7 +959,7 @@ void OCPP201::process_session_started(const int32_t evse_id, const int32_t conne
trigger_reason = ocpp::v201::TriggerReasonEnum::RemoteStart;
}
}
const auto timestamp = ocpp::DateTime(session_event.timestamp);
const auto timestamp = ocpp_conversions::to_ocpp_datetime_or_now(session_event.timestamp);
const auto reservation_id = session_started.reservation_id;

// this is always the first transaction related interaction, so we create TransactionData here
Expand Down
3 changes: 2 additions & 1 deletion modules/OCPP201/conversions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <conversions.hpp>
#include <everest/logging.hpp>
#include <ocpp_conversions.hpp>

namespace module {
namespace conversions {
Expand Down Expand Up @@ -137,7 +138,7 @@ to_ocpp_meter_value(const types::powermeter::Powermeter& power_meter,
const ocpp::v201::ReadingContextEnum& reading_context,
const std::optional<types::units_signed::SignedMeterValue> signed_meter_value) {
ocpp::v201::MeterValue meter_value;
meter_value.timestamp = ocpp::DateTime(power_meter.timestamp);
meter_value.timestamp = ocpp_conversions::to_ocpp_datetime_or_now(power_meter.timestamp);

// signed_meter_value is intended for OCMF style blobs of signed meter value reports during transaction start or end
// This is interpreted as Energy.Active.Import.Register
Expand Down
1 change: 1 addition & 0 deletions modules/OCPP201/error_handling.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#define OCPP201_ERROR_HANDLING_HPP

#include <ocpp/v201/ocpp_types.hpp>
#include <ocpp_conversions.hpp>
#include <utils/error.hpp>

#include <unordered_map>
Expand Down
7 changes: 2 additions & 5 deletions modules/OCPP201/ocpp_generic/ocppImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "ocppImpl.hpp"
#include <conversions.hpp>
#include <ocpp_conversions.hpp>

namespace module {
namespace ocpp_generic {
Expand All @@ -26,11 +27,7 @@ bool ocppImpl::handle_restart() {
void ocppImpl::handle_security_event(types::ocpp::SecurityEvent& event) {
std::optional<ocpp::DateTime> timestamp;
if (event.timestamp.has_value()) {
try {
timestamp = ocpp::DateTime(event.timestamp.value());
} catch (...) {
EVLOG_warning << "Timestamp in security event could not be parsed, using current datetime.";
}
timestamp = ocpp_conversions::to_ocpp_datetime_or_now(event.timestamp.value());
}
this->mod->charge_point->on_security_event(event.type, event.info, event.critical, timestamp);
}
Expand Down

0 comments on commit 06038e4

Please sign in to comment.