@@ -113,6 +113,21 @@ bool is_transaction_message(const ocpp::v16::MessageType message_type);
113
113
// / \return true if MessageType is TransactionEvent or SecurityEventNotification
114
114
bool is_transaction_message (const ocpp::v201::MessageType message_type);
115
115
116
+ // / \brief Indicates if the given \p message_type is a StartTransaction message
117
+ // / \param message_type
118
+ // / \return true if MessageType is a StartTransaction
119
+ bool is_start_transaction_message (const ocpp::v16::MessageType message_type);
120
+
121
+ // / \brief Indicates if the given \p message_type is a StartTransaction message.
122
+ // / \param message_type
123
+ // / \return Always return false
124
+ bool is_start_transaction_message (const ocpp::v201::MessageType message_type);
125
+
126
+ // / \brief Indicates if the given \p control_message is a start transaction message
127
+ template <typename M> auto is_start_transaction_message (const ControlMessage<M>& control_message) {
128
+ return is_start_transaction_message (control_message.messageType );
129
+ }
130
+
116
131
// / \brief Indicates if the given \p control_message is a transaction related message
117
132
template <typename M> auto is_transaction_message (const ControlMessage<M>& control_message) {
118
133
return is_transaction_message (control_message.messageType );
@@ -186,6 +201,10 @@ template <typename M> class MessageQueue {
186
201
// was queued. This can happen when the CP has not received a StartTransaction.conf from the CSMS.
187
202
std::map<std::string, std::vector<std::string>> start_transaction_mid_meter_values_mid_map;
188
203
204
+ // This callback is called when a StartTransaction.req message could not be delivered due to a timeout or CALL_ERROR
205
+ std::function<void (const std::string& new_message_id, const std::string& old_message_id)>
206
+ start_transaction_message_retry_callback;
207
+
189
208
MessageId getMessageId (const json::array_t & json_message) {
190
209
return MessageId (json_message.at (MESSAGE_ID).get <std::string>());
191
210
}
@@ -363,9 +382,12 @@ template <typename M> class MessageQueue {
363
382
364
383
public:
365
384
// / \brief Creates a new MessageQueue object with the provided \p configuration and \p send_callback
366
- MessageQueue (const std::function<bool (json message)>& send_callback, const MessageQueueConfig& config,
367
- const std::vector<M>& external_notify,
368
- std::shared_ptr<common::DatabaseHandlerCommon> database_handler) :
385
+ MessageQueue (
386
+ const std::function<bool (json message)>& send_callback, const MessageQueueConfig& config,
387
+ const std::vector<M>& external_notify, std::shared_ptr<common::DatabaseHandlerCommon> database_handler,
388
+ const std::function<void (const std::string& new_message_id, const std::string& old_message_id)>
389
+ start_transaction_message_retry_callback =
390
+ [](const std::string& new_message_id, const std::string& old_message_id) {}) :
369
391
database_handler (std::move(database_handler)),
370
392
config (config),
371
393
external_notify (external_notify),
@@ -374,7 +396,8 @@ template <typename M> class MessageQueue {
374
396
running (true ),
375
397
new_message (false ),
376
398
is_registration_status_accepted (false ),
377
- uuid_generator (boost::uuids::random_generator()) {
399
+ uuid_generator (boost::uuids::random_generator()),
400
+ start_transaction_message_retry_callback (start_transaction_message_retry_callback) {
378
401
379
402
this ->send_callback = send_callback;
380
403
this ->in_flight = nullptr ;
@@ -446,10 +469,12 @@ template <typename M> class MessageQueue {
446
469
return false ;
447
470
};
448
471
449
- // Find the first allowed transaction message
472
+ // Transaction messages must persist the order, so only check the first in the queue
450
473
auto selected_transaction_message_it =
451
- std::find_if (transaction_message_queue.begin (), transaction_message_queue.end (),
452
- is_transaction_message_available);
474
+ (!transaction_message_queue.empty () and
475
+ is_transaction_message_available (transaction_message_queue.front ()))
476
+ ? transaction_message_queue.begin ()
477
+ : transaction_message_queue.end ();
453
478
454
479
if (selected_transaction_message_it != transaction_message_queue.end ()) {
455
480
message = *selected_transaction_message_it;
@@ -808,6 +833,7 @@ template <typename M> class MessageQueue {
808
833
if (this ->in_flight ->message_attempts < this ->config .transaction_message_attempts ) {
809
834
EVLOG_warning << " Message shall be persisted and will therefore be sent again" ;
810
835
// Generate a new message ID for the retry
836
+ const auto old_message_id = this ->in_flight ->message [MESSAGE_ID];
811
837
this ->in_flight ->message [MESSAGE_ID] = this ->createMessageId ();
812
838
if (this ->config .transaction_message_retry_interval > 0 ) {
813
839
// exponential backoff
@@ -832,6 +858,10 @@ template <typename M> class MessageQueue {
832
858
} else if (queue_type == QueueType::Normal) {
833
859
this ->normal_message_queue .push_front (this ->in_flight );
834
860
}
861
+ if (is_start_transaction_message (*this ->in_flight )) {
862
+ this ->start_transaction_message_retry_callback (this ->in_flight ->message [MESSAGE_ID],
863
+ old_message_id);
864
+ }
835
865
this ->notify_queue_timer .at (
836
866
[this ]() {
837
867
this ->new_message = true ;
0 commit comments