From 24304f0002f910fd9f4f3642b23ebae861c22671 Mon Sep 17 00:00:00 2001 From: "Maaike Zijderveld, Alfen" Date: Thu, 3 Aug 2023 12:14:52 +0200 Subject: [PATCH 1/4] Send a transaction event after every charging state changed. Store remote start id and send trigger reason RemoteStart with the very first transaction event after the remote start request. Signed-off-by: Maaike Zijderveld, Alfen --- include/ocpp/v201/charge_point.hpp | 2 ++ lib/ocpp/v201/charge_point.cpp | 45 ++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index e28e1318f..9d9e33054 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -90,6 +90,8 @@ class ChargePoint : ocpp::ChargingStationBase { data_transfer_callbacks; std::mutex data_transfer_callbacks_mutex; + std::map> remote_start_id_per_evse; + // timers Everest::SteadyTimer heartbeat_timer; Everest::SteadyTimer boot_notification_timer; diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 9f4b8a3a6..5d7ce50d6 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -231,6 +231,14 @@ bool ChargePoint::on_charging_state_changed(const uint32_t evse_id, this->evses.at(static_cast(evse_id))->get_transaction(); if (transaction != nullptr) { transaction->chargingState = charging_state; + this->transaction_event_req( + TransactionEventEnum::Updated, DateTime(), + transaction->get_transaction(), + TriggerReasonEnum::ChargingStateChanged, + transaction->get_seq_no(), std::nullopt, + this->evses.at(static_cast(evse_id))->get_evse_info(), + std::nullopt, std::nullopt, std::nullopt, std::nullopt, + std::nullopt); return true; } else { EVLOG_warning @@ -860,6 +868,36 @@ void ChargePoint::transaction_event_req(const TransactionEventEnum& event_type, // TODO(piet): offline handling } } else { + // Check if id token is in the remote start map, because when a remote + // start request is done, the first transaction event request should + // always contain trigger reason 'RemoteStart'. + auto it = std::find_if( + remote_start_id_per_evse.begin(), remote_start_id_per_evse.end(), + [&id_token, &evse](const std::pair>& remote_start_per_evse) { + if (id_token.has_value() && + remote_start_per_evse.second.first.idToken == id_token.value().idToken) { + + if (remote_start_per_evse.first == 0) { + return true; + } + + if (evse.has_value() && + evse.value().id == remote_start_per_evse.first) { + return true; + } + } + return false; + } + ); + + if (it != remote_start_id_per_evse.end()) { + // Found remote start. Set remote start id and the trigger reason. + call.msg.triggerReason = TriggerReasonEnum::RemoteStart; + call.msg.transactionInfo.remoteStartId = it->second.second; + + remote_start_id_per_evse.erase(it); + } + this->send(call); } } @@ -1246,12 +1284,15 @@ void ChargePoint::handle_remote_start_transaction_request(Call Date: Tue, 8 Aug 2023 11:09:34 +0200 Subject: [PATCH 2/4] Also add charging state to newly created transaction Signed-off-by: Maaike Signed-off-by: Maaike Zijderveld, Alfen --- lib/ocpp/v201/charge_point.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 5d7ce50d6..03b5d8889 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -146,6 +146,7 @@ void ChargePoint::on_transaction_started(const int32_t evse_id, const int32_t co ControllerComponentVariables::SampledDataTxStartedMeasurands))); Transaction transaction{enhanced_transaction->transactionId}; + transaction.chargingState = charging_state; if (remote_start_id.has_value()) { transaction.remoteStartId = remote_start_id.value(); enhanced_transaction->remoteStartId = remote_start_id.value(); From a2008b47aed2e7d34711991ce0985b84a8cde74b Mon Sep 17 00:00:00 2001 From: Maaike Date: Tue, 8 Aug 2023 14:18:20 +0200 Subject: [PATCH 3/4] Add charging state to on_transaction_stopped Signed-off-by: Maaike Signed-off-by: Maaike Zijderveld, Alfen --- include/ocpp/v201/charge_point.hpp | 2 +- lib/ocpp/v201/charge_point.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index 9d9e33054..dcc843544 100644 --- a/include/ocpp/v201/charge_point.hpp +++ b/include/ocpp/v201/charge_point.hpp @@ -299,7 +299,7 @@ class ChargePoint : ocpp::ChargingStationBase { /// \param signed_meter_value void on_transaction_finished(const int32_t evse_id, const DateTime& timestamp, const MeterValue& meter_stop, const ReasonEnum reason, const std::optional& id_token, - const std::optional& signed_meter_value); + const std::optional& signed_meter_value, const ChargingStateEnum charging_state); /// \brief Event handler that should be called when a session has finished /// \param evse_id diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 03b5d8889..5f346e99e 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -163,8 +163,10 @@ void ChargePoint::on_transaction_started(const int32_t evse_id, const int32_t co void ChargePoint::on_transaction_finished(const int32_t evse_id, const DateTime& timestamp, const MeterValue& meter_stop, const ReasonEnum reason, const std::optional& id_token, - const std::optional& signed_meter_value) { - const auto& enhanced_transaction = this->evses.at(evse_id)->get_transaction(); + const std::optional& signed_meter_value, + const ChargingStateEnum charging_state) { + auto& enhanced_transaction = this->evses.at(evse_id)->get_transaction(); + enhanced_transaction->chargingState = charging_state; if (enhanced_transaction == nullptr) { EVLOG_warning << "Received notification of finished transaction while no transaction was active"; return; From e9297567be9d55f28e1c41d781faf6a15408db52 Mon Sep 17 00:00:00 2001 From: Maaike Date: Wed, 16 Aug 2023 14:39:57 +0200 Subject: [PATCH 4/4] Move remote start triggerreason up so it is also sent for a TransactionEventEnum::Started Signed-off-by: Maaike Zijderveld, Alfen --- lib/ocpp/v201/charge_point.cpp | 61 +++++++++++++++++----------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/lib/ocpp/v201/charge_point.cpp b/lib/ocpp/v201/charge_point.cpp index 5f346e99e..c72eb8dea 100644 --- a/lib/ocpp/v201/charge_point.cpp +++ b/lib/ocpp/v201/charge_point.cpp @@ -856,12 +856,43 @@ void ChargePoint::transaction_event_req(const TransactionEventEnum& event_type, ocpp::Call call(req, this->message_queue->createMessageId()); + // Check if id token is in the remote start map, because when a remote + // start request is done, the first transaction event request should + // always contain trigger reason 'RemoteStart'. + auto it = std::find_if( + remote_start_id_per_evse.begin(), remote_start_id_per_evse.end(), + [&id_token, &evse](const std::pair>& remote_start_per_evse) { + if (id_token.has_value() && + remote_start_per_evse.second.first.idToken == id_token.value().idToken) { + + if (remote_start_per_evse.first == 0) { + return true; + } + + if (evse.has_value() && + evse.value().id == remote_start_per_evse.first) { + return true; + } + } + return false; + } + ); + + if (it != remote_start_id_per_evse.end()) { + // Found remote start. Set remote start id and the trigger reason. + call.msg.triggerReason = TriggerReasonEnum::RemoteStart; + call.msg.transactionInfo.remoteStartId = it->second.second; + + remote_start_id_per_evse.erase(it); + } + if (event_type == TransactionEventEnum::Started) { if (!evse.has_value() or !id_token.has_value()) { EVLOG_error << "Request to send TransactionEvent(Started) without given evse or id_token. These properties " "are required for this eventType \"Started\"!"; return; } + auto future = this->send_async(call); const auto enhanced_message = future.get(); if (enhanced_message.messageType == MessageType::TransactionEventResponse) { @@ -871,36 +902,6 @@ void ChargePoint::transaction_event_req(const TransactionEventEnum& event_type, // TODO(piet): offline handling } } else { - // Check if id token is in the remote start map, because when a remote - // start request is done, the first transaction event request should - // always contain trigger reason 'RemoteStart'. - auto it = std::find_if( - remote_start_id_per_evse.begin(), remote_start_id_per_evse.end(), - [&id_token, &evse](const std::pair>& remote_start_per_evse) { - if (id_token.has_value() && - remote_start_per_evse.second.first.idToken == id_token.value().idToken) { - - if (remote_start_per_evse.first == 0) { - return true; - } - - if (evse.has_value() && - evse.value().id == remote_start_per_evse.first) { - return true; - } - } - return false; - } - ); - - if (it != remote_start_id_per_evse.end()) { - // Found remote start. Set remote start id and the trigger reason. - call.msg.triggerReason = TriggerReasonEnum::RemoteStart; - call.msg.transactionInfo.remoteStartId = it->second.second; - - remote_start_id_per_evse.erase(it); - } - this->send(call); } }