1 /*
2  * Copyright (c) 2025 Linumiz GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #ifndef __OCPP_I_
8 #define __OCPP_I_
9 
10 #include "string.h"
11 #include <zephyr/logging/log.h>
12 #include <zephyr/net/ocpp.h>
13 #include <zephyr/net/socket.h>
14 #include <zephyr/net/websocket.h>
15 #include <zephyr/sys/slist.h>
16 
17 #if __POSIX_VISIBLE < 200809
18 char    *strdup(const char *);
19 #endif
20 
21 /* case-insensitive */
22 #define CISTR20	20
23 #define CISTR25	25
24 #define CISTR500 500
25 
26 #define INVALID_CONN_ID ((uint8_t) -1)
27 #define INVALID_TXN_ID ((int) -1)
28 
29 #define to_session(ptr) CONTAINER_OF(ptr, struct ocpp_session, node)
30 
31 enum ocpp_pdu_msg {
32 	PDU_BOOTNOTIFICATION,
33 	PDU_AUTHORIZE,
34 	PDU_START_TRANSACTION,
35 	PDU_STOP_TRANSACTION,
36 	PDU_HEARTBEAT,
37 	PDU_METER_VALUES,
38 	PDU_CLEAR_CACHE,
39 	PDU_REMOTE_START_TRANSACTION,
40 	PDU_REMOTE_STOP_TRANSACTION,
41 	PDU_GET_CONFIGURATION,
42 	PDU_CHANGE_CONFIGURATION,
43 	PDU_CHANGE_AVAILABILITY,
44 	PDU_UNLOCK_CONNECTOR,
45 	PDU_RESET,
46 
47 	PDU_MSG_END,
48 
49 	/* internal msg */
50 	PDU_CS_ONLINE,
51 };
52 
53 enum ocpp_key_type {
54 	KEY_TYPE_BOOL = 1,
55 	KEY_TYPE_INT = sizeof(int),
56 	KEY_TYPE_STR,
57 	KEY_TYPE_CSL,
58 };
59 
60 enum boot_status {
61 	BOOT_ACCEPTED,
62 	BOOT_PENDING,
63 	BOOT_REJECTED
64 };
65 
66 enum ocpp_key {
67 	/* core mandatory */
68 	CFG_ALLOW_OFFLINE_TX_FOR_UNKN_ID,
69 	CFG_AUTH_CACHE_ENABLED,
70 	CFG_AUTH_REMOTE_TX_REQ,
71 	CFG_BLINK_REPEAT,
72 	CFG_CLK_ALIGN_DATA_INTERVAL,
73 	CFG_CONN_TIMEOUT,
74 	CFG_GETCFG_MAX_KEY,
75 	CFG_HEARTBEAT_INTERVAL,
76 	CFG_LIGHT_INTENSITY,
77 	CFG_LOCAL_AUTH_OFFLINE,
78 	CFG_LOCAL_PREAUTH,
79 	CFG_MAX_ENERGYON_INVL_ID,
80 	CFG_MTR_VAL_ALGIN_DATA,
81 	CFG_MTR_VAL_ALGIN_DATA_MAXLEN,
82 	CFG_MTR_VAL_SAMPLED_DATA,
83 	CFG_MTR_VAL_SAMPLED_DATA_MAXLEN,
84 	CFG_MTR_VAL_SAMPLE_INTERVAL,
85 	CFG_MIN_STATUS_DURATION,
86 	CFG_NO_OF_CONNECTORS,
87 	CFG_REST_RETRIES,
88 	CFG_CONN_PHASE_ROT,
89 	CFG_CONN_PHASE_ROT_MAXLEN,
90 	CFG_STOP_TXN_ON_EVSIDE_DISCON,
91 	CFG_STOP_TXN_ON_INVL_ID,
92 	CFG_STOP_TXN_ALIGNED_DATA,
93 	CFG_STOP_TXN_ALIGNED_DATA_MAXLEN,
94 	CFG_SUPPORTED_FEATURE_PROFILE,
95 	CFG_SUPPORTED_FEATURE_PROFILE_MAXLEN,
96 	CFG_TXN_MSG_ATTEMPTS,
97 	CFG_TXN_MSG_RETRY_INTERVAL,
98 	CFG_UNLOCK_CONN_ON_EVSIDE_DISCON,
99 	CFG_WEBSOCK_PING_INTERVAL,
100 
101 	/* optional */
102 
103 	OCPP_CFG_END
104 };
105 
106 enum ocpp_cp_state {
107 	CP_STATE_INIT,
108 	CP_STATE_BOOTNOTIF,
109 	CP_STATE_READY,
110 };
111 
112 enum ocpp_wamp_rpc {
113 	OCPP_WAMP_RPC_REQ = '2',
114 	OCPP_WAMP_RPC_RESP = '3',
115 	OCPP_WAMP_RPC_ERR = '4'
116 };
117 
118 typedef int (*ocpp_msg_fp_t)(char *buf, ...);
119 
120 struct boot_notif {
121 	enum boot_status status;
122 	int interval;
123 	struct timeval date;
124 };
125 
126 struct ocpp_idtag_info {
127 	char idtag[CISTR20];
128 	char p_idtag[CISTR20];
129 	enum ocpp_auth_status auth_status;
130 	char exptime[CISTR25];
131 };
132 
133 struct ocpp_upstream_info {
134 	struct k_mutex ws_sndlock; /* to server */
135 	struct k_poll_signal ws_rspsig; /* wait for resp parsed */
136 	int tcpsock;
137 	int wssock;
138 	struct k_thread tinfo;
139 	char recv_buf[CONFIG_OCPP_RECV_BUFFER_SIZE];
140 	char wsrecv_buf[CONFIG_OCPP_RECV_BUFFER_SIZE * 2];
141 
142 	struct ocpp_cs_info csi;
143 };
144 
145 struct ocpp_info {
146 	struct k_mutex ilock; /* internal to lib */
147 	sys_slist_t slist; /* session list */
148 	ocpp_msg_fp_t *cfn;
149 	ocpp_msg_fp_t *pfn;
150 	bool is_cs_offline;
151 	struct k_timer hb_timer;
152 	struct k_timer mtr_timer;
153 	atomic_t mtr_timer_ref_cnt;
154 	int hb_sec; /* heartbeat interval */
155 	struct k_msgq *msgq;
156 	struct k_thread tinfo;
157 	struct ocpp_upstream_info ui;
158 	bool is_cs_connected; /* central system */
159 
160 	ocpp_user_notify_callback_t cb;
161 	void *user_data;
162 	enum ocpp_cp_state state;
163 	/* only for pdu message from internal thread (ocpp_internal_handler) */
164 	char pdu_buf[512];
165 };
166 
167 struct ocpp_session {
168 	struct k_mutex slock; /* session lock */
169 	char idtag[CISTR20];
170 	bool is_active;
171 	uint8_t idcon;
172 	int idtxn;
173 	int resp_status;
174 	int uid;
175 	sys_snode_t node;
176 	struct ocpp_info *ctx;
177 };
178 
179 union ocpp_keyval {
180 	int ival;
181 	char *str;
182 };
183 
184 struct ocpp_wamp_rpc_msg {
185 	char *msg;
186 	size_t msg_len;
187 	struct ocpp_info *ctx;
188 	struct k_mutex *sndlock;
189 	struct k_poll_signal *rspsig;
190 };
191 
192 struct internal_msg {
193 	enum ocpp_pdu_msg msgtype;
194 	union ocpp_io_value usr;
195 };
196 
197 void ocpp_parser_init(ocpp_msg_fp_t **cfn, ocpp_msg_fp_t **pfn);
198 int parse_rpc_msg(char *msg, int msglen, char *uid, int uidlen,
199 		  int *pdu, bool *is_rsp);
200 int ocpp_send_to_server(struct ocpp_wamp_rpc_msg *snd, k_timeout_t timeout);
201 int ocpp_receive_from_server(struct ocpp_wamp_rpc_msg *rcv, uint32_t *msg_type,
202 			     uint32_t timeout);
203 
204 int ocpp_unlock_connector(struct ocpp_info *ctx,
205 			  struct internal_msg *msg, char *uid);
206 int ocpp_get_configuration(enum ocpp_key key, struct ocpp_info *ctx, char *uid);
207 int ocpp_boot_notification(ocpp_session_handle_t hndl,
208 			   struct ocpp_cp_info *cpi);
209 int ocpp_heartbeat(ocpp_session_handle_t hndl);
210 void ocpp_get_utc_now(char utc[CISTR25]);
211 bool ocpp_session_is_valid(struct ocpp_session *sh);
212 int ocpp_remote_start_transaction(struct ocpp_info *ctx,
213 				  struct internal_msg *msg,
214 				  char *uid);
215 int ocpp_remote_stop_transaction(struct ocpp_info *ctx,
216 				 struct internal_msg *msg,
217 				 int idtxn, char *uid);
218 int ocpp_change_configuration(char *skey, struct ocpp_info *ctx,
219 			      char *sval, char *uid);
220 int ocpp_meter_values(ocpp_session_handle_t hndl,
221 		      enum ocpp_meter_measurand mes,
222 		      char *sval);
223 
224 union ocpp_keyval *ocpp_get_key_val(enum ocpp_key key);
225 enum ocpp_key ocpp_key_to_cfg(const char *skey);
226 enum ocpp_key_type ocpp_get_keyval_type(enum ocpp_key key);
227 char *ocpp_get_key_literal(enum ocpp_key key);
228 bool ocpp_is_key_rw(enum ocpp_key key);
229 int ocpp_set_cfg_val(enum ocpp_key key, union ocpp_keyval *val);
230 int ocpp_update_cfg_val(enum ocpp_key key, union ocpp_keyval *val);
231 int ocpp_find_pdu_from_literal(const char *msg);
232 const char *ocpp_get_pdu_literal(enum ocpp_pdu_msg pdu);
233 #endif /* __OCPP_I_ */
234