Skip to content

Commit 7e017cf

Browse files
authored
Fix MeterValues tx-related message behavior (#356)
* revise latest changes in actual integration * fix MeterValues tx-related message order * adopt tx retry behavior * fix TriggerMessage for MeterValues
1 parent ed3034f commit 7e017cf

File tree

16 files changed

+635
-139
lines changed

16 files changed

+635
-139
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
- Don't change into Unavailable upon Reset ([#344](https://github.com/matth-x/MicroOcpp/pull/344))
4242
- Reject DataTransfer by default ([#344](https://github.com/matth-x/MicroOcpp/pull/344))
4343
- UnlockConnector NotSupported if connectorId invalid ([#344](https://github.com/matth-x/MicroOcpp/pull/344))
44-
- Fix regression bug of [#345](https://github.com/matth-x/MicroOcpp/pull/345) ([#353](https://github.com/matth-x/MicroOcpp/pull/353))
44+
- Fix regression bug of [#345](https://github.com/matth-x/MicroOcpp/pull/345) ([#353](https://github.com/matth-x/MicroOcpp/pull/353), [#356](https://github.com/matth-x/MicroOcpp/pull/356))
4545
- Correct MeterValue PreBoot timestamp ([#354](https://github.com/matth-x/MicroOcpp/pull/354))
4646

4747
## [1.1.0] - 2024-05-21

src/MicroOcpp/Core/Request.cpp

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ namespace MicroOcpp {
2929

3030
using namespace MicroOcpp;
3131

32-
Request::Request(std::unique_ptr<Operation> msg, const char *memory_tag) : MemoryManaged(memory_tag), messageID(makeString(getMemoryTag())), operation(std::move(msg)) {
32+
Request::Request(std::unique_ptr<Operation> msg) : MemoryManaged("Request.", msg->getOperationType()), messageID(makeString(getMemoryTag())), operation(std::move(msg)) {
3333
timeout_start = mocpp_tick_ms();
3434
debugRequest_start = mocpp_tick_ms();
3535
}
@@ -289,19 +289,15 @@ bool Request::isRequestSent() {
289289

290290
namespace MicroOcpp {
291291

292-
std::unique_ptr<Request> makeRequest(std::unique_ptr<Operation> operation, const char *memoryTag){
292+
std::unique_ptr<Request> makeRequest(std::unique_ptr<Operation> operation){
293293
if (operation == nullptr) {
294294
return nullptr;
295295
}
296-
return std::unique_ptr<Request>(new Request(std::move(operation), memoryTag));
296+
return std::unique_ptr<Request>(new Request(std::move(operation)));
297297
}
298298

299299
std::unique_ptr<Request> makeRequest(Operation *operation) {
300300
return makeRequest(std::unique_ptr<Operation>(operation));
301301
}
302302

303-
std::unique_ptr<Request> makeRequest(const char *memoryTag, Operation *operation) {
304-
return makeRequest(std::unique_ptr<Operation>(operation), memoryTag);
305-
}
306-
307303
} //end namespace MicroOcpp

src/MicroOcpp/Core/Request.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class Request : public MemoryManaged {
4141
bool requestSent = false;
4242
public:
4343

44-
Request(std::unique_ptr<Operation> msg, const char *memory_tag = "Request");
44+
Request(std::unique_ptr<Operation> msg);
4545

4646
~Request();
4747

@@ -121,9 +121,8 @@ class Request : public MemoryManaged {
121121
/*
122122
* Simple factory functions
123123
*/
124-
std::unique_ptr<Request> makeRequest(std::unique_ptr<Operation> op, const char *memoryTag = "Request");
124+
std::unique_ptr<Request> makeRequest(std::unique_ptr<Operation> op);
125125
std::unique_ptr<Request> makeRequest(Operation *op); //takes ownership of op
126-
std::unique_ptr<Request> makeRequest(const char *memoryTag, Operation *op); //takes ownership of op
127126

128127
} //end namespace MicroOcpp
129128

src/MicroOcpp/Core/RequestQueue.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#endif
1919

2020
#ifndef MO_NUM_REQUEST_QUEUES
21-
#define MO_NUM_REQUEST_QUEUES 5
21+
#define MO_NUM_REQUEST_QUEUES 10
2222
#endif
2323

2424
namespace MicroOcpp {

src/MicroOcpp/Model/ConnectorBase/Connector.cpp

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -92,14 +92,14 @@ Connector::Connector(Context& context, std::shared_ptr<FilesystemAdapter> filesy
9292
if (txNrPivot == std::numeric_limits<unsigned int>::max()) {
9393
txNrPivot = parsedTxNr;
9494
txNrBegin = parsedTxNr;
95-
txNrBack = (parsedTxNr + 1) % MAX_TX_CNT;
95+
txNrEnd = (parsedTxNr + 1) % MAX_TX_CNT;
9696
return 0;
9797
}
9898

9999
if ((parsedTxNr + MAX_TX_CNT - txNrPivot) % MAX_TX_CNT < MAX_TX_CNT / 2) {
100100
//parsedTxNr is after pivot point
101-
if ((parsedTxNr + 1 + MAX_TX_CNT - txNrPivot) % MAX_TX_CNT > (txNrBack + MAX_TX_CNT - txNrPivot) % MAX_TX_CNT) {
102-
txNrBack = (parsedTxNr + 1) % MAX_TX_CNT;
101+
if ((parsedTxNr + 1 + MAX_TX_CNT - txNrPivot) % MAX_TX_CNT > (txNrEnd + MAX_TX_CNT - txNrPivot) % MAX_TX_CNT) {
102+
txNrEnd = (parsedTxNr + 1) % MAX_TX_CNT;
103103
}
104104
} else if ((txNrPivot + MAX_TX_CNT - parsedTxNr) % MAX_TX_CNT < MAX_TX_CNT / 2) {
105105
//parsedTxNr is before pivot point
@@ -108,16 +108,16 @@ Connector::Connector(Context& context, std::shared_ptr<FilesystemAdapter> filesy
108108
}
109109
}
110110

111-
MO_DBG_DEBUG("found %s%u.jsn - Internal range from %u to %u (exclusive)", txFnamePrefix, parsedTxNr, txNrBegin, txNrBack);
111+
MO_DBG_DEBUG("found %s%u.jsn - Internal range from %u to %u (exclusive)", txFnamePrefix, parsedTxNr, txNrBegin, txNrEnd);
112112
}
113113
return 0;
114114
});
115115

116-
MO_DBG_DEBUG("found %u transactions for connector %u. Internal range from %u to %u (exclusive)", (txNrBack + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT, connectorId, txNrBegin, txNrBack);
116+
MO_DBG_DEBUG("found %u transactions for connector %u. Internal range from %u to %u (exclusive)", (txNrEnd + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT, connectorId, txNrBegin, txNrEnd);
117117
txNrFront = txNrBegin;
118118

119119
if (model.getTransactionStore()) {
120-
unsigned int txNrLatest = (txNrBack + MAX_TX_CNT - 1) % MAX_TX_CNT; //txNr of the most recent tx on flash
120+
unsigned int txNrLatest = (txNrEnd + MAX_TX_CNT - 1) % MAX_TX_CNT; //txNr of the most recent tx on flash
121121
transaction = model.getTransactionStore()->getTransaction(connectorId, txNrLatest); //returns nullptr if txNrLatest does not exist on flash
122122
} else {
123123
MO_DBG_ERR("must initialize TxStore before Connector");
@@ -263,26 +263,26 @@ void Connector::loop() {
263263
}
264264

265265
if (removed) {
266-
if (txNrFront == txNrBack) {
266+
if (txNrFront == txNrEnd) {
267267
txNrFront = transaction->getTxNr();
268268
}
269-
txNrBack = transaction->getTxNr(); //roll back creation of last tx entry
269+
txNrEnd = transaction->getTxNr(); //roll back creation of last tx entry
270270
}
271271

272272
MO_DBG_DEBUG("collect aborted or silent transaction %u-%u %s", connectorId, transaction->getTxNr(), removed ? "" : "failure");
273-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
273+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
274274
transaction = nullptr;
275275
}
276276

277277
if (transaction && transaction->isAborted()) {
278278
MO_DBG_DEBUG("collect aborted transaction %u-%u", connectorId, transaction->getTxNr());
279-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
279+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
280280
transaction = nullptr;
281281
}
282282

283283
if (transaction && transaction->getStopSync().isRequested()) {
284284
MO_DBG_DEBUG("collect obsolete transaction %u-%u", connectorId, transaction->getTxNr());
285-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
285+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
286286
transaction = nullptr;
287287
}
288288

@@ -550,8 +550,8 @@ std::shared_ptr<Transaction> Connector::allocateTransaction() {
550550
std::shared_ptr<Transaction> tx;
551551

552552
//clean possible aborted tx
553-
unsigned int txr = txNrBack;
554-
unsigned int txSize = (txNrBack + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT;
553+
unsigned int txr = txNrEnd;
554+
unsigned int txSize = (txNrEnd + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT;
555555
for (unsigned int i = 0; i < txSize; i++) {
556556
txr = (txr + MAX_TX_CNT - 1) % MAX_TX_CNT; //decrement by 1
557557

@@ -567,10 +567,10 @@ std::shared_ptr<Transaction> Connector::allocateTransaction() {
567567
removed &= model.getTransactionStore()->remove(connectorId, txr);
568568
}
569569
if (removed) {
570-
if (txNrFront == txNrBack) {
570+
if (txNrFront == txNrEnd) {
571571
txNrFront = txr;
572572
}
573-
txNrBack = txr;
573+
txNrEnd = txr;
574574
MO_DBG_WARN("deleted dangling silent or aborted tx for new transaction");
575575
} else {
576576
MO_DBG_ERR("memory corruption");
@@ -582,18 +582,18 @@ std::shared_ptr<Transaction> Connector::allocateTransaction() {
582582
}
583583
}
584584

585-
txSize = (txNrBack + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT; //refresh after cleaning txs
585+
txSize = (txNrEnd + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT; //refresh after cleaning txs
586586

587587
//try to create new transaction
588588
if (txSize < MO_TXRECORD_SIZE) {
589-
tx = model.getTransactionStore()->createTransaction(connectorId, txNrBack);
589+
tx = model.getTransactionStore()->createTransaction(connectorId, txNrEnd);
590590
}
591591

592592
if (!tx) {
593593
//could not create transaction - now, try to replace tx history entry
594594

595595
unsigned int txl = txNrBegin;
596-
txSize = (txNrBack + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT;
596+
txSize = (txNrEnd + MAX_TX_CNT - txNrBegin) % MAX_TX_CNT;
597597

598598
for (unsigned int i = 0; i < txSize; i++) {
599599

@@ -621,9 +621,9 @@ std::shared_ptr<Transaction> Connector::allocateTransaction() {
621621
txNrFront = txNrBegin;
622622
}
623623
MO_DBG_DEBUG("deleted tx history entry for new transaction");
624-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
624+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
625625

626-
tx = model.getTransactionStore()->createTransaction(connectorId, txNrBack);
626+
tx = model.getTransactionStore()->createTransaction(connectorId, txNrEnd);
627627
} else {
628628
MO_DBG_ERR("memory corruption");
629629
break;
@@ -643,7 +643,7 @@ std::shared_ptr<Transaction> Connector::allocateTransaction() {
643643
//couldn't create normal transaction -> check if to start charging without real transaction
644644
if (silentOfflineTransactionsBool && silentOfflineTransactionsBool->getBool()) {
645645
//try to handle charging session without sending StartTx or StopTx to the server
646-
tx = model.getTransactionStore()->createTransaction(connectorId, txNrBack, true);
646+
tx = model.getTransactionStore()->createTransaction(connectorId, txNrEnd, true);
647647

648648
if (tx) {
649649
MO_DBG_DEBUG("created silent transaction");
@@ -661,9 +661,9 @@ std::shared_ptr<Transaction> Connector::allocateTransaction() {
661661
}
662662

663663
if (tx) {
664-
txNrBack = (txNrBack + 1) % MAX_TX_CNT;
665-
MO_DBG_DEBUG("advance txNrBack %u-%u", connectorId, txNrBack);
666-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
664+
txNrEnd = (txNrEnd + 1) % MAX_TX_CNT;
665+
MO_DBG_DEBUG("advance txNrEnd %u-%u", connectorId, txNrEnd);
666+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
667667
}
668668

669669
return tx;
@@ -1083,12 +1083,12 @@ unsigned int Connector::getFrontRequestOpNr() {
10831083
* Advance front transaction?
10841084
*/
10851085

1086-
unsigned int txSize = (txNrBack + MAX_TX_CNT - txNrFront) % MAX_TX_CNT;
1086+
unsigned int txSize = (txNrEnd + MAX_TX_CNT - txNrFront) % MAX_TX_CNT;
10871087

10881088
if (transactionFront && txSize == 0) {
10891089
//catch edge case where txBack has been rolled back and txFront was equal to txBack
10901090
MO_DBG_DEBUG("collect front transaction %u-%u after tx rollback", connectorId, transactionFront->getTxNr());
1091-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
1091+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
10921092
transactionFront = nullptr;
10931093
}
10941094

@@ -1110,7 +1110,7 @@ unsigned int Connector::getFrontRequestOpNr() {
11101110
MO_DBG_DEBUG("collect front transaction %u-%u", connectorId, transactionFront->getTxNr());
11111111
transactionFront = nullptr;
11121112
txNrFront = (txNrFront + 1) % MAX_TX_CNT;
1113-
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrBack=%u", txNrBegin, txNrFront, txNrBack);
1113+
MO_DBG_VERBOSE("txNrBegin=%u, txNrFront=%u, txNrEnd=%u", txNrBegin, txNrFront, txNrEnd);
11141114
} else {
11151115
//front is accurate. Done here
11161116
break;
@@ -1166,7 +1166,7 @@ std::unique_ptr<Request> Connector::fetchFrontRequest() {
11661166
}
11671167

11681168
Timestamp nextAttempt = transactionFront->getStartSync().getAttemptTime() +
1169-
transactionFront->getStartSync().getAttemptNr() * transactionMessageRetryIntervalInt->getInt();
1169+
transactionFront->getStartSync().getAttemptNr() * std::max(0, transactionMessageRetryIntervalInt->getInt());
11701170

11711171
if (nextAttempt > model.getClock().now()) {
11721172
return nullptr;
@@ -1223,7 +1223,7 @@ std::unique_ptr<Request> Connector::fetchFrontRequest() {
12231223
}
12241224

12251225
Timestamp nextAttempt = transactionFront->getStopSync().getAttemptTime() +
1226-
transactionFront->getStopSync().getAttemptNr() * transactionMessageRetryIntervalInt->getInt();
1226+
transactionFront->getStopSync().getAttemptNr() * std::max(0, transactionMessageRetryIntervalInt->getInt());
12271227

12281228
if (nextAttempt > model.getClock().now()) {
12291229
return nullptr;
@@ -1270,3 +1270,15 @@ std::unique_ptr<Request> Connector::fetchFrontRequest() {
12701270

12711271
return nullptr;
12721272
}
1273+
1274+
unsigned int Connector::getTxNrBeginHistory() {
1275+
return txNrBegin;
1276+
}
1277+
1278+
unsigned int Connector::getTxNrFront() {
1279+
return txNrFront;
1280+
}
1281+
1282+
unsigned int Connector::getTxNrEnd() {
1283+
return txNrEnd;
1284+
}

src/MicroOcpp/Model/ConnectorBase/Connector.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class Connector : public RequestEmitter, public MemoryManaged {
9595

9696
unsigned int txNrBegin = 0; //oldest (historical) transaction on flash. Has no function, but is useful for error diagnosis
9797
unsigned int txNrFront = 0; //oldest transaction which is still queued to be sent to the server
98-
unsigned int txNrBack = 0; //one position behind newest transaction
98+
unsigned int txNrEnd = 0; //one position behind newest transaction
9999

100100
std::shared_ptr<Transaction> transactionFront;
101101
public:
@@ -157,6 +157,10 @@ class Connector : public RequestEmitter, public MemoryManaged {
157157

158158
unsigned int getFrontRequestOpNr() override;
159159
std::unique_ptr<Request> fetchFrontRequest() override;
160+
161+
unsigned int getTxNrBeginHistory(); //if getTxNrBeginHistory() != getTxNrFront(), then return value is the txNr of the oldest tx history entry. If equal to getTxNrFront(), then the history is empty
162+
unsigned int getTxNrFront(); //if getTxNrEnd() != getTxNrFront(), then return value is the txNr of the oldest transaction queued to be sent to the server. If equal to getTxNrEnd(), then there is no tx to be sent to the server
163+
unsigned int getTxNrEnd(); //upper limit for the range of valid txNrs
160164
};
161165

162166
} //end namespace MicroOcpp

src/MicroOcpp/Model/Diagnostics/DiagnosticsService.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919
#include <MicroOcpp/Version.h> //for MO_ENABLE_V201
2020
#include <MicroOcpp/Model/ConnectorBase/UnlockConnectorResult.h> //for MO_ENABLE_CONNECTOR_LOCK
2121

22-
using namespace MicroOcpp;
23-
using Ocpp16::DiagnosticsStatus;
22+
using MicroOcpp::DiagnosticsService;
23+
using MicroOcpp::Ocpp16::DiagnosticsStatus;
24+
using MicroOcpp::Request;
2425

2526
DiagnosticsService::DiagnosticsService(Context& context) : MemoryManaged("v16.Diagnostics.DiagnosticsService"), context(context), location(makeString(getMemoryTag())), diagFileList(makeVector<String>(getMemoryTag())) {
2627

src/MicroOcpp/Model/Metering/MeterValue.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Copyright Matthias Akstaller 2019 - 2024
33
// MIT License
44

5+
#include <limits>
6+
57
#include <MicroOcpp/Model/Metering/MeterValue.h>
68
#include <MicroOcpp/Core/Configuration.h>
79
#include <MicroOcpp/Debug.h>
@@ -67,6 +69,42 @@ ReadingContext MeterValue::getReadingContext() {
6769
return ReadingContext::NOT_SET;
6870
}
6971

72+
void MeterValue::setTxNr(unsigned int txNr) {
73+
if (txNr > (unsigned int)std::numeric_limits<int>::max()) {
74+
MO_DBG_ERR("invalid arg");
75+
return;
76+
}
77+
this->txNr = (int)txNr;
78+
}
79+
80+
int MeterValue::getTxNr() {
81+
return txNr;
82+
}
83+
84+
void MeterValue::setOpNr(unsigned int opNr) {
85+
this->opNr = opNr;
86+
}
87+
88+
unsigned int MeterValue::getOpNr() {
89+
return opNr;
90+
}
91+
92+
void MeterValue::advanceAttemptNr() {
93+
attemptNr++;
94+
}
95+
96+
unsigned int MeterValue::getAttemptNr() {
97+
return attemptNr;
98+
}
99+
100+
unsigned long MeterValue::getAttemptTime() {
101+
return attemptTime;
102+
}
103+
104+
void MeterValue::setAttemptTime(unsigned long timestamp) {
105+
this->attemptTime = timestamp;
106+
}
107+
70108
MeterValueBuilder::MeterValueBuilder(const Vector<std::unique_ptr<SampledValueSampler>> &samplers,
71109
std::shared_ptr<Configuration> samplersSelectStr) :
72110
MemoryManaged("v16.Metering.MeterValueBuilder"),

src/MicroOcpp/Model/Metering/MeterValue.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ class MeterValue : public MemoryManaged {
1818
private:
1919
Timestamp timestamp;
2020
Vector<std::unique_ptr<SampledValue>> sampledValue;
21+
22+
int txNr = -1;
23+
unsigned int opNr = 1;
24+
unsigned int attemptNr = 0;
25+
unsigned long attemptTime = 0;
2126
public:
2227
MeterValue(const Timestamp& timestamp);
2328
MeterValue(const MeterValue& other) = delete;
@@ -30,6 +35,18 @@ class MeterValue : public MemoryManaged {
3035
void setTimestamp(Timestamp timestamp);
3136

3237
ReadingContext getReadingContext();
38+
39+
void setTxNr(unsigned int txNr);
40+
int getTxNr();
41+
42+
void setOpNr(unsigned int opNr);
43+
unsigned int getOpNr();
44+
45+
void advanceAttemptNr();
46+
unsigned int getAttemptNr();
47+
48+
unsigned long getAttemptTime();
49+
void setAttemptTime(unsigned long timestamp);
3350
};
3451

3552
class MeterValueBuilder : public MemoryManaged {

0 commit comments

Comments
 (0)