Module_OcppBackend.c 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611
  1. #include "Module_OcppBackend.h"
  2. #undef FALSE
  3. #undef TRUE
  4. typedef enum boolean { FALSE, TRUE } BOOL;
  5. struct lws *wsi_client;
  6. struct lws_context *context;
  7. static int req_SendQueue = 0;
  8. pthread_t tid_connectServer;
  9. pthread_t tid_ProcQueue;
  10. pthread_t tid_Watchdog;
  11. struct StartTime
  12. {
  13. struct timespec connect;
  14. struct timespec bootNotification;
  15. struct timespec reConnect;
  16. struct timespec disconnectServer;
  17. struct timespec startTimeQueue;
  18. struct timespec pingOn;
  19. }startTime;
  20. struct QueueOpInfo queueOpInfo;
  21. //==========================================
  22. // Function prototype
  23. //==========================================
  24. void ReceivedMessage(void *in, size_t len);
  25. int SendBufLen=0;//(1024*4);//(1024*3);
  26. unsigned char SendBuffer[WEBSOCKET_BUFFER_SIZE]={0};
  27. static int ConnectionEstablished=0;
  28. int defaultWaitingTime = 60; //10 second
  29. char OcppPath[384]={0};
  30. char OcppProtocol[10]={0},OcppHost[128]={0}, OcppTempPath[256]={0};
  31. int OcppPort=0;
  32. unsigned char StartTransactionIdTagTemp[20]={0};
  33. int LastQueuedTransactionId[8] = {0};
  34. uint8_t isWebsocketSendable = 1;
  35. uint8_t isQueueSendable = 1;
  36. uint8_t counterQueueSent = 0;
  37. uint8_t counterConnect = 0;
  38. uint8_t counterPingSend = 0;
  39. uint8_t counterBootNotificationSend = 0;
  40. sqlite3 *db;
  41. char *errMsg = NULL;
  42. static char *createsql = "CREATE TABLE IF NOT EXISTS log_buffer("
  43. "idx integer primary key,"
  44. "user_id text,"
  45. "cmd_sn text,"
  46. "charger_id text,"
  47. "gun_type text,"
  48. "gun_no text,"
  49. "rfid_no text,"
  50. "stime text,"
  51. "etime text,"
  52. "time_len text,"
  53. "s_soc text,"
  54. "e_soc text,"
  55. "stop_reason text,"
  56. "power text,"
  57. "meter_before text,"
  58. "meter_after text,"
  59. "charge_price text,"
  60. "reserve text,"
  61. "surplus_before text,"
  62. "surplus_after text,"
  63. "service_price text,"
  64. "is_pay text,"
  65. "charge_strategy text,"
  66. "charge_parameter text,"
  67. "vin text,"
  68. "vehicle_no text,"
  69. "start_method text,"
  70. "card_type text,"
  71. "is_upload text,"
  72. "guid text UNIQUE,"
  73. "is_buf2OK text);";
  74. static char *sqlOcppAuthCache = "create table if not exists ocpp_auth_cache (idx integer primary key,"
  75. "idtag text UNIQUE,"
  76. "parent_idtag text,"
  77. "expir_date text,"
  78. "status text);";
  79. static char *sqlOcppAuthLocal = "create table if not exists ocpp_auth_local (idx integer primary key,"
  80. "idtag text UNIQUE,"
  81. "parent_idtag text,"
  82. "expir_date text,"
  83. "status text,"
  84. "version text);";
  85. static char *sqlTransaction = "create table if not exists ocpp_transaction_record (idx integer primary key,"
  86. "occurDatetime text,"
  87. "message_type text,"
  88. "message_content text);";
  89. static char *sqlPeriodEnergy = "create table if not exists ocpp_period_energy ( transactionId integer primary key UNIQUE,"
  90. "connectorId integer,"
  91. "occurDatetime text,"
  92. "periodEnergy text);";
  93. static char *sqlReportDeduct = "create table if not exists report_deduct_info ( idx integer primary key,"
  94. "txId integer UNIQUE,"
  95. "creditNo text,"
  96. "deductResult text,"
  97. "isDonateInvoice text,"
  98. "amount text,"
  99. "vemData text,"
  100. "ROC text,"
  101. "RRN text,"
  102. "approvalNo text,"
  103. "storeId text,"
  104. "isUploaded text);";
  105. static char *sqlReportOccupancyDeduct = "create table if not exists report_occupancyDeduct_info ( idx integer primary key,"
  106. "occupancySN text,"
  107. "creditNo text,"
  108. "deductResult text,"
  109. "amount text,"
  110. "approvalNo text,"
  111. "isUploaded text);";
  112. static char *sqlMeterValueBuffer = "create table if not exists meterValuesBuffer( idx integer primary key,"
  113. "occurDatetime text,"
  114. "gun_index text,"
  115. "transactionId text,"
  116. "ReadingContext text,"
  117. "meterValue text);";
  118. //=================================
  119. // Common routine
  120. //=================================
  121. int GetTransactionQueueNum(void)
  122. {
  123. return queueOpInfo.TransactionQueueNum;
  124. }
  125. //==========================================
  126. // Web socket tranceive routine
  127. //==========================================
  128. int SendData(struct lws *wsi)
  129. {
  130. int n;
  131. int len;
  132. unsigned char out[LWS_SEND_BUFFER_PRE_PADDING + ARRAY_SIZE(SendBuffer) + LWS_SEND_BUFFER_POST_PADDING] = {0};
  133. len = strlen((char *)SendBuffer);
  134. if(len == 0)return 0;
  135. if((strstr((char*)SendBuffer, "\"MeterValues\"") != NULL)
  136. || (strstr((char*)SendBuffer, "\"StartTransaction\"") != NULL)
  137. || (strstr((char*)SendBuffer, "\"StopTransaction\"") != NULL))
  138. {
  139. isQueueSendable = 0;
  140. }
  141. memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, SendBuffer, len );
  142. DEBUG_OCPPMESSAGE_INFO("===========> %s\n", out + LWS_SEND_BUFFER_PRE_PADDING);
  143. n = lws_write(wsi, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);
  144. memset(SendBuffer, 0, len);
  145. SendBufLen = 0;
  146. return n;
  147. }
  148. int SendPing(struct lws *wsi)
  149. {
  150. uint8_t ping[LWS_PRE + 125];
  151. DEBUG_OCPPMESSAGE_INFO("===========> Set PING packet.\n");
  152. return lws_write(wsi, ping + LWS_PRE, 0, LWS_WRITE_PING);
  153. }
  154. static int OCPP16Callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
  155. {
  156. char buf[256]={0}, hash[20]={0}, key_b64[40]={0}, tempin[WEBSOCKET_BUFFER_SIZE]={0}, sstr[WEBSOCKET_BUFFER_SIZE]={0};
  157. uint8_t auth_b64[256]={0}, boxId[128]={0}, password[64]={0};
  158. int c = 0;
  159. char *loc;
  160. switch (reason)
  161. {
  162. case LWS_CALLBACK_PROTOCOL_INIT:
  163. DEBUG_INFO("LWS_CALLBACK_PROTOCOL_INIT\n");
  164. break;
  165. case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
  166. DEBUG_INFO("LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH\n");
  167. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Client Request START -----\n");
  168. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_URI);
  169. DEBUG_OCPPMESSAGE_INFO("GET %s HTTP/1.1 \n", buf);
  170. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_HOST);
  171. DEBUG_OCPPMESSAGE_INFO("Host: %s\n", buf);
  172. DEBUG_OCPPMESSAGE_INFO("Upgrade: websocket\n");
  173. DEBUG_OCPPMESSAGE_INFO("Connection: Upgrade\n");
  174. lws_b64_encode_string(hash, 16, key_b64, ARRAY_SIZE(key_b64));// Sec-WebSocket-Key
  175. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Key: %s\n", key_b64);
  176. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
  177. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  178. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Version: %d\n", SPEC_LATEST_SUPPORTED);
  179. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Client Request END -----\n");
  180. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Server response START -----\n");
  181. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_HTTP);
  182. DEBUG_OCPPMESSAGE_INFO("HTTP/1.1 %s\n", buf);
  183. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_UPGRADE);
  184. DEBUG_OCPPMESSAGE_INFO("Upgrade: %s\n", buf);
  185. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_CONNECTION);
  186. DEBUG_OCPPMESSAGE_INFO("Connection: %s\n", buf);
  187. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_ACCEPT);
  188. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Accept: %s\n", buf);
  189. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_PROTOCOL);
  190. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  191. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Server response END -----\n");
  192. SetOcppVersion((uint8_t*)buf);
  193. break;
  194. case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
  195. DEBUG_INFO("LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION\n");
  196. break;
  197. case LWS_CALLBACK_WSI_DESTROY:
  198. DEBUG_INFO("LWS_CALLBACK_WSI_DESTROY\n");
  199. pthread_detach(tid_connectServer);
  200. SetServerSign(FALSE);
  201. ConnectionEstablished = 0;
  202. context = NULL;
  203. break;
  204. case LWS_CALLBACK_LOCK_POLL:
  205. break;
  206. case LWS_CALLBACK_ADD_POLL_FD:
  207. DEBUG_INFO("LWS_CALLBACK_ADD_POLL_FD\n");
  208. break;
  209. case LWS_CALLBACK_DEL_POLL_FD:
  210. DEBUG_INFO("LWS_CALLBACK_DEL_POLL_FD\n");
  211. break;
  212. case LWS_CALLBACK_UNLOCK_POLL:
  213. break;
  214. case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
  215. break;
  216. case LWS_CALLBACK_WSI_CREATE:
  217. DEBUG_INFO("LWS_CALLBACK_WSI_CREATE\n");
  218. break;
  219. case LWS_CALLBACK_GET_THREAD_ID:
  220. break;
  221. case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
  222. DEBUG_INFO("LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER\n");
  223. unsigned char** pos = (unsigned char**)in;
  224. unsigned char* end = (*pos) + len;
  225. switch(GetOcppSecurityProfile())
  226. {
  227. case 1:
  228. case 2:
  229. case 3:
  230. GetOcppChargerBoxId(boxId);
  231. GetOcppSecurityPassword(password);
  232. sprintf(buf, "%s:%s", boxId, password);
  233. lws_b64_encode_string(buf, strlen(buf), (char*)auth_b64, ARRAY_SIZE(auth_b64));
  234. sprintf(buf, "Basic %s", auth_b64);
  235. if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_AUTHORIZATION, (uint8_t *)buf, strlen(buf), pos, end))
  236. {
  237. DEBUG_ERROR("lws_add_http_header_by_token : WSI_TOKEN_HTTP_AUTHORIZATION\n");
  238. return -1;
  239. }
  240. DEBUG_OCPPMESSAGE_INFO("SecurityProfile: %d\n", GetOcppSecurityProfile());
  241. DEBUG_OCPPMESSAGE_INFO("Password: %s\n", password);
  242. DEBUG_OCPPMESSAGE_INFO("Authorization: %s\n", buf);
  243. break;
  244. case 0:
  245. default:
  246. break;
  247. }
  248. break;
  249. case LWS_CALLBACK_CLIENT_ESTABLISHED: //3
  250. DEBUG_INFO("LWS_CALLBACK_CLIENT_ESTABLISHED\n");
  251. //connected
  252. ConnectionEstablished=1;
  253. SetOcppConnStatus(TRUE);
  254. refreshStartTimer(&startTime.pingOn);
  255. counterPingSend = 0;
  256. counterBootNotificationSend = 0;
  257. queueOpInfo.TransactionMessageResend = 0;
  258. break;
  259. case LWS_CALLBACK_CLIENT_CONNECTION_ERROR://1
  260. DEBUG_ERROR("LWS_CALLBACK_CLIENT_CONNECTION_ERROR %s\n", (char *)in );
  261. //disconnected
  262. ConnectionEstablished=0;
  263. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Client START =====\n");
  264. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_URI);
  265. DEBUG_OCPPMESSAGE_INFO("GET %s HTTP/1.1 \n", buf);
  266. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_HOST);
  267. DEBUG_OCPPMESSAGE_INFO("Host: %s\n", buf);
  268. DEBUG_OCPPMESSAGE_INFO("Upgrade: websocket\n");
  269. DEBUG_OCPPMESSAGE_INFO("Connection: Upgrade\n");
  270. lws_b64_encode_string(hash, 16, key_b64, ARRAY_SIZE(key_b64));// Sec-WebSocket-Key
  271. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Key: %s\n", key_b64);
  272. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
  273. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  274. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Version: %d\n", SPEC_LATEST_SUPPORTED);
  275. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Client END =====\n");
  276. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Server response START =====\n");
  277. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_HTTP);
  278. DEBUG_OCPPMESSAGE_INFO("HTTP/1.1 %s\n", buf);
  279. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_UPGRADE);
  280. DEBUG_OCPPMESSAGE_INFO("Upgrade: %s\n", buf);
  281. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_CONNECTION);
  282. DEBUG_OCPPMESSAGE_INFO("Connection: %s\n", buf);
  283. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_ACCEPT);
  284. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Accept: %s\n", buf);
  285. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_PROTOCOL);
  286. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  287. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Server response END =====\n");
  288. break;
  289. case LWS_CALLBACK_CLOSED://4
  290. DEBUG_INFO("LWS_CALLBACK_CLOSED\n");
  291. //disconnected
  292. ConnectionEstablished=0;
  293. break;
  294. case LWS_CALLBACK_CLIENT_WRITEABLE://10
  295. if(isWebsocketSendable && (0 < GetWebSocketPingInterval()) && (GetWebSocketPingInterval() <= getDiffSecNow(startTime.pingOn)) && (GetServerSign() == TRUE))
  296. SendPing(wsi);
  297. else
  298. SendData(wsi);
  299. break;
  300. case LWS_CALLBACK_CLIENT_RECEIVE://8
  301. ((char *)in)[len] = '\0';
  302. DEBUG_OCPPMESSAGE_INFO("<===== %s\n", (char *)in);
  303. //**********Receive Message**********/
  304. c = 0;
  305. loc = strstr((const char *)in, "][2,");
  306. if(loc == NULL)
  307. {
  308. loc = strstr((const char *)in, "][3,");
  309. if(loc == NULL)
  310. {
  311. loc = strstr((const char *)in, "][4,");
  312. }
  313. }
  314. memset(sstr, 0, ARRAY_SIZE(sstr) );
  315. if(loc != NULL)
  316. {
  317. DEBUG_INFO("There are continuous second packet []\n");
  318. while (loc[1+c] != '\0')
  319. {
  320. sstr[c] = loc[1+c];
  321. c++;
  322. }
  323. sstr[c] = '\0';
  324. strcpy(tempin, sstr);
  325. DEBUG_INFO("Final Receive: %s\n", tempin);
  326. }
  327. else
  328. {
  329. strcpy(tempin,(char *)in);
  330. }
  331. ReceivedMessage((void *)strtrim(tempin), strlen(tempin));
  332. isWebsocketSendable = 1;
  333. refreshStartTimer(&startTime.pingOn);
  334. break;
  335. case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
  336. DEBUG_INFO("LWS_CALLBACK_CLIENT_RECEIVE_PONG\n");
  337. DEBUG_OCPPMESSAGE_INFO("<===== Get PONG packet.\n");
  338. refreshStartTimer(&startTime.pingOn);
  339. isWebsocketSendable = 1;
  340. counterPingSend = 0;
  341. break;
  342. case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
  343. DEBUG_INFO("LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION\n");
  344. break;
  345. case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
  346. DEBUG_INFO("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS\n");
  347. break;
  348. case LWS_CALLBACK_PROTOCOL_DESTROY:
  349. DEBUG_INFO("LWS_CALLBACK_PROTOCOL_DESTROY\n");
  350. break;
  351. case LWS_CALLBACK_RECEIVE_PONG:
  352. DEBUG_INFO("LWS_CALLBACK_RECEIVE_PONG\n");
  353. break;
  354. case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
  355. DEBUG_INFO("LWS_CALLBACK_WS_PEER_INITIATED_CLOSE\n");
  356. break;
  357. case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
  358. DEBUG_INFO("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n");
  359. if(GetInternetConn() == 1)
  360. {
  361. DEBUG_INFO("Download new CA certification.\n", system("wget --no-check-certificate -O /root/cacert.pem http://curl.haxx.se/ca/cacert.pem &"));
  362. }
  363. break;
  364. default:
  365. DEBUG_INFO("Reason = %d\n", reason);
  366. break;
  367. }
  368. return 0;
  369. }
  370. static struct lws_protocols protocols[] =
  371. {
  372. {
  373. "ocpp1.6",
  374. OCPP16Callback,
  375. WEBSOCKET_BUFFER_SIZE,
  376. WEBSOCKET_BUFFER_SIZE,
  377. },
  378. {
  379. "ocpp2.0.1",
  380. OCPP16Callback,
  381. WEBSOCKET_BUFFER_SIZE,
  382. WEBSOCKET_BUFFER_SIZE,
  383. },
  384. {
  385. "ocpp1.6,ocpp2.0.1",
  386. OCPP16Callback,
  387. WEBSOCKET_BUFFER_SIZE,
  388. WEBSOCKET_BUFFER_SIZE,
  389. },
  390. {
  391. NULL, NULL, 0 /* End of list */
  392. }
  393. };
  394. void* ConnectWsServer(void* data) //int ConnectWsServer()
  395. {
  396. struct lws_context_creation_info ContextInfo;
  397. struct lws_client_connect_info ConnInfo;
  398. int use_ssl=0;
  399. counterConnect += 1;
  400. // If internet available synchronize datetime with ntp server
  401. if(GetInternetConn() == 1)
  402. {
  403. system("pkill ntpd");
  404. DEBUG_INFO("NTP synchronize with Microsoft\n", system("/usr/sbin/ntpd -nqp time.windows.com &"));
  405. DEBUG_INFO("NTP synchronize with China\n", system("/usr/sbin/ntpd -nqp cn.ntp.org.cn &"));
  406. DEBUG_INFO("NTP synchronize with Taiwan\n", system("/usr/sbin/ntpd -nqp tock.stdtime.gov.tw &"));
  407. DEBUG_INFO("NTP synchronize with Europe\n", system("/usr/sbin/ntpd -nqp 0.europe.pool.ntp.org &"));
  408. }
  409. if(context!=NULL)
  410. {
  411. pthread_detach(pthread_self());
  412. lws_context_destroy(context);
  413. ConnectionEstablished=0;
  414. context = NULL;
  415. }
  416. memset(&ContextInfo, 0, sizeof(struct lws_context_creation_info));
  417. if((GetOcppServerURL()==0) || (GetOcppPort() == 0) || (GetOcppPath()==0))
  418. {
  419. DEBUG_ERROR("OCPP URL is NULL or OCPP Port is zero or OCPP Path is NULL\n");
  420. goto end;
  421. }
  422. if((strcmp(OcppProtocol,"ws")==0)&&(strlen(OcppProtocol)== 2))
  423. {
  424. DEBUG_INFO("Web socket is non-security mode.\n");
  425. use_ssl=0;
  426. }
  427. else if((strcmp(OcppProtocol,"wss")==0)&&(strlen(OcppProtocol)== 3))
  428. {
  429. DEBUG_INFO("Web socket is security mode.\n");
  430. use_ssl=1;
  431. }
  432. MergeCertificates();
  433. ContextInfo.port = CONTEXT_PORT_NO_LISTEN;
  434. ContextInfo.iface = NULL;
  435. ContextInfo.ssl_private_key_password = NULL;
  436. ContextInfo.ssl_cert_filepath = ((GetOcppSecurityProfile()==3) && (access("/Storage/OCPP/certCP.pem",F_OK) != -1))?"/Storage/OCPP/certCP.pem":NULL;
  437. ContextInfo.ssl_private_key_filepath = ((GetOcppSecurityProfile()==3) && (access("/Storage/OCPP/certCP.key",F_OK) != -1))?"/Storage/OCPP/certCP.key":NULL;
  438. ContextInfo.ssl_ca_filepath = "/root/certCA.pem";
  439. ContextInfo.ssl_cipher_list = NULL; //use default one
  440. ContextInfo.gid = -1;
  441. ContextInfo.uid = -1;
  442. if(use_ssl)
  443. {
  444. ContextInfo.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
  445. }
  446. ContextInfo.protocols = protocols;
  447. ContextInfo.timeout_secs = GetBackendConnectionTimeout();
  448. //ContextInfo.ws_ping_pong_interval = GetWebSocketPingInterval();
  449. ContextInfo.ka_time = 20;
  450. ContextInfo.keepalive_timeout = 5;
  451. ContextInfo.ka_probes = 2;
  452. ContextInfo.ka_interval = 5;
  453. context = lws_create_context(&ContextInfo);
  454. if (context == NULL)
  455. {
  456. DEBUG_ERROR("lws_create_context NG");
  457. goto end;
  458. }
  459. memset(&ConnInfo,0,sizeof(struct lws_client_connect_info));
  460. // fill up below information
  461. ConnInfo.context = context;
  462. ConnInfo.address=(const char *)OcppHost;
  463. DEBUG_INFO("ConnInfo.address: %s\n", ConnInfo.address);
  464. ConnInfo.port = GetOcppPort();
  465. DEBUG_INFO("ConnInfo.port: %d\n", ConnInfo.port);
  466. ConnInfo.path=(const char *)OcppPath;
  467. DEBUG_INFO("ConnInfo.path: %s\n", ConnInfo.path);
  468. char addr_port[256] = { 0 };
  469. sprintf(addr_port, "%s:%u", ConnInfo.address, (ConnInfo.port & 65535) );
  470. ConnInfo.host= addr_port; // ConnInfo.address;//lws_canonical_hostname(context);
  471. //ConnInfo.origin="origin";
  472. ConnInfo.protocol = protocols[0].name;
  473. ConnInfo.ietf_version_or_minus_one = -1;
  474. if(use_ssl)
  475. {
  476. #ifdef TLS_VALID_CERT_EXPIRED
  477. ConnInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
  478. DEBUG_INFO("TLS does not allow expired certification.\n");
  479. #else
  480. ConnInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_EXPIRED;
  481. DEBUG_INFO("TLS allow expired certification.\n");
  482. #endif
  483. }
  484. wsi_client = lws_client_connect_via_info(&ConnInfo);
  485. if (!wsi_client)
  486. {
  487. DEBUG_ERROR("lws_client_connect_via_info NG\n");
  488. //goto end;
  489. }
  490. counterConnect=0;
  491. DEBUG_INFO("counterConnect: %d\n", counterConnect);
  492. end:
  493. pthread_exit(NULL/*(void *) fname*/);
  494. }
  495. int isQueueOverSize()
  496. {
  497. FILE *fp;
  498. uint32_t file_size;
  499. uint8_t result = FALSE;
  500. fp = fopen("/Storage/OCPP/TransactionRelatedQueue" , "r");
  501. if(fp != NULL)
  502. {
  503. fseek(fp, 0L, SEEK_END);
  504. file_size = ftell(fp);
  505. if(file_size > (500*1024*1024))
  506. {
  507. result = TRUE;
  508. DEBUG_WARN("Queue file over size.\n");
  509. }
  510. fclose(fp);
  511. }
  512. return result;
  513. }
  514. int showfront(char *uuid, char *data)
  515. {
  516. FILE *fp;
  517. int result = FALSE; // 1: TRUE 0:FALSE
  518. char str[QUEUE_MESSAGE_LENGTH]={0};
  519. char sstr[50]={ 0 };//sstr[200]={ 0 };
  520. int c = 0;
  521. char *loc;
  522. char rmFileCmd[100]={0};
  523. struct stat stats;
  524. stat("/Storage/OCPP", &stats);
  525. // Check for directory existence
  526. if (S_ISDIR(stats.st_mode) == 1)
  527. {
  528. //DEBUG_INFO("\n OCPP directory exist \n");
  529. }
  530. else
  531. {
  532. DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  533. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  534. system(rmFileCmd);
  535. }
  536. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  537. if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1)
  538. {
  539. //DEBUG_INFO("TransactionRelatedQueue exist.\n");
  540. }
  541. else
  542. {
  543. //DEBUG_INFO("TransactionRelatedQueue not exist\n");
  544. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+");
  545. if(log == NULL)
  546. {
  547. DEBUG_INFO("Can't Create File TransactionRelatedQueue \n");
  548. return FALSE;
  549. }
  550. else
  551. {
  552. fclose(log);
  553. }
  554. }
  555. /* opening file for reading */
  556. fp = fopen("/Storage/OCPP/TransactionRelatedQueue" , "r");
  557. if(fp == NULL) {
  558. DEBUG_INFO("Error opening TransactionRelatedQueue file");
  559. return FALSE;
  560. }
  561. if( fgets (str, QUEUE_MESSAGE_LENGTH, fp)!=NULL ) {
  562. /* writing content to stdout */
  563. //DEBUG_INFO("str=%s",str);
  564. if ((str[0] == '\n')||(strcmp(str,"")==0))
  565. {
  566. DEBUG_INFO("It is a blank line");
  567. fclose(fp);
  568. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  569. sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/TransactionRelatedQueue");
  570. system(rmFileCmd);
  571. result = FALSE;
  572. return result;
  573. }
  574. else
  575. {
  576. //puts(str);
  577. //----------------uuid--------------//
  578. loc = strstr(str, "\"");
  579. memset(sstr ,0, ARRAY_SIZE(sstr) );
  580. c = 0;
  581. while (loc[1+c] != '\"')
  582. {
  583. sstr[c] = loc[1+c];
  584. c++;
  585. }
  586. sstr[c] = '\0';
  587. //DEBUG_INFO("\n uuid:%s", sstr);
  588. //DEBUG_INFO("\n data:%s", str);
  589. strcpy(uuid,sstr);
  590. strcpy(data,str);
  591. result = TRUE;
  592. }
  593. }
  594. else
  595. {
  596. //DEBUG_INFO("queue is null\n");
  597. strcpy(uuid,"");
  598. strcpy(data,"");
  599. result = FALSE;
  600. }
  601. fclose(fp);
  602. return result;
  603. }
  604. int addq(char *uuid, char *data)
  605. {
  606. FILE *outfile;
  607. char rmFileCmd[100]={0};
  608. struct stat stats;
  609. stat("/Storage/OCPP", &stats);
  610. DEBUG_INFO("addq\n");
  611. // Check for directory existence
  612. if (S_ISDIR(stats.st_mode) == 1)
  613. {
  614. //DEBUG_INFO("\n OCPP directory exist \n");
  615. }
  616. else
  617. {
  618. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  619. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  620. system(rmFileCmd);
  621. }
  622. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  623. if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1)
  624. {
  625. //DEBUG_INFO("TransactionRelatedQueue exist.\n");
  626. }
  627. else
  628. {
  629. //DEBUG_INFO("TransactionRelatedQueue not exist\n");
  630. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+");
  631. if(log == NULL)
  632. {
  633. //DEBUG_INFO("Can't Create File TransactionRelatedQueue \n");
  634. return FALSE;
  635. }
  636. else
  637. {
  638. fclose(log);
  639. }
  640. }
  641. // open file for writing
  642. outfile = fopen ("/Storage/OCPP/TransactionRelatedQueue", "a");
  643. DEBUG_INFO("data = %s\n",data);
  644. fputs(data, outfile);
  645. fputs("\n", outfile);
  646. fclose (outfile);
  647. queueOpInfo.TransactionQueueNum += 1;
  648. DEBUG_INFO("add queue end\n");
  649. system("/bin/fsync -d /dev/mtdblock13;/bin/sync &");
  650. return FALSE;
  651. }
  652. //---------------- delq(): delete the top item --------------//
  653. int delq()
  654. {
  655. char tempfile[] = "/Storage/OCPP/delqtemp.json";
  656. FILE *infile;
  657. FILE *outfile;
  658. int resultRename=0;
  659. char filename[60]={0};
  660. char rmFileCmd[100]={0};
  661. struct stat stats;
  662. stat("/Storage/OCPP", &stats);
  663. DEBUG_INFO("delq()\n");
  664. // Check for directory existence
  665. if (S_ISDIR(stats.st_mode) == 1)
  666. {
  667. //DEBUG_INFO("\n OCPP directory exist \n");
  668. }
  669. else
  670. {
  671. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  672. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  673. system(rmFileCmd);
  674. }
  675. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  676. if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1)
  677. {
  678. //DEBUG_INFO("TransactionRelatedQueue exist.\n");
  679. }
  680. else
  681. {
  682. //DEBUG_INFO("TransactionRelatedQueue not exist\n");
  683. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+");
  684. if(log == NULL)
  685. {
  686. //DEBUG_INFO("log is NULL\n");
  687. return 0;
  688. }
  689. else
  690. {
  691. fclose(log);
  692. }
  693. }
  694. // open file for writing
  695. strcpy(filename, "/Storage/OCPP/TransactionRelatedQueue");
  696. infile = fopen ("/Storage/OCPP/TransactionRelatedQueue", "r");
  697. outfile = fopen (tempfile, "w");
  698. /*检测到文件结束标识返回1,否则返回0。*/
  699. //DEBUG_INFO("feof(infile) =%d\n",feof(infile));
  700. int c;
  701. c = fgetc(infile);
  702. //printf("file c:%d\n",c);
  703. rewind(infile);
  704. if(c == EOF)
  705. {
  706. //DEBUG_INFO("TransactionRelatedQueue is NULL\n");
  707. fclose(infile);
  708. fclose(outfile);
  709. sprintf(rmFileCmd,"rm -f %s",tempfile);
  710. system(rmFileCmd);
  711. }
  712. else
  713. {
  714. char buf[QUEUE_MESSAGE_LENGTH]={0};
  715. int i = 0;
  716. //DEBUG_INFO("Orignal File is not NULL\n");
  717. while (fgets(buf, sizeof(buf), infile) != NULL)
  718. {
  719. //printf("Orignal File get strings \n");
  720. buf[strlen(buf) - 1] = '\0'; // eat the newline fgets() stores
  721. if(i==0)
  722. {
  723. queueOpInfo.TransactionQueueNum -= 1;
  724. queueOpInfo.TransactionMessageResend = 0;
  725. DEBUG_INFO("delete the item\n");
  726. }
  727. if(i != 0)
  728. {
  729. fprintf(outfile,"%s\n", buf);
  730. }
  731. i = i + 1;
  732. }
  733. fclose(infile);
  734. fclose(outfile);
  735. sprintf(rmFileCmd,"rm -f %s",filename);
  736. system(rmFileCmd);
  737. resultRename = rename(tempfile, filename);
  738. if(resultRename == 0)
  739. {
  740. //DEBUG_INFO("TransactionRelatedQueue file renamed successfully");
  741. }
  742. else
  743. {
  744. //DEBUG_INFO("Error: unable to rename the TransactionRelatedQueue file");
  745. }
  746. DEBUG_INFO("delq() end\n");
  747. }
  748. system("/bin/fsync -d /dev/mtdblock13;/bin/sync &");
  749. return 0;
  750. }
  751. int showqueue()
  752. {
  753. char rmFileCmd[100]={0};
  754. struct stat stats;
  755. stat("/Storage/OCPP", &stats);
  756. // Check for directory existence
  757. if (S_ISDIR(stats.st_mode) == 1)
  758. {
  759. //DEBUG_INFO("\n OCPP directory exist \n");
  760. }
  761. else
  762. {
  763. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  764. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  765. system(rmFileCmd);
  766. }
  767. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  768. if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1)
  769. {
  770. //DEBUG_INFO("TransactionRelatedQueue exist.\n");
  771. }
  772. else
  773. {
  774. //DEBUG_INFO("TransactionRelatedQueue not exist\n");
  775. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+");
  776. if(log == NULL)
  777. {
  778. DEBUG_INFO("log is NULL\n");
  779. return FALSE;
  780. }
  781. else
  782. {
  783. fclose(log);
  784. }
  785. }
  786. FILE *fp = fopen("/Storage/OCPP/TransactionRelatedQueue", "r");
  787. char line[QUEUE_MESSAGE_LENGTH]={0};
  788. // check if file exist (and you can open it) or not
  789. if (fp == NULL) {
  790. DEBUG_INFO("can open file TransactionRelatedQueue!");
  791. return FALSE;
  792. }
  793. queueOpInfo.TransactionQueueNum = 0; // the number of packets in queue
  794. while(fgets(line, sizeof line, fp) != NULL) {
  795. //DEBUG_INFO("%s\n", line);
  796. queueOpInfo.TransactionQueueNum += 1; //the number of packets in queue
  797. }
  798. fclose(fp);
  799. return TRUE;
  800. }
  801. int sentqueue()
  802. {
  803. int result = FAIL;
  804. struct stat stats;
  805. FILE *fp;
  806. json_object *obj = NULL;
  807. json_object *objPayload = NULL;
  808. json_object *objData = NULL;
  809. char cmd[128];
  810. char str[QUEUE_MESSAGE_LENGTH]={0};
  811. char queueData[QUEUE_MESSAGE_LENGTH]={0};
  812. char payload[QUEUE_MESSAGE_LENGTH]={0};
  813. char key_value[65]={0};
  814. char hashData[65]={0};
  815. char action[32];
  816. char guid[37];
  817. uint8_t connectorId;
  818. DEBUG_INFO("Sent queue.\n");
  819. stat("/Storage/OCPP", &stats);
  820. // Check for directory existence
  821. if (S_ISDIR(stats.st_mode) != 1)
  822. {
  823. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  824. sprintf(cmd, "mkdir -p /Storage/OCPP");
  825. system(cmd);
  826. }
  827. if((fp = fopen("/Storage/OCPP/TransactionRelatedQueue" , "r")) == NULL)
  828. {
  829. DEBUG_ERROR("Error opening file");
  830. }
  831. else
  832. {
  833. // parse message content
  834. if(fgets(str, QUEUE_MESSAGE_LENGTH, fp) != NULL)
  835. {
  836. // parse connectorId
  837. connectorId = (str[0]-0x30);
  838. memcpy(&queueData, &str[2], strlen(str)-2);
  839. obj = json_tokener_parse(queueData);
  840. if(!is_error(obj))
  841. {
  842. sprintf(guid, "%s", json_object_get_string(json_object_array_get_idx(obj, 1)));
  843. sprintf(action, "%s", json_object_get_string(json_object_array_get_idx(obj, 2)));
  844. sprintf(payload, "%s", json_object_to_json_string_ext(json_object_array_get_idx(obj, 3), JSON_C_TO_STRING_PLAIN));
  845. objPayload = json_tokener_parse(payload);
  846. if(!is_error(objPayload))
  847. {
  848. if(strstr(action, "StartTransaction") != NULL)
  849. {
  850. char idtag[21]={0};
  851. char timestamp[36]={0};
  852. int meterStart=0;
  853. int reservationId=-1;
  854. if(json_object_object_get(objPayload, "idTag") != NULL)
  855. {
  856. sprintf(idtag, "%s", json_object_get_string(json_object_object_get(objPayload, "idTag")));
  857. }
  858. if(json_object_object_get(objPayload, "meterStart") != NULL)
  859. {
  860. meterStart = json_object_get_int(json_object_object_get(objPayload, "meterStart"));
  861. }
  862. if(json_object_object_get(objPayload, "reservationId") != NULL)
  863. {
  864. reservationId = json_object_get_int(json_object_object_get(objPayload, "reservationId"));
  865. }
  866. if(json_object_object_get(objPayload, "timestamp") != NULL)
  867. {
  868. sprintf(timestamp, "%s", json_object_get_string(json_object_object_get(objPayload, "timestamp")));
  869. }
  870. FillStartTransaction(connectorId, (unsigned char*)idtag, meterStart, reservationId, (unsigned char*)timestamp);
  871. if(hashmap_operation(HASH_OP_GET, guid, key_value) == TRUE)
  872. {
  873. //DEBUG_INFO("\n 1. sent queue guid=%s\n",guid);
  874. }
  875. else
  876. {
  877. sprintf(hashData, "StartTransaction,%d", (connectorId-1));
  878. hashmap_operation(HASH_OP_ADD, guid, hashData);
  879. //DEBUG_INFO("\n 2. sent queue guid=%s\n",guid);
  880. }
  881. LWS_Send((char*)json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
  882. json_object_put(objPayload);
  883. }
  884. else if((strstr(action, "MeterValues") != NULL) || strstr(action, "StopTransaction") != NULL)
  885. {
  886. char idtag[21]={0};
  887. int transactionId_org=0;
  888. int transactionId_map=0;
  889. if(json_object_object_get(objPayload, "transactionId") != NULL)
  890. {
  891. transactionId_org = json_object_get_int(json_object_object_get(objPayload, "transactionId"));
  892. if(json_object_object_get(objPayload, "idTag") != NULL)
  893. {
  894. sprintf(idtag, "%s", json_object_get_string(json_object_object_get(objPayload, "idTag")));
  895. }
  896. //Get IdTag from StartTransaction , store to StartTransactionIdTagTemp, For StopTransaction usage in Queue (StartTransaction. StopTransaction user id different), get actual TransactionId
  897. GetStartTransactionIdTag(connectorId-1);
  898. transactionId_map = GetTransactionId(connectorId, (unsigned char*)idtag, ((strstr(action, "StopTransaction") != NULL)?YES:NO));
  899. DEBUG_INFO("queue map transactionId = %d\n", transactionId_map);
  900. DEBUG_INFO("original connectorId = %d\n", connectorId);
  901. DEBUG_INFO("original transactionId = %d\n", transactionId_org);
  902. DEBUG_INFO("original IdtagStr = %s\n", "");
  903. if((transactionId_map != 0)&&(transactionId_org != transactionId_map))
  904. {
  905. //replace transactionId
  906. json_object_object_add(objPayload, "transactionId", json_object_new_int(transactionId_map));
  907. }
  908. else
  909. {
  910. transactionId_map = transactionId_org;
  911. }
  912. LastQueuedTransactionId[connectorId-1] = transactionId_map;
  913. //FillTransactionId(connectorId, transactionId_map);
  914. DEBUG_INFO("Final transactionId = %d\n", transactionId_map);
  915. }
  916. json_object_array_put_idx(obj, 3, objPayload);
  917. LWS_Send((char*)json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
  918. if(strstr(action, "StopTransaction") != NULL)
  919. queueOpInfo.stopTransactionId = transactionId_map;
  920. }
  921. else
  922. {
  923. int transactionId_org=0;
  924. int transactionId_map=0;
  925. if(strstr(json_object_get_string(json_object_object_get(objPayload, "messageId")), "ConnectorUnplugged") != NULL)
  926. {
  927. objData = json_tokener_parse(json_object_get_string(json_object_object_get(objPayload, "data")));
  928. if(!is_error(objData))
  929. {
  930. transactionId_org = json_object_get_int(json_object_object_get(objData, "idTx"));
  931. //Get IdTag from StartTransaction , store to StartTransactionIdTagTemp, For StopTransaction usage in Queue (StartTransaction. StopTransaction user id different), get actual TransactionId
  932. GetStartTransactionIdTag(connectorId-1);
  933. transactionId_map = GetTransactionId(connectorId, (unsigned char*)"", NO);
  934. DEBUG_INFO("queue map transactionId = %d\n", transactionId_map);
  935. DEBUG_INFO("original connectorId = %d\n", connectorId);
  936. DEBUG_INFO("original transactionId = %d\n", transactionId_org);
  937. DEBUG_INFO("original IdtagStr = %s\n", "");
  938. if((transactionId_map != 0)&&(transactionId_org == 0)&&(transactionId_org != transactionId_map))
  939. {
  940. //replace transactionId
  941. json_object_object_add(objData, "idTx", json_object_new_int(transactionId_map));
  942. }
  943. else if((transactionId_map == 0) && (transactionId_org == 0))
  944. {
  945. //replace transactionId
  946. transactionId_map = GetStartTransactionId(connectorId-1);
  947. json_object_object_add(objData, "idTx", json_object_new_int(transactionId_map));
  948. }
  949. else
  950. {
  951. transactionId_map = transactionId_org;
  952. }
  953. DEBUG_INFO("Final transactionId = %d\n", transactionId_map);
  954. json_object_object_add(objPayload, "data", json_object_new_string(json_object_to_json_string_ext(objData, JSON_C_TO_STRING_PLAIN)));
  955. json_object_array_put_idx(obj, 3, objPayload);
  956. LWS_Send((char*)json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
  957. }
  958. }
  959. else if(strstr(json_object_get_string(json_object_object_get(objPayload, "messageId")), "ID_OCMF") != NULL)
  960. {
  961. DEBUG_INFO(">>> Sending OCMF queue message...\n");
  962. objData = json_tokener_parse(json_object_get_string(json_object_object_get(objPayload, "data")));
  963. if(!is_error(objData))
  964. {
  965. transactionId_org = json_object_get_int(json_object_object_get(objData, "txId"));
  966. DEBUG_INFO("original transactionId = %d\n", transactionId_org);
  967. if(transactionId_org == 0)
  968. {
  969. //replace transactionId
  970. transactionId_map = GetStartTransactionId(connectorId-1);
  971. if(transactionId_map == 0)
  972. transactionId_map = LastQueuedTransactionId[connectorId-1];
  973. json_object_object_add(objData, "txId", json_object_new_int(transactionId_map));
  974. }
  975. else
  976. {
  977. transactionId_map = transactionId_org;
  978. }
  979. DEBUG_INFO("Final transactionId = %d\n", transactionId_map);
  980. json_object_object_add(objPayload, "data", json_object_new_string(json_object_to_json_string_ext(objData, JSON_C_TO_STRING_PLAIN)));
  981. json_object_array_put_idx(obj, 3, objPayload);
  982. LWS_Send((char*)json_object_to_json_string_ext(obj, JSON_C_TO_STRING_PLAIN));
  983. }
  984. }
  985. }
  986. result = PASS;
  987. }
  988. }
  989. json_object_put(obj);
  990. }
  991. }
  992. fclose(fp);
  993. return result;
  994. }
  995. void* processTransactionQueue(void* data)
  996. {
  997. char frontUUID[100] ={0};
  998. char frontData[QUEUE_MESSAGE_LENGTH] ={0};
  999. int queueNotEmpty = FALSE;
  1000. while(1)
  1001. {
  1002. if(!req_SendQueue && ((getDiffSecNow(startTime.startTimeQueue) >= ((TransactionMessageRetryIntervalGet()>10?TransactionMessageRetryIntervalGet():10)*(queueOpInfo.TransactionMessageResend>1?2:1))) || (isWebsocketSendable && isQueueSendable && (getDiffSecNow(startTime.startTimeQueue) >= ((counterQueueSent>=20)?5:0)))))
  1003. {
  1004. if(FirstHeartBeatResponse() == 1)
  1005. {
  1006. memset(frontUUID, 0, ARRAY_SIZE(frontUUID));
  1007. memset(frontData, 0, ARRAY_SIZE(frontData));
  1008. queueNotEmpty = queue_operation(QUEUE_OPERATION_SHOWFRONT,frontUUID, frontData);
  1009. if((queueNotEmpty == TRUE) && (GetOcppConnStatus() == 1))
  1010. {
  1011. if(isWebsocketSendable)
  1012. DEBUG_INFO("isWebsocketSendable on.\n");
  1013. if(isQueueSendable)
  1014. DEBUG_INFO("isQueueSendable on.\n");
  1015. if(((getDiffSecNow(startTime.startTimeQueue) > (TransactionMessageRetryIntervalGet()>10?TransactionMessageRetryIntervalGet():10))))
  1016. DEBUG_INFO("Queue timer(%d) over spec(%d).\n", getDiffSecNow(startTime.startTimeQueue), TransactionMessageRetryIntervalGet());
  1017. if(queueOpInfo.TransactionMessageResend < TransactionMessageAttemptsGet())
  1018. {
  1019. DEBUG_INFO("Sent message from queue request.\n");
  1020. DEBUG_INFO("TransactionMessageResend time: %d\n", queueOpInfo.TransactionMessageResend);
  1021. req_SendQueue = 1;
  1022. queueOpInfo.TransactionMessageResend += 1;
  1023. }
  1024. else
  1025. {
  1026. DEBUG_INFO("Transaction message resend(%d) over spec(%d) message abandon.\n", queueOpInfo.TransactionMessageResend, TransactionMessageAttemptsGet());
  1027. queue_operation(QUEUE_OPERATION_DEL,"","");
  1028. queueOpInfo.TransactionMessageResend = 0;
  1029. req_SendQueue = 0;
  1030. }
  1031. }
  1032. }
  1033. // Refresh queue timer
  1034. refreshStartTimer(&startTime.startTimeQueue);
  1035. if((counterQueueSent >= 10) || (queueNotEmpty == FALSE))
  1036. {
  1037. counterQueueSent = 0;
  1038. }
  1039. else
  1040. {
  1041. counterQueueSent += 1;
  1042. }
  1043. }
  1044. usleep(500000);
  1045. }
  1046. pthread_exit(NULL);
  1047. return 0;
  1048. }
  1049. void* processWatchdog()
  1050. {
  1051. for(;;)
  1052. {
  1053. if((getDiffSecNow(startTime.disconnectServer) >= 7200))
  1054. {
  1055. DEBUG_INFO("OCPP server disconnect timer(%d) over 7200 seconds.\n", getDiffSecNow(startTime.disconnectServer));
  1056. system("killall OcppBackend");
  1057. }
  1058. if(counterConnect >= 3)
  1059. {
  1060. DEBUG_INFO("Connect OCPP server timeout over 3 count.\n");
  1061. system("killall OcppBackend");
  1062. }
  1063. if((0 < GetWebSocketPingInterval()) && (0 < counterPingSend) && ((GetWebSocketPingInterval()+5) <= getDiffSecNow(startTime.pingOn)) && (wsi_client != NULL) && (GetServerSign() == TRUE))
  1064. {
  1065. DEBUG_WARN("Pong packet receive timeout.\n");
  1066. //system("killall OcppBackend");
  1067. lws_context_destroy(context);
  1068. ConnectionEstablished = 0;
  1069. context = NULL;
  1070. }
  1071. usleep(500000);
  1072. }
  1073. pthread_exit(NULL); //
  1074. }
  1075. void CheckTransactionPacket(char *uuid)
  1076. {
  1077. char frontUUID[100]={0};
  1078. char frontData[QUEUE_MESSAGE_LENGTH]={0};
  1079. int queueNotEmpty = FALSE;
  1080. int cmpResult = 0;
  1081. queueNotEmpty = queue_operation(QUEUE_OPERATION_SHOWFRONT,frontUUID, frontData);//showfront(frontUUID, frontData); ---> remove temporally
  1082. if(queueNotEmpty == TRUE)
  1083. {
  1084. cmpResult = strcmp(frontUUID, uuid);
  1085. if (cmpResult == 0)
  1086. {
  1087. DEBUG_INFO("Receive queue response match.\n");
  1088. queue_operation(QUEUE_OPERATION_DEL,"","");//delq(); ---> remove temporally
  1089. queueOpInfo.TransactionMessageResend = 0;
  1090. }
  1091. else
  1092. DEBUG_INFO("Receive queue response mismatch.\n");
  1093. }
  1094. }
  1095. int queue_operation(int type, char *frontUUID, char *frontData)
  1096. {
  1097. int result=0;
  1098. while(1)
  1099. {
  1100. if (!queueOpInfo.IsUsing )
  1101. {
  1102. queueOpInfo.IsUsing = TRUE;
  1103. if(type == QUEUE_OPERATION_SHOWQUEUE) // show items in queue
  1104. {
  1105. result = showqueue();
  1106. }
  1107. else if(type == QUEUE_OPERATION_SHOWFRONT) // show first item
  1108. {
  1109. result = showfront(frontUUID, frontData);
  1110. }
  1111. else if(type == QUEUE_OPERATION_DEL) // delete item
  1112. {
  1113. result = delq();
  1114. }
  1115. else if(type == QUEUE_OPERATION_SENT) // sent items in queue
  1116. {
  1117. result = sentqueue();
  1118. }
  1119. else if(type == QUEUE_OPERATION_ADD) // add items to the queue
  1120. {
  1121. // If queue file over size only add start * stop transaction message
  1122. if(!isQueueOverSize() || (strstr(frontData, "MeterValues") == NULL))
  1123. {
  1124. result = addq(frontUUID, frontData);
  1125. }
  1126. }
  1127. queueOpInfo.IsUsing = FALSE;
  1128. break;
  1129. }
  1130. usleep(100000);
  1131. }
  1132. return result;
  1133. }
  1134. int removeMessageSentFile(void)
  1135. {
  1136. char rmFileCmd[100]={0};
  1137. struct stat stats;
  1138. stat("/Storage/OCPP", &stats);
  1139. // Check for directory existence
  1140. if(S_ISDIR(stats.st_mode) == 1)
  1141. {
  1142. //DEBUG_INFO("\n OCPP directory exist \n");
  1143. }
  1144. else
  1145. {
  1146. DEBUG_INFO("\n directory not exist, create dir \n");
  1147. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  1148. system(rmFileCmd);
  1149. }
  1150. stat("/Storage/OCPP/TransactionRelatedQueue", &stats);
  1151. if(stats.st_size < 10)
  1152. {
  1153. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  1154. if((access("/Storage/OCPP/MessageSent",F_OK))!=-1)
  1155. {
  1156. DEBUG_INFO("MessageSent file exist.\n");
  1157. sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/MessageSent");
  1158. system(rmFileCmd);
  1159. }
  1160. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  1161. }
  1162. return 0;
  1163. }
  1164. //================================================
  1165. // Main process
  1166. //================================================
  1167. int main(void)
  1168. {
  1169. char rmFileCmd[100]={0};
  1170. struct stat stats;
  1171. queueOpInfo.IsUsing = FALSE;
  1172. queueOpInfo.TransactionMessageResend = 0;
  1173. DEBUG_INFO("Module_OcppBackend task initialization...\n");
  1174. DEBUG_INFO("Git update date: 2022/12/27 \n");
  1175. //lws_set_log_level(LLL_PARSER | LLL_HEADER | LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO | LLL_DEBUG | LLL_EXT | LLL_CLIENT | LLL_LATENCY , NULL);
  1176. if(ProcessShareMemory()== FAIL)
  1177. {
  1178. return FAIL;
  1179. }
  1180. // Check & create OCPP dir
  1181. stat("/Storage/OCPP", &stats);
  1182. if(S_ISDIR(stats.st_mode) != 1)
  1183. {
  1184. DEBUG_INFO("OCPP directory not exist, create dir \n");
  1185. sprintf(rmFileCmd,"mkdir -p /Storage/OCPP");
  1186. system(rmFileCmd);
  1187. }
  1188. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  1189. // Create Process: Resend Transaction
  1190. refreshStartTimer(&startTime.disconnectServer);
  1191. pthread_create(&tid_ProcQueue, NULL, processTransactionQueue, NULL);
  1192. pthread_create(&tid_Watchdog, NULL, processWatchdog, NULL);
  1193. // Sqlite3 initial
  1194. sqlite3_config(SQLITE_CONFIG_URI,1);
  1195. if(sqlite3_open("file:/Storage/OCPP/charger.db", &db))
  1196. {
  1197. DEBUG_INFO( "Can't open database: %s\n", sqlite3_errmsg(db));
  1198. sqlite3_close( db );
  1199. exit(0);
  1200. }
  1201. else
  1202. {
  1203. DEBUG_INFO( "Opened database successfully\n");
  1204. }
  1205. //Create Table log buffer
  1206. if(sqlite3_exec(db, createsql, 0, 0, &errMsg) != SQLITE_OK)
  1207. {
  1208. DEBUG_INFO( "Create log buffer table error message: %s\n", errMsg);
  1209. return 0;
  1210. }
  1211. else
  1212. {
  1213. DEBUG_INFO( "Opened log buffer table successfully\n");
  1214. }
  1215. // Create Table OcppAuthCache
  1216. if(sqlite3_exec(db, sqlOcppAuthCache, 0, 0, &errMsg) != SQLITE_OK)
  1217. {
  1218. DEBUG_INFO( "Create OcppAuthCache error message: %s\n", errMsg);
  1219. return 0;
  1220. }
  1221. else
  1222. {
  1223. DEBUG_INFO( "Opened OcppAuthCache table successfully\n");
  1224. }
  1225. // Create Table OcppAuthLocal
  1226. if(sqlite3_exec(db, sqlOcppAuthLocal, 0, 0, &errMsg) != SQLITE_OK)
  1227. {
  1228. DEBUG_INFO( "Create Table OcppAuthLocal error %s\n",errMsg);
  1229. return 0;
  1230. }
  1231. else
  1232. {
  1233. DEBUG_INFO( "Opened OcppAuthLocal table successfully\n");
  1234. }
  1235. // Create Table Transaction
  1236. if(sqlite3_exec(db, sqlTransaction, 0, 0, &errMsg) != SQLITE_OK)
  1237. {
  1238. DEBUG_INFO( "Create Table ocpp_transaction_record error %s\n",errMsg);
  1239. return 0;
  1240. }
  1241. else
  1242. {
  1243. DEBUG_INFO( "Opened ocpp_transaction_record table successfully\n");
  1244. }
  1245. // Create transaction period energy
  1246. if(sqlite3_exec(db, sqlPeriodEnergy, 0, 0, &errMsg) != SQLITE_OK)
  1247. {
  1248. DEBUG_INFO( "Create Table ocpp_period_energy error %s\n",errMsg);
  1249. return 0;
  1250. }
  1251. else
  1252. {
  1253. DEBUG_INFO( "Opened ocpp_period_energy table successfully\n");
  1254. }
  1255. // Create credit deduct info
  1256. if(sqlite3_exec(db, sqlReportDeduct, 0, 0, &errMsg) != SQLITE_OK)
  1257. {
  1258. DEBUG_INFO( "Create Table report_deduct_info error %s\n",errMsg);
  1259. return 0;
  1260. }
  1261. else
  1262. {
  1263. DEBUG_INFO( "Opened report_deduct_info table successfully\n");
  1264. }
  1265. // Create occupancy deduct info
  1266. if(sqlite3_exec(db, sqlReportOccupancyDeduct, 0, 0, &errMsg) != SQLITE_OK)
  1267. {
  1268. DEBUG_INFO( "Create Table report_occupancyDeduct_info error %s\n",errMsg);
  1269. return 0;
  1270. }
  1271. else
  1272. {
  1273. DEBUG_INFO( "Opened report_occupancyDeduct_info table successfully\n");
  1274. }
  1275. // Create meter values buffer table
  1276. if(sqlite3_exec(db, sqlMeterValueBuffer, 0, 0, &errMsg) != SQLITE_OK)
  1277. {
  1278. DEBUG_INFO( "Create Table meterValuesBuffer error %s\n",errMsg);
  1279. return 0;
  1280. }
  1281. else
  1282. {
  1283. DEBUG_INFO( "Opened meterValuesBuffer table successfully\n");
  1284. }
  1285. if(initialConfigurationTable() != PASS)
  1286. {
  1287. DEBUG_WARN("OCPPConfiguration version mismatch, upgrade it.\n");
  1288. system("rm -f /Storage/OCPP/OCPPConfiguration");
  1289. initialConfigurationTable();
  1290. }
  1291. removeMessageSentFile();
  1292. for(;;)
  1293. {
  1294. // Connect server
  1295. if(ConnectionEstablished==FALSE) // Check InternetConn 0: disconnected, 1: connected
  1296. {
  1297. isWebsocketSendable = 1;
  1298. isQueueSendable = 1;
  1299. SetOcppConnStatus(FALSE);
  1300. SetServerSign(FALSE);
  1301. InitialSystemValue();
  1302. if(getDiffSecNow(startTime.connect) >= 30)
  1303. {
  1304. DEBUG_INFO("Server connecting...\n");
  1305. pthread_create(&tid_connectServer, NULL, ConnectWsServer, NULL);
  1306. refreshStartTimer(&startTime.connect);
  1307. }
  1308. CheckSystemValue();
  1309. }
  1310. else
  1311. {
  1312. // Sign in
  1313. if((GetServerSign() == FALSE) &&
  1314. (isConnectorInitMode(0) != TRUE) &&
  1315. ((GetBootNotificationInterval()>0) ? (getDiffSecNow(startTime.bootNotification) >= GetBootNotificationInterval()) : (getDiffSecNow(startTime.bootNotification) >= defaultWaitingTime))
  1316. )
  1317. {
  1318. if(counterBootNotificationSend>=10)
  1319. {
  1320. lws_context_destroy(context);
  1321. ConnectionEstablished = 0;
  1322. context = NULL;
  1323. counterBootNotificationSend = 0;
  1324. DEBUG_INFO("Disconnect because of 10 times no BootNotification response.\n");
  1325. }
  1326. else
  1327. {
  1328. sendBootNotificationRequest();
  1329. refreshStartTimer(&startTime.bootNotification);
  1330. counterBootNotificationSend++;
  1331. }
  1332. }
  1333. // Check System Value
  1334. CheckSystemValue();
  1335. // On line operation
  1336. if(GetServerSign() == TRUE)
  1337. {
  1338. counterBootNotificationSend = 0;
  1339. // Send message from queue
  1340. if((req_SendQueue == 1) && (isWebsocketSendable || ((queueOpInfo.TransactionMessageResend > 1) && (queueOpInfo.PreTransactionMessageResend != queueOpInfo.TransactionMessageResend))))
  1341. {
  1342. queue_operation(QUEUE_OPERATION_SENT, "", "");
  1343. req_SendQueue = 0;
  1344. queueOpInfo.PreTransactionMessageResend = queueOpInfo.TransactionMessageResend;
  1345. }
  1346. // PING packet
  1347. if(isWebsocketSendable && (0 < GetWebSocketPingInterval()) && ((GetWebSocketPingInterval()+counterPingSend) <= getDiffSecNow(startTime.pingOn)))
  1348. {
  1349. lws_callback_on_writable(wsi_client);
  1350. counterPingSend++;
  1351. }
  1352. if(GetHeartBeatWithNOResponse() >= 30)
  1353. {
  1354. lws_context_destroy(context);
  1355. ConnectionEstablished = 0;
  1356. context = NULL;
  1357. SetHeartBeatWithNOResponse();
  1358. DEBUG_WARN("Heartbeat re-send over 30 count.\n");
  1359. }
  1360. if((GetOcppConnStatus() == 0))
  1361. {
  1362. if(getDiffSecNow(startTime.reConnect) >= 3)
  1363. {
  1364. DEBUG_INFO("GetOcppConnStatus() = %d\n", GetOcppConnStatus());
  1365. lws_context_destroy(context);
  1366. ConnectionEstablished = 0;
  1367. context = NULL;
  1368. }
  1369. }
  1370. else
  1371. {
  1372. refreshStartTimer(&startTime.reConnect);
  1373. }
  1374. refreshStartTimer(&startTime.disconnectServer);
  1375. }
  1376. }
  1377. do
  1378. {
  1379. lws_service(context, 0);//timeout_ms
  1380. }while((SendBufLen>0) && (context!=NULL) && GetOcppConnStatus());
  1381. refreshProcDogTimer();
  1382. usleep(100000);
  1383. }
  1384. pthread_join(tid_ProcQueue, NULL);
  1385. pthread_join(tid_Watchdog, NULL);
  1386. return FAIL;
  1387. }