Skip to content

Commit 8eb9e2e

Browse files
authored
C-API for custom Configurations store (#297)
* add C-API for custom Configs storage * clean patches (#297)
1 parent e38e9f8 commit 8eb9e2e

File tree

7 files changed

+375
-7
lines changed

7 files changed

+375
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
- Function `bool isConnected()` in `Connection` interface ([#282](https://github.com/matth-x/MicroOcpp/pull/282))
1717
- Build flags for customizing memory limits of SmartCharging ([#260](https://github.com/matth-x/MicroOcpp/pull/260))
1818
- SConscript ([#287](https://github.com/matth-x/MicroOcpp/pull/287))
19+
- C-API for custom Configs store ([297](https://github.com/matth-x/MicroOcpp/pull/297))
1920
- 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))
2021
- FTP Client ([#291](https://github.com/matth-x/MicroOcpp/pull/291))
2122
- `ProtocolVersion` selects v1.6 or v2.0.1 ([#247](https://github.com/matth-x/MicroOcpp/pull/247))

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ cmake_minimum_required(VERSION 3.15)
77
set(CMAKE_CXX_STANDARD 11)
88

99
set(MO_SRC
10+
src/MicroOcpp/Core/Configuration_c.cpp
1011
src/MicroOcpp/Core/Configuration.cpp
1112
src/MicroOcpp/Core/ConfigurationContainer.cpp
1213
src/MicroOcpp/Core/ConfigurationContainerFlash.cpp

src/MicroOcpp/Core/ConfigurationKeyValue.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// matth-x/MicroOcpp
2-
// Copyright Matthias Akstaller 2019 - 2023
2+
// Copyright Matthias Akstaller 2019 - 2024
33
// MIT License
44

55
#include <MicroOcpp/Core/ConfigurationKeyValue.h>
@@ -12,10 +12,6 @@
1212
#define KEY_MAXLEN 60
1313
#define STRING_VAL_MAXLEN 512
1414

15-
#ifndef MO_CONFIG_TYPECHECK
16-
#define MO_CONFIG_TYPECHECK 1 //enable this for debugging
17-
#endif
18-
1915
namespace MicroOcpp {
2016

2117
template<> TConfig convertType<int>() {return TConfig::Int;}

src/MicroOcpp/Core/ConfigurationKeyValue.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// matth-x/MicroOcpp
2-
// Copyright Matthias Akstaller 2019 - 2023
2+
// Copyright Matthias Akstaller 2019 - 2024
33
// MIT License
44

55
#ifndef CONFIGURATIONKEYVALUE_H
@@ -14,6 +14,10 @@
1414
#define MO_CONFIG_EXT_PREFIX "Cst_"
1515
#endif
1616

17+
#ifndef MO_CONFIG_TYPECHECK
18+
#define MO_CONFIG_TYPECHECK 1 //enable this for debugging
19+
#endif
20+
1721
namespace MicroOcpp {
1822

1923
using revision_t = uint16_t;
@@ -49,7 +53,7 @@ class Configuration {
4953

5054
virtual TConfig getType() = 0;
5155

52-
revision_t getValueRevision();
56+
virtual revision_t getValueRevision();
5357

5458
void setRebootRequired();
5559
bool isRebootRequired();
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// matth-x/MicroOcpp
2+
// Copyright Matthias Akstaller 2019 - 2024
3+
// MIT License
4+
5+
#include <MicroOcpp/Core/Configuration_c.h>
6+
#include <MicroOcpp/Core/Configuration.h>
7+
#include <MicroOcpp/Debug.h>
8+
9+
using namespace MicroOcpp;
10+
11+
class ConfigurationC : public Configuration {
12+
private:
13+
ocpp_configuration *config;
14+
public:
15+
ConfigurationC(ocpp_configuration *config) :
16+
config(config) {
17+
config->mo_data = this;
18+
}
19+
20+
bool setKey(const char *key) override {
21+
return config->set_key(config->user_data, key);
22+
}
23+
24+
const char *getKey() override {
25+
return config->get_key(config->user_data);
26+
}
27+
28+
void setInt(int val) override {
29+
#if MO_CONFIG_TYPECHECK
30+
if (config->get_type(config->user_data) != ENUM_CDT_INT) {
31+
MO_DBG_ERR("type err");
32+
return;
33+
}
34+
#endif
35+
config->set_int(config->user_data, val);
36+
}
37+
38+
void setBool(bool val) override {
39+
#if MO_CONFIG_TYPECHECK
40+
if (config->get_type(config->user_data) != ENUM_CDT_BOOL) {
41+
MO_DBG_ERR("type err");
42+
return;
43+
}
44+
#endif
45+
config->set_bool(config->user_data, val);
46+
}
47+
48+
bool setString(const char *val) override {
49+
#if MO_CONFIG_TYPECHECK
50+
if (config->get_type(config->user_data) != ENUM_CDT_STRING) {
51+
MO_DBG_ERR("type err");
52+
return false;
53+
}
54+
#endif
55+
return config->set_string(config->user_data, val);
56+
}
57+
58+
int getInt() override {
59+
#if MO_CONFIG_TYPECHECK
60+
if (config->get_type(config->user_data) != ENUM_CDT_INT) {
61+
MO_DBG_ERR("type err");
62+
return 0;
63+
}
64+
#endif
65+
return config->get_int(config->user_data);
66+
}
67+
68+
bool getBool() override {
69+
#if MO_CONFIG_TYPECHECK
70+
if (config->get_type(config->user_data) != ENUM_CDT_BOOL) {
71+
MO_DBG_ERR("type err");
72+
return false;
73+
}
74+
#endif
75+
return config->get_bool(config->user_data);
76+
}
77+
78+
const char *getString() override {
79+
#if MO_CONFIG_TYPECHECK
80+
if (config->get_type(config->user_data) != ENUM_CDT_STRING) {
81+
MO_DBG_ERR("type err");
82+
return "";
83+
}
84+
#endif
85+
return config->get_string(config->user_data);
86+
}
87+
88+
TConfig getType() override {
89+
TConfig res = TConfig::Int;
90+
switch (config->get_type(config->user_data)) {
91+
case ENUM_CDT_INT:
92+
res = TConfig::Int;
93+
break;
94+
case ENUM_CDT_BOOL:
95+
res = TConfig::Bool;
96+
break;
97+
case ENUM_CDT_STRING:
98+
res = TConfig::String;
99+
break;
100+
default:
101+
MO_DBG_ERR("type conversion");
102+
break;
103+
}
104+
105+
return res;
106+
}
107+
108+
uint16_t getValueRevision() override {
109+
return config->get_write_count(config->user_data);
110+
}
111+
112+
ocpp_configuration *getConfiguration() {
113+
return config;
114+
}
115+
};
116+
117+
class ConfigurationContainerC : public ConfigurationContainer {
118+
private:
119+
ocpp_configuration_container *container;
120+
public:
121+
ConfigurationContainerC(ocpp_configuration_container *container, const char *filename, bool accessible) :
122+
ConfigurationContainer(filename, accessible), container(container) {
123+
124+
}
125+
126+
bool load() override {
127+
return container->load(container->user_data);
128+
}
129+
130+
bool save() override {
131+
return container->save(container->user_data);
132+
}
133+
134+
std::shared_ptr<Configuration> createConfiguration(TConfig type, const char *key) override {
135+
ocpp_config_datatype dt;
136+
switch (type) {
137+
case TConfig::Int:
138+
dt = ENUM_CDT_INT;
139+
break;
140+
case TConfig::Bool:
141+
dt = ENUM_CDT_BOOL;
142+
break;
143+
case TConfig::String:
144+
dt = ENUM_CDT_STRING;
145+
break;
146+
default:
147+
MO_DBG_ERR("internal error");
148+
return nullptr;
149+
}
150+
ocpp_configuration *config = container->create_configuration(container->user_data, dt, key);
151+
152+
if (config) {
153+
return std::make_shared<ConfigurationC>(config);
154+
} else {
155+
MO_DBG_ERR("could not create config: %s", key);
156+
return nullptr;
157+
}
158+
}
159+
160+
void remove(Configuration *config) override {
161+
container->remove(container->user_data, config->getKey());
162+
}
163+
164+
size_t size() override {
165+
return container->size(container->user_data);
166+
}
167+
168+
Configuration *getConfiguration(size_t i) override {
169+
auto config = container->get_configuration(container->user_data, i);
170+
if (config) {
171+
return static_cast<Configuration*>(config->mo_data);
172+
} else {
173+
return nullptr;
174+
}
175+
}
176+
177+
std::shared_ptr<Configuration> getConfiguration(const char *key) override {
178+
ocpp_configuration *config = container->get_configuration_by_key(container->user_data, key);
179+
if (config) {
180+
return std::make_shared<ConfigurationC>(config);
181+
} else {
182+
return nullptr;
183+
}
184+
}
185+
186+
void loadStaticKey(Configuration& config, const char *key) override {
187+
if (container->load_static_key) {
188+
container->load_static_key(container->user_data, key);
189+
}
190+
}
191+
};
192+
193+
void ocpp_configuration_container_add(ocpp_configuration_container *container, const char *container_path, bool accessible) {
194+
addConfigurationContainer(std::make_shared<ConfigurationContainerC>(container, container_path, accessible));
195+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// matth-x/MicroOcpp
2+
// Copyright Matthias Akstaller 2019 - 2024
3+
// MIT License
4+
5+
#ifndef MO_CONFIGURATION_C_H
6+
#define MO_CONFIGURATION_C_H
7+
8+
#include <stddef.h>
9+
#include <stdint.h>
10+
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
typedef enum ocpp_config_datatype {
16+
ENUM_CDT_INT,
17+
ENUM_CDT_BOOL,
18+
ENUM_CDT_STRING
19+
} ocpp_config_datatype;
20+
21+
typedef struct ocpp_configuration {
22+
void *user_data; // Set this at your choice. MO passes it back to the functions below
23+
24+
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
25+
const char* (*get_key) (void *user_data); // Return Configuration key
26+
27+
ocpp_config_datatype (*get_type) (void *user_data); // Return internal data type of config (determines which of the following getX()/setX() pairs are valid)
28+
29+
// Set value of Config
30+
union {
31+
void (*set_int) (void *user_data, int val);
32+
void (*set_bool) (void *user_data, bool val);
33+
bool (*set_string) (void *user_data, const char *val);
34+
};
35+
36+
// Get value of Config
37+
union {
38+
int (*get_int) (void *user_data);
39+
bool (*get_bool) (void *user_data);
40+
const char* (*get_string) (void *user_data);
41+
};
42+
43+
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
44+
45+
void *mo_data; // Reserved for MO
46+
} ocpp_configuration;
47+
48+
typedef struct ocpp_configuration_container {
49+
void *user_data; //set this at your choice. MO passes it back to the functions below
50+
51+
bool (*load) (void *user_data); // Called after declaring Configurations, to load them with their values
52+
bool (*save) (void *user_data); // Commit all Configurations to memory
53+
54+
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)
55+
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
56+
57+
size_t (*size) (void *user_data); // Number of Configurations currently managed by this container
58+
ocpp_configuration* (*get_configuration) (void *user_data, size_t i); // Return config at container position i
59+
ocpp_configuration* (*get_configuration_by_key) (void *user_data, const char *key); // Return config for given key
60+
61+
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
62+
} ocpp_configuration_container;
63+
64+
// Add custom Configuration container. Add one container per container_path before mocpp_initialize(...)
65+
void ocpp_configuration_container_add(ocpp_configuration_container *container, const char *container_path, bool accessible);
66+
67+
#ifdef __cplusplus
68+
} // extern "C"
69+
#endif
70+
71+
#endif

0 commit comments

Comments
 (0)