Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/pio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@ jobs:

runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
example: [examples/ESP/main.cpp, examples/ESP-TLS/main.cpp]
# "pinned" keeps the ArduinoJson version pinned in platformio.ini (currently v6.20.1); "v7" overrides it to
# verify ArduinoJson v7 compatibility as well
arduinojson: [pinned, v7]

steps:
- uses: actions/checkout@v4
Expand All @@ -42,6 +46,11 @@ jobs:
- name: Install library dependencies
run: pio pkg install
- name: Run PlatformIO
run: pio ci --lib="." --project-conf=platformio.ini ${{ matrix.dashboard-extra }}
run: |
if [ "${{ matrix.arduinojson }}" = "v7" ]; then
pio ci --lib="." --project-conf=platformio.ini -O "lib_deps=bblanchon/ArduinoJson@7.4.3" ${{ matrix.dashboard-extra }}
else
pio ci --lib="." --project-conf=platformio.ini ${{ matrix.dashboard-extra }}
fi
env:
PLATFORMIO_CI_SRC: ${{ matrix.example }}
22 changes: 19 additions & 3 deletions .github/workflows/platformless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,24 @@ on:
jobs:

compile-platform:
name: Compile (no linking)
name: Compile (no linking, ArduinoJson ${{ matrix.arduinojson-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- arduinojson-version: v6.19.4
arduinojson-url: https://github.com/bblanchon/ArduinoJson/releases/download/v6.19.4/ArduinoJson-v6.19.4.h
# ArduinoJson v6 doesn't emit any deprecation warnings for the API used here, so keep treating warnings as errors
werror-flag: -Werror
- arduinojson-version: v7.4.3
arduinojson-url: https://github.com/bblanchon/ArduinoJson/releases/download/v7.4.3/ArduinoJson-v7.4.3.h
# ArduinoJson v7 deprecates containsKey()/DynamicJsonDocument/StaticJsonDocument (still fully functional, kept
# intentionally for now to preserve v6 presence-check semantics) and, worse, JSON_OBJECT_SIZE/JSON_ARRAY_SIZE
# unconditionally emit a "#pragma GCC warning" that cannot be suppressed via any -Wno-* flag. Since this codebase
# still calls those macros (harmlessly, as a buffer-size hint v7 no longer needs) in ~50 files, -Werror is dropped
# for this leg rather than doing an invasive, version-branched rewrite of every call site.
werror-flag: ""
steps:
- name: Check out repository code
uses: actions/checkout@v3
Expand All @@ -27,6 +43,6 @@ jobs:
g++ --version
echo "g++ version must be 9.4.0"
- name: Get ArduinoJson
run: wget -Uri https://github.com/bblanchon/ArduinoJson/releases/download/v6.19.4/ArduinoJson-v6.19.4.h -O ./src/ArduinoJson.h
run: wget -Uri ${{ matrix.arduinojson-url }} -O ./src/ArduinoJson.h
- name: Compile
run: g++ -c -std=c++11 -I ./src $(find ./src -type f -iregex ".*\.cpp") -DMO_PLATFORM=MO_PLATFORM_NONE -Wall -Wextra -Wno-unused-parameter -Wno-redundant-move -Werror
run: g++ -c -std=c++11 -I ./src $(find ./src -type f -iregex ".*\.cpp") -DMO_PLATFORM=MO_PLATFORM_NONE -Wall -Wextra -Wno-unused-parameter -Wno-redundant-move ${{ matrix.werror-flag }}
12 changes: 10 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@ on:
jobs:

compile-and-run:
name: Automated Tests
name: Automated Tests (ArduinoJson ${{ matrix.arduinojson-version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- arduinojson-version: v6.21.3
arduinojson-url: https://github.com/bblanchon/ArduinoJson/releases/download/v6.21.3/ArduinoJson-v6.21.3.h
- arduinojson-version: v7.4.3
arduinojson-url: https://github.com/bblanchon/ArduinoJson/releases/download/v7.4.3/ArduinoJson-v7.4.3.h
steps:
- name: Check out repository code
uses: actions/checkout@v3
Expand All @@ -33,7 +41,7 @@ jobs:
g++ --version
echo "g++ version must be 9.4.0"
- name: Get ArduinoJson
run: wget -Uri https://github.com/bblanchon/ArduinoJson/releases/download/v6.21.3/ArduinoJson-v6.21.3.h -O ./src/ArduinoJson.h
run: wget -Uri ${{ matrix.arduinojson-url }} -O ./src/ArduinoJson.h
- name: Generate CMake build files
run: cmake -S . -B ./build -DMO_BUILD_UNIT_MBEDTLS=True
- name: Compile
Expand Down
49 changes: 47 additions & 2 deletions src/MicroOcpp/Core/Memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ namespace Memory {

void* (*malloc_override)(size_t);
void (*free_override)(void*);
void* (*realloc_override)(void*, size_t);

}
}
Expand All @@ -103,6 +104,10 @@ void mo_mem_set_malloc_free(void* (*malloc_override)(size_t), void (*free_overri
MicroOcpp::Memory::free_override = free_override;
}

void mo_mem_set_realloc(void* (*realloc_override)(void*, size_t)) {
MicroOcpp::Memory::realloc_override = realloc_override;
}

void *mo_mem_malloc(const char *tag, size_t size) {
MO_DBG_VERBOSE("malloc %zu B (%s)", size, tag ? tag : "unspecified");

Expand Down Expand Up @@ -152,6 +157,42 @@ void mo_mem_free(void* ptr) {
}
}

void *mo_mem_realloc(const char *tag, void *ptr, size_t size) {
MO_DBG_VERBOSE("realloc %zu B (%s)", size, tag ? tag : "unspecified");

#if MO_ENABLE_HEAP_PROFILER
if (ptr) {
auto blockInfo = memBlocks.find(ptr);
if (blockInfo != memBlocks.end()) {
auto tagInfo = memTags.find(blockInfo->second.tag);
if (tagInfo != memTags.end()) {
tagInfo->second -= blockInfo->second.size;
}
memTotal -= blockInfo->second.size;
memBlocks.erase(blockInfo);
}
}
#endif

void *new_ptr;
if (realloc_override) {
new_ptr = realloc_override(ptr, size);
} else {
new_ptr = realloc(ptr, size);
}

#if MO_ENABLE_HEAP_PROFILER
if (new_ptr) {
memBlocks.emplace(new_ptr, MemBlockInfo(new_ptr, tag, size));

memTotal += size;
memTotalMax = std::max(memTotalMax, memTotal);
}
#endif

return new_ptr;
}

#endif //MO_OVERRIDE_ALLOCATION

#if MO_OVERRIDE_ALLOCATION && MO_ENABLE_HEAP_PROFILER
Expand Down Expand Up @@ -310,17 +351,21 @@ String makeString(const char *tag, const char *val) {
}

JsonDoc initJsonDoc(const char *tag, size_t capacity) {
#if MO_OVERRIDE_ALLOCATION
#if MO_OVERRIDE_ALLOCATION && ARDUINOJSON_VERSION_MAJOR < 7
return JsonDoc(capacity, ArduinoJsonAllocator(tag));
#else
//ArduinoJson >= v7 wraps TAllocator in a process-wide singleton (see AllocatorAdapter)
//and therefore doesn't support passing a per-call allocator instance (i.e. a memory tag) anymore
(void)tag;
return JsonDoc(capacity);
#endif
}

std::unique_ptr<JsonDoc> makeJsonDoc(const char *tag, size_t capacity) {
#if MO_OVERRIDE_ALLOCATION
#if MO_OVERRIDE_ALLOCATION && ARDUINOJSON_VERSION_MAJOR < 7
return std::unique_ptr<JsonDoc>(new JsonDoc(capacity, ArduinoJsonAllocator(tag)));
#else
(void)tag;
return std::unique_ptr<JsonDoc>(new JsonDoc(capacity));
#endif
}
Expand Down
13 changes: 13 additions & 0 deletions src/MicroOcpp/Core/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,18 @@ void *mo_mem_malloc(const char *tag, size_t size);

void mo_mem_free(void* ptr);

void mo_mem_set_realloc(void* (*realloc_override)(void*, size_t)); //pass custom realloc function to be used with the OCPP lib (needed because ArduinoJson >= v7 reallocates its JSON document buffer as it grows). If not set or NULL, defaults to standard realloc

void *mo_mem_realloc(const char *tag, void *ptr, size_t size);

#define MO_MALLOC mo_mem_malloc
#define MO_FREE mo_mem_free
#define MO_REALLOC mo_mem_realloc

#else
#define MO_MALLOC(TAG, SIZE) malloc(SIZE) //default malloc provided by host system
#define MO_FREE(PTR) free(PTR) //default free provided by host system
#define MO_REALLOC(TAG, PTR, SIZE) realloc(PTR, SIZE) //default realloc provided by host system
#endif //MO_OVERRIDE_ALLOCATION


Expand Down Expand Up @@ -358,6 +364,13 @@ class ArduinoJsonAllocator {
void deallocate(void *ptr) {
MO_FREE(ptr);
}
void *reallocate(void *ptr, size_t new_size) {
#if MO_ENABLE_HEAP_PROFILER
return MO_REALLOC(tag, ptr, new_size);
#else
return MO_REALLOC(nullptr, ptr, new_size);
#endif
}
};

using JsonDoc = BasicJsonDocument<ArduinoJsonAllocator>;
Expand Down
2 changes: 1 addition & 1 deletion src/MicroOcpp/Operations/ReserveNow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const char* ReserveNow::getOperationType(){

void ReserveNow::processReq(JsonObject payload) {
if (!payload.containsKey("connectorId") ||
payload["connectorId"] < 0 ||
payload["connectorId"].as<int>() < 0 ||
!payload.containsKey("expiryDate") ||
!payload.containsKey("idTag") ||
//parentIdTag is optional
Expand Down
26 changes: 13 additions & 13 deletions tests/SmartCharging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_2_RELATIVE_TXDEF_24A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -573,7 +573,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_0_ALT_SAME_ID);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
(*doc)["connectorId"] = 2;
return doc;},
[&checkProcessed] (JsonObject response) {
Expand All @@ -592,7 +592,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_1_ABSOLUTE_LIMIT_16A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -615,7 +615,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_1_ABSOLUTE_LIMIT_16A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -637,7 +637,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_5_VALID_UNTIL_2022_16A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -661,7 +661,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_2_RELATIVE_TXDEF_24A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
(*doc)["csChargingProfiles"]["stackLevel"] = MO_ChargeProfileMaxStackLevel;
return doc;},
[&checkProcessed] (JsonObject response) {
Expand All @@ -680,7 +680,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_2_RELATIVE_TXDEF_24A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
(*doc)["csChargingProfiles"]["stackLevel"] = MO_ChargeProfileMaxStackLevel + 1;
return doc;},
[] (JsonObject) { }, //ignore conf
Expand All @@ -706,7 +706,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_2_RELATIVE_TXDEF_24A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
JsonArray chargingSchedulePeriod = (*doc)["csChargingProfiles"]["chargingSchedule"]["chargingSchedulePeriod"];
chargingSchedulePeriod.clear();
for (size_t i = 0; i < MO_ChargingScheduleMaxPeriods; i++) {
Expand All @@ -731,7 +731,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_2_RELATIVE_TXDEF_24A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
JsonArray chargingSchedulePeriod = (*doc)["csChargingProfiles"]["chargingSchedule"]["chargingSchedulePeriod"];
chargingSchedulePeriod.clear();
for (size_t i = 0; i < MO_ChargingScheduleMaxPeriods + 1; i++) {
Expand Down Expand Up @@ -767,7 +767,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_0);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -785,7 +785,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_1_ABSOLUTE_LIMIT_16A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -807,7 +807,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_0);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand All @@ -825,7 +825,7 @@ TEST_CASE( "SmartCharging" ) {
StaticJsonDocument<2048> raw;
deserializeJson(raw, SCPROFILE_1_ABSOLUTE_LIMIT_16A);
auto doc = makeJsonDoc("UnitTests", 2048);
*doc = raw[3];
doc->set(raw[3]);
return doc;},
[&checkProcessed] (JsonObject response) {
checkProcessed = true;
Expand Down