diff --git a/CHANGELOG.md b/CHANGELOG.md index 46857bce..73ebdbc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ - Reject DataTransfer by default ([#344](https://github.com/matth-x/MicroOcpp/pull/344)) - UnlockConnector NotSupported if connectorId invalid ([#344](https://github.com/matth-x/MicroOcpp/pull/344)) - Fix regression bug of [#345](https://github.com/matth-x/MicroOcpp/pull/345) ([#353](https://github.com/matth-x/MicroOcpp/pull/353)) +- Correct MeterValue PreBoot timestamp ([#354](https://github.com/matth-x/MicroOcpp/pull/354)) ## [1.1.0] - 2024-05-21 diff --git a/src/MicroOcpp/Model/Metering/MeteringConnector.cpp b/src/MicroOcpp/Model/Metering/MeteringConnector.cpp index 45373443..737a106e 100644 --- a/src/MicroOcpp/Model/Metering/MeteringConnector.cpp +++ b/src/MicroOcpp/Model/Metering/MeteringConnector.cpp @@ -57,7 +57,7 @@ std::unique_ptr MeteringConnector::loop() { } if ((txBreak || meterData.size() >= (size_t) meterValueCacheSizeInt->getInt()) && !meterData.empty()) { - auto meterValues = std::unique_ptr(new MeterValues(std::move(meterData), connectorId, transaction)); + auto meterValues = std::unique_ptr(new MeterValues(model, std::move(meterData), connectorId, transaction)); meterData = makeVector>(getMemoryTag()); return std::move(meterValues); //std::move is required for some compilers even if it's not mandated by standard C++ } @@ -168,7 +168,7 @@ std::unique_ptr MeteringConnector::takeTriggeredMeterValues() { transaction = model.getConnector(connectorId)->getTransaction(); } - return std::unique_ptr(new MeterValues(std::move(mv_now), connectorId, transaction)); + return std::unique_ptr(new MeterValues(model, std::move(mv_now), connectorId, transaction)); } void MeteringConnector::addMeterValueSampler(std::unique_ptr meterValueSampler) { diff --git a/src/MicroOcpp/Model/Metering/MeteringService.cpp b/src/MicroOcpp/Model/Metering/MeteringService.cpp index 9196865f..a404ab48 100644 --- a/src/MicroOcpp/Model/Metering/MeteringService.cpp +++ b/src/MicroOcpp/Model/Metering/MeteringService.cpp @@ -78,8 +78,8 @@ MeteringService::MeteringService(Context& context, int numConn, std::shared_ptr< * is connected with a WebSocket echo server, let it reply to its own requests. * Mocking an OCPP Server on the same device makes running (unit) tests easier. */ - context.getOperationRegistry().registerOperation("MeterValues", [] () { - return new Ocpp16::MeterValues();}); + context.getOperationRegistry().registerOperation("MeterValues", [this] () { + return new Ocpp16::MeterValues(this->context.getModel());}); } void MeteringService::loop(){ diff --git a/src/MicroOcpp/Operations/MeterValues.cpp b/src/MicroOcpp/Operations/MeterValues.cpp index 905e63dc..f6ab2d7c 100644 --- a/src/MicroOcpp/Operations/MeterValues.cpp +++ b/src/MicroOcpp/Operations/MeterValues.cpp @@ -14,12 +14,12 @@ using MicroOcpp::JsonDoc; #define ENERGY_METER_TIMEOUT_MS 30 * 1000 //after waiting for 30s, send MeterValues without missing readings //can only be used for echo server debugging -MeterValues::MeterValues() : MemoryManaged("v16.Operation.", "MeterValues") { +MeterValues::MeterValues(Model& model) : MemoryManaged("v16.Operation.", "MeterValues"), model(model) { } -MeterValues::MeterValues(Vector>&& meterValue, unsigned int connectorId, std::shared_ptr transaction) - : MemoryManaged("v16.Operation.", "MeterValues"), meterValue{std::move(meterValue)}, connectorId{connectorId}, transaction{transaction} { +MeterValues::MeterValues(Model& model, Vector>&& meterValue, unsigned int connectorId, std::shared_ptr transaction) + : MemoryManaged("v16.Operation.", "MeterValues"), model(model), meterValue{std::move(meterValue)}, connectorId{connectorId}, transaction{transaction} { } @@ -36,8 +36,15 @@ std::unique_ptr MeterValues::createReq() { size_t capacity = 0; auto entries = makeVector>(getMemoryTag()); - for (auto value = meterValue.begin(); value != meterValue.end(); value++) { - auto entry = (*value)->toJson(); + for (auto mv = meterValue.begin(); mv != meterValue.end(); mv++) { + + if ((*mv)->getTimestamp() < MIN_TIME) { + MO_DBG_DEBUG("adjust preboot MeterValue timestamp"); + Timestamp adjusted = model.getClock().adjustPrebootTimestamp((*mv)->getTimestamp()); + (*mv)->setTimestamp(adjusted); + } + + auto entry = (*mv)->toJson(); if (entry) { capacity += entry->capacity(); entries.push_back(std::move(entry)); diff --git a/src/MicroOcpp/Operations/MeterValues.h b/src/MicroOcpp/Operations/MeterValues.h index 012151d5..f4e4be4e 100644 --- a/src/MicroOcpp/Operations/MeterValues.h +++ b/src/MicroOcpp/Operations/MeterValues.h @@ -11,6 +11,7 @@ namespace MicroOcpp { +class Model; class MeterValue; class Transaction; @@ -18,6 +19,7 @@ namespace Ocpp16 { class MeterValues : public Operation, public MemoryManaged { private: + Model& model; //for adjusting the timestamp if MeterValue has been created before BootNotification Vector> meterValue; unsigned int connectorId = 0; @@ -25,9 +27,9 @@ class MeterValues : public Operation, public MemoryManaged { std::shared_ptr transaction; public: - MeterValues(Vector>&& meterValue, unsigned int connectorId, std::shared_ptr transaction = nullptr); + MeterValues(Model& model, Vector>&& meterValue, unsigned int connectorId, std::shared_ptr transaction = nullptr); - MeterValues(); //for debugging only. Make this for the server pendant + MeterValues(Model& model); //for debugging only. Make this for the server pendant ~MeterValues();