Skip to content

Commit

Permalink
C-API for custom Configurations store (#297)
Browse files Browse the repository at this point in the history
* add C-API for custom Configs storage

* clean patches (#297)
  • Loading branch information
matth-x authored May 10, 2024
1 parent e38e9f8 commit 8eb9e2e
Show file tree
Hide file tree
Showing 7 changed files with 375 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- Function `bool isConnected()` in `Connection` interface ([#282](https://github.com/matth-x/MicroOcpp/pull/282))
- Build flags for customizing memory limits of SmartCharging ([#260](https://github.com/matth-x/MicroOcpp/pull/260))
- SConscript ([#287](https://github.com/matth-x/MicroOcpp/pull/287))
- C-API for custom Configs store ([297](https://github.com/matth-x/MicroOcpp/pull/297))
- Certificate Management, UCs M03 - M05 ([#262](https://github.com/matth-x/MicroOcpp/pull/262), [#274](https://github.com/matth-x/MicroOcpp/pull/274), [#292](https://github.com/matth-x/MicroOcpp/pull/292))
- FTP Client ([#291](https://github.com/matth-x/MicroOcpp/pull/291))
- `ProtocolVersion` selects v1.6 or v2.0.1 ([#247](https://github.com/matth-x/MicroOcpp/pull/247))
Expand Down
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ cmake_minimum_required(VERSION 3.15)
set(CMAKE_CXX_STANDARD 11)

set(MO_SRC
src/MicroOcpp/Core/Configuration_c.cpp
src/MicroOcpp/Core/Configuration.cpp
src/MicroOcpp/Core/ConfigurationContainer.cpp
src/MicroOcpp/Core/ConfigurationContainerFlash.cpp
Expand Down
6 changes: 1 addition & 5 deletions src/MicroOcpp/Core/ConfigurationKeyValue.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// matth-x/MicroOcpp
// Copyright Matthias Akstaller 2019 - 2023
// Copyright Matthias Akstaller 2019 - 2024
// MIT License

#include <MicroOcpp/Core/ConfigurationKeyValue.h>
Expand All @@ -12,10 +12,6 @@
#define KEY_MAXLEN 60
#define STRING_VAL_MAXLEN 512

#ifndef MO_CONFIG_TYPECHECK
#define MO_CONFIG_TYPECHECK 1 //enable this for debugging
#endif

namespace MicroOcpp {

template<> TConfig convertType<int>() {return TConfig::Int;}
Expand Down
8 changes: 6 additions & 2 deletions src/MicroOcpp/Core/ConfigurationKeyValue.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// matth-x/MicroOcpp
// Copyright Matthias Akstaller 2019 - 2023
// Copyright Matthias Akstaller 2019 - 2024
// MIT License

#ifndef CONFIGURATIONKEYVALUE_H
Expand All @@ -14,6 +14,10 @@
#define MO_CONFIG_EXT_PREFIX "Cst_"
#endif

#ifndef MO_CONFIG_TYPECHECK
#define MO_CONFIG_TYPECHECK 1 //enable this for debugging
#endif

namespace MicroOcpp {

using revision_t = uint16_t;
Expand Down Expand Up @@ -49,7 +53,7 @@ class Configuration {

virtual TConfig getType() = 0;

revision_t getValueRevision();
virtual revision_t getValueRevision();

void setRebootRequired();
bool isRebootRequired();
Expand Down
195 changes: 195 additions & 0 deletions src/MicroOcpp/Core/Configuration_c.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
// matth-x/MicroOcpp
// Copyright Matthias Akstaller 2019 - 2024
// MIT License

#include <MicroOcpp/Core/Configuration_c.h>
#include <MicroOcpp/Core/Configuration.h>
#include <MicroOcpp/Debug.h>

using namespace MicroOcpp;

class ConfigurationC : public Configuration {
private:
ocpp_configuration *config;
public:
ConfigurationC(ocpp_configuration *config) :
config(config) {
config->mo_data = this;
}

bool setKey(const char *key) override {
return config->set_key(config->user_data, key);
}

const char *getKey() override {
return config->get_key(config->user_data);
}

void setInt(int val) override {
#if MO_CONFIG_TYPECHECK
if (config->get_type(config->user_data) != ENUM_CDT_INT) {
MO_DBG_ERR("type err");
return;
}
#endif
config->set_int(config->user_data, val);
}

void setBool(bool val) override {
#if MO_CONFIG_TYPECHECK
if (config->get_type(config->user_data) != ENUM_CDT_BOOL) {
MO_DBG_ERR("type err");
return;
}
#endif
config->set_bool(config->user_data, val);
}

bool setString(const char *val) override {
#if MO_CONFIG_TYPECHECK
if (config->get_type(config->user_data) != ENUM_CDT_STRING) {
MO_DBG_ERR("type err");
return false;
}
#endif
return config->set_string(config->user_data, val);
}

int getInt() override {
#if MO_CONFIG_TYPECHECK
if (config->get_type(config->user_data) != ENUM_CDT_INT) {
MO_DBG_ERR("type err");
return 0;
}
#endif
return config->get_int(config->user_data);
}

bool getBool() override {
#if MO_CONFIG_TYPECHECK
if (config->get_type(config->user_data) != ENUM_CDT_BOOL) {
MO_DBG_ERR("type err");
return false;
}
#endif
return config->get_bool(config->user_data);
}

const char *getString() override {
#if MO_CONFIG_TYPECHECK
if (config->get_type(config->user_data) != ENUM_CDT_STRING) {
MO_DBG_ERR("type err");
return "";
}
#endif
return config->get_string(config->user_data);
}

TConfig getType() override {
TConfig res = TConfig::Int;
switch (config->get_type(config->user_data)) {
case ENUM_CDT_INT:
res = TConfig::Int;
break;
case ENUM_CDT_BOOL:
res = TConfig::Bool;
break;
case ENUM_CDT_STRING:
res = TConfig::String;
break;
default:
MO_DBG_ERR("type conversion");
break;
}

return res;
}

uint16_t getValueRevision() override {
return config->get_write_count(config->user_data);
}

ocpp_configuration *getConfiguration() {
return config;
}
};

class ConfigurationContainerC : public ConfigurationContainer {
private:
ocpp_configuration_container *container;
public:
ConfigurationContainerC(ocpp_configuration_container *container, const char *filename, bool accessible) :
ConfigurationContainer(filename, accessible), container(container) {

}

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

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

std::shared_ptr<Configuration> createConfiguration(TConfig type, const char *key) override {
ocpp_config_datatype dt;
switch (type) {
case TConfig::Int:
dt = ENUM_CDT_INT;
break;
case TConfig::Bool:
dt = ENUM_CDT_BOOL;
break;
case TConfig::String:
dt = ENUM_CDT_STRING;
break;
default:
MO_DBG_ERR("internal error");
return nullptr;
}
ocpp_configuration *config = container->create_configuration(container->user_data, dt, key);

if (config) {
return std::make_shared<ConfigurationC>(config);
} else {
MO_DBG_ERR("could not create config: %s", key);
return nullptr;
}
}

void remove(Configuration *config) override {
container->remove(container->user_data, config->getKey());
}

size_t size() override {
return container->size(container->user_data);
}

Configuration *getConfiguration(size_t i) override {
auto config = container->get_configuration(container->user_data, i);
if (config) {
return static_cast<Configuration*>(config->mo_data);
} else {
return nullptr;
}
}

std::shared_ptr<Configuration> getConfiguration(const char *key) override {
ocpp_configuration *config = container->get_configuration_by_key(container->user_data, key);
if (config) {
return std::make_shared<ConfigurationC>(config);
} else {
return nullptr;
}
}

void loadStaticKey(Configuration& config, const char *key) override {
if (container->load_static_key) {
container->load_static_key(container->user_data, key);
}
}
};

void ocpp_configuration_container_add(ocpp_configuration_container *container, const char *container_path, bool accessible) {
addConfigurationContainer(std::make_shared<ConfigurationContainerC>(container, container_path, accessible));
}
71 changes: 71 additions & 0 deletions src/MicroOcpp/Core/Configuration_c.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// matth-x/MicroOcpp
// Copyright Matthias Akstaller 2019 - 2024
// MIT License

#ifndef MO_CONFIGURATION_C_H
#define MO_CONFIGURATION_C_H

#include <stddef.h>
#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef enum ocpp_config_datatype {
ENUM_CDT_INT,
ENUM_CDT_BOOL,
ENUM_CDT_STRING
} ocpp_config_datatype;

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

bool (*set_key) (void *user_data, const char *key); // Optional. MO may provide a static key value which you can use to replace a possibly malloc'd key buffer
const char* (*get_key) (void *user_data); // Return Configuration key

ocpp_config_datatype (*get_type) (void *user_data); // Return internal data type of config (determines which of the following getX()/setX() pairs are valid)

// Set value of Config
union {
void (*set_int) (void *user_data, int val);
void (*set_bool) (void *user_data, bool val);
bool (*set_string) (void *user_data, const char *val);
};

// Get value of Config
union {
int (*get_int) (void *user_data);
bool (*get_bool) (void *user_data);
const char* (*get_string) (void *user_data);
};

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

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

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

bool (*load) (void *user_data); // Called after declaring Configurations, to load them with their values
bool (*save) (void *user_data); // Commit all Configurations to memory

ocpp_configuration* (*create_configuration) (void *user_data, ocpp_config_datatype dt, const char *key); // Called to get a reference to a Configuration managed by this container (create new or return existing)
void (*remove) (void *user_data, const char *key); // Remove this config from the container. Do not free the config here, the config must outlive the MO lifecycle

size_t (*size) (void *user_data); // Number of Configurations currently managed by this container
ocpp_configuration* (*get_configuration) (void *user_data, size_t i); // Return config at container position i
ocpp_configuration* (*get_configuration_by_key) (void *user_data, const char *key); // Return config for given key

void (*load_static_key) (void *user_data, const char *key); // Optional. MO may provide a static key value which you can use to replace a possibly malloc'd key buffer
} ocpp_configuration_container;

// Add custom Configuration container. Add one container per container_path before mocpp_initialize(...)
void ocpp_configuration_container_add(ocpp_configuration_container *container, const char *container_path, bool accessible);

#ifdef __cplusplus
} // extern "C"
#endif

#endif
Loading

0 comments on commit 8eb9e2e

Please sign in to comment.