Module_OcppBackend20.c 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234
  1. #include "Module_OcppBackend20.h"
  2. typedef enum boolean { FALSE, TRUE } BOOL;
  3. struct lws *wsi_client;
  4. struct lws_context *context;
  5. static int req_SendQueue = 0;
  6. pthread_t tid_connectServer;
  7. pthread_t tid_ProcQueue;
  8. pthread_t tid_Watchdog;
  9. struct StartTime
  10. {
  11. struct timespec connect;
  12. struct timespec bootNotification;
  13. struct timespec reConnect;
  14. struct timespec startTimeDog;
  15. struct timespec startTimeQueue;
  16. struct timespec pingOn;
  17. }startTime;
  18. struct QueueOpInfo queueOpInfo;
  19. //==========================================
  20. // Function prototype
  21. //==========================================
  22. void ReceivedMessage(void *in, size_t len);
  23. int SendBufLen=0;//(1024*4);//(1024*3);
  24. unsigned char SendBuffer[WEBSOCKET_BUFFER_SIZE]={0};
  25. static int ConnectionEstablished=0;
  26. int defaultWaitingTime = 10; //10 second
  27. char OcppPath[384]={0};
  28. char OcppProtocol[10]={0},OcppHost[128]={0}, OcppTempPath[256]={0};
  29. int OcppPort=0;
  30. unsigned char StartTransactionIdTagTemp[20]={0};
  31. uint8_t isWebsocketSendable = 1;
  32. uint8_t isQueueSendable = 1;
  33. uint8_t counterLwsRestart = 0;;
  34. uint8_t counterQueueSent = 0;
  35. uint8_t counterConnect = 0;
  36. uint8_t counterPingSend = 0;
  37. //=================================
  38. // Common routine
  39. //=================================
  40. int GetTransactionQueueNum(void)
  41. {
  42. return queueOpInfo.TransactionQueueNum;
  43. }
  44. //==========================================
  45. // Web socket tranceive routine
  46. //==========================================
  47. int SendData(struct lws *wsi)
  48. {
  49. int n;
  50. int len;
  51. unsigned char out[LWS_SEND_BUFFER_PRE_PADDING + (1024*20) + LWS_SEND_BUFFER_POST_PADDING] = {0};
  52. len = strlen((char *)SendBuffer);
  53. if(len == 0)return 0;
  54. if((strstr((char*)SendBuffer, "\"MeterValues\"") != NULL)
  55. || (strstr((char*)SendBuffer, "\"TransactionEven\"") != NULL))
  56. {
  57. isQueueSendable = OFF;
  58. }
  59. memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, SendBuffer, len );
  60. DEBUG_OCPPMESSAGE_INFO("===========> %s\n", out + LWS_SEND_BUFFER_PRE_PADDING);
  61. n = lws_write(wsi, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT);
  62. memset(SendBuffer, 0, len);
  63. SendBufLen = 0;
  64. return n;
  65. }
  66. int SendPing(struct lws *wsi)
  67. {
  68. uint8_t ping[LWS_PRE + 125];
  69. DEBUG_OCPPMESSAGE_INFO("===========> Set PING packet.\n");
  70. return lws_write(wsi, ping + LWS_PRE, 0, LWS_WRITE_PING);
  71. }
  72. static int OCPP20Callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len)
  73. {
  74. char buf[256]={0}, hash[20]={0}, key_b64[40]={0}, tempin[WEBSOCKET_BUFFER_SIZE]={0}, sstr[WEBSOCKET_BUFFER_SIZE]={0};
  75. uint8_t auth_b64[256]={0}, boxId[128]={0}, password[64]={0};
  76. int c = 0;
  77. char *loc;
  78. switch (reason)
  79. {
  80. case LWS_CALLBACK_PROTOCOL_INIT:
  81. DEBUG_INFO("LWS_CALLBACK_PROTOCOL_INIT\n");
  82. break;
  83. case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH:
  84. DEBUG_INFO("LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH\n");
  85. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Client Request START -----\n");
  86. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_URI);
  87. DEBUG_OCPPMESSAGE_INFO("GET %s HTTP/1.1 \n", buf);
  88. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_HOST);
  89. DEBUG_OCPPMESSAGE_INFO("Host: %s\n", buf);
  90. DEBUG_OCPPMESSAGE_INFO("Upgrade: websocket\n");
  91. DEBUG_OCPPMESSAGE_INFO("Connection: Upgrade\n");
  92. lws_b64_encode_string(hash, 16, key_b64, ARRAY_SIZE(key_b64));// Sec-WebSocket-Key
  93. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Key: %s\n", key_b64);
  94. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
  95. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  96. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Version: %d\n", SPEC_LATEST_SUPPORTED);
  97. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Client Request END -----\n");
  98. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Server response START -----\n");
  99. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_HTTP);
  100. DEBUG_OCPPMESSAGE_INFO("HTTP/1.1 %s\n", buf);
  101. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_UPGRADE);
  102. DEBUG_OCPPMESSAGE_INFO("Upgrade: %s\n", buf);
  103. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_CONNECTION);
  104. DEBUG_OCPPMESSAGE_INFO("Connection: %s\n", buf);
  105. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_ACCEPT);
  106. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Accept: %s\n", buf);
  107. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_PROTOCOL);
  108. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  109. DEBUG_OCPPMESSAGE_INFO("----- Handshake: Server response END -----\n");
  110. break;
  111. case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION:
  112. DEBUG_INFO("LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION\n");
  113. break;
  114. case LWS_CALLBACK_WSI_DESTROY:
  115. DEBUG_INFO("LWS_CALLBACK_WSI_DESTROY\n");
  116. pthread_detach(tid_connectServer);
  117. SetServerSign(FALSE);
  118. ConnectionEstablished = 0;
  119. context = NULL;
  120. break;
  121. case LWS_CALLBACK_LOCK_POLL:
  122. break;
  123. case LWS_CALLBACK_ADD_POLL_FD:
  124. DEBUG_INFO("LWS_CALLBACK_ADD_POLL_FD\n");
  125. break;
  126. case LWS_CALLBACK_DEL_POLL_FD:
  127. DEBUG_INFO("LWS_CALLBACK_DEL_POLL_FD\n");
  128. break;
  129. case LWS_CALLBACK_UNLOCK_POLL:
  130. break;
  131. case LWS_CALLBACK_CHANGE_MODE_POLL_FD:
  132. break;
  133. case LWS_CALLBACK_WSI_CREATE:
  134. DEBUG_INFO("LWS_CALLBACK_WSI_CREATE\n");
  135. break;
  136. case LWS_CALLBACK_GET_THREAD_ID:
  137. break;
  138. case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER:
  139. DEBUG_INFO("LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER\n");
  140. unsigned char** pos = (unsigned char**)in;
  141. unsigned char* end = (*pos) + len;
  142. switch(GetOcppSecurityProfile())
  143. {
  144. case 1:
  145. case 2:
  146. case 3:
  147. GetOcppChargerBoxId(boxId);
  148. GetOcppSecurityPassword(password);
  149. sprintf(buf, "%s:%s", boxId, password);
  150. lws_b64_encode_string(buf, strlen(buf), (char*)auth_b64, ARRAY_SIZE(auth_b64));
  151. sprintf(buf, "Basic %s", auth_b64);
  152. if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_AUTHORIZATION, (uint8_t *)buf, strlen(buf), pos, end))
  153. {
  154. DEBUG_ERROR("lws_add_http_header_by_token : WSI_TOKEN_HTTP_AUTHORIZATION\n");
  155. return -1;
  156. }
  157. DEBUG_OCPPMESSAGE_INFO("Authorization: %s\n", buf);
  158. break;
  159. case 0:
  160. default:
  161. break;
  162. }
  163. break;
  164. case LWS_CALLBACK_CLIENT_ESTABLISHED: //3
  165. DEBUG_INFO("LWS_CALLBACK_CLIENT_ESTABLISHED\n");
  166. //connected
  167. ConnectionEstablished=1;
  168. SetOcppConnStatus(TRUE);
  169. refreshStartTimer(&startTime.pingOn);
  170. counterPingSend = 0;
  171. queueOpInfo.PreTransactionMessageResend = 0;
  172. break;
  173. case LWS_CALLBACK_CLIENT_CONNECTION_ERROR://1
  174. DEBUG_ERROR("LWS_CALLBACK_CLIENT_CONNECTION_ERROR %s\n", (char *)in );
  175. //disconnected
  176. ConnectionEstablished=0;
  177. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Client START =====\n");
  178. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_URI);
  179. DEBUG_OCPPMESSAGE_INFO("GET %s HTTP/1.1 \n", buf);
  180. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_HOST);
  181. DEBUG_OCPPMESSAGE_INFO("Host: %s\n", buf);
  182. DEBUG_OCPPMESSAGE_INFO("Upgrade: websocket\n");
  183. DEBUG_OCPPMESSAGE_INFO("Connection: Upgrade\n");
  184. lws_b64_encode_string(hash, 16, key_b64, ARRAY_SIZE(key_b64));// Sec-WebSocket-Key
  185. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Key: %s\n", key_b64);
  186. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS);
  187. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  188. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Version: %d\n", SPEC_LATEST_SUPPORTED);
  189. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Client END =====\n");
  190. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Server response START =====\n");
  191. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_HTTP);
  192. DEBUG_OCPPMESSAGE_INFO("HTTP/1.1 %s\n", buf);
  193. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_UPGRADE);
  194. DEBUG_OCPPMESSAGE_INFO("Upgrade: %s\n", buf);
  195. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_CONNECTION);
  196. DEBUG_OCPPMESSAGE_INFO("Connection: %s\n", buf);
  197. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_ACCEPT);
  198. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Accept: %s\n", buf);
  199. lws_hdr_copy(wsi, buf, ARRAY_SIZE(buf) - 1, WSI_TOKEN_PROTOCOL);
  200. DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf);
  201. DEBUG_OCPPMESSAGE_INFO("===== Handshake: Server response END =====\n");
  202. break;
  203. case LWS_CALLBACK_CLOSED://4
  204. DEBUG_INFO("LWS_CALLBACK_CLOSED\n");
  205. //disconnected
  206. ConnectionEstablished=0;
  207. break;
  208. case LWS_CALLBACK_CLIENT_WRITEABLE://10
  209. if(isWebsocketSendable && (0 < GetWebSocketPingInterval()) && (GetWebSocketPingInterval() <= getDiffSecNow(startTime.pingOn)) && (GetServerSign() == TRUE))
  210. SendPing(wsi);
  211. else
  212. SendData(wsi);
  213. break;
  214. case LWS_CALLBACK_CLIENT_RECEIVE://8
  215. ((char *)in)[len] = '\0';
  216. DEBUG_OCPPMESSAGE_INFO("<==== %s\n", (char *)in);
  217. //**********Receive Message**********/
  218. c = 0;
  219. loc = strstr((const char *)in, "][2,");
  220. if(loc == NULL)
  221. {
  222. loc = strstr((const char *)in, "][3,");
  223. if(loc == NULL)
  224. {
  225. loc = strstr((const char *)in, "][4,");
  226. }
  227. }
  228. memset(sstr, 0, ARRAY_SIZE(sstr) );
  229. if(loc != NULL)
  230. {
  231. DEBUG_INFO("There are continuous second packet []\n");
  232. while (loc[1+c] != '\0')
  233. {
  234. sstr[c] = loc[1+c];
  235. c++;
  236. }
  237. sstr[c] = '\0';
  238. strcpy(tempin, sstr);
  239. DEBUG_INFO("Final Receive: %s\n", tempin);
  240. }
  241. else
  242. {
  243. strcpy(tempin,(char *)in);
  244. }
  245. ReceivedMessage((void *)strtrim(tempin), strlen(tempin));
  246. isWebsocketSendable = 1;
  247. refreshStartTimer(&startTime.pingOn);
  248. break;
  249. case LWS_CALLBACK_CLIENT_RECEIVE_PONG:
  250. DEBUG_INFO("LWS_CALLBACK_CLIENT_RECEIVE_PONG\n");
  251. DEBUG_OCPPMESSAGE_INFO("<==== Get PONG packet.\n");
  252. refreshStartTimer(&startTime.pingOn);
  253. isWebsocketSendable = ON;
  254. counterPingSend = 0;
  255. break;
  256. case LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION:
  257. DEBUG_INFO("LWS_CALLBACK_OPENSSL_PERFORM_SERVER_CERT_VERIFICATION\n");
  258. break;
  259. case LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS:
  260. DEBUG_INFO("LWS_CALLBACK_OPENSSL_LOAD_EXTRA_CLIENT_VERIFY_CERTS\n");
  261. break;
  262. case LWS_CALLBACK_PROTOCOL_DESTROY:
  263. DEBUG_INFO("LWS_CALLBACK_PROTOCOL_DESTROY\n");
  264. break;
  265. case LWS_CALLBACK_RECEIVE_PONG:
  266. DEBUG_INFO("LWS_CALLBACK_RECEIVE_PONG\n");
  267. break;
  268. case LWS_CALLBACK_WS_PEER_INITIATED_CLOSE:
  269. DEBUG_INFO("LWS_CALLBACK_WS_PEER_INITIATED_CLOSE\n");
  270. break;
  271. case LWS_CALLBACK_CLOSED_CLIENT_HTTP:
  272. DEBUG_INFO("LWS_CALLBACK_CLOSED_CLIENT_HTTP\n");
  273. if(GetInternetConn() == 1)
  274. {
  275. DEBUG_INFO("Download new CA certification.\n", system("wget --no-check-certificate -O /root/cacert.pem http://curl.haxx.se/ca/cacert.pem &"));
  276. }
  277. break;
  278. default:
  279. DEBUG_INFO("Reason = %d\n", reason);
  280. break;
  281. }
  282. return 0;
  283. }
  284. static struct lws_protocols protocols[] =
  285. {
  286. {
  287. "ocpp2.0.1",
  288. OCPP20Callback,
  289. WEBSOCKET_BUFFER_SIZE,
  290. WEBSOCKET_BUFFER_SIZE,
  291. },
  292. {
  293. "ocpp2.0.1",
  294. OCPP20Callback,
  295. WEBSOCKET_BUFFER_SIZE,
  296. WEBSOCKET_BUFFER_SIZE,
  297. },
  298. {
  299. NULL, NULL, 0 /* End of list */
  300. }
  301. };
  302. void* ConnectWsServer(void* data) //int ConnectWsServer()
  303. {
  304. struct lws_context_creation_info ContextInfo;
  305. struct lws_client_connect_info ConnInfo;
  306. int use_ssl=0;
  307. counterConnect += 1;
  308. // If internet available synchronize datetime with ntp server
  309. if(GetInternetConn() == 1)
  310. {
  311. system("pkill ntpd");
  312. DEBUG_INFO("NTP synchronize with Microsoft\n", system("/usr/sbin/ntpd -nqp time.windows.com &"));
  313. DEBUG_INFO("NTP synchronize with China\n", system("/usr/sbin/ntpd -nqp cn.ntp.org.cn &"));
  314. DEBUG_INFO("NTP synchronize with Taiwan\n", system("/usr/sbin/ntpd -nqp tock.stdtime.gov.tw &"));
  315. DEBUG_INFO("NTP synchronize with Europe\n", system("/usr/sbin/ntpd -nqp 0.europe.pool.ntp.org &"));
  316. }
  317. if(context!=NULL)
  318. {
  319. pthread_detach(pthread_self());
  320. lws_context_destroy(context);
  321. ConnectionEstablished=0;
  322. context = NULL;
  323. }
  324. checkNetworkProfile();
  325. memset(&ContextInfo, 0, sizeof(struct lws_context_creation_info));
  326. if((GetOcppServerURL()==0) || (GetOcppPort() == 0) || (GetOcppPath()==0))
  327. {
  328. DEBUG_ERROR("OCPP URL is NULL or OCPP Port is zero or OCPP Path is NULL\n");
  329. goto end;
  330. }
  331. if((strcmp(OcppProtocol,"ws")==0)&&(strlen(OcppProtocol)== 2))
  332. {
  333. DEBUG_INFO("Web socket is non-security mode.\n");
  334. use_ssl=0;
  335. }
  336. else if((strcmp(OcppProtocol,"wss")==0)&&(strlen(OcppProtocol)== 3))
  337. {
  338. DEBUG_INFO("Web socket is security mode.\n");
  339. use_ssl=1;
  340. }
  341. ContextInfo.port = CONTEXT_PORT_NO_LISTEN;
  342. ContextInfo.iface = NULL;
  343. ContextInfo.ssl_private_key_password = NULL;
  344. ContextInfo.ssl_cert_filepath = NULL;//"./ssl_key/client_cert.pem";
  345. ContextInfo.ssl_private_key_filepath = NULL;//"./ssl_key/client_key.pem";
  346. ContextInfo.ssl_ca_filepath = "/root/cacert.pem";//"./cacert.pem";
  347. ContextInfo.ssl_cipher_list = NULL; //use default one
  348. ContextInfo.gid = -1;
  349. ContextInfo.uid = -1;
  350. if(use_ssl)
  351. {
  352. ContextInfo.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT ;
  353. }
  354. ContextInfo.protocols = protocols;
  355. ContextInfo.timeout_secs = GetBackendConnectionTimeout();
  356. //ContextInfo.ws_ping_pong_interval = GetWebSocketPingInterval();
  357. ContextInfo.ka_time = 20;
  358. ContextInfo.keepalive_timeout = 5;
  359. ContextInfo.ka_probes = 2;
  360. ContextInfo.ka_interval = 5;
  361. context = lws_create_context(&ContextInfo);
  362. if (context == NULL)
  363. {
  364. DEBUG_ERROR("lws_create_context NG");
  365. goto end;
  366. }
  367. memset(&ConnInfo,0,sizeof(struct lws_client_connect_info));
  368. // fill up below information
  369. ConnInfo.context = context;
  370. ConnInfo.address=(const char *)OcppHost;
  371. DEBUG_INFO("ConnInfo.address: %s\n", ConnInfo.address);
  372. ConnInfo.port = GetOcppPort();
  373. DEBUG_INFO("ConnInfo.port: %d\n", ConnInfo.port);
  374. ConnInfo.path=(const char *)OcppPath;
  375. DEBUG_INFO("ConnInfo.path: %s\n", ConnInfo.path);
  376. char addr_port[256] = { 0 };
  377. sprintf(addr_port, "%s:%u", ConnInfo.address, (ConnInfo.port & 65535) );
  378. ConnInfo.host= addr_port; // ConnInfo.address;//lws_canonical_hostname(context);
  379. //ConnInfo.origin="origin";
  380. ConnInfo.protocol = protocols[1].name;
  381. ConnInfo.ietf_version_or_minus_one = -1;
  382. if(use_ssl)
  383. {
  384. #ifdef TLS_VALID_CERT_EXPIRED
  385. ConnInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;
  386. DEBUG_INFO("TLS does not allow expired certification.\n");
  387. #else
  388. ConnInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_EXPIRED;
  389. DEBUG_INFO("TLS allow expired certification.\n");
  390. #endif
  391. }
  392. wsi_client = lws_client_connect_via_info(&ConnInfo);
  393. if (!wsi_client)
  394. {
  395. DEBUG_ERROR("lws_client_connect_via_info NG\n");
  396. //goto end;
  397. }
  398. counterConnect=0;
  399. DEBUG_INFO("counterConnect: %d\n", counterConnect);
  400. end:
  401. pthread_exit(NULL/*(void *) fname*/);
  402. }
  403. int isQueueOverSize()
  404. {
  405. FILE *fp;
  406. uint32_t file_size;
  407. uint8_t result = FALSE;
  408. fp = fopen("/Storage/OCPP/TransactionRelatedQueue20" , "r");
  409. if(fp != NULL)
  410. {
  411. fseek(fp, 0L, SEEK_END);
  412. file_size = ftell(fp);
  413. if(file_size > (100*1024*1024))
  414. {
  415. result = TRUE;
  416. DEBUG_WARN("Queue file over size.\n");
  417. }
  418. fclose(fp);
  419. }
  420. return result;
  421. }
  422. int showfront(char *uuid, char *data)
  423. {
  424. FILE *fp;
  425. int result = FALSE; // 1: TRUE 0:FALSE
  426. char str[QUEUE_MESSAGE_LENGTH]={0};
  427. char sstr[50]={ 0 };//sstr[200]={ 0 };
  428. int c = 0;
  429. char *loc;
  430. char rmFileCmd[100]={0};
  431. struct stat stats;
  432. stat("/Storage/OCPP", &stats);
  433. // Check for directory existence
  434. if (S_ISDIR(stats.st_mode) == 1)
  435. {
  436. //DEBUG_INFO("\n OCPP directory exist \n");
  437. }
  438. else
  439. {
  440. DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  441. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  442. system(rmFileCmd);
  443. }
  444. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  445. if((access("/Storage/OCPP/TransactionRelatedQueue20",F_OK))!=-1)
  446. {
  447. //DEBUG_INFO("TransactionRelatedQueue20 exist.\n");
  448. }
  449. else
  450. {
  451. //DEBUG_INFO("TransactionRelatedQueue20 not exist\n");
  452. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue20", "w+");
  453. if(log == NULL)
  454. {
  455. DEBUG_INFO("Can't Create File TransactionRelatedQueue20 \n");
  456. return FALSE;
  457. }
  458. else
  459. {
  460. fclose(log);
  461. }
  462. }
  463. /* opening file for reading */
  464. fp = fopen("/Storage/OCPP/TransactionRelatedQueue20" , "r");
  465. if(fp == NULL) {
  466. DEBUG_INFO("Error opening TransactionRelatedQueue20 file");
  467. return FALSE;
  468. }
  469. if( fgets (str, QUEUE_MESSAGE_LENGTH, fp)!=NULL ) {
  470. /* writing content to stdout */
  471. //DEBUG_INFO("str=%s",str);
  472. if ((str[0] == '\n')||(strcmp(str,"")==0))
  473. {
  474. DEBUG_INFO("It is a blank line");
  475. fclose(fp);
  476. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  477. sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/TransactionRelatedQueue20");
  478. system(rmFileCmd);
  479. result = FALSE;
  480. return result;
  481. }
  482. else
  483. {
  484. //puts(str);
  485. //----------------uuid--------------//
  486. loc = strstr(str, "\"");
  487. memset(sstr ,0, ARRAY_SIZE(sstr) );
  488. c = 0;
  489. while (loc[1+c] != '\"')
  490. {
  491. sstr[c] = loc[1+c];
  492. c++;
  493. }
  494. sstr[c] = '\0';
  495. //DEBUG_INFO("\n uuid:%s", sstr);
  496. //DEBUG_INFO("\n data:%s", str);
  497. strcpy(uuid,sstr);
  498. strcpy(data,str);
  499. result = TRUE;
  500. }
  501. }
  502. else
  503. {
  504. //DEBUG_INFO("queue is null\n");
  505. strcpy(uuid,"");
  506. strcpy(data,"");
  507. result = FALSE;
  508. }
  509. fclose(fp);
  510. return result;
  511. }
  512. int addq(char *uuid, char *data)
  513. {
  514. FILE *outfile;
  515. char rmFileCmd[100]={0};
  516. struct stat stats;
  517. stat("/Storage/OCPP", &stats);
  518. DEBUG_INFO("addq\n");
  519. // Check for directory existence
  520. if (S_ISDIR(stats.st_mode) == 1)
  521. {
  522. //DEBUG_INFO("\n OCPP directory exist \n");
  523. }
  524. else
  525. {
  526. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  527. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  528. system(rmFileCmd);
  529. }
  530. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  531. if((access("/Storage/OCPP/TransactionRelatedQueue20",F_OK))!=-1)
  532. {
  533. //DEBUG_INFO("TransactionRelatedQueue20 exist.\n");
  534. }
  535. else
  536. {
  537. //DEBUG_INFO("TransactionRelatedQueue20 not exist\n");
  538. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue20", "w+");
  539. if(log == NULL)
  540. {
  541. //DEBUG_INFO("Can't Create File TransactionRelatedQueue20 \n");
  542. return FALSE;
  543. }
  544. else
  545. {
  546. fclose(log);
  547. }
  548. }
  549. // open file for writing
  550. outfile = fopen ("/Storage/OCPP/TransactionRelatedQueue20", "a");
  551. DEBUG_INFO("data = %s\n",data);
  552. fputs(data, outfile);
  553. fputs("\n", outfile);
  554. fclose (outfile);
  555. queueOpInfo.TransactionQueueNum += 1;
  556. DEBUG_INFO("add queue end\n");
  557. system("/bin/fsync -d /dev/mtdblock13;/bin/sync &");
  558. return FALSE;
  559. }
  560. int delq()
  561. {
  562. char tempfile[] = "/Storage/OCPP/delqtemp.json";
  563. FILE *infile;
  564. FILE *outfile;
  565. int resultRename=0;
  566. char filename[60]={0};
  567. char rmFileCmd[100]={0};
  568. struct stat stats;
  569. stat("/Storage/OCPP", &stats);
  570. DEBUG_INFO("delq()\n");
  571. // Check for directory existence
  572. if (S_ISDIR(stats.st_mode) == 1)
  573. {
  574. //DEBUG_INFO("\n OCPP directory exist \n");
  575. }
  576. else
  577. {
  578. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  579. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  580. system(rmFileCmd);
  581. }
  582. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  583. if((access("/Storage/OCPP/TransactionRelatedQueue20",F_OK))!=-1)
  584. {
  585. //DEBUG_INFO("TransactionRelatedQueue20 exist.\n");
  586. }
  587. else
  588. {
  589. //DEBUG_INFO("TransactionRelatedQueue20 not exist\n");
  590. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue20", "w+");
  591. if(log == NULL)
  592. {
  593. //DEBUG_INFO("log is NULL\n");
  594. return 0;
  595. }
  596. else
  597. {
  598. fclose(log);
  599. }
  600. }
  601. // open file for writing
  602. strcpy(filename, "/Storage/OCPP/TransactionRelatedQueue20");
  603. infile = fopen ("/Storage/OCPP/TransactionRelatedQueue20", "r");
  604. outfile = fopen (tempfile, "w");
  605. //DEBUG_INFO("feof(infile) =%d\n",feof(infile));
  606. int c;
  607. c = fgetc(infile);
  608. //printf("file c:%d\n",c);
  609. rewind(infile);
  610. if(c == EOF)
  611. {
  612. //DEBUG_INFO("TransactionRelatedQueue20 is NULL\n");
  613. fclose(infile);
  614. fclose(outfile);
  615. sprintf(rmFileCmd,"rm -f %s",tempfile);
  616. system(rmFileCmd);
  617. }
  618. else
  619. {
  620. char buf[QUEUE_MESSAGE_LENGTH]={0};
  621. int i = 0;
  622. //DEBUG_INFO("Orignal File is not NULL\n");
  623. while (fgets(buf, sizeof(buf), infile) != NULL)
  624. {
  625. //printf("Orignal File get strings \n");
  626. buf[strlen(buf) - 1] = '\0'; // eat the newline fgets() stores
  627. if(i==0)
  628. {
  629. queueOpInfo.TransactionQueueNum -= 1;
  630. queueOpInfo.TransactionMessageResend = 0;
  631. DEBUG_INFO("delete the item\n");
  632. }
  633. if(i != 0)
  634. {
  635. fprintf(outfile,"%s\n", buf);
  636. }
  637. i = i + 1;
  638. }
  639. fclose(infile);
  640. fclose(outfile);
  641. sprintf(rmFileCmd,"rm -f %s",filename);
  642. system(rmFileCmd);
  643. resultRename = rename(tempfile, filename);
  644. if(resultRename == 0)
  645. {
  646. //DEBUG_INFO("TransactionRelatedQueue20 file renamed successfully");
  647. }
  648. else
  649. {
  650. //DEBUG_INFO("Error: unable to rename the TransactionRelatedQueue20 file");
  651. }
  652. DEBUG_INFO("delq() end\n");
  653. }
  654. system("/bin/fsync -d /dev/mtdblock13;/bin/sync &");
  655. return 0;
  656. }
  657. int showqueue()
  658. {
  659. char rmFileCmd[100]={0};
  660. struct stat stats;
  661. stat("/Storage/OCPP", &stats);
  662. // Check for directory existence
  663. if (S_ISDIR(stats.st_mode) == 1)
  664. {
  665. //DEBUG_INFO("\n OCPP directory exist \n");
  666. }
  667. else
  668. {
  669. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  670. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  671. system(rmFileCmd);
  672. }
  673. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  674. if((access("/Storage/OCPP/TransactionRelatedQueue20",F_OK))!=-1)
  675. {
  676. //DEBUG_INFO("TransactionRelatedQueue20 exist.\n");
  677. }
  678. else
  679. {
  680. //DEBUG_INFO("TransactionRelatedQueue20 not exist\n");
  681. FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue20", "w+");
  682. if(log == NULL)
  683. {
  684. DEBUG_INFO("log is NULL\n");
  685. return FALSE;
  686. }
  687. else
  688. {
  689. fclose(log);
  690. }
  691. }
  692. FILE *fp = fopen("/Storage/OCPP/TransactionRelatedQueue20", "r");
  693. char line[QUEUE_MESSAGE_LENGTH]={0};
  694. // check if file exist (and you can open it) or not
  695. if (fp == NULL) {
  696. DEBUG_INFO("can open file TransactionRelatedQueue20!");
  697. return FALSE;
  698. }
  699. queueOpInfo.TransactionQueueNum = 0; // the number of packets in queue
  700. while(fgets(line, sizeof line, fp) != NULL) {
  701. //DEBUG_INFO("%s\n", line);
  702. queueOpInfo.TransactionQueueNum += 1; //the number of packets in queue
  703. }
  704. fclose(fp);
  705. return TRUE;
  706. }
  707. int sentqueue(){
  708. FILE *fp;
  709. int result = FALSE; // 1: TRUE 0:FALSE
  710. char str[QUEUE_MESSAGE_LENGTH]={0};
  711. char cmdBuf[100]={0};
  712. struct stat stats;
  713. json_object *queueJson;
  714. DEBUG_INFO("Sent queue.\n");
  715. stat("/Storage/OCPP", &stats);
  716. // Check for directory existence
  717. if (S_ISDIR(stats.st_mode) == 1)
  718. {
  719. //DEBUG_INFO("\n OCPP directory exist \n");
  720. }
  721. else
  722. {
  723. //DEBUG_INFO("\n OCPP directory not exist, create dir \n");
  724. sprintf(cmdBuf,"mkdir -p %s","/Storage/OCPP");
  725. system(cmdBuf);
  726. }
  727. /* opening file for reading */
  728. fp = fopen("/Storage/OCPP/TransactionRelatedQueue20" , "r");
  729. if(fp == NULL)
  730. {
  731. DEBUG_ERROR("Error opening file");
  732. return FALSE;
  733. }
  734. if( fgets (str, QUEUE_MESSAGE_LENGTH, fp)!=NULL )
  735. {
  736. queueJson = json_tokener_parse(str);
  737. if(!is_error(queueJson))
  738. {
  739. LWS_Send(str);
  740. }
  741. json_object_put(queueJson);
  742. result = TRUE;
  743. }
  744. else
  745. {
  746. result = FALSE;
  747. }
  748. fclose(fp);
  749. return result;
  750. }
  751. void* processTransactionQueue(void* data)
  752. {
  753. char frontUUID[100] ={0};
  754. char frontData[QUEUE_MESSAGE_LENGTH] ={0};
  755. int queueNotEmpty = FALSE;
  756. while(1)
  757. {
  758. if(!req_SendQueue && ((getDiffSecNow(startTime.startTimeQueue) >= ((TransactionMessageRetryIntervalGet()>10?TransactionMessageRetryIntervalGet():10)*(queueOpInfo.TransactionMessageResend>1?2:1))) || (isWebsocketSendable && isQueueSendable && (getDiffSecNow(startTime.startTimeQueue) >= ((counterQueueSent>=20)?5:0)))))
  759. {
  760. if(FirstHeartBeatResponse() == 1)
  761. {
  762. memset(frontUUID, 0, ARRAY_SIZE(frontUUID));
  763. memset(frontData, 0, ARRAY_SIZE(frontData));
  764. queueNotEmpty = queue_operation(QUEUE_OPERATION_SHOWFRONT,frontUUID, frontData);
  765. if((queueNotEmpty == TRUE) && (GetOcppConnStatus() == 1))
  766. {
  767. if(isWebsocketSendable)
  768. DEBUG_INFO("isWebsocketSendable on.\n");
  769. if(isQueueSendable)
  770. DEBUG_INFO("isQueueSendable on.\n");
  771. if(((getDiffSecNow(startTime.startTimeQueue) > (TransactionMessageRetryIntervalGet()>10?TransactionMessageRetryIntervalGet():10))))
  772. DEBUG_INFO("Queue timer(%d) over spec(%d).\n", getDiffSecNow(startTime.startTimeQueue), TransactionMessageRetryIntervalGet());
  773. if(queueOpInfo.TransactionMessageResend < TransactionMessageAttemptsGet())
  774. {
  775. DEBUG_INFO("Sent message from queue request.\n");
  776. DEBUG_INFO("TransactionMessageResend time: %d\n", queueOpInfo.TransactionMessageResend);
  777. req_SendQueue = 1;
  778. queueOpInfo.TransactionMessageResend += 1;
  779. }
  780. else
  781. {
  782. DEBUG_INFO("Transaction message resend(%d) over spec(%d) message abandon.\n", queueOpInfo.TransactionMessageResend, TransactionMessageAttemptsGet());
  783. queue_operation(QUEUE_OPERATION_DEL,"","");
  784. queueOpInfo.TransactionMessageResend = 0;
  785. req_SendQueue = 0;
  786. }
  787. }
  788. }
  789. // Refresh queue timer
  790. refreshStartTimer(&startTime.startTimeQueue);
  791. if((counterQueueSent >= 10) || (queueNotEmpty == FALSE))
  792. {
  793. counterQueueSent = 0;
  794. }
  795. else
  796. {
  797. counterQueueSent += 1;
  798. }
  799. }
  800. usleep(500000);
  801. }
  802. pthread_exit(NULL);
  803. return 0;
  804. }
  805. void* processWatchdog()
  806. {
  807. for(;;)
  808. {
  809. if((getDiffSecNow(startTime.startTimeDog) > 10) && (context != NULL))
  810. {
  811. DEBUG_INFO("LWS watch dog timeout.\n");
  812. lws_cancel_service(context);
  813. lws_cancel_service_pt(wsi_client);
  814. if(counterLwsRestart >= 3)
  815. {
  816. DEBUG_INFO("LWS watch dog timeout over 3 count.\n");
  817. system("killall OcppBackend20");
  818. }
  819. else
  820. counterLwsRestart++;
  821. refreshStartTimer(&startTime.startTimeDog);
  822. }
  823. if(counterConnect >= 3)
  824. {
  825. DEBUG_INFO("Connect OCPP server timeout over 3 count.\n");
  826. system("killall OcppBackend20");
  827. }
  828. if((0 < GetWebSocketPingInterval()) && ((GetWebSocketPingInterval()+5) <= getDiffSecNow(startTime.pingOn)) && (wsi_client != NULL) && (GetServerSign() == TRUE))
  829. {
  830. DEBUG_WARN("Pong packet receive timeout.\n");
  831. //system("killall OcppBackend20");
  832. lws_context_destroy(context);
  833. ConnectionEstablished = 0;
  834. context = NULL;
  835. }
  836. usleep(500000);
  837. }
  838. pthread_exit(NULL); //
  839. }
  840. void CheckTransactionPacket(char *uuid)
  841. {
  842. char frontUUID[100]={0};
  843. char frontData[QUEUE_MESSAGE_LENGTH]={0};
  844. int queueNotEmpty = FALSE;
  845. int cmpResult = 0;
  846. queueNotEmpty = queue_operation(QUEUE_OPERATION_SHOWFRONT,frontUUID, frontData);//showfront(frontUUID, frontData); ---> remove temporally
  847. if(queueNotEmpty == TRUE)
  848. {
  849. cmpResult = strcmp(frontUUID, uuid);
  850. if (cmpResult == 0)
  851. {
  852. DEBUG_INFO("Receive queue response match.\n");
  853. queue_operation(QUEUE_OPERATION_DEL,"","");//delq(); ---> remove temporally
  854. queueOpInfo.TransactionMessageResend = 0;
  855. }
  856. else
  857. DEBUG_INFO("Receive queue response mismatch.\n");
  858. }
  859. }
  860. int queue_operation(int type, char *frontUUID, char *frontData)
  861. {
  862. int result=0;
  863. while(1)
  864. {
  865. if (!queueOpInfo.IsUsing )
  866. {
  867. queueOpInfo.IsUsing = TRUE;
  868. if(type == QUEUE_OPERATION_SHOWQUEUE) // show items in queue
  869. {
  870. result = showqueue();
  871. }
  872. else if(type == QUEUE_OPERATION_SHOWFRONT) // show first item
  873. {
  874. result = showfront(frontUUID, frontData);
  875. }
  876. else if(type == QUEUE_OPERATION_DEL) // delete item
  877. {
  878. result = delq();
  879. }
  880. else if(type == QUEUE_OPERATION_SENT) // sent items in queue
  881. {
  882. result = sentqueue();
  883. }
  884. else if(type == QUEUE_OPERATION_ADD) // add items to the queue
  885. {
  886. // If queue file over size only add start * stop transaction message
  887. if(!isQueueOverSize() || (strstr(frontData, "MeterValues") == NULL))
  888. {
  889. result = addq(frontUUID, frontData);
  890. }
  891. }
  892. queueOpInfo.IsUsing = FALSE;
  893. break;
  894. }
  895. usleep(100000);
  896. }
  897. return result;
  898. }
  899. int removeMessageSentFile(void)
  900. {
  901. char rmFileCmd[100]={0};
  902. struct stat stats;
  903. stat("/Storage/OCPP", &stats);
  904. // Check for directory existence
  905. if(S_ISDIR(stats.st_mode) == 1)
  906. {
  907. //DEBUG_INFO("\n OCPP directory exist \n");
  908. }
  909. else
  910. {
  911. DEBUG_INFO("\n directory not exist, create dir \n");
  912. sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP");
  913. system(rmFileCmd);
  914. }
  915. stat("/Storage/OCPP/TransactionRelatedQueue20", &stats);
  916. if(stats.st_size < 10)
  917. {
  918. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  919. if((access("/Storage/OCPP/MessageSent",F_OK))!=-1)
  920. {
  921. DEBUG_INFO("MessageSent file exist.\n");
  922. sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/MessageSent");
  923. system(rmFileCmd);
  924. }
  925. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  926. }
  927. return 0;
  928. }
  929. //================================================
  930. // Main process
  931. //================================================
  932. int main(void)
  933. {
  934. char rmFileCmd[100]={0};
  935. struct stat stats;
  936. queueOpInfo.IsUsing = FALSE;
  937. queueOpInfo.TransactionMessageResend = 0;
  938. DEBUG_INFO("Module_OcppBackend20 task initialization...\n");
  939. //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);
  940. if(ProcessShareMemory()== FAIL)
  941. {
  942. return FAIL;
  943. }
  944. // Check & create OCPP dir
  945. stat("/Storage/OCPP", &stats);
  946. if(S_ISDIR(stats.st_mode) != 1)
  947. {
  948. DEBUG_INFO("OCPP directory not exist, create dir \n");
  949. sprintf(rmFileCmd,"mkdir -p /Storage/OCPP");
  950. system(rmFileCmd);
  951. }
  952. memset(rmFileCmd, 0, ARRAY_SIZE(rmFileCmd));
  953. // Create Process: Resend Transaction
  954. pthread_create(&tid_ProcQueue, NULL, processTransactionQueue, NULL);
  955. pthread_create(&tid_Watchdog, NULL, processWatchdog, NULL);
  956. // Sqlite3 initial
  957. if(DB_Initial() != PASS)
  958. {
  959. DEBUG_ERROR("OCPP 2.0 local database initial fail.\n");
  960. return 0;
  961. }
  962. initialConfigurationTable();
  963. removeMessageSentFile();
  964. for(;;)
  965. {
  966. refreshStartTimer(&startTime.startTimeDog);
  967. counterLwsRestart = 0;
  968. // Connect server
  969. if(ConnectionEstablished==0) // Check InternetConn 0: disconnected, 1: connected
  970. {
  971. isWebsocketSendable = 1;
  972. isQueueSendable = 1;
  973. SetOcppConnStatus(FALSE);
  974. SetServerSign(FALSE);
  975. InitialSystemValue();
  976. if(getDiffSecNow(startTime.connect) >= 30)
  977. {
  978. DEBUG_INFO("Server connecting...\n");
  979. pthread_create(&tid_connectServer, NULL, ConnectWsServer, NULL);
  980. refreshStartTimer(&startTime.connect);
  981. }
  982. CheckSystemValue();
  983. }
  984. else
  985. {
  986. // Sign in
  987. if((GetServerSign() == FALSE) &&
  988. (isConnectorInitMode(0) != TRUE) &&
  989. ( (GetBootNotificationInterval()>0) ? (getDiffSecNow(startTime.bootNotification) >= GetBootNotificationInterval()) : (getDiffSecNow(startTime.bootNotification) >= 10) )
  990. )
  991. {
  992. sendBootNotificationRequest();
  993. refreshStartTimer(&startTime.bootNotification);
  994. }
  995. // Check System Value
  996. CheckSystemValue();
  997. // On line operation
  998. if(GetServerSign() == TRUE)
  999. {
  1000. // Send message from queue
  1001. if((req_SendQueue == 1) && (isWebsocketSendable || ((queueOpInfo.TransactionMessageResend > 1) && (queueOpInfo.PreTransactionMessageResend != queueOpInfo.TransactionMessageResend))))
  1002. {
  1003. queue_operation(QUEUE_OPERATION_SENT, "", "");
  1004. req_SendQueue = 0;
  1005. queueOpInfo.PreTransactionMessageResend = queueOpInfo.TransactionMessageResend;
  1006. }
  1007. // PING packet
  1008. if(isWebsocketSendable && (0 < GetWebSocketPingInterval()) && ((GetWebSocketPingInterval()+counterPingSend) <= getDiffSecNow(startTime.pingOn)))
  1009. {
  1010. lws_callback_on_writable(wsi_client);
  1011. counterPingSend++;
  1012. }
  1013. if(GetHeartBeatWithNOResponse() >= 30)
  1014. {
  1015. lws_context_destroy(context);
  1016. ConnectionEstablished = 0;
  1017. context = NULL;
  1018. SetHeartBeatWithNOResponse();
  1019. DEBUG_WARN("Heartbeat re-send over 30 count.\n");
  1020. }
  1021. if((GetOcppConnStatus() == 0))
  1022. {
  1023. if(getDiffSecNow(startTime.reConnect) >= 3)
  1024. {
  1025. DEBUG_INFO("GetOcppConnStatus() = %d\n", GetOcppConnStatus());
  1026. lws_context_destroy(context);
  1027. ConnectionEstablished = 0;
  1028. context = NULL;
  1029. }
  1030. }
  1031. else
  1032. {
  1033. refreshStartTimer(&startTime.reConnect);
  1034. }
  1035. }
  1036. }
  1037. do
  1038. {
  1039. lws_service(context, 0);//timeout_ms
  1040. }while((SendBufLen>0) && (context!=NULL) && GetOcppConnStatus());
  1041. refreshProcDogTimer();
  1042. usleep(100000);
  1043. }
  1044. pthread_join(tid_ProcQueue, NULL);
  1045. pthread_join(tid_Watchdog, NULL);
  1046. return FAIL;
  1047. }