Skip to content

Commit

Permalink
Merge pull request #400 from matth-x/feature/improve-platform-compat
Browse files Browse the repository at this point in the history
Improvements for custom platform integrations
  • Loading branch information
matth-x authored Feb 2, 2025
2 parents 4b080f6 + bb88b16 commit 0455ec0
Show file tree
Hide file tree
Showing 16 changed files with 279 additions and 65 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:
uses: actions/checkout@v3
with:
repository: google/bloaty
ref: 379d5305670c00c36a57e608079fd253f13bde63
ref: e1155149d54bb09b81e86f0e4e5cb7fbd2a318eb
path: tools/bloaty
submodules: recursive
- name: Install bloaty
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
run: ./build/mo_unit_tests --abort
- name: Create coverage report
run: |
lcov --directory . --capture --output-file coverage.info
lcov --directory . --capture --output-file coverage.info --ignore-errors mismatch
lcov --remove coverage.info '/usr/*' '*/tests/*' '*/ArduinoJson.h' --output-file coverage.info
lcov --list coverage.info
- name: Upload coverage reports to Codecov
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,21 @@
- Change `MicroOcpp::TxNotification` into C-style enum, replace `OCPP_TxNotication` ([#386](https://github.com/matth-x/MicroOcpp/pull/386))
- Improved UUID generation ([#383](https://github.com/matth-x/MicroOcpp/pull/383))
- `beginTransaction()` returns bool for better v2.0.1 interop ([#386](https://github.com/matth-x/MicroOcpp/pull/386))
- Configurations C-API updates ([#400](https://github.com/matth-x/MicroOcpp/pull/400))
- Platform integrations C-API upates ([#400](https://github.com/matth-x/MicroOcpp/pull/400))

### Added

- `getTransactionV201()` exposes v201 Tx in API ([#386](https://github.com/matth-x/MicroOcpp/pull/386))
- v201 support in Transaction.h C-API ([#386](https://github.com/matth-x/MicroOcpp/pull/386))
- Write-only Configurations ([#400](https://github.com/matth-x/MicroOcpp/pull/400))

### Fixed

- Timing issues for OCTT test cases ([#383](https://github.com/matth-x/MicroOcpp/pull/383))
- Misleading Reset failure dbg msg ([#388](https://github.com/matth-x/MicroOcpp/pull/388))
- Reject negative ints in ChangeConfig ([#388](https://github.com/matth-x/MicroOcpp/pull/388))
- Revised SCons integration ([#400](https://github.com/matth-x/MicroOcpp/pull/400))

## [1.2.0] - 2024-11-03

Expand Down
11 changes: 5 additions & 6 deletions SConscript.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
# Use this file as a starting point for writing your own SCons integration. And as always, any
# contributions are highly welcome!

Import("env", "ARDUINOJSON_DIR")
Import("env")

import os, pathlib

Expand All @@ -17,16 +17,15 @@ def getAllDirs(root_dir):
dir_list.append(Dir(root))
return dir_list

SOURCE_DIR = Dir(".").srcnode()
SOURCE_DIR = Dir(".").srcnode().Dir("src")

source_dirs = getAllDirs(SOURCE_DIR.Dir("src"))
source_dirs += getAllDirs(ARDUINOJSON_DIR.Dir("src"))
source_dirs = getAllDirs(SOURCE_DIR)

source_files = []

for folder in source_dirs:
source_files += folder.glob("*.c")
source_files += folder.glob("*.cpp")
env["CPPPATH"].append(folder)

compiled_objects = []
for source_file in source_files:
Expand All @@ -44,7 +43,7 @@ def getAllDirs(root_dir):

exports = {
'library': libmicroocpp,
'CPPPATH': source_dirs.copy()
'CPPPATH': SOURCE_DIR
}

Return("exports")
20 changes: 18 additions & 2 deletions src/MicroOcpp/Core/ConfigurationKeyValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,27 @@ bool Configuration::isRebootRequired() {
}

void Configuration::setReadOnly() {
readOnly = true;
if (mutability == Mutability::ReadWrite) {
mutability = Mutability::ReadOnly;
} else {
mutability = Mutability::None;
}
}

bool Configuration::isReadOnly() {
return readOnly;
return mutability == Mutability::ReadOnly;
}

bool Configuration::isReadable() {
return mutability == Mutability::ReadWrite || mutability == Mutability::ReadOnly;
}

void Configuration::setWriteOnly() {
if (mutability == Mutability::ReadWrite) {
mutability = Mutability::WriteOnly;
} else {
mutability = Mutability::None;
}
}

/*
Expand Down
13 changes: 12 additions & 1 deletion src/MicroOcpp/Core/ConfigurationKeyValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,15 @@ class Configuration {
revision_t value_revision = 0; //write access counter; used to check if this config has been changed
private:
bool rebootRequired = false;
bool readOnly = false;

enum class Mutability : uint8_t {
ReadWrite,
ReadOnly,
WriteOnly,
None
};
Mutability mutability = Mutability::ReadWrite;

public:
virtual ~Configuration();

Expand All @@ -60,6 +68,9 @@ class Configuration {

void setReadOnly();
bool isReadOnly();
bool isReadable();

void setWriteOnly();
};

/*
Expand Down
138 changes: 128 additions & 10 deletions src/MicroOcpp/Core/Configuration_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,15 @@ class ConfigurationC : public Configuration, public MemoryManaged {
public:
ConfigurationC(ocpp_configuration *config) :
config(config) {
config->mo_data = this;
if (config->read_only) {
setReadOnly();
}
if (config->write_only) {
setWriteOnly();
}
if (config->reboot_required) {
setRebootRequired();
}
}

bool setKey(const char *key) override {
Expand Down Expand Up @@ -116,6 +124,59 @@ class ConfigurationC : public Configuration, public MemoryManaged {
}
};

namespace MicroOcpp {

ConfigurationC *getConfigurationC(ocpp_configuration *config) {
if (!config->mo_data) {
return nullptr;
}
return reinterpret_cast<std::shared_ptr<ConfigurationC>*>(config->mo_data)->get();
}

}

using namespace MicroOcpp;


void ocpp_setRebootRequired(ocpp_configuration *config) {
if (auto c = getConfigurationC(config)) {
c->setRebootRequired();
}
config->reboot_required = true;
}
bool ocpp_isRebootRequired(ocpp_configuration *config) {
if (auto c = getConfigurationC(config)) {
return c->isRebootRequired();
}
return config->reboot_required;
}

void ocpp_setReadOnly(ocpp_configuration *config) {
if (auto c = getConfigurationC(config)) {
c->setReadOnly();
}
config->read_only = true;
}
bool ocpp_isReadOnly(ocpp_configuration *config) {
if (auto c = getConfigurationC(config)) {
return c->isReadOnly();
}
return config->read_only;
}
bool ocpp_isReadable(ocpp_configuration *config) {
if (auto c = getConfigurationC(config)) {
return c->isReadable();
}
return !config->write_only;
}

void ocpp_setWriteOnly(ocpp_configuration *config) {
if (auto c = getConfigurationC(config)) {
c->setWriteOnly();
}
config->write_only = true;
}

class ConfigurationContainerC : public ConfigurationContainer, public MemoryManaged {
private:
ocpp_configuration_container *container;
Expand All @@ -125,15 +186,41 @@ class ConfigurationContainerC : public ConfigurationContainer, public MemoryMana

}

~ConfigurationContainerC() {
for (size_t i = 0; i < container->size(container->user_data); i++) {
if (auto config = container->get_configuration(container->user_data, i)) {
if (config->mo_data) {
delete reinterpret_cast<std::shared_ptr<ConfigurationC>*>(config->mo_data);
config->mo_data = nullptr;
}
}
}
}

bool load() override {
return container->load(container->user_data);
if (container->load) {
return container->load(container->user_data);
} else {
return true;
}
}

bool save() override {
return container->save(container->user_data);
if (container->save) {
return container->save(container->user_data);
} else {
return true;
}
}

std::shared_ptr<Configuration> createConfiguration(TConfig type, const char *key) override {

auto result = std::shared_ptr<ConfigurationC>(nullptr, std::default_delete<ConfigurationC>(), makeAllocator<ConfigurationC>(getMemoryTag()));

if (!container->create_configuration) {
return result;
}

ocpp_config_datatype dt;
switch (type) {
case TConfig::Int:
Expand All @@ -147,19 +234,38 @@ class ConfigurationContainerC : public ConfigurationContainer, public MemoryMana
break;
default:
MO_DBG_ERR("internal error");
return nullptr;
return result;
}
ocpp_configuration *config = container->create_configuration(container->user_data, dt, key);
if (!config) {
return result;
}

result.reset(new ConfigurationC(config));

if (config) {
return std::allocate_shared<ConfigurationC>(makeAllocator<ConfigurationC>(getMemoryTag()), config);
if (result) {
auto captureConfigC = new std::shared_ptr<ConfigurationC>(result);
config->mo_data = reinterpret_cast<void*>(captureConfigC);
} else {
MO_DBG_ERR("could not create config: %s", key);
return nullptr;
if (container->remove) {
container->remove(container->user_data, key);
}
}

return result;
}

void remove(Configuration *config) override {
if (!container->remove) {
return;
}

if (auto c = container->get_configuration_by_key(container->user_data, config->getKey())) {
delete reinterpret_cast<std::shared_ptr<ConfigurationC>*>(c->mo_data);
c->mo_data = nullptr;
}

container->remove(container->user_data, config->getKey());
}

Expand All @@ -170,16 +276,28 @@ class ConfigurationContainerC : public ConfigurationContainer, public MemoryMana
Configuration *getConfiguration(size_t i) override {
auto config = container->get_configuration(container->user_data, i);
if (config) {
return static_cast<Configuration*>(config->mo_data);
if (!config->mo_data) {
auto c = new ConfigurationC(config);
if (c) {
config->mo_data = reinterpret_cast<void*>(new std::shared_ptr<ConfigurationC>(c, std::default_delete<ConfigurationC>(), makeAllocator<ConfigurationC>(getMemoryTag())));
}
}
return static_cast<Configuration*>(config->mo_data ? reinterpret_cast<std::shared_ptr<ConfigurationC>*>(config->mo_data)->get() : nullptr);
} else {
return nullptr;
}
}

std::shared_ptr<Configuration> getConfiguration(const char *key) override {
ocpp_configuration *config = container->get_configuration_by_key(container->user_data, key);
auto config = container->get_configuration_by_key(container->user_data, key);
if (config) {
return std::allocate_shared<ConfigurationC>(makeAllocator<ConfigurationC>(getMemoryTag()), config);
if (!config->mo_data) {
auto c = new ConfigurationC(config);
if (c) {
config->mo_data = reinterpret_cast<void*>(new std::shared_ptr<ConfigurationC>(c, std::default_delete<ConfigurationC>(), makeAllocator<ConfigurationC>(getMemoryTag())));
}
}
return config->mo_data ? *reinterpret_cast<std::shared_ptr<ConfigurationC>*>(config->mo_data) : nullptr;
} else {
return nullptr;
}
Expand Down
13 changes: 13 additions & 0 deletions src/MicroOcpp/Core/Configuration_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,22 @@ typedef struct ocpp_configuration {

uint16_t (*get_write_count) (void *user_data); // Return number of changes of the value. MO uses this to detect if the firmware has updated the config

bool read_only;
bool write_only;
bool reboot_required;

void *mo_data; // Reserved for MO
} ocpp_configuration;

void ocpp_setRebootRequired(ocpp_configuration *config);
bool ocpp_isRebootRequired(ocpp_configuration *config);

void ocpp_setReadOnly(ocpp_configuration *config);
bool ocpp_isReadOnly(ocpp_configuration *config);
bool ocpp_isReadable(ocpp_configuration *config);

void ocpp_setWriteOnly(ocpp_configuration *config);

typedef struct ocpp_configuration_container {
void *user_data; //set this at your choice. MO passes it back to the functions below

Expand Down
10 changes: 10 additions & 0 deletions src/MicroOcpp/Model/Transactions/Transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,16 @@ const char *ocpp_tx_getIdTag(OCPP_Transaction *tx) {
return reinterpret_cast<MicroOcpp::Transaction*>(tx)->getIdTag();
}

const char *ocpp_tx_getParentIdTag(OCPP_Transaction *tx) {
#if MO_ENABLE_V201
if (g_ocpp_tx_compat_v201) {
MO_DBG_ERR("only supported in v16");
return nullptr;
}
#endif //MO_ENABLE_V201
return reinterpret_cast<MicroOcpp::Transaction*>(tx)->getParentIdTag();
}

bool ocpp_tx_getBeginTimestamp(OCPP_Transaction *tx, char *buf, size_t len) {
#if MO_ENABLE_V201
if (g_ocpp_tx_compat_v201) {
Expand Down
4 changes: 3 additions & 1 deletion src/MicroOcpp/Model/Transactions/Transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extern "C" {

//TxNotification - event from MO to the main firmware to notify it about transaction state changes
typedef enum {
UNDEFINED,
TxNotification_UNDEFINED,

//Authorization events
TxNotification_Authorized, //success
Expand Down Expand Up @@ -473,6 +473,8 @@ bool ocpp_tx_isCompleted(OCPP_Transaction *tx);

const char *ocpp_tx_getIdTag(OCPP_Transaction *tx);

const char *ocpp_tx_getParentIdTag(OCPP_Transaction *tx);

bool ocpp_tx_getBeginTimestamp(OCPP_Transaction *tx, char *buf, size_t len);

int32_t ocpp_tx_getMeterStart(OCPP_Transaction *tx);
Expand Down
Loading

0 comments on commit 0455ec0

Please sign in to comment.