diff --git a/include/ocpp/v201/charge_point.hpp b/include/ocpp/v201/charge_point.hpp index e28e1318f..dcc843544 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; @@ -297,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 9f4b8a3a6..c72eb8dea 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(); @@ -162,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; @@ -231,6 +234,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 @@ -845,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) { @@ -1246,12 +1288,15 @@ void ChargePoint::handle_remote_start_transaction_request(Call