Skip to content

Commit

Permalink
Merge pull request #383 from matth-x/fix/octt_16_2
Browse files Browse the repository at this point in the history
  • Loading branch information
matth-x authored Nov 6, 2024
2 parents 2187f79 + 301dd5f commit 2d5dee9
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 12 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## Unreleased

### Changed

- Improved UUID generation ([#383](https://github.com/matth-x/MicroOcpp/pull/383))

### Fixed

- Timing issues for OCTT test cases ([#383](https://github.com/matth-x/MicroOcpp/pull/383))

## [1.2.0] - 2024-11-03

### Changed
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ set(MO_SRC
src/MicroOcpp/Core/Request.cpp
src/MicroOcpp/Core/Connection.cpp
src/MicroOcpp/Core/Time.cpp
src/MicroOcpp/Core/UuidUtils.cpp
src/MicroOcpp/Operations/Authorize.cpp
src/MicroOcpp/Operations/BootNotification.cpp
src/MicroOcpp/Operations/CancelReservation.cpp
Expand Down
14 changes: 4 additions & 10 deletions src/MicroOcpp/Core/Request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <MicroOcpp/Core/Operation.h>
#include <MicroOcpp/Core/Connection.h>
#include <MicroOcpp/Model/Transactions/Transaction.h>
#include <MicroOcpp/Core/UuidUtils.h>

#include <MicroOcpp/Operations/StartTransaction.h>
#include <MicroOcpp/Operations/StopTransaction.h>
Expand Down Expand Up @@ -68,16 +69,9 @@ void Request::setMessageID(const char *id){
Request::CreateRequestResult Request::createRequest(JsonDoc& requestJson) {

if (messageID.empty()) {
unsigned char random [18];
char guuid [sizeof(random) * 2 + 1];

writeRandomNonsecure(random, sizeof(random));

for (size_t i = 0; i < sizeof(random); i++) {
snprintf(guuid + i * 2, 3, "%02x", random[i]);
}
guuid[8] = guuid[13] = guuid[18] = guuid[23] = '-';
messageID = guuid;
char uuid [37] = {'\0'};
generateUUID(uuid, 37);
messageID = uuid;
}

/*
Expand Down
7 changes: 7 additions & 0 deletions src/MicroOcpp/Core/Time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,13 @@ int Timestamp::operator-(const Timestamp &rhs) const {
}

int dt = (lhsDays - rhsDays) * (24 * 3600) + (hour - rhs.hour) * 3600 + (minute - rhs.minute) * 60 + second - rhs.second;

#if MO_ENABLE_TIMESTAMP_MILLISECONDS
// Make it so that we round the difference to the nearest second, instead of being up to almost a whole second off
if ((ms - rhs.ms) > 500) dt++;
if ((ms - rhs.ms) < -500) dt--;
#endif //MO_ENABLE_TIMESTAMP_MILLISECONDS

return dt;
}

Expand Down
56 changes: 56 additions & 0 deletions src/MicroOcpp/Core/UuidUtils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#include <MicroOcpp/Core/UuidUtils.h>
#include <MicroOcpp/Platform.h>

#include <stdint.h>

namespace MicroOcpp {

#define UUID_STR_LEN 36

bool generateUUID(char *uuidBuffer, size_t len) {
if (len < UUID_STR_LEN + 1)
{
return false;
}

uint32_t ar[4];
for (uint8_t i = 0; i < 4; i++) {
ar[i] = mocpp_rng();
}

// Conforming to RFC 4122 Specification
// - byte 7: four most significant bits ==> 0100 --> always 4
// - byte 9: two most significant bits ==> 10 --> always {8, 9, A, B}.
//
// patch bits for version 1 and variant 4 here
ar[1] &= 0xFFF0FFFF; // remove 4 bits.
ar[1] |= 0x00040000; // variant 4
ar[2] &= 0xFFFFFFF3; // remove 2 bits
ar[2] |= 0x00000008; // version 1

// loop through the random 16 byte array
for (uint8_t i = 0, j = 0; i < 16; i++) {
// multiples of 4 between 8 and 20 get a -.
// note we are processing 2 digits in one loop.
if ((i & 0x1) == 0) {
if ((4 <= i) && (i <= 10)) {
uuidBuffer[j++] = '-';
}
}

// encode the byte as two hex characters
uint8_t nr = i / 4;
uint8_t xx = ar[nr];
uint8_t ch = xx & 0x0F;
uuidBuffer[j++] = (ch < 10)? '0' + ch : ('a' - 10) + ch;

ch = (xx >> 4) & 0x0F;
ar[nr] >>= 8;
uuidBuffer[j++] = (ch < 10)? '0' + ch : ('a' - 10) + ch;
}

uuidBuffer[UUID_STR_LEN] = 0;
return true;
}

}
14 changes: 14 additions & 0 deletions src/MicroOcpp/Core/UuidUtils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#ifndef MO_UUIDUTILS_H
#define MO_UUIDUTILS_H

#include <stddef.h>
namespace MicroOcpp {

// Generates a UUID (Universally Unique Identifier) and writes it into a given buffer
// Returns false if the generation failed
// The buffer must be at least 37 bytes long (36 characters + zero termination)
bool generateUUID(char *uuidBuffer, size_t len);

}

#endif
2 changes: 1 addition & 1 deletion src/MicroOcpp/Model/ConnectorBase/Connector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ void Connector::loop() {
transaction->getBeginTimestamp() > MIN_TIME &&
connectionTimeOutInt && connectionTimeOutInt->getInt() > 0 &&
!connectorPluggedInput() &&
model.getClock().now() - transaction->getBeginTimestamp() >= connectionTimeOutInt->getInt()) {
model.getClock().now() - transaction->getBeginTimestamp() > connectionTimeOutInt->getInt()) {

MO_DBG_INFO("Session mngt: timeout");
transaction->setInactive();
Expand Down
2 changes: 2 additions & 0 deletions src/MicroOcpp/Model/Heartbeat/HeartbeatService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ void HeartbeatService::loop() {
lastHeartbeat = now;

auto heartbeat = makeRequest(new Ocpp16::Heartbeat(context.getModel()));
// Heartbeats can not deviate more than 4s from the configured interval
heartbeat->setTimeout(std::min(4000UL, hbInterval));
context.initiateRequest(std::move(heartbeat));
}
}
2 changes: 1 addition & 1 deletion src/MicroOcpp/Model/Metering/MeteringConnector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void MeteringConnector::loop() {

auto& timestampNow = model.getClock().now();
auto dt = nextAlignedTime - timestampNow;
if (dt <= 0 || //normal case: interval elapsed
if (dt < 0 || //normal case: interval elapsed
dt > clockAlignedDataIntervalInt->getInt()) { //special case: clock has been adjusted or first run

MO_DBG_DEBUG("Clock aligned measurement %ds: %s", dt,
Expand Down
28 changes: 28 additions & 0 deletions src/MicroOcpp/Platform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,31 @@ unsigned long mocpp_tick_ms_unix() {
}
#endif
#endif

#ifdef MO_CUSTOM_RNG
uint32_t (*mocpp_rng_impl)() = nullptr;

void mocpp_set_rng(uint32_t (*rng)()) {
mocpp_rng_impl = rng;
}

uint32_t mocpp_rng_custom(void) {
if (mocpp_rng_impl) {
return mocpp_rng_impl();
} else {
return 0;
}
}
#else

// Time-based Pseudo RNG.
// Contains internal state which is mixed with the current timestamp
// each time it is called. Then this is passed through a multiply-with-carry
// PRNG operation to get a pseudo-random number.
uint32_t mocpp_time_based_prng(void) {
static uint32_t prng_state = 1;
uint32_t entropy = mocpp_tick_ms();
prng_state = (prng_state ^ entropy)*1664525U + 1013904223U; // assuming complement-2 integers and non-signaling overflow
return prng_state;
}
#endif
11 changes: 11 additions & 0 deletions src/MicroOcpp/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef MO_PLATFORM_H
#define MO_PLATFORM_H

#include <stdint.h>

#define MO_PLATFORM_NONE 0
#define MO_PLATFORM_ARDUINO 1
#define MO_PLATFORM_ESPIDF 2
Expand Down Expand Up @@ -95,6 +97,15 @@ extern "C" unsigned long mocpp_tick_ms_unix();
#endif
#endif

#ifdef MO_CUSTOM_RNG
void mocpp_set_rng(uint32_t (*rng)());
uint32_t mocpp_rng_custom();
#define mocpp_rng mocpp_rng_custom
#else
uint32_t mocpp_time_based_prng(void);
#define mocpp_rng mocpp_time_based_prng
#endif

#ifndef MO_MAX_JSON_CAPACITY
#if MO_PLATFORM == MO_PLATFORM_UNIX
#define MO_MAX_JSON_CAPACITY 16384
Expand Down
7 changes: 7 additions & 0 deletions src/MicroOcpp_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,13 @@ void ocpp_set_console_out_c(void (*console_out)(const char *msg)) {
mocpp_set_console_out(console_out);
}

#ifdef MO_CUSTOM_RNG
void ocpp_set_rng_c(uint32_t (*rng)(void))
{
mocpp_set_rng(rng);
}
#endif

void ocpp_authorize(const char *idTag, AuthorizeConfCallback onConfirmation, AuthorizeAbortCallback onAbort, AuthorizeTimeoutCallback onTimeout, AuthorizeErrorCallback onError, void *user_data) {

auto idTag_capture = MicroOcpp::makeString("MicroOcpp_c.cpp", idTag);
Expand Down
8 changes: 8 additions & 0 deletions src/MicroOcpp_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,14 @@ void ocpp_setOnSendConf(const char *operationType, OnMessage onConfirmation);
*/
void ocpp_set_console_out_c(void (*console_out)(const char *msg));

#ifdef MO_CUSTOM_RNG
/**
* If build flag MO_CUSTOM_RNG is set, calls to get random numbers shall be
* forwarded to the function provided through this setter.
*/
void ocpp_set_rng_c( uint32_t (*rng)(void));
#endif

/*
* Send OCPP operations
*/
Expand Down

0 comments on commit 2d5dee9

Please sign in to comment.