#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libwebsockets.h" #include #include "hashmap.h" #include "SystemLogMessage.h" #include "ShareMemory.h" #include #include "MessageHandler.h" #include "sqlite3.h" #ifndef SPEC_LATEST_SUPPORTED #define SPEC_LATEST_SUPPORTED 13 #endif #define Debug //#define ARRAY_SIZE(A) (sizeof(A) / sizeof(A[0])) #define PASS 1 #define FAIL -1 typedef enum boolean { FALSE, TRUE } BOOL; struct lws *wsi_client; struct lws_context *context; static int sendbuffer = 0; pthread_t pid; extern int server_sign; extern void CheckSystemValue(void); //extern int TransactionMessageAttemptsGet(void); extern int FirstHeartBeatResponse(void); extern void OCPP_get_TableAuthlocalAllData(void); extern int TransactionMessageAttemptsGet(void); extern int TransactionMessageRetryIntervalGet(void); extern int GetOcppConnStatus(void); extern void SetOcppConnStatus(uint8_t status); extern int GetHeartBeatWithNOResponse(void); extern void SetHeartBeatWithNOResponse(void); pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t lock_sentData = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t receiveData = PTHREAD_MUTEX_INITIALIZER; //========================================== // Function prototype //========================================== void trim(char *s); int mystrcmp(char *p1,char *p2); void substr(char *dest, const char* src, unsigned int start, unsigned int cnt); void getSubStr(char *dest, char* src, char *split, int idx); void split(char **arr, char *str, const char *del); int strpos(char *source, char *substr, int skip); int strposs(char *source, char *substr, int idx); char *random_uuid( char buf[37] ); static int OCPP16Callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); char * strchr(const char *p, int ch); void ReceivedMessage(void *in, size_t len); struct StartTime { unsigned int connect; unsigned int bootNotification; }startTime; #if 0 unsigned char *SendBuffer; int SendBufLen=(1024*4);//(1024*3); #endif int SendBufLen=(1024*4);//(1024*3); unsigned char SendBuffer[1024*4]={0}; static int ConnectionEstablished=0; static int TransactionMessageResend = 1; static int TransactionQueueInterval = 10;//3; // TransactionMessageAttempts static int TransactionQueueNum = 0; static int OfflineTransactionQueueNum = 0; static int OfflineTransaction = 0; int defaultWaitingTime = 10; //10 second char OcppPath[160]={0}; char OcppProtocol[10]={0},OcppHost[50]={0}, OcppTempPath[50]={0}; //=============================== // OCPP SentQueue TransactionId //=============================== //static int SentQueueTransactionId[10]={0}; extern int BootNotificationInterval; //char guid[37]; //map_t hashMap; //data_struct_t* mapItem; --- remove for temporally //data_struct_t mapItem[0]={0}; sqlite3 *db; char *errMsg = NULL; static char *createsql = "CREATE TABLE IF NOT EXISTS log_buffer(" "idx integer primary key," "user_id text," "cmd_sn text," "charger_id text," "gun_type text," "gun_no text," "rfid_no text," "stime text," "etime text," "time_len text," "s_soc text," "e_soc text," "stop_reason text," "power text," "meter_before text," "meter_after text," "charge_price text," "reserve text," "surplus_before text," "surplus_after text," "service_price text," "is_pay text," "charge_strategy text," "charge_parameter text," "vin text," "vehicle_no text," "start_method text," "card_type text," "is_upload text," "guid text UNIQUE," "is_buf2OK text);"; #if 0 static char *createsChargingRecordsql = "CREATE TABLE IF NOT EXISTS ChargingRecord(" "idx integer primary key," "gun_type text," "connectorId text," "idTag text," "transactionId text," "stime text," "etime text," "time_len text," "s_soc text," "e_soc text," "stop_reason text," "power text," "meter_before text," "meter_after text," "reservationId text," "guid text UNIQUE);"; //"is_buf2OK text);"; #endif static char *sqlOcppAuthCache = "create table if not exists ocpp_auth_cache (idx integer primary key," "idtag text UNIQUE," "parent_idtag text," "expir_date text," "status text);"; static char *sqlOcppAuthLocal = "create table if not exists ocpp_auth_local (idx integer primary key," "idtag text UNIQUE," "parent_idtag text," "expir_date text," "status text," "version text);"; #if 0 static char *sqlInitialOcppAuthLocal = "insert or replace into ocpp_auth_local(idtag, parent_idtag, expir_date, status, version) values('PaHdImHiOnNG','none','2099-12-31T23:59:59.999Z','Accepted','0')"; #endif int DiffTimeb(struct timeb ST, struct timeb ET) { //return milli-second unsigned int StartTime,StopTime; StartTime=(unsigned int)ST.time; StopTime=(unsigned int)ET.time; return (StopTime-StartTime)*1000+ET.millitm-ST.millitm; } //================================= // Common routine //================================= void trim(char *s) { int i=0, j, k, l=0; while((s[i]==' ')||(s[i]=='\t')||(s[i]=='\n')) i++; j = strlen(s)-1; while((s[j]==' ')||(s[j]=='\t')||(s[j]=='\n')) j--; if(i==0 && j==strlen(s)-1) { } else if(i==0) s[j+1] = '\0'; else { for(k=i; k<=j; k++) s[l++] = s[k]; s[l] = '\0'; } } int mystrcmp(char *p1,char *p2) { while(*p1==*p2) { if(*p1=='\0' || *p2=='\0') break; p1++; p2++; } if(*p1=='\0' && *p2=='\0') return(PASS); else return(FAIL); } void substr(char *dest, const char* src, unsigned int start, unsigned int cnt) { strncpy(dest, src + start, cnt); dest[cnt] = 0; } void getSubStr(char *dest, char* src, char *split, int idx) { int start = (strposs(src,",",idx)+1); int cnt = (strposs(src,",",idx+1)-2)-(strposs(src,",",idx)+1); strncpy(dest, src + start, cnt); dest[cnt] = 0; } void split(char **arr, char *str, const char *del) { char *s = strtok(str, del); while(s != NULL) { *arr++ = s; s = strtok(NULL, del); } } int strpos(char *source, char *substr, int skip) { char stack[strlen(source)]; strncpy(stack, source+skip, strlen(source)-skip); char *p = strstr(stack, substr); if (p) return p - stack+skip; return -1; } int strposs(char *source, char *substr, int idx) { char stack[strlen(source)]; int result=0; int count=0; while(count<=idx) { memset(stack,0,sizeof stack); strncpy(stack, source+result, strlen(source)-result); int loc = strcspn(stack, substr); if(loc>0) result += (loc+1); else result = -1; count++; } return result; } static int testnum = 0; char *random_uuid( char buf[37] ) { // const char *c = "89ab"; char *p = buf; // int n; #if 1 // test time_t seconds; seconds = time(NULL); testnum = testnum % 999; testnum = testnum + 1; //printf("\n testnum:%d\n", testnum); //printf("\n seconds:%d\n", seconds); sprintf(p, "%03d%034d", testnum, (unsigned int)(seconds)); //printf("\n p:%s\n", p); #endif #if 0 for( n = 0; n < 16; ++n ) { int b = rand()%255; switch( n ) { case 6: sprintf(p, "4%x", b%15 ); break; case 8: sprintf(p, "%c%x", c[rand()%strlen(c)], b%15 ); break; default: sprintf(p, "%02x", b); break; } p += 2; switch( n ) { case 3: case 5: case 7: case 9: *p++ = '-'; break; } } *p = 0; #endif return buf; } int GetTransactionQueueNum(void) { return TransactionQueueNum; } //========================================== // Web socket tranceive routine //========================================== int SendData(struct lws *wsi) { int n; int len; char *ret; unsigned char out[LWS_SEND_BUFFER_PRE_PADDING + 4096 + LWS_SEND_BUFFER_POST_PADDING] = {0}; len = strlen((char *)SendBuffer); if(len == 0) return 0; memcpy (out + LWS_SEND_BUFFER_PRE_PADDING, SendBuffer, len ); ret = strstr((const char *)(out + LWS_SEND_BUFFER_PRE_PADDING), "Heartbeat"); if(ret == NULL) { DEBUG_OCPPMESSAGE_INFO(" SendData= %s\n", out + LWS_SEND_BUFFER_PRE_PADDING); } n = lws_write(wsi, out + LWS_SEND_BUFFER_PRE_PADDING, len, LWS_WRITE_TEXT); memset(SendBuffer, 0, len); return n; } static int OCPP16Callback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len) { switch (reason) { case LWS_CALLBACK_PROTOCOL_INIT: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_PROTOCOL_INIT\n"); #endif break; case LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH\n"); #endif char buf[64]; char hash[20], key_b64[40]; lws_b64_encode_string(hash, 16, key_b64, sizeof(key_b64));// Sec-WebSocket-Key DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Client Request START----------------\n"); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_URI); DEBUG_OCPPMESSAGE_INFO("GET %s HTTP/1.1 \n", buf); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_HOST); DEBUG_OCPPMESSAGE_INFO("Host: %s\n", buf); //lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_PEER_ADDRESS); //DEBUG_OCPPMESSAGE_INFO("_WSI_TOKEN_CLIENT_PEER_ADDRESS %s\n", buf); DEBUG_OCPPMESSAGE_INFO("Upgrade: websocket\n"); DEBUG_OCPPMESSAGE_INFO("Connection: Upgrade\n"); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Key: %s\n", key_b64); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Version: %d\n", SPEC_LATEST_SUPPORTED); DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Client Request END----------------\n"); DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Server response START----------------\n"); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_HTTP); DEBUG_OCPPMESSAGE_INFO("HTTP/1.1 %s\n", buf); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_UPGRADE); DEBUG_OCPPMESSAGE_INFO("Upgrade: %s\n", buf); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_CONNECTION); DEBUG_OCPPMESSAGE_INFO("Connection: %s\n", buf); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_ACCEPT); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Accept: %s\n", buf); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, WSI_TOKEN_PROTOCOL); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf); DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Server response END----------------\n"); break; case LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_FILTER_PROTOCOL_CONNECTION\n"); #endif break; case LWS_CALLBACK_WSI_DESTROY: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_WSI_DESTROY\n"); #endif pthread_detach(pid); server_sign = FALSE; ConnectionEstablished=0; context = NULL; break; case LWS_CALLBACK_LOCK_POLL: break; case LWS_CALLBACK_ADD_POLL_FD: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_ADD_POLL_FD\n"); #endif break; case LWS_CALLBACK_DEL_POLL_FD: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_DEL_POLL_FD\n"); #endif break; case LWS_CALLBACK_UNLOCK_POLL: break; case LWS_CALLBACK_CHANGE_MODE_POLL_FD: break; case LWS_CALLBACK_WSI_CREATE: #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_WSI_CREATE\n"); #endif break; case LWS_CALLBACK_GET_THREAD_ID: break; case LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER: { #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER\n"); #endif #if 0 unsigned char **p, *end; struct lws *parent; char buf[8192]; parent = lws_get_parent(wsi); if (!parent) break; p = (unsigned char **)in; end = (*p) + len; #endif } break; case LWS_CALLBACK_CLIENT_ESTABLISHED: //3 { #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_CLIENT_ESTABLISHED\n"); #endif char frontUUID[100] ={0}; char frontData[1200] ={0}; int queueNotEmpty = 0; //connected ConnectionEstablished=1; queueNotEmpty = queue_operation(1,frontUUID, frontData); if(queueNotEmpty == TRUE) { OfflineTransaction = 1; } TransactionQueueInterval = 0; TransactionMessageResend = 1; //get offline number queue_operation(0,"",""); OfflineTransactionQueueNum =TransactionQueueNum ; } break; case LWS_CALLBACK_CLIENT_CONNECTION_ERROR://1 #ifdef SystemLogMessage DEBUG_ERROR("LWS_CALLBACK_CLIENT_CONNECTION_ERROR %s\n", (char *)in ); #endif //disconnected ConnectionEstablished=0; char buf1[64]; char hash1[20]={0}, key_b641[40]={0}; lws_b64_encode_string(hash1, 16, key_b641, sizeof(key_b641));// Sec-WebSocket-Key DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Client START----------------\n"); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_URI); DEBUG_OCPPMESSAGE_INFO("GET %s HTTP/1.1 \n", buf); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_HOST); DEBUG_OCPPMESSAGE_INFO("Host: %s\n", buf); //lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_PEER_ADDRESS); //DEBUG_OCPPMESSAGE_INFO("_WSI_TOKEN_CLIENT_PEER_ADDRESS %s\n", buf); DEBUG_OCPPMESSAGE_INFO("Upgrade: websocket\n"); DEBUG_OCPPMESSAGE_INFO("Connection: Upgrade\n"); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Key: %s\n", key_b641); lws_hdr_copy(wsi, buf, sizeof(buf) - 1, _WSI_TOKEN_CLIENT_SENT_PROTOCOLS); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Version: %d\n", SPEC_LATEST_SUPPORTED); DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Client END----------------\n"); DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Server response START----------------\n"); lws_hdr_copy(wsi, buf1, sizeof(buf1) - 1, WSI_TOKEN_HTTP); DEBUG_OCPPMESSAGE_INFO("HTTP/1.1 %s\n", buf1); lws_hdr_copy(wsi, buf1, sizeof(buf1) - 1, WSI_TOKEN_UPGRADE); DEBUG_OCPPMESSAGE_INFO("Upgrade: %s\n", buf1); lws_hdr_copy(wsi, buf1, sizeof(buf1) - 1, WSI_TOKEN_CONNECTION); DEBUG_OCPPMESSAGE_INFO("Connection: %s\n", buf1); lws_hdr_copy(wsi, buf1, sizeof(buf1) - 1, WSI_TOKEN_ACCEPT); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Accept: %s\n", buf1); lws_hdr_copy(wsi, buf1, sizeof(buf1) - 1, WSI_TOKEN_PROTOCOL); DEBUG_OCPPMESSAGE_INFO("Sec-WebSocket-Protocol: %s\n", buf1); DEBUG_OCPPMESSAGE_INFO("------------------Handshake: Server response END----------------\n"); break; case LWS_CALLBACK_CLOSED://4 #ifdef SystemLogMessage DEBUG_INFO("LWS_CALLBACK_CLOSED\n"); #endif //disconnected ConnectionEstablished=0; break; case LWS_CALLBACK_CLIENT_WRITEABLE://10 //if(need to send message and its relevant data already store into SendBuffer) #ifdef SystemLogMessage //DEBUG_INFO("LWS_CALLBACK_CLIENT_WRITEABLE\n"); #endif SendData(wsi); //lws_rx_flow_control( wsi, 1 ); break; case LWS_CALLBACK_CLIENT_RECEIVE://8 // lws_rx_flow_control( wsi, 0 ); ((char *)in)[len] = '\0'; //Print Out Adjudgement { char *ret, *ret1; ret = strstr((const char *)in, "currentTime"); ret1 = strstr((const char *)in, "interval"); if(!((ret != NULL)&&(ret1 == NULL))) { DEBUG_OCPPMESSAGE_INFO("Original Receive %s\n", (char *)in); } } char tempin[65536]={0}; //char tempin[1024*4]={0}; int c = 0; char *loc; char sstr[65536]={ 0 }; //char sstr[600]={ 0 }; //**********Receive Message**********/ c = 0; loc = strstr((const char *)in, "][2,"); if(loc == NULL) { loc = strstr((const char *)in, "][3,"); if(loc == NULL) { loc = strstr((const char *)in, "][4,"); } } memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { DEBUG_INFO("there are continuous second packet []\n"); while (loc[1+c] != '\0') { sstr[c] = loc[1+c]; c++; } sstr[c] = '\0'; strcpy(tempin, sstr); DEBUG_INFO("Final Receive: %s\n", tempin); } else { strcpy(tempin,(char *)in); } ReceivedMessage((void *)tempin, len); break; default: #ifdef Debug DEBUG_INFO("OCPP16Callback:reason=%d\n", reason); #endif break; } return 0; } static struct lws_protocols protocols[] = { { "ocpp1.6", OCPP16Callback, 10240,//65536,//10240, 10240,//65536,//10240, }, { "ocpp1.6", OCPP16Callback, 10240,//65536,//10240, 10240,//65536,//10240, }, { NULL, NULL, 0 /* End of list */ } }; void* ConnectWsServer(void* data) //int ConnectWsServer() { //pthread_detach(pthread_self()); //int result = PASS; struct lws_context_creation_info ContextInfo; struct lws_client_connect_info ConnInfo; int use_ssl=0; //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); if(context!=NULL) { pthread_detach(pthread_self()); lws_context_destroy(context); ConnectionEstablished=0; context = NULL; } memset(&ContextInfo, 0, sizeof(struct lws_context_creation_info)); if((GetOcppServerURL()==0) || (GetOcppPort() == 0) || (GetOcppPath()==0) ) { //result = FAIL; DEBUG_ERROR("OCPP URL is NULL or OCPP Port is zero or OCPP Path is NULL\n"); goto end; //return result; } if((strcmp(OcppProtocol,"ws")==0)&&(strlen(OcppProtocol)== 2)) { printf("ws!!! \n"); use_ssl=0; } else if((strcmp(OcppProtocol,"wss")==0)&&(strlen(OcppProtocol)== 3)) { printf("wss!!! \n"); use_ssl=1; } ContextInfo.port = CONTEXT_PORT_NO_LISTEN; ContextInfo.iface = NULL; ContextInfo.ssl_private_key_password = NULL; ContextInfo.ssl_cert_filepath = NULL;//"./ssl_key/client_cert.pem"; ContextInfo.ssl_private_key_filepath = NULL;//"./ssl_key/client_key.pem"; ContextInfo.ssl_ca_filepath = "/root/cacert.pem";//"./cacert.pem"; ContextInfo.ssl_cipher_list = NULL; //use default one ContextInfo.gid = -1; ContextInfo.uid = -1; if(use_ssl) { ContextInfo.options |= LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT ; } ContextInfo.protocols = protocols; ContextInfo.timeout_secs = GetWebSocketPingInterval();//WebSocketPingInterval;//30;//9999;//30; //if(ping pong enabled) ContextInfo.ws_ping_pong_interval = GetWebSocketPingInterval();//WebSocketPingInterval;//30;//0 for none, else interval in seconds context = lws_create_context(&ContextInfo); if (context == NULL) { //#ifdef SystemLogMessage DEBUG_ERROR("lws_create_context NG"); //#endif //result = FAIL; goto end; } memset(&ConnInfo,0,sizeof(struct lws_client_connect_info)); // fill up below information ConnInfo.context = context; ConnInfo.address=(const char *)OcppHost; printf("\n ConnInfo.address=%s\n",ConnInfo.address); ConnInfo.port = GetOcppPort(); printf("\n ConnInfo.port=%d\n",ConnInfo.port); ConnInfo.path=(const char *)OcppPath; printf("\n ConnInfo.path=%s\n",ConnInfo.path); char addr_port[256] = { 0 }; sprintf(addr_port, "%s:%u", ConnInfo.address, ConnInfo.port & 65535 ); ConnInfo.host= addr_port; // ConnInfo.address;//lws_canonical_hostname(context); ConnInfo.origin="origin"; ConnInfo.protocol = protocols[1].name; ConnInfo.ietf_version_or_minus_one = -1; if(use_ssl) ConnInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_ALLOW_SELFSIGNED | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK;; wsi_client = lws_client_connect_via_info(&ConnInfo); if (!wsi_client) { //#ifdef SystemLogMessage DEBUG_ERROR("lws_client_connect_via_info NG"); //#endif //result = FAIL; goto end; } end: pthread_exit(NULL/*(void *) fname*/); //return result; } //void createq(); int showfront(char *uuid, char *data); int addq(char *uuid, char *data) ; int delq(); int sentqueue(); void CheckTransactionPacket(char *uuid); int queue_operation(int type, char *frontUUID, char *frontData); int showfront(char *uuid, char *data) { FILE *fp; int result = FALSE; // 1: TRUE 0:FALSE char str[1200]={0}; char sstr[50]={ 0 };//sstr[200]={ 0 }; int c = 0; char *loc; char rmFileCmd[100]={0}; struct stat stats; stat("/Storage/OCPP", &stats); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { DEBUG_INFO("\n OCPP directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1) { //DEBUG_INFO("TransactionRelatedQueue exist.\n"); } else { //DEBUG_INFO("TransactionRelatedQueue not exist\n"); FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+"); if(log == NULL) { DEBUG_INFO("Can't Create File TransactionRelatedQueue \n"); return 0; } else { fclose(log); } } /* opening file for reading */ fp = fopen("/Storage/OCPP/TransactionRelatedQueue" , "r"); if(fp == NULL) { DEBUG_INFO("Error opening TransactionRelatedQueue file"); return FALSE; } #if 0 if(fgetc(fp)==EOF) { //DEBUG_INFO("It is end of file"); fclose(fp); memset(rmFileCmd, 0, sizeof rmFileCmd); if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1) { sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/TransactionRelatedQueue"); system(rmFileCmd); } result = FALSE; return result; } #endif if( fgets (str, 1200, fp)!=NULL ) { /* writing content to stdout */ //DEBUG_INFO("str=%s",str); if ((str[0] == '\n')||(strcmp(str,"")==0)) { DEBUG_INFO("It is a blank line"); fclose(fp); memset(rmFileCmd, 0, sizeof rmFileCmd); sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/TransactionRelatedQueue"); system(rmFileCmd); result = FALSE; return result; } else { //puts(str); //----------------uuid--------------// loc = strstr(str, "\""); memset(sstr ,0, sizeof(sstr) ); c = 0; while (loc[1+c] != '\"') { sstr[c] = loc[1+c]; c++; } sstr[c] = '\0'; //DEBUG_INFO("\n uuid:%s", sstr); //DEBUG_INFO("\n data:%s", str); strcpy(uuid,sstr); strcpy(data,str); result = TRUE; } } else { //DEBUG_INFO("queue is null\n"); strcpy(uuid,""); strcpy(data,""); result = FALSE; } fclose(fp); return result; } int addq(char *uuid, char *data) { FILE *outfile; char rmFileCmd[100]={0}; struct stat stats; stat("/Storage/OCPP", &stats); DEBUG_INFO("addq "); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { //DEBUG_INFO("\n OCPP directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1) { //DEBUG_INFO("TransactionRelatedQueue exist.\n"); } else { //DEBUG_INFO("TransactionRelatedQueue not exist\n"); FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+"); if(log == NULL) { //DEBUG_INFO("Can't Create File TransactionRelatedQueue \n"); return 0; } else { fclose(log); } } // open file for writing outfile = fopen ("/Storage/OCPP/TransactionRelatedQueue", "a"); DEBUG_INFO("data=%s\n",data); fputs(data, outfile); fputs("\n", outfile); fclose (outfile); TransactionQueueNum = TransactionQueueNum + 1; DEBUG_INFO("add queue end\n"); return 0; } int delq() { char tempfile[] = "/Storage/OCPP/delqtemp.json"; FILE *infile; FILE *outfile; int resultRename=0; char filename[60]={0}; char rmFileCmd[100]={0}; struct stat stats; stat("/Storage/OCPP", &stats); DEBUG_INFO("delq()\n"); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { //DEBUG_INFO("\n OCPP directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1) { //DEBUG_INFO("TransactionRelatedQueue exist.\n"); } else { //DEBUG_INFO("TransactionRelatedQueue not exist\n"); FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+"); if(log == NULL) { //DEBUG_INFO("log is NULL\n"); return 0; } else { fclose(log); } } // open file for writing strcpy(filename, "/Storage/OCPP/TransactionRelatedQueue"); infile = fopen ("/Storage/OCPP/TransactionRelatedQueue", "r"); outfile = fopen (tempfile, "w"); /*检测到文件结束标识返回1,否则返回0。*/ //DEBUG_INFO("feof(infile) =%d\n",feof(infile)); int c; c = fgetc(infile); //printf("file c:%d\n",c); rewind(infile); if(c == EOF) { //DEBUG_INFO("TransactionRelatedQueue is NULL\n"); fclose(infile); fclose(outfile); sprintf(rmFileCmd,"rm -f %s",tempfile); system(rmFileCmd); } else { char buf[1200]={0}; int i = 0; //DEBUG_INFO("Orignal File is not NULL\n"); while (fgets(buf, sizeof(buf), infile) != NULL) { //printf("Orignal File get strings \n"); buf[strlen(buf) - 1] = '\0'; // eat the newline fgets() stores if(i==0) { TransactionQueueNum = TransactionQueueNum - 1; TransactionQueueInterval = 0; TransactionMessageResend = 1; DEBUG_INFO("delete the item\n"); } if(i != 0) { fprintf(outfile,"%s\n", buf); } i = i + 1; } fclose(infile); fclose(outfile); sprintf(rmFileCmd,"rm -f %s",filename); system(rmFileCmd); resultRename = rename(tempfile, filename); if(resultRename == 0) { //DEBUG_INFO("TransactionRelatedQueue file renamed successfully"); } else { //DEBUG_INFO("Error: unable to rename the TransactionRelatedQueue file"); } DEBUG_INFO("delq() end\n"); } return 0; } int showqueue() { char rmFileCmd[100]={0}; struct stat stats; stat("/Storage/OCPP", &stats); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { //DEBUG_INFO("\n OCPP directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); if((access("/Storage/OCPP/TransactionRelatedQueue",F_OK))!=-1) { //DEBUG_INFO("TransactionRelatedQueue exist.\n"); } else { //DEBUG_INFO("TransactionRelatedQueue not exist\n"); FILE *log = fopen("/Storage/OCPP/TransactionRelatedQueue", "w+"); if(log == NULL) { DEBUG_INFO("log is NULL\n"); return 0; } else { fclose(log); } } FILE *fp = fopen("/Storage/OCPP/TransactionRelatedQueue", "r"); char line[1200]={0}; // check if file exist (and you can open it) or not if (fp == NULL) { DEBUG_INFO("can open file TransactionRelatedQueue!"); return 0; } TransactionQueueNum = 0; while(fgets(line, sizeof line, fp) != NULL) { //DEBUG_INFO("%s\n", line); TransactionQueueNum = TransactionQueueNum + 1; } fclose(fp); return 1; } int sentqueue(){ FILE *fp; int result = FALSE; // 1: TRUE 0:FALSE int temptransactionId = 0, gettransactionId = 0; int tempconnectorId = 0; //int gunIndex = 0; char guid[37]={0}; char tempdata[65]={0}; char key_value[65]={0}; int IsStopTransaction = FALSE; //int IsconnectorIdNULL = FALSE; //int IsIdtagNULL = FALSE; char str[1200]={0}; char strcomposite[1200]={0}; char rmFileCmd[100]={0}; struct stat stats; char sstr[28]={0}; unsigned char IdtagStr[20]={0}; unsigned char timestampStr[30]={0}; int tempmeterStart = 0; int tempreservationId = 0; int c = 0; char *loc; DEBUG_INFO("sentqueue\n"); stat("/Storage/OCPP", &stats); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { //DEBUG_INFO("\n OCPP directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); /* opening file for reading */ fp = fopen("/Storage/OCPP/TransactionRelatedQueue" , "r"); if(fp == NULL) { DEBUG_INFO("Error opening file"); return FALSE; } if( fgets (str, 1200, fp)!=NULL ) { //---- writing content to stdout ---// //*********************StopTransaction***************************/ loc = strstr(str, "StopTransaction"); c = 0; memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { IsStopTransaction = TRUE; } //*********************Start:connectorId***************************/ loc = strstr(str, "connectorId"); c = 0; memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { while (loc[strlen("connectorId")+2+c] != ',') { sstr[c] = loc[strlen("connectorId")+2+c]; c++; } sstr[c] = '\0'; tempconnectorId = atoi(sstr); } // else // { // IsconnectorIdNULL = TRUE; // } //*********************End:connectorId***************************/ //*********************Start:idTag***************************/ loc = strstr(str, "idTag"); c = 0; memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { while (loc[3+strlen("idTag")+c] != '\"') { sstr[c] = loc[3+strlen("idTag")+c]; c++; } sstr[c] = '\0'; strcpy((char*)IdtagStr, sstr); } // else // { // IsIdtagNULL = TRUE; // } //*********************End:idTag***************************/ //*********************Start: StartTransaction***************************/ loc = strstr(str, "StartTransaction"); c = 0; memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { // [2,0200000000000000000000000001584415776,StartTransaction,{connectorId:1,idTag:123,meterStart:100,reservationId:0,timestamp:2020-03-17T03:29:36Z}] //DEBUG_INFO("\n sent queue StartTransaction\n"); if(tempconnectorId > 0) { sprintf(tempdata, "StartTransaction,%d", (tempconnectorId-1)); } //GUID memset(sstr ,0, sizeof(sstr) ); c=0; while (str[4+c] != '\"') { sstr[c] = str[4+c]; c++; } sstr[c] = '\0'; strcpy(guid, sstr); //Idtag loc = strstr(str, "idTag"); memset(sstr ,0, sizeof(sstr) ); c=0; while (loc[3+strlen("idTag")+c] != '\"') { sstr[c] = loc[3+strlen("idTag")+c]; c++; } sstr[c] = '\0'; strcpy((char*)IdtagStr, sstr); //meterStart loc = strstr(str, "meterStart"); c = 0; memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { while (loc[strlen("meterStart")+2+c] != ',') { sstr[c] = loc[strlen("meterStart")+2+c]; c++; } sstr[c] = '\0'; tempmeterStart = atoi(sstr); } //reservationId loc = strstr(str, "reservationId"); c = 0; memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { while (loc[strlen("reservationId")+2+c] != ',') { sstr[c] = loc[strlen("reservationId")+2+c]; c++; } sstr[c] = '\0'; tempreservationId = atoi(sstr); } //timestamp loc = strstr(str, "timestamp"); memset(sstr ,0, sizeof(sstr) ); c=0; while (loc[3+strlen("timestamp")+c] != '\"') { sstr[c] = loc[3+strlen("timestamp")+c]; c++; } sstr[c] = '\0'; strcpy((char*)timestampStr, sstr); if(hashmap_operation(1, guid, key_value) == TRUE) { //DEBUG_INFO("\n 1. sent queue guid=%s\n",guid); } else { hashmap_operation(0, guid, tempdata); FillStartTransaction(tempconnectorId, IdtagStr, tempmeterStart, tempreservationId, timestampStr); //DEBUG_INFO("\n 2. sent queue guid=%s\n",guid); } } //*********************End: StartTransaction***************************/ //****************transactionId********************/ c=0; loc = strstr(str, "transactionId"); memset(sstr ,0, sizeof(sstr) ); if(loc != NULL) { while ((loc[strlen("transactionId")+2+c] != '}') && (loc[strlen("transactionId")+2+c] != ',')) { sstr[c] = loc[strlen("transactionId")+2+c]; c++; } sstr[c] = '\0'; temptransactionId = atoi(sstr); gettransactionId = GetTransactionId(tempconnectorId, IdtagStr); if((gettransactionId != 0)&&(temptransactionId != gettransactionId)) { strncpy(strcomposite,str, (loc-str)+2+strlen("transactionId")); sprintf(strcomposite+((loc-str)+2+strlen("transactionId")),"%d",gettransactionId); strcat(strcomposite, loc+strlen("transactionId")+2+c); LWS_Send(strcomposite); } else { LWS_Send(str); } if((IsStopTransaction == TRUE)&&(gettransactionId != 0)) { SetTransactionIdZero(gettransactionId); } } else { LWS_Send(str); } result = TRUE; } else { result = FALSE; } fclose(fp); return result; } // void* processTransactionQueue(void* data) { char frontUUID[100] ={0}; char frontData[1200/*1024*4*/] ={0}; int queueNotEmpty = 0; while(1) { if(FirstHeartBeatResponse() == 1) { memset(frontUUID, 0, sizeof(frontUUID)); memset(frontData, 0, sizeof(frontData)); queueNotEmpty = 0; queueNotEmpty = queue_operation(1,frontUUID, frontData);//showfront(frontUUID, frontData); ---> remove temporally if((queueNotEmpty == 1) && (GetOcppConnStatus() == 1)) { if((OfflineTransaction == 1) && (OfflineTransactionQueueNum != 0)) { TransactionQueueInterval = 10;//10;//2; sendbuffer = 1; OfflineTransactionQueueNum = OfflineTransactionQueueNum - 1; if(OfflineTransactionQueueNum == 0) { OfflineTransaction = 0; } DEBUG_INFO(" Offline Transaction , online sent queue .... \n"); sleep(TransactionQueueInterval); } else { DEBUG_INFO(" online sent queue .... \n"); //OfflineTransaction = 0; if(TransactionMessageResend < TransactionMessageAttemptsGet()) // { //DEBUG_INFO("processTransactionQueue queue is not empty!\n"); TransactionQueueInterval= TransactionMessageRetryIntervalGet()* TransactionMessageResend; //DEBUG_INFO("TransactionQueueInterval =%d\n",TransactionQueueInterval); sendbuffer = 1; TransactionMessageResend = TransactionMessageResend + 1; //DEBUG_INFO("After ADD,TransactionMessageResend=%d\n",TransactionMessageResend); sleep(TransactionQueueInterval); } else { queue_operation(2,"",""); //// delete item TransactionQueueInterval = 0; TransactionMessageResend = 1; sleep(TransactionQueueInterval); } } } else { TransactionQueueInterval = 0;//10; sleep(TransactionQueueInterval); } } if(GetOcppConnStatus() == 0) { //DEBUG_INFO(" Offline .... \n"); if(queueNotEmpty == 1) { OfflineTransaction = 1; DEBUG_INFO(" Offline Transaction .... \n"); } } usleep(5000); } pthread_exit(NULL); // return 0; } void CheckTransactionPacket(char *uuid) { char frontUUID[100]={0}; char frontData[1200]={0}; int queueNotEmpty = 0; int cmpResult = 0; //queue_operation(0,"","");//showqueue(); ---> remove temporally queueNotEmpty = queue_operation(1,frontUUID, frontData);//showfront(frontUUID, frontData); ---> remove temporally if(queueNotEmpty == 1) { cmpResult = strcmp(frontUUID, uuid); if (cmpResult == 0) { DEBUG_INFO("TransactionPacket Compare All right!\n"); //DEBUG_INFO("frontUUID=%s\n",frontUUID); //DEBUG_INFO("uuid=%s\n",uuid); queue_operation(2,"","");//delq(); ---> remove temporally TransactionQueueInterval = 0; TransactionMessageResend = 1; } } } /* type: 0 (showqueue ); type: 1(showfront); type: 2(delq) type: 3 (sentqueue) type: 4 (addq) type: 5(store queue to /Storage/OCPP/ )*/ int queue_operation(int type, char *frontUUID, char *frontData) { pthread_mutex_unlock(&lock_sentData); pthread_mutex_lock(&lock_sentData); int result=0; if(type == 0) // show items in queue result = showqueue(); else if(type == 1) // show first item result = showfront(frontUUID, frontData); else if(type == 2) // delete item result = delq(); else if(type == 3) // sent items in queue result = sentqueue(); else if(type == 4) // add items to the queue result = addq(frontUUID, frontData); pthread_mutex_unlock(&lock_sentData); return result; } char * strchr(const char *p, int ch) { char c; c = ch; for (;; ++p) { if (*p == c) return ((char *)p); if (*p == '\0') return (NULL); } /* NOTREACHED */ return NULL; } int removeMessageSentFile(void) { char rmFileCmd[100]={0}; struct stat stats; // stat("/Storage/OCPP", &stats); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { DEBUG_INFO("\n directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); if((access("/Storage/OCPP/MessageSent",F_OK))!=-1) { DEBUG_INFO("MessageSent file exist.\n"); sprintf(rmFileCmd,"rm -f %s","/Storage/OCPP/MessageSent"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); return 0; } void work(char s[]) //删除首尾空格 {int i,j; for(i=0;s[i]==' ';i++); //找到开头第一个非空格 for(j=0;s[i];)s[j++]=s[i++]; //删除开头空格 for(i--;s[i]==' ';i--)s[i]='\0'; //删除末尾空格 } static int changeChageWebSocketPingInterval = FALSE; void ChageWebSocketPingInterval(int WebSocketPingInterval) { changeChageWebSocketPingInterval = TRUE; } #define SystemLogMessage //================================================ // Main process //================================================ int main(void) { char rmFileCmd[100]={0}; struct stat stats; pthread_t t; //pthread_t pid; #ifdef SystemLogMessage DEBUG_INFO("Initialization...\n"); #endif if(ProcessShareMemory()== FAIL) { return FAIL; } //Create OCPP dir stat("/Storage/OCPP", &stats); // Check for directory existence if (S_ISDIR(stats.st_mode) == 1) { //DEBUG_INFO("\n OCPP directory exist \n"); } else { DEBUG_INFO("\n OCPP directory not exist, create dir \n"); sprintf(rmFileCmd,"mkdir -p %s","/Storage/OCPP"); system(rmFileCmd); } memset(rmFileCmd, 0, sizeof rmFileCmd); //Create Process: Resend Transaction pthread_create(&t, NULL, processTransactionQueue, NULL); // sqlite3_config(SQLITE_CONFIG_URI,1); if(sqlite3_open("file:/Storage/OCPP/charger.db", &db)) { #ifdef Debug DEBUG_INFO( "Can't open database: %s\n", sqlite3_errmsg(db)); #endif sqlite3_close( db ); exit(0); } else { #ifdef Debug DEBUG_INFO( "Opened database successfully\n"); #endif } //Create Table log buffer int rc =sqlite3_exec(db, createsql, 0, 0, &errMsg); if (SQLITE_OK != rc) { #ifdef Debug DEBUG_INFO( "Create log buffer table error message: %s\n", errMsg); #endif return 0; } else { #ifdef Debug DEBUG_INFO( "Opened log buffer table successfully\n"); #endif } // Create Table OcppAuthCache rc =sqlite3_exec(db, sqlOcppAuthCache, 0, 0, &errMsg); if (SQLITE_OK != rc) { #ifdef Debug DEBUG_INFO( "Create OcppAuthCache error message: %s\n", errMsg); #endif return 0; } else { #ifdef Debug DEBUG_INFO( "Opened OcppAuthCache table successfully\n"); #endif } // Create Table OcppAuthLocal rc =sqlite3_exec(db, sqlOcppAuthLocal, 0, 0, &errMsg); if (SQLITE_OK != rc) { #ifdef Debug DEBUG_INFO( "Create Table OcppAuthLocal error %s\n",errMsg); #endif return 0; } else { #ifdef Debug DEBUG_INFO( "Opened OcppAuthLocal table successfully\n"); #endif } initialConfigurationTable(); removeMessageSentFile(); //OCPP_get_TableAuthlocalAllData(); for(;;) { while(ConnectionEstablished==0) { SetOcppConnStatus(FALSE); if((time((time_t*)NULL)-startTime.connect)>=60) { #ifdef Debug DEBUG_INFO("Execute ConnectWsServer\n"); #endif //ConnectWsServer(); pthread_create(&pid, NULL, ConnectWsServer, NULL); startTime.connect=time((time_t*)NULL); } // Check System Value, process offline Transaction CheckSystemValue(); lws_service(context, 10000);//timeout_ms } if(( (BootNotificationInterval != 0 && ((time((time_t*)NULL)-startTime.bootNotification)>=BootNotificationInterval) ) || ((time((time_t*)NULL)-startTime.bootNotification)>=defaultWaitingTime) ) && ((server_sign == FALSE)/*|| (server_pending == TRUE)*/)) { //hashmapForMessageNew(); sendBootNotificationRequest(); startTime.bootNotification=time((time_t*)NULL); } if(server_sign == TRUE) { if(sendbuffer == 1) { queue_operation(3, "", "");//sentqueue() sendbuffer = 0; } SetOcppConnStatus(TRUE); // Check System Value CheckSystemValue(); if(GetHeartBeatWithNOResponse() >= 3) { lws_context_destroy(context); ConnectionEstablished=0; context = NULL; SetHeartBeatWithNOResponse(); } if(changeChageWebSocketPingInterval == TRUE) { changeChageWebSocketPingInterval = FALSE; lws_context_destroy(context); ConnectionEstablished=0; context = NULL; } } lws_service(context, 100);//timeout_ms } pthread_join(t, NULL); // //hashmapForMessageFree(); return FAIL; }