1 /*
2 * Copyright (c) 2025 Linumiz GmbH
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "ocpp_i.h"
8
9 #if defined(CONFIG_OCPP_PROFILE_SMART_CHARGE)
10 #define CP_SC ",SmartCharging"
11 #else
12 #define CP_SC ""
13 #endif
14
15 #if defined(CONFIG_OCPP_PROFILE_REMOTE_TRIG)
16 #define CP_RT ",RemoteTrigger"
17 #else
18 #define CP_RT ""
19 #endif
20
21 #if defined(CONFIG_OCPP_PROFILE_RESERVATION)
22 #define CP_RE ",Reservation"
23 #else
24 #define CP_RE ""
25 #endif
26
27 #if defined(CONFIG_OCPP_PROFILE_LOCAL_AUTH_LIST)
28 #define CP_LAL ",LocalAuthListManagement"
29 #else
30 #define CP_LAL ""
31 #endif
32
33 #if defined(CONFIG_OCPP_PROFILE_FIRMWARE_MGNT)
34 #define CP_FM ",FirmwareManagement"
35 #else
36 #define CP_FM ""
37 #endif
38
39 #define CP_CORE "Core"
40
41 struct ocpp_cfg_info {
42 enum ocpp_key_type type;
43 bool is_rw;
44 enum ocpp_key key;
45 char *skey;
46 union ocpp_keyval val;
47 };
48
49 #define FILL_KEY_TABLE(_type, _rw, _key, _skey, _val)[_key] = \
50 {.type = _type, .is_rw = _rw, .key = _key, .skey = _skey, .val = {_val}}
51
52 static struct ocpp_cfg_info cached_key_cfg[OCPP_CFG_END] = {
53 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_ALLOW_OFFLINE_TX_FOR_UNKN_ID,
54 "AllowOfflineTxForUnknownId", false),
55 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_AUTH_CACHE_ENABLED,
56 "AuthorizationCacheEnabled", false),
57 FILL_KEY_TABLE(KEY_TYPE_BOOL, 0, CFG_AUTH_REMOTE_TX_REQ,
58 "AuthorizeRemoteTxRequests", true),
59 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_BLINK_REPEAT, "BlinkRepeat", 0),
60 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_CLK_ALIGN_DATA_INTERVAL,
61 "ClockAlignedDataInterval", 0),
62 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_CONN_TIMEOUT,
63 "ConnectionTimeOut", 0),
64 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_GETCFG_MAX_KEY,
65 "GetConfigurationMaxKeys", 1),
66 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_HEARTBEAT_INTERVAL,
67 "HeartbeatInterval", 0),
68 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_LIGHT_INTENSITY,
69 "LightIntensity", 0),
70 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_LOCAL_AUTH_OFFLINE,
71 "LocalAuthorizeOffline", 0),
72 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_LOCAL_PREAUTH,
73 "LocalPreAuthorize", 0),
74 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_MAX_ENERGYON_INVL_ID,
75 "MaxEnergyOnInvalidId", 0),
76 FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_MTR_VAL_ALGIN_DATA,
77 "MeterValuesAlignedData", .str = "0"),
78 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_MTR_VAL_ALGIN_DATA_MAXLEN,
79 "MeterValuesAlignedDataMaxLength", 1),
80 FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_MTR_VAL_SAMPLED_DATA,
81 "MeterValuesSampledData", .str = "0"),
82 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_MTR_VAL_SAMPLED_DATA_MAXLEN,
83 "MeterValuesSampledDataMaxLength", 1),
84 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_MTR_VAL_SAMPLE_INTERVAL,
85 "MeterValueSampleInterval", 5),
86 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_MIN_STATUS_DURATION,
87 "MinimumStatusDuration", 0),
88 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_NO_OF_CONNECTORS,
89 "NumberOfConnectors", 0),
90 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_REST_RETRIES,
91 "ResetRetries", 0),
92 FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_CONN_PHASE_ROT,
93 "ConnectorPhaseRotation", .str = "0"),
94 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_CONN_PHASE_ROT_MAXLEN,
95 "ConnectorPhaseRotationMaxLength", 1),
96 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_STOP_TXN_ON_EVSIDE_DISCON,
97 "StopTransactionOnEVSideDisconnect", 0),
98 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_STOP_TXN_ON_INVL_ID,
99 "StopTransactionOnInvalidId", 0),
100 FILL_KEY_TABLE(KEY_TYPE_CSL, 1, CFG_STOP_TXN_ALIGNED_DATA,
101 "StopTxnAlignedData", .str = "0"),
102 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_STOP_TXN_ALIGNED_DATA_MAXLEN,
103 "StopTxnAlignedDataMaxLength", 1),
104 FILL_KEY_TABLE(KEY_TYPE_CSL, 0, CFG_SUPPORTED_FEATURE_PROFILE,
105 "SupportedFeatureProfiles",
106 .str = CP_CORE CP_SC CP_RT CP_RE CP_LAL CP_FM),
107 FILL_KEY_TABLE(KEY_TYPE_INT, 0, CFG_SUPPORTED_FEATURE_PROFILE_MAXLEN,
108 "SupportedFeatureProfilesMaxLength", 6),
109 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_TXN_MSG_ATTEMPTS,
110 "TransactionMessageAttempts", 0),
111 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_TXN_MSG_RETRY_INTERVAL,
112 "TransactionMessageRetryInterval", 0),
113 FILL_KEY_TABLE(KEY_TYPE_BOOL, 1, CFG_UNLOCK_CONN_ON_EVSIDE_DISCON,
114 "UnlockConnectorOnEVSideDisconnect", 0),
115 FILL_KEY_TABLE(KEY_TYPE_INT, 1, CFG_WEBSOCK_PING_INTERVAL,
116 "WebSocketPingInterval", 0),
117
118 /* optional */
119 };
120
ocpp_get_keyval_type(enum ocpp_key key)121 enum ocpp_key_type ocpp_get_keyval_type(enum ocpp_key key)
122 {
123 return cached_key_cfg[key].type;
124 }
125
ocpp_key_to_cfg(const char * skey)126 enum ocpp_key ocpp_key_to_cfg(const char *skey)
127 {
128 int i;
129 struct ocpp_cfg_info *cfg = cached_key_cfg;
130
131 for (i = 0; i < OCPP_CFG_END; i++) {
132 if (strncmp(cfg[i].skey, skey, strlen(cfg[i].skey)) == 0) {
133 break;
134 }
135 }
136
137 return i;
138 }
139
ocpp_is_key_rw(enum ocpp_key key)140 bool ocpp_is_key_rw(enum ocpp_key key)
141 {
142 return cached_key_cfg[key].is_rw;
143 }
144
ocpp_get_key_val(enum ocpp_key key)145 union ocpp_keyval *ocpp_get_key_val(enum ocpp_key key)
146 {
147 if (key >= OCPP_CFG_END) {
148 return NULL;
149 }
150
151 return &cached_key_cfg[key].val;
152 }
153
ocpp_get_key_literal(enum ocpp_key key)154 char *ocpp_get_key_literal(enum ocpp_key key)
155 {
156 if (key >= OCPP_CFG_END) {
157 return NULL;
158 }
159
160 return cached_key_cfg[key].skey;
161 }
162
ocpp_set_cfg_val(enum ocpp_key key,union ocpp_keyval * val)163 int ocpp_set_cfg_val(enum ocpp_key key, union ocpp_keyval *val)
164 {
165 enum ocpp_key_type type;
166 struct ocpp_cfg_info *key_cfg;
167
168 key_cfg = &cached_key_cfg[key];
169 type = ocpp_get_keyval_type(key);
170 if (type < KEY_TYPE_STR) {
171 key_cfg->val.ival = val->ival;
172 } else {
173 if (key_cfg->val.str) {
174 free(key_cfg->val.str);
175 }
176 key_cfg->val.str = strdup(val->str);
177 }
178
179 return 0;
180 }
181
ocpp_update_cfg_val(enum ocpp_key key,union ocpp_keyval * val)182 int ocpp_update_cfg_val(enum ocpp_key key, union ocpp_keyval *val)
183 {
184
185 if (key >= OCPP_CFG_END ||
186 !cached_key_cfg[key].is_rw) {
187 return -EINVAL;
188 }
189
190 return ocpp_set_cfg_val(key, val);
191 }
192