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