Explorar el Código

Merge branch 'master' into DD360Tcci

Simon Xue hace 2 años
padre
commit
043f511e2c

+ 775 - 127
EVSE/Modularization/DcMeter/Module_DcMeter.c

@@ -1,15 +1,23 @@
 /*
- * Module_DcMeter.c
+ * Module_DcMeter.c 
  *
- *  Created on: 2021/5/31
+ *  Created on: 2021/5/31 
  *      Author: foluswen
  */
 #include "Module_DcMeter.h"
 #include "meterComm.h"
 #include "Module_RatedCurrent.h"
 
+#define _DEBUG_ 1
+
+#if _DEBUG_
+#define PR(...) printf(__VA_ARGS__)
+#else
+#define PR(...)
+#endif
+
 /**
- * Initial share memory
+ * Initial share memory  
  * @return
  */
 int InitShareMemory()
@@ -64,18 +72,32 @@ int InitShareMemory()
     return result;
 }
 
+
+
+
+
+
 //==========================================
 // Main loop
 //==========================================
 int main(void)
 {
+	printf("main start\n");
 	ParsingRatedCur modelnameInfo = {0};
 	Meter_Info meter_info[4];
-	uint8_t pollingIndex = 0;
-	uint8_t	meterIndex = 0;
+	Meter_Status_Info meter_status_info[4];
+	Meter_transaction_Action meter_read_transaction_record[4];
+	Meter_transaction_Action meter_transaction_Action[4];
+	Meter_transaction_Result meter_transaction_Result[4];
 	uint8_t failCount[4];
+	uint8_t startTransactionFailCount[4];
+	uint8_t stopTransactionFailCount[4];
+	uint8_t getTransactionOcmfFailCount[4];
+	uint8_t meterSyncTimeFailCount[4];
+	uint16_t RecordLogTimerCount = 0;
 
 #ifndef DEBUG_STANDALONG
+
 	// Initialize share memory
 	if(InitShareMemory() == FAIL)
 	{
@@ -88,11 +110,19 @@ int main(void)
 		sleep(5);
 		return -1;
 	}
+	
+	/*
+	for(;;)
+	{
+		printf("ActionCmd : %d \n", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[0].ActionCmd);
+		sleep(1);
+	}
+	*/
 
 	RatedCurrentParsing((char*)ShmSysConfigAndInfo->SysConfig.ModelName, &modelnameInfo);
 
 #else
-	modelnameInfo.GetGunCount = 4;
+	modelnameInfo.GetGunCount = 1;
 
 #endif//DEBUG_STANDALONG
 
@@ -105,163 +135,781 @@ int main(void)
 	meterInitialize(METER_MODEL_LEM_L18005A);
 	
 	
+	//DEBUG_INFO("modelnameInfo.GetGunCount : %d \n", modelnameInfo.GetGunCount);
+	#ifndef DEBUG_STANDALONG
+	//if Power up and DC meter is runing (need stop)
+	for(uint8_t gun_index=0;gun_index<modelnameInfo.GetGunCount;gun_index++){
+		
+		readMeterStatusInfo(gun_index,&meter_status_info[gun_index]);
+		if(meter_status_info[gun_index].MeterStatusFlag.bits.transactionIsOnGoing == 1)
+		{
+			ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].ActionCmd = 2;
+			readMeterLegal(gun_index,&meter_transaction_Action[gun_index]);
+			strcpy((char*)ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.transactionId,(char*)meter_transaction_Action[gun_index].head.transactionId);
+		}
+	}
+	
+		printf("shm ");
+	DEBUG_INFO("shm ");
+	#endif
+	
+	printf("modelnameInfo.GetGunCount : %d \n", modelnameInfo.GetGunCount);
 	DEBUG_INFO("modelnameInfo.GetGunCount : %d \n", modelnameInfo.GetGunCount);
+	
 
+	
+	//uint8_t gun_index=0;
+	//meter_transaction_Action[0].ActionCmd = 2;
+	//strcpy(meter_transaction_Action[0].head.transactionId, "ddd5002");	
+
+	//strcpy(ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[0].head.transactionId, "12345678" );
+	//ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[0].ActionCmd = 1;
+	
 	// Main loop
 	for(;;)
 	{
 		for(uint8_t gun_index=0;gun_index<modelnameInfo.GetGunCount;gun_index++)
 		{
-			if(gun_index == 0)
-				meterIndex = 0;
-			meterIndex = gun_index;
 
 			if(modelnameInfo.ParsingInfo[gun_index].GunType != Gun_Type_AC)
 			{
-				meterApiAssign(meterIndex);
-				
-				for(pollingIndex=0;pollingIndex<4;pollingIndex++)
-				{
-					switch(pollingIndex)
+					#ifndef DEBUG_STANDALONG
+					meter_transaction_Action[gun_index].ActionCmd = ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].ActionCmd;
+					meter_read_transaction_record[gun_index].ActionCmd = ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].ActionCmd;
+					meter_read_transaction_record[gun_index].OcmfInfoReady = ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].OcmfInfoReady;
+					meter_transaction_Action[gun_index].OcmfInfoReady = ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].OcmfInfoReady;
+					#endif
+					
+					
+					
+					PR("for index : %d \n", gun_index);
+					//if Transaction Cmd				
+					if(meter_transaction_Action[gun_index].ActionCmd || meter_read_transaction_record[gun_index].ActionCmd)
 					{
-						case 0:
-							if(readCurrent(&meter_info[meterIndex]) != FAIL)
-							{
-								#ifndef DEBUG_STANDALONG
-								/*
-								 *	TODO:
-								 *		1. Synchronize data to share memory
-								 */
-								 
-								 ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentCurrent = meter_info[meterIndex].presentCurrent;
-								 #ifdef DEBUG_SHAREMEM_LOG
-								 DEBUG_INFO("shm Output current %d : %.3f A\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentCurrent);
-								 #endif
-								 
-								#else
-								DEBUG_INFO("Output current %d : %.3f A\n", meterIndex, meter_info[meterIndex].presentCurrent);
-								#endif//DEBUG_STANDALONG
-								//pollingIndex++;
-								failCount[meterIndex] = 0;
-							}
-							else
+							//if start Transaction record
+							if(meter_transaction_Action[gun_index].ActionCmd == 1)
 							{
-								if(failCount[meterIndex] < 10)
-									failCount[meterIndex]++;
+									PR("<<<<<<<<<  meter_sync_time : %d  >>>>>>>>>\n", gun_index);
+									//first sync sys time
+									if(configure_meter_time(gun_index) != FAIL)
+									{
+											
+											//update transaction content
+											#ifndef DEBUG_STANDALONG											
+											strcpy((char*)meter_transaction_Action[gun_index].head.evseId, (char*)ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.evseId);
+											strcpy((char*)meter_transaction_Action[gun_index].head.transactionId,  (char*)ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.transactionId);
+											strcpy((char*)meter_transaction_Action[gun_index].head.clientId,  (char*)ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.clientId);
+											meter_transaction_Action[gun_index].head.tariffId =  ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.tariffId;
+											meter_transaction_Action[gun_index].head.cableId = ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.cableId;
+											strcpy((char*)meter_transaction_Action[gun_index].head.userData,  (char*)ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].head.userData);
+											#else
+											strcpy(meter_transaction_Action[gun_index].head.evseId, "evse45");
+											strcpy(meter_transaction_Action[gun_index].head.transactionId, "ddd5002");
+											strcpy(meter_transaction_Action[gun_index].head.clientId, "client1");
+											meter_transaction_Action[gun_index].head.tariffId = 2;
+											meter_transaction_Action[gun_index].head.cableId =3;
+											strcpy(meter_transaction_Action[gun_index].head.userData, "Phihong12");
+											#endif
+
+											PR(" ****** evseId : %s\n",meter_transaction_Action[gun_index].head.evseId);	
+											PR(" ****** transactionId : %s\n",meter_transaction_Action[gun_index].head.transactionId);	
+											PR(" ****** clientId : %s\n",meter_transaction_Action[gun_index].head.clientId);	
+											PR(" ****** tariffId : %d\n",meter_transaction_Action[gun_index].head.tariffId);
+											PR(" ****** clientId : %d\n",meter_transaction_Action[gun_index].head.cableId);
+											PR(" ****** userData : %s\n",meter_transaction_Action[gun_index].head.userData);
+																						
+																						
+											meterSyncTimeFailCount[gun_index] = 0;
+											#ifndef DEBUG_STANDALONG
+											ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterSyncTimeError = OFF;
+											#endif 
+											
+											PR("<<<<<<<<<  meter_transaction_Action : %d  >>>>>>>>>\n", gun_index);
+											//start Transaction
+											if(startMeterTransaction(gun_index,&meter_transaction_Action[gun_index]) != FAIL)
+											{
+														#ifndef DEBUG_STANDALONG
+														/*
+														 *	TODO:
+														 *		1. Synchronize data to share memory
+														 */
+														//clear ocmf value
+														strcpy((char *) meter_transaction_Action[gun_index].transactionOCMF, "");
+														sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].transactionOCMF,
+															"%s",meter_transaction_Action[gun_index].transactionOCMF);
+															
+														 #ifdef DEBUG_SHAREMEM_TRANSACTION_START_LOG
+
+														 #endif
+														 
+														#else
+
+														#endif//DEBUG_STANDALONG
+														
+														//clear OCMF info flag
+														meter_transaction_Action[gun_index].OcmfInfoReady = 0;
+							
+														failCount[gun_index] = 0;
+														startTransactionFailCount[gun_index] = 0;														
+														#ifndef DEBUG_STANDALONG
+														ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertStartTransactionError = OFF;
+														#endif
+
+														//clear need action cmd
+														meter_transaction_Action[gun_index].ActionCmd = 0;
+														
+											}
+											else
+											{
+														if(failCount[gun_index] < 5){
+															failCount[gun_index]++;
+														}
+														
+														if(startTransactionFailCount[gun_index] < 5){
+															startTransactionFailCount[gun_index]++;
+														}else{
+															meter_transaction_Action[gun_index].ActionCmd = 0;
+															#ifndef DEBUG_STANDALONG
+															ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertStartTransactionError = ON;
+															#endif
+														}
+											}
+										}
+										else
+										{
+												if(failCount[gun_index] < 5){
+													failCount[gun_index]++;
+												}
+												
+												if(meterSyncTimeFailCount[gun_index] < 5){
+													meterSyncTimeFailCount[gun_index]++;
+												}else{
+													meter_transaction_Action[gun_index].ActionCmd = 0;
+													#ifndef DEBUG_STANDALONG
+													ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterSyncTimeError = ON;
+													#endif 
+														
+												}
+										}							
 							}
-							break;
-						case 1:
-							if(readVoltage(&meter_info[meterIndex]) != FAIL)
+
+							//if stop Transaction and record
+							if(meter_transaction_Action[gun_index].ActionCmd == 2)
 							{
-								#ifndef DEBUG_STANDALONG
-								/*
-								 *	TODO:
-								 *		1. Synchronize data to share memory
-								 */
-								 
-								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presetVoltage = meter_info[meterIndex].presetVoltage;
-								#ifdef DEBUG_SHAREMEM_LOG
-								DEBUG_INFO("shm Output voltage %d : %.3f V\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presetVoltage);
-								#endif
-								#else
-								DEBUG_INFO("Output voltage %d : %.3f V\n", meterIndex, meter_info[meterIndex].presetVoltage);
-								#endif//DEBUG_STANDALONG
-								//pollingIndex++;
-								failCount[meterIndex] = 0;
+									PR("<<<<<<<<<  stopMeterTransaction : %d >>>>>>>>>\n", gun_index);
+									if(stopMeterTransaction(gun_index,&meter_transaction_Action[gun_index],&meter_transaction_Result[gun_index]) != FAIL)
+									{
+												#ifndef DEBUG_STANDALONG
+												/*
+												 *	TODO:
+												 *		1. Synchronize data to share memory
+												 */
+												 
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].paginationCounter = 
+												 meter_transaction_Result[gun_index].paginationCounter;
+												 
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.transactionId,
+												"%s",meter_transaction_Result[gun_index].head.transactionId);										 
+												 
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.evseId,
+												"%s",meter_transaction_Result[gun_index].head.evseId);										 
+
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.clientId,
+												"%s",meter_transaction_Result[gun_index].head.clientId);										 
+												 
+												ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.tariffId = 
+												meter_transaction_Result[gun_index].head.tariffId;	
+												
+												ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.cableId = 
+												meter_transaction_Result[gun_index].head.cableId;	
+
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.userData,
+												"%s",meter_transaction_Result[gun_index].head.userData);										 
+												 
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].timestampStart,
+												"%s",meter_transaction_Result[gun_index].timestampStart);
+												
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].timestampStop,
+												"%s",meter_transaction_Result[gun_index].timestampStop);
+												
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].transactionDuration = 
+												 meter_transaction_Result[gun_index].transactionDuration;
+												
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].transactionStatus = 
+												 meter_transaction_Result[gun_index].transactionStatus;
+												
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyUnit,
+												"%s",meter_transaction_Result[gun_index].energyUnit);
+												
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyImport = 
+												 meter_transaction_Result[gun_index].energyImport;
+
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyImportTotalStart = 
+												 meter_transaction_Result[gun_index].energyImportTotalStart;										
+
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyImportTotalStop = 
+												 meter_transaction_Result[gun_index].energyImportTotalStop;
+
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyExport = 
+												 meter_transaction_Result[gun_index].energyExport;
+												 
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyExportTotalStart = 
+												 meter_transaction_Result[gun_index].energyExportTotalStart;
+
+												 ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyExportTotalStop = 
+												 meter_transaction_Result[gun_index].energyExportTotalStop;
+												 
+												sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].signature,
+												"%s",meter_transaction_Result[gun_index].signature);										 
+												 
+			
+														#ifdef DEBUG_SHAREMEM_TRANSACTION_RESULT_LOG
+														DEBUG_INFO(" ================================= ShareMem Transaction Result : %d ================================= \n",gun_index);
+														DEBUG_INFO(" %-26s : %d\n", "paginationCounter", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].paginationCounter);										
+														DEBUG_INFO(" %-26s : %s\n", "transactionId", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.transactionId);										
+														DEBUG_INFO(" %-26s : %s\n", "evseId", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.evseId);										
+														DEBUG_INFO(" %-26s : %s\n", "clientId", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.clientId);										
+														DEBUG_INFO(" %-26s : %d\n", "tariffId", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.tariffId);
+														DEBUG_INFO(" %-26s : %d\n", "cableId", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.cableId);
+														DEBUG_INFO(" %-26s : %s\n", "userData", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].head.userData);										
+														DEBUG_INFO(" %-26s : %s\n", "timestampStart", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].timestampStart);
+														DEBUG_INFO(" %-26s : %s\n", "timestampStop", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].timestampStop);
+														DEBUG_INFO(" %-26s : %d\n", "transactionDuration", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].transactionDuration);
+														DEBUG_INFO(" %-26s : %d\n", "transactionStatus", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].transactionStatus);
+														DEBUG_INFO(" %-26s : %s\n", "energyUnit", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyUnit);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyImport", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyImport);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyImportTotalStart", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyImportTotalStart);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyImportTotalStop", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyImportTotalStop);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyExport", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyExport);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyExportTotalStart", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyExportTotalStart);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyExportTotalStop", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].energyExportTotalStop);
+														DEBUG_INFO(" %-26s : %s\n\n\n\n\n\n", "signature", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionResult[gun_index].signature);												
+														#endif
+												 
+												#else
+														#ifdef DEBUG_STANDALONE_TRANSACTION_RESULT_LOG
+														DEBUG_INFO(" ================================= Standalone Transaction Result : %d ================================= \n",gun_index);
+														DEBUG_INFO(" %-26s : %d\n", "paginationCounter", meter_transaction_Result[gun_index].paginationCounter);										
+														DEBUG_INFO(" %-26s : %s\n", "transactionId", meter_transaction_Result[gun_index].head.transactionId);										
+														DEBUG_INFO(" %-26s : %s\n", "evseId", meter_transaction_Result[gun_index].head.evseId);										
+														DEBUG_INFO(" %-26s : %s\n", "clientId", meter_transaction_Result[gun_index].head.clientId);										
+														DEBUG_INFO(" %-26s : %d\n", "tariffId", meter_transaction_Result[gun_index].head.tariffId);
+														DEBUG_INFO(" %-26s : %d\n", "cableId", meter_transaction_Result[gun_index].head.cableId);
+														DEBUG_INFO(" %-26s : %s\n", "userData", meter_transaction_Result[gun_index].head.userData);										
+														DEBUG_INFO(" %-26s : %s\n", "timestampStart", meter_transaction_Result[gun_index].timestampStart);
+														DEBUG_INFO(" %-26s : %s\n", "timestampStop", meter_transaction_Result[gun_index].timestampStop);
+														DEBUG_INFO(" %-26s : %d\n", "transactionDuration", meter_transaction_Result[gun_index].transactionDuration);
+														DEBUG_INFO(" %-26s : %d\n", "transactionStatus", meter_transaction_Result[gun_index].transactionStatus);
+														DEBUG_INFO(" %-26s : %s\n", "energyUnit", meter_transaction_Result[gun_index].energyUnit);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyImport", meter_transaction_Result[gun_index].energyImport);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyImportTotalStart", meter_transaction_Result[gun_index].energyImportTotalStart);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyImportTotalStop", meter_transaction_Result[gun_index].energyImportTotalStop);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyExport", meter_transaction_Result[gun_index].energyExport);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyExportTotalStart", meter_transaction_Result[gun_index].energyExportTotalStart);
+														DEBUG_INFO(" %-26s : %.3f\n", "energyExportTotalStop", gun_index, meter_transaction_Result[gun_index].energyExportTotalStop);
+														DEBUG_INFO(" %-26s : %s\n\n\n\n\n\n", "signature", meter_transaction_Result[gun_index].signature);
+														#endif
+												#endif//DEBUG_STANDALONG
+					
+												failCount[gun_index] = 0;
+												stopTransactionFailCount[gun_index] = 0;
+												#ifndef DEBUG_STANDALONG
+												ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertStopTransactionError = OFF;
+												#endif 
+													
+												PR("<<<<<<<<<  Get Transaction OCMF : %d >>>>>>>>>\n", gun_index);
+												//auto OCMF
+												if(readMeterTransactionOCMF(gun_index,&meter_transaction_Action[gun_index]) != FAIL)
+												{
+															#ifndef DEBUG_STANDALONG
+															/*
+															 *	TODO:
+															 *		1. Synchronize data to share memory
+															 */
+															 
+														
+															sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].transactionOCMF,
+															"%s",meter_transaction_Action[gun_index].transactionOCMF);
+															
+															PR("OCMF : %s , %s\n", ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].transactionOCMF,
+																				   meter_transaction_Action[gun_index].transactionOCMF);
+															
+																	#ifdef DEBUG_SHAREMEM_TRANSACTION_RESULT_LOG
+																	DEBUG_INFO("shm transactionOCMF %d : %s\n", gun_index, ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].transactionOCMF);															
+																	#endif
+															 
+															#else
+															
+																PR("OCMF : %s\n",meter_transaction_Action[gun_index].transactionOCMF);
+																				   
+																	#ifdef DEBUG_STANDALONE_TRANSACTION_RESULT_LOG
+																	DEBUG_INFO("transactionOCMF %d : %s\n", gun_index, meter_transaction_Action[gun_index].transactionOCMF);
+																	#endif													
+															#endif//DEBUG_STANDALONG	
+															
+															meter_transaction_Action[gun_index].OcmfInfoReady = 1;
+					
+															failCount[gun_index] = 0;
+															getTransactionOcmfFailCount[gun_index] = 0;
+															meter_transaction_Action[gun_index].ActionCmd = 0;
+															#ifndef DEBUG_STANDALONG
+															ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertGetTransactionOcmfError = OFF;
+															#endif 
+												}
+												else
+												{
+													
+															meter_transaction_Action[gun_index].OcmfInfoReady = 0;
+															
+															if(failCount[gun_index] < 5){
+																failCount[gun_index]++;
+															}
+															
+															if(getTransactionOcmfFailCount[gun_index] < 5){
+																getTransactionOcmfFailCount[gun_index]++;
+															}else{
+																meter_transaction_Action[gun_index].ActionCmd = 0;
+																#ifndef DEBUG_STANDALONG
+																ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertGetTransactionOcmfError = ON;
+																#endif 																	
+															}
+												}				
+									}
+									else
+									{
+												if(failCount[gun_index] < 5){
+													failCount[gun_index]++;
+												}
+												
+												if(stopTransactionFailCount[gun_index] < 5){
+													stopTransactionFailCount[gun_index]++;
+												}else{
+													meter_transaction_Action[gun_index].ActionCmd = 0;
+													#ifndef DEBUG_STANDALONG
+													ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertStopTransactionError = ON;
+													#endif 
+														
+												}
+									}
 							}
-							else
+
+
+							//if stop Transaction and record
+							if(meter_read_transaction_record[gun_index].ActionCmd == 1)
 							{
-								if(failCount[meterIndex] < 10)
-									failCount[meterIndex]++;
+												meter_read_transaction_record[gun_index].OcmfInfoReady = 0;
+												
+												#ifndef DEBUG_STANDALONG
+												strcpy((char*)meter_read_transaction_record[gun_index].head.transactionId,  (char*)ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].head.transactionId);
+												#endif
+												
+												PR("<<<<<<<<<  Get Record Transaction OCMF : %d - ID : %s>>>>>>>>>\n", gun_index,meter_read_transaction_record[gun_index].head.transactionId);
+												//auto OCMF
+												if(readMeterTransactionOCMF(gun_index,&meter_read_transaction_record[gun_index]) != FAIL)
+												{
+															#ifndef DEBUG_STANDALONG
+															/*
+															 *	TODO:
+															 *		1. Synchronize data to share memory
+															 */
+															 
+														
+															sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].transactionOCMF,
+															"%s",meter_read_transaction_record[gun_index].transactionOCMF);
+															
+															PR("OCMF : %s ,%s\n", ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].transactionOCMF,
+																	      	   	  meter_read_transaction_record[gun_index].transactionOCMF);
+
+															
+																	#ifdef DEBUG_SHAREMEM_TRANSACTION_RESULT_LOG
+																	DEBUG_INFO("shm transactionOCMF %d : %s\n", gun_index, ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].transactionOCMF);															
+																	#endif
+																	 
+																	#else
+																			#ifdef DEBUG_STANDALONE_TRANSACTION_RESULT_LOG
+																			DEBUG_INFO("transactionOCMF %d : %s\n", gun_index, meter_read_transaction_record[gun_index].transactionOCMF);
+																			#endif													
+																	#endif//DEBUG_STANDALONG	
+																	
+																	meter_read_transaction_record[gun_index].OcmfInfoReady = 1;
+							
+																	failCount[gun_index] = 0;
+																	getTransactionOcmfFailCount[gun_index] = 0;
+																	meter_read_transaction_record[gun_index].ActionCmd = 0;
+																	#ifndef DEBUG_STANDALONG
+																	ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertGetTransactionOcmfError = OFF;
+																	#endif 
+												}
+												else
+												{
+													
+															meter_read_transaction_record[gun_index].OcmfInfoReady = 0;
+															
+															if(failCount[gun_index] < 5){
+																failCount[gun_index]++;
+															}
+															
+															if(getTransactionOcmfFailCount[gun_index] < 5){
+																getTransactionOcmfFailCount[gun_index]++;
+															}else{
+																meter_read_transaction_record[gun_index].ActionCmd = 0;
+																getTransactionOcmfFailCount[gun_index] = 0;
+																#ifndef DEBUG_STANDALONG
+																meter_read_transaction_record[gun_index].OcmfInfoReady = 2;
+																//ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MetertGetTransactionOcmfError = ON;
+																#endif 																	
+															}
+												}	
+
+
+								
 							}
-							break;
-						case 2:
-							if(readPower(&meter_info[meterIndex]) != FAIL)
+														
+							#ifndef DEBUG_STANDALONG
+							ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].ActionCmd = meter_read_transaction_record[gun_index].ActionCmd;
+							ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].ActionCmd = meter_transaction_Action[gun_index].ActionCmd;
+							ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].OcmfInfoReady = meter_read_transaction_record[gun_index].OcmfInfoReady;
+							ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].OcmfInfoReady = meter_transaction_Action[gun_index].OcmfInfoReady;
+							#endif
+						
+					}					
+					else
+					{		
+
+							if(readMeterLivemeasure(gun_index,&meter_info[gun_index]) != FAIL)
 							{
-								#ifndef DEBUG_STANDALONG
-								/*
-								 *	TODO:
-								 *		1. Synchronize data to share memory
-								 */
-								 
-								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentPower = meter_info[meterIndex].presentPower;
-								#ifdef DEBUG_SHAREMEM_LOG
-								DEBUG_INFO("shm Output power %d : %.3f kw\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].presentPower);
-								#endif
-								#else
-								DEBUG_INFO("Output power %d : %.3f kw\n", meterIndex, meter_info[meterIndex].presentPower);
-								#endif//DEBUG_STANDALONG
-								//pollingIndex++;
-								failCount[meterIndex] = 0;
+										#ifndef DEBUG_STANDALONG
+										/*
+										 *	TODO:
+										 *		1. Synchronize data to share memory
+										 */
+										ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].presetVoltage = meter_info[gun_index].presetVoltage;
+										ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].presentCurrent = meter_info[gun_index].presentCurrent;
+										ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].presentPower = meter_info[gun_index].presentPower;
+										ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].totlizeImportEnergy = meter_info[gun_index].totlizeImportEnergy;
+										ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].totlizeExportEnergy = meter_info[gun_index].totlizeExportEnergy;
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].timestamp, "%s",meter_info[gun_index].timestamp);
+										 
+											#ifdef DEBUG_SHAREMEM_LIVEMEASURE_LOG
+											//evern 60s record 1s
+											if((RecordLogTimerCount % 60 == 0)
+											{
+											DEBUG_INFO(" ================================= ShareMem Livemeasure : %d ================================= \n",gun_index);
+											DEBUG_INFO(" %-26s : %.3f V\n", "Output voltage", ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].presetVoltage);
+											DEBUG_INFO(" %-26s : %.3f A\n", "Output current", ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].presentCurrent);
+											DEBUG_INFO(" %-26s : %.3f kw\n", "Output power", ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].presentPower);
+											DEBUG_INFO(" %-26s : %.3f kwh\n", "Totalize import energy", ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].totlizeImportEnergy);
+											DEBUG_INFO(" %-26s : %.3f kwh\n", "Totalize export energy", ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].totlizeExportEnergy);
+											DEBUG_INFO(" %-26s : %s\n\n\n\n\n\n", "timestamp", ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].timestamp);
+											}
+											#endif
+										 
+										#else
+										
+											#ifdef DEBUG_STANDALONE_LIVEMEASURE_LOG
+											DEBUG_INFO(" ================================= Standalone Livemeasure : %d ================================= \n",gun_index);
+											DEBUG_INFO(" %-26s : %.3f V\n", "Output voltage", meter_info[gun_index].presetVoltage);
+											DEBUG_INFO(" %-26s : %.3f A\n", "Output current", meter_info[gun_index].presentCurrent);
+											DEBUG_INFO(" %-26s : %.3f kw\n", "Output power", meter_info[gun_index].presentPower);
+											DEBUG_INFO(" %-26s : %.3f kwh\n", "Totalize import energy", meter_info[gun_index].totlizeImportEnergy);   
+											DEBUG_INFO(" %-26s : %.3f kwh\n", "Totalize export energy", meter_info[gun_index].totlizeExportEnergy);
+											DEBUG_INFO(" %-26s : %s\n\n\n\n\n\n", "timestamp", meter_info[gun_index].timestamp);
+											#endif
+											
+										#endif//DEBUG_STANDALONG
+			
+										failCount[gun_index] = 0;
 							}
 							else
 							{
-								if(failCount[meterIndex] < 10)
-									failCount[meterIndex]++;
+										PR("read Livemeasure fail : %d \n", gun_index);
+										if(failCount[gun_index] < 5)
+											failCount[gun_index]++;
 							}
-							break;
-						case 3:
-							if(readEnergy(&meter_info[meterIndex]) != FAIL)
+
+
+							if(readMeterStatusInfo(gun_index,&meter_status_info[gun_index]) != FAIL)
 							{
-								#ifndef DEBUG_STANDALONG
-								/*
-								 *	TODO:
-								 *		1. Synchronize data to share memory
-								 */
-								 
-								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeImportEnergy = meter_info[meterIndex].totlizeImportEnergy;
-								#ifdef DEBUG_SHAREMEM_LOG
-								DEBUG_INFO("shm Totalize import energy %d : %.3f kwh\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeImportEnergy);
-								#endif
-								ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeExportEnergy = meter_info[meterIndex].totlizeExportEnergy;
-								#ifdef DEBUG_SHAREMEM_LOG
-								DEBUG_INFO("shm Totalize export energy %d : %.3f kwh\n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].totlizeExportEnergy);
-								#endif
-								#else
-								DEBUG_INFO("Totalize import energy %d : %.3f kwh\n", meterIndex, meter_info[meterIndex].totlizeImportEnergy);   
-								DEBUG_INFO("Totalize export energy %d : %.3f kwh\n", meterIndex, meter_info[meterIndex].totlizeExportEnergy);
-								#endif//DEBUG_STANDALONG
-								//pollingIndex++;
-								failCount[meterIndex] = 0;
+										//PR("run readMeterStatusInfo : %d \n", gun_index);
+										#ifndef DEBUG_STANDALONG
+										/*
+										 *	TODO:
+										 *		1. Synchronize data to share memory
+										 */
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].StatusValue = meter_status_info[gun_index].StatusValue;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.muFatalErrorOccured = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.muFatalErrorOccured;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.transactionIsOnGoing = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.transactionIsOnGoing;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.tamperingIsDetected = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.tamperingIsDetected;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.overTemperatureIsDetected = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.overTemperatureIsDetected;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.reversedVoltage = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.reversedVoltage;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.suMeasureFailureOccurred = 
+										meter_status_info[gun_index].MeterStatusFlag.bits.suMeasureFailureOccurred;
+										 								 
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].applicationFirmwareVersion,
+										"%s",meter_status_info[gun_index].applicationFirmwareVersion);
+										  
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].applicationFirmwareAuthTag,
+										"%s",meter_status_info[gun_index].applicationFirmwareAuthTag);
+										 
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].legalFirmwareVersion,
+										"%s",meter_status_info[gun_index].legalFirmwareVersion);
+										
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].legalFirmwareAuthTag,
+										"%s",meter_status_info[gun_index].legalFirmwareAuthTag);
+										 
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].sensorFirmwareVersion,
+										"%s",meter_status_info[gun_index].sensorFirmwareVersion);								
+
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].sensorFirmwareCrc,
+										"%s",meter_status_info[gun_index].sensorFirmwareCrc);
+										
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].ipAddress,
+										"%s",meter_status_info[gun_index].ipAddress);
+										 
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].meterId,
+										"%s",meter_status_info[gun_index].meterId);
+										
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muInitIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.muInitIsFailed;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.suStateIsInvalid = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.suStateIsInvalid;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.versionCheckIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.versionCheckIsFailed;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muRngInitIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.muRngInitIsFailed;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muDataIntegrityIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.muDataIntegrityIsFailed;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muFwIntegrityIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.muFwIntegrityIsFailed;
+																		
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.suIntegrityIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.suIntegrityIsFailed;
+
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.logbookIntegrityIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.logbookIntegrityIsFailed;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.logbookIsFull = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.logbookIsFull;								
+										
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.memoryAccessIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.memoryAccessIsFailed;
+										 
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muStateIsFailed = 
+										meter_status_info[gun_index].MeterErrorFlag.bits.muStateIsFailed;
+										
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].publicKey,
+										"%s",meter_status_info[gun_index].publicKey);
+										 
+										sprintf((char*)&ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].publicKeyOcmf,
+										"%s",meter_status_info[gun_index].publicKeyOcmf);								
+										
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].indexOfLastTransaction = meter_status_info[gun_index].indexOfLastTransaction;
+										ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].numberOfStoredTransactions = meter_status_info[gun_index].numberOfStoredTransactions;							
+
+												#ifdef DEBUG_SHAREMEM_STATUS_INFO_LOG	
+												//evern 60s record 1s
+												if((RecordLogTimerCount % 60 == 0)
+												{
+												DEBUG_INFO(" ================================= ShareMem Status info : %d ================================= \n",gun_index);
+												DEBUG_INFO(" %-26s : %d \n", "status-value",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].StatusValue);
+												DEBUG_INFO(" %-26s : %d \n", "b-suLinkStatusIsOk",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk);
+												DEBUG_INFO(" %-26s : %d \n", "b-muFatalErrorOccured",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.muFatalErrorOccured);
+												DEBUG_INFO(" %-26s : %d \n", "b-transactionIsOnGoing",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.transactionIsOnGoing);
+												DEBUG_INFO(" %-26s : %d \n", "b-tamperingIsDetected",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.tamperingIsDetected);
+												DEBUG_INFO(" %-26s : %d \n", "b-timeSyncStatusIsOk",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk);
+												DEBUG_INFO(" %-26s : %d \n", "b-overTemperatureIsDetected",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.overTemperatureIsDetected);
+												DEBUG_INFO(" %-26s : %d \n", "b-reversedVoltage",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.reversedVoltage);
+												DEBUG_INFO(" %-26s : %d \n", "b-suMeasureFailureOccurred",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.suMeasureFailureOccurred);
+												DEBUG_INFO(" %-26s : %s \n", "applicationFirmwareVersion",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].applicationFirmwareVersion);
+												DEBUG_INFO(" %-26s : %s \n", "applicationFirmwareAuthTag",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].applicationFirmwareAuthTag);
+												DEBUG_INFO(" %-26s : %s \n", "legalFirmwareVersion",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].legalFirmwareVersion);
+												DEBUG_INFO(" %-26s : %s \n", "applicationFirmwareAuthTag",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].legalFirmwareAuthTag);
+												DEBUG_INFO(" %-26s : %s \n", "sensorFirmwareVersion",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].sensorFirmwareVersion);
+												DEBUG_INFO(" %-26s : %s \n", "sensorFirmwareCrc",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].sensorFirmwareCrc);
+												DEBUG_INFO(" %-26s : %s \n", "ipAddress",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].ipAddress);
+												DEBUG_INFO(" %-26s : %s \n", "meterId",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].meterId);
+												DEBUG_INFO(" %-26s : %d \n", "b-muInitIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muInitIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-suStateIsInvalid",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.suStateIsInvalid);
+												DEBUG_INFO(" %-26s : %d \n", "b-versionCheckIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.versionCheckIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muRngInitIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muRngInitIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muDataIntegrityIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muDataIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muFwIntegrityIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muFwIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-suIntegrityIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.suIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-logbookIntegrityIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.logbookIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-logbookIsFull",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.logbookIsFull);
+												DEBUG_INFO(" %-26s : %d \n", "b-memoryAccessIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.memoryAccessIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muStateIsFailed",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterErrorFlag.bits.muStateIsFailed);
+												DEBUG_INFO(" %-26s : %s \n", "publicKey",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].publicKey);
+												DEBUG_INFO(" %-26s : %s \n", "publicKeyOcmf",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].publicKeyOcmf);
+												DEBUG_INFO(" %-26s : %d \n", "indexOfLastTransaction",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].indexOfLastTransaction);
+												DEBUG_INFO(" %-26s : %d \n\n\n\n\n\n", "numberOfStoredTransactions",ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].numberOfStoredTransactions);
+												}
+												#endif
+										 
+										#else
+												#ifdef DEBUG_STANDALONG_STATUS_INFO_LOG	
+												DEBUG_INFO(" =================================  Standalong Status info : %d ================================= \n",gun_index);
+												DEBUG_INFO(" %-26s : %d \n", "status-value",meter_status_info[gun_index].StatusValue);
+												DEBUG_INFO(" %-26s : %d \n", "b-suLinkStatusIsOk",meter_status_info[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk);
+												DEBUG_INFO(" %-26s : %d \n", "b-muFatalErrorOccured",meter_status_info[gun_index].MeterStatusFlag.bits.muFatalErrorOccured);
+												DEBUG_INFO(" %-26s : %d \n", "b-transactionIsOnGoing",meter_status_info[gun_index].MeterStatusFlag.bits.transactionIsOnGoing);
+												DEBUG_INFO(" %-26s : %d \n", "b-tamperingIsDetected",meter_status_info[gun_index].MeterStatusFlag.bits.tamperingIsDetected);
+												DEBUG_INFO(" %-26s : %d \n", "b-timeSyncStatusIsOk",meter_status_info[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk);
+												DEBUG_INFO(" %-26s : %d \n", "b-overTemperatureIsDetected",meter_status_info[gun_index].MeterStatusFlag.bits.overTemperatureIsDetected);
+												DEBUG_INFO(" %-26s : %d \n", "b-reversedVoltage",meter_status_info[gun_index].MeterStatusFlag.bits.reversedVoltage);
+												DEBUG_INFO(" %-26s : %d \n", "b-suMeasureFailureOccurred",meter_status_info[gun_index].MeterStatusFlag.bits.suMeasureFailureOccurred);
+												DEBUG_INFO(" %-26s : %s \n", "applicationFirmwareVersion",meter_status_info[gun_index].applicationFirmwareVersion);
+												DEBUG_INFO(" %-26s : %s \n", "applicationFirmwareAuthTag",meter_status_info[gun_index].applicationFirmwareAuthTag);
+												DEBUG_INFO(" %-26s : %s \n", "legalFirmwareVersion",meter_status_info[gun_index].legalFirmwareVersion);
+												DEBUG_INFO(" %-26s : %s \n", "applicationFirmwareAuthTag",meter_status_info[gun_index].legalFirmwareAuthTag);
+												DEBUG_INFO(" %-26s : %s \n", "sensorFirmwareVersion",meter_status_info[gun_index].sensorFirmwareVersion);
+												DEBUG_INFO(" %-26s : %s \n", "sensorFirmwareCrc",meter_status_info[gun_index].sensorFirmwareCrc);
+												DEBUG_INFO(" %-26s : %s \n", "ipAddress",meter_status_info[gun_index].ipAddress);
+												DEBUG_INFO(" %-26s : %s \n", "meterId",meter_status_info[gun_index].meterId);
+												DEBUG_INFO(" %-26s : %d \n", "b-muInitIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.muInitIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-suStateIsInvalid",meter_status_info[gun_index].MeterErrorFlag.bits.suStateIsInvalid);
+												DEBUG_INFO(" %-26s : %d \n", "b-versionCheckIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.versionCheckIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muRngInitIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.muRngInitIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muDataIntegrityIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.muDataIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-muFwIntegrityIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.muFwIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-suIntegrityIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.suIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-logbookIntegrityIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.logbookIntegrityIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "b-logbookIsFull",meter_status_info[gun_index].MeterErrorFlag.bits.logbookIsFull);
+												DEBUG_INFO(" %-26s : %d \n", "bits-memoryAccessIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.memoryAccessIsFailed);
+												DEBUG_INFO(" %-26s : %d \n", "bits-muStateIsFailed",meter_status_info[gun_index].MeterErrorFlag.bits.muStateIsFailed);
+												DEBUG_INFO(" %-26s : %s \n", "publicKey",meter_status_info[gun_index].publicKey);
+												DEBUG_INFO(" %-26s : %s \n", "publicKeyOcmf",meter_status_info[gun_index].publicKeyOcmf);
+												DEBUG_INFO(" %-26s : %d \n", "indexOfLastTransaction",meter_status_info[gun_index].indexOfLastTransaction);
+												DEBUG_INFO(" %-26s : %d \n\n\n\n\n\n", "numberOfStoredTransactions",meter_status_info[gun_index].numberOfStoredTransactions);
+												#endif
+										#endif//DEBUG_STANDALONG
+
+										//sync meter systime
+										if(meter_status_info[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk == 1 && 
+												meter_status_info[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk == 0)
+										{
+												configure_meter_time(gun_index);											
+										}
+										
+										failCount[gun_index] = 0;
 							}
 							else
 							{
-								if(failCount[meterIndex] < 10)
-									failCount[meterIndex]++;
+										PR("read status fail : %d \n", gun_index);
+										if(failCount[gun_index] < 5)
+											failCount[gun_index]++;
 							}
-							break;
-						default:
-							pollingIndex = 0;
-							break;
 					}
-				}
 
-				//meterIndex++;
-			}
 
-			
-			if(failCount[meterIndex] >= 8)
-			{
-				//if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout)
-				//{
-					DEBUG_ERROR("Meter communication timeout");
-					ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].LinkStatus = 2;
-					ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = ON;
-				//}
+					if(failCount[gun_index] >= 5)
+					{
+							//if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout)
+							//{
+							DEBUG_ERROR("Meter %d communication timeout",gun_index);
+							#ifndef DEBUG_STANDALONG
+							ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].LinkStatus = 3;
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = ON;
+							#else
+							meter_info[gun_index].LinkStatus = 3;
+							#endif
+							//}
+							PR("failconut fail : %d \n", gun_index);
+					}
+					else
+					{
+						
+							if(meter_status_info[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk == 1 && 
+						  	meter_status_info[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk == 1)
+							{
+									meter_info[gun_index].LinkStatus = 2;
+							}else{
+									meter_info[gun_index].LinkStatus = 1;
+							}
+							
+							#ifndef DEBUG_STANDALONG							
+							ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].LinkStatus = meter_info[gun_index].LinkStatus;							
+							ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = OFF;							
+							//linkstatus 1 = los meter slave, 2 is can to be Transaction
+						  if(ShmSysConfigAndInfo->SysInfo.DcMeterInfo[gun_index].LinkStatus == 1)
+							{															
+									ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterSlaveLosLink = ON;										
+							}else{
+									ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterSlaveLosLink = OFF;
+							}	
+							#endif
+							//PR("failconut pass : %d \n", gun_index);
+					}
 			}
-			else
-			{
-				ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].LinkStatus = 1; 
-				ShmStatusCodeData->AlarmCode.AlarmEvents.bits.MeterCommTimeout = OFF;
+				
+			#ifndef DEBUG_STANDALONG
+			DEBUG_INFO("shm Meter %d - LinkStatus %d :  failCount: %d   ActionCmd: %d  OcmpInfoReady: %d\n RecordActionCmd: %d RecordOcmpInfoReady: %d", gun_index, 
+			meter_info[gun_index].LinkStatus,failCount[gun_index] ,
+			ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].ActionCmd ,
+			ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].OcmfInfoReady,
+			ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].ActionCmd ,
+			ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].OcmfInfoReady);
+			PR ("===================   ModelName %s\n", ShmSysConfigAndInfo->SysConfig.ModelName);
+			PR("end : %d  ActionCmd : %d OcmfInfoReady : %d RecordActionCmd: %d RecordOcmpInfoReady: %d \n", gun_index,ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].ActionCmd, 
+			ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].OcmfInfoReady,
+			ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].ActionCmd,
+			ShmSysConfigAndInfo->SysInfo.DcMeterReadTransactionRecord[gun_index].OcmfInfoReady);
+			PR("shm bits-suLinkStatusIsOk %d : %d \n", gun_index,ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk);
+			PR("shm bits-transactionIsOnGoing %d : %d \n", gun_index,ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.transactionIsOnGoing);
+			PR("shm bits-timeSyncStatusIsOk %d : %d \n", gun_index,ShmSysConfigAndInfo->SysInfo.DcMeterStatusInfo[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk);
+			
+			
+			#else
+			DEBUG_INFO("Meter %d - LinkStatus %d :  failCount: %d  ActionCmd: %d  OcmpInfoReady: %d RecordActionCmd: %d RecordOcmpInfoReady: %d\n", gun_index,
+			meter_info[gun_index].LinkStatus,failCount[gun_index] ,
+			meter_transaction_Action[gun_index].ActionCmd ,
+			meter_transaction_Action[gun_index].OcmfInfoReady,
+			meter_read_transaction_record[gun_index].ActionCmd ,
+			meter_read_transaction_record[gun_index].OcmfInfoReady);
+			
+			PR ("===================   STAND ALONE\n");
+			PR("end : %d  ActionCmd : %d OcmfInfoReady : %d RecordActionCmd: %d RecordOcmpInfoReady: %d \n", gun_index,meter_transaction_Action[gun_index].ActionCmd, 
+			meter_transaction_Action[gun_index].OcmfInfoReady,
+			meter_read_transaction_record[gun_index].ActionCmd,
+			meter_read_transaction_record[gun_index].OcmfInfoReady);
+			PR("shm bits-suLinkStatusIsOk %d : %d \n", gun_index,meter_status_info[gun_index].MeterStatusFlag.bits.suLinkStatusIsOk);
+			PR("shm bits-transactionIsOnGoing %d : %d \n", gun_index,meter_status_info[gun_index].MeterStatusFlag.bits.transactionIsOnGoing);
+			PR("shm bits-timeSyncStatusIsOk %d : %d \n", gun_index,meter_status_info[gun_index].MeterStatusFlag.bits.timeSyncStatusIsOk);			
+			
+			#endif
+			
+			usleep(1000000/modelnameInfo.GetGunCount);
+			if(gun_index == modelnameInfo.GetGunCount){
+					RecordLogTimerCount++;
 			}
 			
-			DEBUG_INFO("Meter %d - LinkStatus %d :  failCount: %d \n", meterIndex, ShmSysConfigAndInfo->SysInfo.DcMeterInfo[meterIndex].LinkStatus,failCount[meterIndex]);
-			usleep(200000);
+			//PR("end : %d  ActionCmd : %d \n", gun_index,ShmSysConfigAndInfo->SysInfo.DcMeterTransactionAction[gun_index].ActionCmd);
+			
 		}
 				
 	}
 
-
-
 	return -1;
 }

+ 12 - 0
EVSE/Modularization/DcMeter/Module_DcMeter.h

@@ -40,7 +40,19 @@
 #include 	"SystemLogMessage.h"
 
 //#define	DEBUG_STANDALONG
+//#define ConsloePrintLog
+#ifndef DEBUG_STANDALONG
+//#define DEBUG_STANDALONG_STATUS_INFO_LOG
+//#define DEBUG_STANDALONG_LIVEMEASURE_LOG
+//#define DEBUG_STANDALONG_TRANSACTION_START_LOG
+//#define DEBUG_STANDALONG_TRANSACTION_RESULT_LOG
+#else
 //#define DEBUG_SHAREMEM_LOG
+//#define DEBUG_SHAREMEM_STATUS_INFO_LOG
+//#define DEBUG_SHAREMEM_LIVEMEASURE_LOG
+//#define DEBUG_SHAREMEM_TRANSACTION_START_LOG
+#define DEBUG_SHAREMEM_TRANSACTION_RESULT_LOG
+#endif
 
 #define ARRAY_SIZE(A)				(sizeof(A) / sizeof(A[0]))
 #define PASS						1

+ 63 - 27
EVSE/Modularization/DcMeter/curlApi.c

@@ -42,6 +42,7 @@ struct MemoryStruct
 {
   uint8_t memory[4096];
   size_t size;
+  uint16_t index;
 };
 
 struct MemoryStruct chunk;
@@ -58,11 +59,9 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, voi
 	size_t realsize = size*nmemb;
 	struct MemoryStruct *mem = (struct MemoryStruct *)userp;
 
-	mem->size = realsize;;
-
-	memset(mem->memory, 0x00, ARRAY_SIZE(mem->memory));
-	chunk.size = realsize;
-	memcpy(mem->memory, contents, realsize);
+	mem->size += realsize;;
+	memcpy(mem->memory + mem->index, contents, realsize);
+	mem->index += realsize;
 
 	return realsize;
 }
@@ -82,6 +81,8 @@ int httpGet(uint8_t *url, uint8_t *responseData)
 	curl_global_init(CURL_GLOBAL_ALL);
 	curl = curl_easy_init();
 
+	memset(&chunk, 0x00, sizeof(struct MemoryStruct));
+
 	if(curl)
 	{
 		 curl_easy_setopt(curl, CURLOPT_URL, (char*)url);
@@ -93,10 +94,21 @@ int httpGet(uint8_t *url, uint8_t *responseData)
 		 //curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
 		 //curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password");
 		 curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 2500L);
+		 struct curl_slist *headers = NULL;
+		 headers = curl_slist_append(headers, "Accept: application/json");
+		 headers = curl_slist_append(headers, "Content-Type: application/json");
+		 headers = curl_slist_append(headers, "charset: utf-8");
+		 curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
+		headers = curl_slist_append(headers, "length: 20");
+		headers = curl_slist_append(headers, "numbers: true");
+
+		 curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
 
 		 res = curl_easy_perform(curl);
+		 long http_code = 0;
+		 curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &http_code);
 
-		 if(res != CURLE_OK)
+		 if(res != CURLE_OK || http_code != 200)
 		 {
 			 DEBUG_ERROR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
 		 }
@@ -131,6 +143,11 @@ int httpPost(uint8_t *url, uint8_t *postData, uint8_t *responseData)
 
 	curl_global_init(CURL_GLOBAL_ALL);
 	curl = curl_easy_init();
+	
+	printf("post url  : %s\n", url);
+	printf("post data : %s\n", postData);
+	
+	memset(&chunk, 0x00, sizeof(struct MemoryStruct));
 
 	if(curl)
 	{
@@ -174,7 +191,8 @@ int httpPost(uint8_t *url, uint8_t *postData, uint8_t *responseData)
  * @param postData
  * @return
  */
-int httpPut(uint8_t *url, uint8_t *postData)
+
+int httpPut(uint8_t *url, uint8_t *postData, uint8_t *responseData)
 {
 	int result = FAIL;
 	CURL *curl;
@@ -184,30 +202,48 @@ int httpPut(uint8_t *url, uint8_t *postData)
 	curl = curl_easy_init();
 
 	if(curl)
-	{
-		struct curl_slist *headers = NULL;
-		headers = curl_slist_append(headers, "Content-Type: literature/classic");
-		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
-		curl_easy_setopt(curl, CURLOPT_URL, (char*)url);
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char*)postData);
+	{	struct curl_slist*        headerlist    = NULL;
+		struct curl_httppost*    formpost    = NULL;
+		struct curl_httppost*    lastptr        = NULL;
 		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
-		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, FALSE);
-		//curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
-		//curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password");
-		curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 2500L);
 
-		res = curl_easy_perform(curl);
+		// 设置表头,表头内容可能不同
+		//headerlist = curl_slist_append(headerlist, "Content-Type:application/x-www-form-urlencoded");
+		headerlist = curl_slist_append(headerlist, "Content-Type:application/json");
+		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
 
-		if(res != CURLE_OK)
-		{
+		// 设置URL
+		curl_easy_setopt(curl, CURLOPT_URL, "http://postit.example.com/moo.cgi");
+		 curl_easy_setopt(curl, CURLOPT_URL, (char*)url);
+		 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+		 curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk);
+		 //curl_easy_setopt(curl, CURLOPT_USERAGENT, "libcurl-agent/1.0");
+		 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, (char*)postData);
+		 //curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen((char*)postData));
+		 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
+		 curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
+		 //curl_easy_setopt(curl, CURLOPT_HTTPAUTH, (long)CURLAUTH_ANY);
+		 //curl_easy_setopt(curl, CURLOPT_USERPWD, "user:password");
+//		 curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 2500L);
+		 curl_easy_setopt(curl, CURLOPT_TIMEOUT, 20L);
+
+		 res = curl_easy_perform(curl);
+
+		 if(res != CURLE_OK)
+		 {
 			 DEBUG_ERROR("curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
-		}
-		else
-		{
-			result = PASS;
-		}
-		curl_easy_cleanup(curl);
-		curl_slist_free_all(headers);
+		 }
+		 else
+		 {
+			 if(chunk.size > 0)
+			 {
+				 DEBUG_INFO("Response content: %s\n", chunk.memory);
+				 memcpy(responseData, chunk.memory, ARRAY_SIZE(chunk.memory));
+			 }
+
+			 result = PASS;
+		 }
+		 curl_easy_cleanup(curl);
 	}
 	curl_global_cleanup();
 

+ 1 - 1
EVSE/Modularization/DcMeter/curlApi.h

@@ -20,7 +20,7 @@
 
 extern int httpGet(uint8_t *url, uint8_t *responseData);
 extern int httpPost(uint8_t *url, uint8_t *postData, uint8_t *responseData);
-extern int httpPut(uint8_t *url, uint8_t *postData);
+extern int httpPut(uint8_t *url, uint8_t *postData, uint8_t *responseData);
 extern int curlDownload(uint8_t *url, uint8_t *filename);
 extern int httpUpload(uint8_t *url, uint8_t *filename);
 extern int ftpUpload(uint8_t *url, uint8_t *filename);

+ 575 - 93
EVSE/Modularization/DcMeter/meterComm.c

@@ -6,11 +6,20 @@
  */
 #include 	"meterComm.h"
 #include 	"curlApi.h"
-#include 	"SystemLogMessage.h"
+#include 	"SystemLogMessage.h" 
 #include	"json-c/json.h"
 
 #define is_error(ptr) 			((unsigned long)ptr > (unsigned long)-4000L)
 
+
+#define _DEBUG_ 0
+
+#if _DEBUG_
+#define PR(...) printf(__VA_ARGS__)
+#else
+#define PR(...)
+#endif
+
 unsigned char 	meterModel = 0;
 char			meterApiAddress[128];
 
@@ -24,66 +33,59 @@ void meterInitialize(uint8_t model)
 	meterModel = model;
 }
 
-/**
- * Meter api address assign
- * @param meterIndex
- */
-void meterApiAssign(uint8_t meterIndex)
-{
-	switch(meterModel)
-	{
-		case METER_MODEL_LEM_L18005A:
-		default:
-			/*
-			 * TODO:
-			 * 	1. Check meter actual API address.
-			 */
-			sprintf(meterApiAddress, "http://192.168.0.%d/v1/livemeasure", (31 + meterIndex));
-			//sprintf(meterApiAddress, "http://192.168.0.31/livemeasure");
-			//sprintf(meterApiAddress, "https://foluswen.com/tmate/livemeasure.php"); // Simulator by web server
-
-			break;
-	}
-}
-
 /**
  * Output voltage read
  * @param meter_info
  * @return
  */
-int readVoltage(Meter_Info *meter_info)
+int readMeterLivemeasure(uint8_t meterIndex, Meter_Info *meter_info)
 {
 	int result = FAIL;
+	char host[128]="";
 	uint8_t	data[4096];
 
+	sprintf(host, "http://192.168.0.%d/v1/livemeasure", (31 + meterIndex));
+	
 	switch(meterModel)
 	{
 
 		case METER_MODEL_LEM_L18005A:
 		default:
-			if(httpGet((uint8_t*)meterApiAddress, data) != FAIL)
+			if(httpGet((uint8_t*)host, data) != FAIL)
 			{
-				//printf("data: %s\n", data);
-				//printf("meterApiAddress: %s\n", meterApiAddress);
+				//PR("data: %s\n", data);
+				//PR("meterApiAddress: %s\n", meterApiAddress);
 				json_object *livemeasure;
 				livemeasure = json_tokener_parse((char*)data);
 				if(!is_error(livemeasure))
 				{
 					if(json_object_object_get(livemeasure, "voltage") != NULL)
 						meter_info->presetVoltage = json_object_get_double(json_object_object_get(livemeasure, "voltage"));
+						PR("Output voltage %d : %.3f V\n", meter_info->presetVoltage);
 
 					if(json_object_object_get(livemeasure, "current") != NULL)
 						meter_info->presentCurrent = json_object_get_double(json_object_object_get(livemeasure, "current"));
+						PR("Output current %d : %.3f V\n", meter_info->presentCurrent);
 
 					if(json_object_object_get(livemeasure, "power") != NULL)
 						meter_info->presentPower = json_object_get_double(json_object_object_get(livemeasure, "power"));
+						PR("Output power %d : %.3f V\n", meter_info->presentPower);
 
 					if(json_object_object_get(livemeasure, "energyImportTotal") != NULL)
 						meter_info->totlizeImportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyImportTotal"));
+						PR("Totalize import energy %d : %.3f V\n", meter_info->totlizeImportEnergy);
 
 					if(json_object_object_get(livemeasure, "energyExportTotal") != NULL)
 						meter_info->totlizeExportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyExportTotal"));
-
+						PR("Totalize export energy %d : %.3f V\n", meter_info->totlizeExportEnergy);
+
+					if(json_object_object_get(livemeasure, "timestamp") != NULL){						
+						sprintf((char*)&meter_info->timestamp, "%s", json_object_get_string(json_object_object_get(livemeasure, "timestamp")));
+						PR("timestamp : %s\n",meter_info->timestamp);	
+					}
+					
+					PR("\n\n\n\n\n\n\n\n");
+						
 					result = PASS;
 				}
 				json_object_put(livemeasure);
@@ -96,137 +98,617 @@ int readVoltage(Meter_Info *meter_info)
 }
 
 /**
- * Output current read
+ * Export & import totalize energy read
  * @param meter_info
  * @return
  */
-int readCurrent(Meter_Info *meter_info)
+int readMeterStatusInfo(uint8_t meterIndex, Meter_Status_Info *meter_status_info)
 {
 	int result = FAIL;
+	char host[128]="";
 	uint8_t	data[4096];
-
+	
+	sprintf(host, "http://192.168.0.%d/v1/status", (31 + meterIndex));
+	
 	switch(meterModel)
 	{
 		case METER_MODEL_LEM_L18005A:
 		default:
-			if(httpGet((uint8_t*)meterApiAddress, data) != FAIL)
+			//if(httpGet((uint8_t*)meterApiAddress, data) != FAIL)
+			if(httpGet((uint8_t*)host,data)!= FAIL)	
 			{
 				json_object *livemeasure;
 				livemeasure = json_tokener_parse((char*)data);
+				
+				//PR("Get %s\n",data);
+				
 				if(!is_error(livemeasure))
 				{
-					if(json_object_object_get(livemeasure, "voltage") != NULL)
-						meter_info->presetVoltage = json_object_get_double(json_object_object_get(livemeasure, "voltage"));
-
-					if(json_object_object_get(livemeasure, "current") != NULL)
-						meter_info->presentCurrent = json_object_get_double(json_object_object_get(livemeasure, "current"));
-
-					if(json_object_object_get(livemeasure, "power") != NULL)
-						meter_info->presentPower = json_object_get_double(json_object_object_get(livemeasure, "power"));
-
-					if(json_object_object_get(livemeasure, "energyImportTotal") != NULL)
-						meter_info->totlizeImportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyImportTotal"));
-
-					if(json_object_object_get(livemeasure, "energyExportTotal") != NULL)
-						meter_info->totlizeExportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyExportTotal"));
+						if(json_object_object_get(json_object_object_get(livemeasure, "status"), "value") != NULL)
+						{
+							meter_status_info->StatusValue = json_object_get_int(json_object_object_get(json_object_object_get(livemeasure, "status"), "value"));
+							PR("status-value : %d \n",meter_status_info->StatusValue);
+						}
+						
+						//ststus bit
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "suLinkStatusIsOk") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.suLinkStatusIsOk = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "suLinkStatusIsOk"));
+							PR("bits-suLinkStatusIsOk : %d \n",meter_status_info->MeterStatusFlag.bits.suLinkStatusIsOk);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "muFatalErrorOccured") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.muFatalErrorOccured = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "muFatalErrorOccured"));
+							PR("bits-muFatalErrorOccured : %d \n",meter_status_info->MeterStatusFlag.bits.muFatalErrorOccured);
+						}
+										
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "transactionIsOnGoing") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.transactionIsOnGoing = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "transactionIsOnGoing"));
+							PR("bits-transactionIsOnGoing : %d \n",meter_status_info->MeterStatusFlag.bits.transactionIsOnGoing);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "tamperingIsDetected") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.tamperingIsDetected = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "tamperingIsDetected"));
+							PR("bits-tamperingIsDetected : %d \n",meter_status_info->MeterStatusFlag.bits.tamperingIsDetected);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "timeSyncStatusIsOk") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.timeSyncStatusIsOk = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "timeSyncStatusIsOk"));
+							PR("bits-timeSyncStatusIsOk : %d \n",meter_status_info->MeterStatusFlag.bits.timeSyncStatusIsOk);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "overTemperatureIsDetected") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.overTemperatureIsDetected = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "overTemperatureIsDetected"));
+							PR("bits-overTemperatureIsDetected : %d \n",meter_status_info->MeterStatusFlag.bits.overTemperatureIsDetected);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "reversedVoltage") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.reversedVoltage = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "reversedVoltage"));
+							PR("bits-reversedVoltage : %d \n",meter_status_info->MeterStatusFlag.bits.reversedVoltage);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "status"), "bits"), "suMeasureFailureOccurred") != NULL)
+						{
+							meter_status_info->MeterStatusFlag.bits.suMeasureFailureOccurred = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "status"), "bits"), "suMeasureFailureOccurred"));
+							PR("bits-suMeasureFailureOccurred : %d \n",meter_status_info->MeterStatusFlag.bits.suMeasureFailureOccurred);
+						}
+				
+		
+						if(json_object_object_get(json_object_object_get(livemeasure, "version"), "applicationFirmwareVersion") != NULL)
+						{
+								sprintf((char*)&meter_status_info->applicationFirmwareVersion, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "version"), "applicationFirmwareVersion")));
+								PR("applicationFirmwareVersion : %s\n",meter_status_info->applicationFirmwareVersion);
+						}
+
+						if(json_object_object_get(json_object_object_get(livemeasure, "version"), "applicationFirmwareAuthTag") != NULL)
+						{
+								sprintf((char*)&meter_status_info->applicationFirmwareAuthTag, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "version"), "applicationFirmwareAuthTag")));
+								PR("applicationFirmwareAuthTag : %s\n",meter_status_info->applicationFirmwareAuthTag);
+						}
+						
+						if(json_object_object_get(json_object_object_get(livemeasure, "version"), "legalFirmwareVersion") != NULL)
+						{
+								sprintf((char*)&meter_status_info->legalFirmwareVersion, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "version"), "legalFirmwareVersion")));
+								PR("applicationFirmwareAuthTag : %s\n",meter_status_info->legalFirmwareVersion);
+						}
+						
+						if(json_object_object_get(json_object_object_get(livemeasure, "version"), "legalFirmwareAuthTag") != NULL)
+						{
+								sprintf((char*)&meter_status_info->legalFirmwareAuthTag, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "version"), "legalFirmwareAuthTag")));
+								PR("applicationFirmwareAuthTag : %s\n",meter_status_info->legalFirmwareAuthTag);
+						}
+						
+						if(json_object_object_get(json_object_object_get(livemeasure, "version"), "sensorFirmwareVersion") != NULL)
+						{
+								sprintf((char*)&meter_status_info->sensorFirmwareVersion, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "version"), "sensorFirmwareVersion")));
+								PR("applicationFirmwareAuthTag : %s\n",meter_status_info->sensorFirmwareVersion);
+						}
+
+						if(json_object_object_get(json_object_object_get(livemeasure, "version"), "sensorFirmwareCrc") != NULL)
+						{
+								sprintf((char*)&meter_status_info->sensorFirmwareCrc, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "version"), "sensorFirmwareCrc")));
+								PR("applicationFirmwareAuthTag : %s\n",meter_status_info->sensorFirmwareCrc);
+						}
+						
+						if(json_object_object_get(livemeasure, "ipAddress") != NULL)
+						{
+								sprintf((char*)&meter_status_info->ipAddress, "%s", json_object_get_string(json_object_object_get(livemeasure, "ipAddress")));
+								PR("ipAddress : %s\n",meter_status_info->ipAddress);
+						}
+
+						if(json_object_object_get(livemeasure, "meterId") != NULL)
+						{
+								sprintf((char*)&meter_status_info->meterId, "%s", json_object_get_string(json_object_object_get(livemeasure, "meterId")));
+								PR("meterId : %s\n",meter_status_info->meterId);
+						}
+
+						//error bit
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "muInitIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.muInitIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "muInitIsFailed"));
+							PR("bits-muInitIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.muInitIsFailed);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "suStateIsInvalid") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.suStateIsInvalid = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "suStateIsInvalid"));
+							PR("bits-suStateIsInvalid : %d \n",meter_status_info->MeterErrorFlag.bits.suStateIsInvalid);
+						}
+										
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "versionCheckIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.versionCheckIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "versionCheckIsFailed"));
+							PR("bits-versionCheckIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.versionCheckIsFailed);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "muRngInitIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.muRngInitIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "muRngInitIsFailed"));
+							PR("bits-muRngInitIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.muRngInitIsFailed);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "muDataIntegrityIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.muDataIntegrityIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "muDataIntegrityIsFailed"));
+							PR("bits-muDataIntegrityIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.muDataIntegrityIsFailed);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "muFwIntegrityIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.muFwIntegrityIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "muFwIntegrityIsFailed"));
+							PR("bits-muFwIntegrityIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.muFwIntegrityIsFailed);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "suIntegrityIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.suIntegrityIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "suIntegrityIsFailed"));
+							PR("bits-suIntegrityIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.suIntegrityIsFailed);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "logbookIntegrityIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.logbookIntegrityIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "logbookIntegrityIsFailed"));
+							PR("bits-logbookIntegrityIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.logbookIntegrityIsFailed);
+						}					
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "logbookIsFull") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.logbookIsFull = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "logbookIsFull"));
+							PR("bits-logbookIsFull : %d \n",meter_status_info->MeterErrorFlag.bits.logbookIsFull);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "memoryAccessIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.memoryAccessIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "memoryAccessIsFailed"));
+							PR("bits-memoryAccessIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.memoryAccessIsFailed);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "errors"), "bits"), "muStateIsFailed") != NULL)
+						{
+							meter_status_info->MeterErrorFlag.bits.muStateIsFailed = json_object_get_boolean(json_object_object_get(json_object_object_get
+							(json_object_object_get(livemeasure, "errors"), "bits"), "muStateIsFailed"));
+							PR("bits-muStateIsFailed : %d \n",meter_status_info->MeterErrorFlag.bits.muStateIsFailed);
+						}	
+
+							
+						if(json_object_object_get(livemeasure, "publicKey") != NULL)
+						{
+								sprintf((char*)&meter_status_info->publicKey, "%s", json_object_get_string(json_object_object_get(livemeasure, "publicKey")));
+								PR("publicKey : %s\n",meter_status_info->publicKey);
+						}
+
+						if(json_object_object_get(livemeasure, "publicKeyOcmf") != NULL)
+						{
+								sprintf((char*)&meter_status_info->publicKeyOcmf, "%s", json_object_get_string(json_object_object_get(livemeasure, "publicKeyOcmf")));
+								PR("publicKeyOcmf : %s\n",meter_status_info->publicKeyOcmf);
+						}
+
+						if(json_object_object_get(livemeasure, "indexOfLastTransaction") != NULL)
+						{
+								meter_status_info->indexOfLastTransaction = json_object_get_int(json_object_object_get(livemeasure, "indexOfLastTransaction"));
+								PR("indexOfLastTransaction : %d \n",meter_status_info->indexOfLastTransaction);
+						}
+						
+						if(json_object_object_get(livemeasure, "numberOfStoredTransactions") != NULL)
+						{
+								meter_status_info->numberOfStoredTransactions = json_object_get_int(json_object_object_get(livemeasure, "numberOfStoredTransactions"));
+								PR("numberOfStoredTransactions : %d \n",meter_status_info->numberOfStoredTransactions);
+						}
+						
+						PR("\n\n\n\n\n\n\n\n");
 
 					result = PASS;
 				}
+				
 				json_object_put(livemeasure);
 			}
 			break;
 	}
-
+	
 	return result;
 }
 
-/**
- * Output power read
- * @param meter_info
- * @return
- */
-int readPower(Meter_Info *meter_info)
+
+int startMeterTransaction(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action)
 {
 	int result = FAIL;
-	uint8_t	data[4096];
-
+	char host[128]="";
+	uint8_t data[4096];
+	uint8_t tmp[4096];
+
+	json_object *TransactionStartData = json_object_new_object();	
+	json_object_object_add(TransactionStartData, "evseId", json_object_new_string((char*)meter_transaction_Action->head.evseId));
+	json_object_object_add(TransactionStartData, "transactionId", json_object_new_string((char*)meter_transaction_Action->head.transactionId));
+	json_object_object_add(TransactionStartData, "clientId", json_object_new_string((char*)meter_transaction_Action->head.clientId));
+	json_object_object_add(TransactionStartData, "tariffId", json_object_new_int(meter_transaction_Action->head.tariffId));
+	json_object_object_add(TransactionStartData, "cableId", json_object_new_int(meter_transaction_Action->head.cableId));
+	json_object_object_add(TransactionStartData, "userData", json_object_new_string((char*)meter_transaction_Action->head.userData));
+
+	sprintf((char*)tmp, "%s",  json_object_to_json_string_ext(TransactionStartData, JSON_C_TO_STRING_PLAIN));
+
+	sprintf(host, "http://192.168.0.%d/v1/legal", (31 + meterIndex));
+		 
 	switch(meterModel)
 	{
 		case METER_MODEL_LEM_L18005A:
 		default:
-			if(httpGet((uint8_t*)meterApiAddress, data) != FAIL)
+ 
+     
+			if(httpPost((uint8_t*)host,tmp,data)!= FAIL)
 			{
 				json_object *livemeasure;
 				livemeasure = json_tokener_parse((char*)data);
+				
 				if(!is_error(livemeasure))
-				{
-					if(json_object_object_get(livemeasure, "voltage") != NULL)
-						meter_info->presetVoltage = json_object_get_double(json_object_object_get(livemeasure, "voltage"));
-
-					if(json_object_object_get(livemeasure, "current") != NULL)
-						meter_info->presentCurrent = json_object_get_double(json_object_object_get(livemeasure, "current"));
+				{							
+					PR("PostStartGet %s\n",data);
+				 result = PASS;
+				}
+				json_object_put(livemeasure);
+				json_object_put(TransactionStartData);
+			}
 
-					if(json_object_object_get(livemeasure, "power") != NULL)
-						meter_info->presentPower = json_object_get_double(json_object_object_get(livemeasure, "power"));
+			break;
+	}
+					
+	return result;
+	
+}
 
-					if(json_object_object_get(livemeasure, "energyImportTotal") != NULL)
-						meter_info->totlizeImportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyImportTotal"));
 
-					if(json_object_object_get(livemeasure, "energyExportTotal") != NULL)
-						meter_info->totlizeExportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyExportTotal"));
+int stopMeterTransaction(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action,Meter_transaction_Result *meter_transaction_Result)
+{
+	int result = FAIL;
+	char host[128]="";
+	uint8_t data[4096];
+	uint8_t tmp[4096];
+
+	sprintf(host, "http://192.168.0.%d/v1/legal?transactionId=%s",(31 + meterIndex), meter_transaction_Action->head.transactionId);
+           
+	json_object *TransactionStopData = json_object_new_object();
+	json_object_object_add(TransactionStopData, "running", json_object_new_boolean(0));
+	sprintf((char*)tmp, "%s", json_object_to_json_string_ext(TransactionStopData, JSON_C_TO_STRING_PLAIN));
+	
+	switch(meterModel)
+	{
+		case METER_MODEL_LEM_L18005A:
+		default:
 
-					result = PASS;
+			if(httpPut((uint8_t*)host,tmp,data)!= FAIL)
+			//if(httpGet(host,data)!= FAIL)	
+			{
+				json_object *livemeasure;
+				livemeasure = json_tokener_parse((char*)data);
+				
+				if(!is_error(livemeasure))
+				{							
+					PR("PutStopGet %s\n",data);
+					
+					
+						if(json_object_object_get(livemeasure, "paginationCounter") != NULL)
+						{
+								meter_transaction_Result->paginationCounter = json_object_get_int(json_object_object_get(livemeasure, "paginationCounter"));
+								PR("paginationCounter : %d\n",meter_transaction_Result->paginationCounter);										
+						}
+
+						if(json_object_object_get(livemeasure, "transactionId") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->head.transactionId, "%s", json_object_get_string(json_object_object_get(livemeasure, "transactionId")));
+								PR("transactionId : %s\n",meter_transaction_Result->head.transactionId);										
+						}
+
+						if(json_object_object_get(livemeasure, "evseId") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->head.evseId, "%s", json_object_get_string(json_object_object_get(livemeasure, "evseId")));
+								PR("evseId : %s\n",meter_transaction_Result->head.evseId);										
+						}
+												
+
+						if(json_object_object_get(livemeasure, "clientId") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->head.clientId, "%s", json_object_get_string(json_object_object_get(livemeasure, "clientId")));
+								PR("clientId : %s\n",meter_transaction_Result->head.clientId);										
+						}
+
+						if(json_object_object_get(livemeasure, "tariffId") != NULL)
+						{
+								meter_transaction_Result->head.tariffId = json_object_get_int(json_object_object_get(livemeasure, "tariffId"));
+								PR("tariffId : %d\n",meter_transaction_Result->head.tariffId);
+						}					
+
+						if(json_object_object_get(livemeasure, "userData") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->head.userData, "%s", json_object_get_string(json_object_object_get(livemeasure, "userData")));
+								PR("clientId : %s\n",meter_transaction_Result->head.userData);										
+						}					
+
+						if(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "timestampStart") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->timestampStart, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "meterValue"), "timestampStart")));
+								PR("timestampStart : %s\n",meter_transaction_Result->timestampStart);
+						}
+
+						if(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "timestampStop") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->timestampStop, "%s", json_object_get_string(json_object_object_get
+								(json_object_object_get(livemeasure, "meterValue"), "timestampStop")));
+								PR("timestampStop : %s\n",meter_transaction_Result->timestampStop);
+						}
+
+						if(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "transactionDuration") != NULL)
+						{
+								meter_transaction_Result->transactionDuration = json_object_get_int(json_object_object_get
+								(json_object_object_get(livemeasure, "meterValue"), "transactionDuration"));
+								PR("transactionDuration : %d\n",meter_transaction_Result->transactionDuration);
+						}
+
+						if(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "transactionStatus") != NULL)
+						{
+								meter_transaction_Result->transactionStatus = json_object_get_int(json_object_object_get
+								(json_object_object_get(livemeasure, "meterValue"), "transactionStatus"));
+								PR("transactionStatus : %d\n",meter_transaction_Result->transactionStatus);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyUnit") != NULL)
+						{
+							strcpy((char*)meter_transaction_Result->energyUnit, json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyUnit")));
+							PR("energyUnit : %s\n",meter_transaction_Result->energyUnit);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyImport") != NULL)
+						{
+							meter_transaction_Result->energyImport = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyImport"));
+							PR("energyImport : %.3f\n",meter_transaction_Result->energyImport);
+						}
+						
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyImportTotalStart") != NULL)
+						{
+							meter_transaction_Result->energyImportTotalStart = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyImportTotalStart"));
+							PR("energyImportTotalStart : %.3f\n",meter_transaction_Result->energyImportTotalStart);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyImportTotalStop") != NULL)
+						{
+							meter_transaction_Result->energyImportTotalStop = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyImportTotalStop"));
+							PR("energyImportTotalStop : %.3f\n",meter_transaction_Result->energyImportTotalStop);
+						}
+
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyExport") != NULL)
+						{
+							meter_transaction_Result->energyExport = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyExport"));
+							PR("energyExport : %.3f\n",meter_transaction_Result->energyExport);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyExportTotalStart") != NULL)
+						{
+							meter_transaction_Result->energyExportTotalStart = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyExportTotalStart"));
+							PR("energyExportTotalStart : %.3f\n",meter_transaction_Result->energyExportTotalStart);
+						}
+
+						if(json_object_object_get(json_object_object_get(json_object_object_get(livemeasure, "meterValue"), "sampleValue"), "energyExportTotalStop") != NULL)
+						{
+							meter_transaction_Result->energyExportTotalStop = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get
+							(livemeasure, "meterValue"), "sampleValue"), "energyExportTotalStop"));
+							PR("energyExportTotalStop : %.3f\n",meter_transaction_Result->energyExportTotalStop);
+						}
+						
+						if(json_object_object_get(livemeasure, "signature") != NULL)
+						{
+								sprintf((char*)&meter_transaction_Result->signature, "%s", json_object_get_string(json_object_object_get(livemeasure, "signature")));
+								PR("signature : %s\n",meter_transaction_Result->signature);										
+						}
+						
+						PR("\n\n\n\n\n\n\n\n");
+											
+				 	result = PASS;
 				}
-				json_object_put(livemeasure);
+			json_object_put(livemeasure);
+			json_object_put(TransactionStopData);		
+				
 			}
 			break;
 	}
-
+					
+	
+	
 	return result;
+	
 }
 
-/**
- * Export & import totalize energy read
- * @param meter_info
- * @return
- */
-int readEnergy(Meter_Info *meter_info)
+
+int readMeterTransactionOCMF(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action)
 {
 	int result = FAIL;
-	uint8_t	data[4096];
-
+	char host[128]="";
+	uint8_t data[4096];
+		
+	sprintf(host, "http://192.168.0.%d/v1/ocmf?transactionId=%s",(31 + meterIndex),meter_transaction_Action->head.transactionId);
+ 	//printf ("host : %s\n",host);
+	
 	switch(meterModel)
 	{
 		case METER_MODEL_LEM_L18005A:
 		default:
-			if(httpGet((uint8_t*)meterApiAddress, data) != FAIL)
+
+			if(httpGet((uint8_t*)host,data)!= FAIL)	
 			{
+				
+				PR("Get %s\n",data);
+				sprintf((char*)&meter_transaction_Action->transactionOCMF, "%s", data);
+				//printf("GETOCMF %s\n",meter_transaction_Result->transactionOCMF);
 				json_object *livemeasure;
 				livemeasure = json_tokener_parse((char*)data);
+				
 				if(!is_error(livemeasure))
-				{
-					if(json_object_object_get(livemeasure, "voltage") != NULL)
-						meter_info->presetVoltage = json_object_get_double(json_object_object_get(livemeasure, "voltage"));
-
-					if(json_object_object_get(livemeasure, "current") != NULL)
-						meter_info->presentCurrent = json_object_get_double(json_object_object_get(livemeasure, "current"));
+				{							
+					result = PASS;
+				}
+				
+				json_object_put(livemeasure);
+				
+			}
+			break;
+	}
+					
+	
+	
+	return result;
+	
+}
 
-					if(json_object_object_get(livemeasure, "power") != NULL)
-						meter_info->presentPower = json_object_get_double(json_object_object_get(livemeasure, "power"));
 
-					if(json_object_object_get(livemeasure, "energyImportTotal") != NULL)
-						meter_info->totlizeImportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyImportTotal"));
-
-					if(json_object_object_get(livemeasure, "energyExportTotal") != NULL)
-						meter_info->totlizeExportEnergy = json_object_get_double(json_object_object_get(livemeasure, "energyExportTotal"));
+int readMeterLegal(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action)
+{
+	int result = FAIL;
+	char host[128]="";
+	uint8_t data[4096];
+		
+	sprintf(host, "http://192.168.0.%d/v1/legal",(31 + meterIndex));
+ 	//printf ("host : %s\n",host);
+	
+	switch(meterModel)
+	{
+		case METER_MODEL_LEM_L18005A:
+		default:
 
+			if(httpGet((uint8_t*)host,data)!= FAIL)	
+			{
+				
+				json_object *livemeasure;
+				livemeasure = json_tokener_parse((char*)data);
+				
+				if(!is_error(livemeasure))
+				{	
+					if(json_object_object_get(livemeasure, "transactionId") != NULL)
+					{
+								sprintf((char*)&meter_transaction_Action->head.transactionId, "%s", json_object_get_string(json_object_object_get(livemeasure, "transactionId")));
+								PR("transactionId : %s\n",meter_transaction_Action->head.transactionId);										
+					}
 					result = PASS;
 				}
+				
 				json_object_put(livemeasure);
+				
 			}
 			break;
 	}
+					
+	
+	
+	return result;
+	
+}
 
+
+int configure_meter_time(uint8_t meterIndex)
+{
+	int result = FAIL;
+	
+	char host[256]="";
+	uint8_t	postdata[256];
+	uint8_t data[4096];
+		
+	time_t tmi;
+	struct tm* utcTime;
+
+	time(&tmi);
+	utcTime = gmtime(&tmi);
+	
+  //{"time": { "utc":"2022-06-29T13:09:26Z" }}
+	sprintf(host,"http://192.168.0.%d/v1/settings",(31 + meterIndex));
+	memset(postdata, 0, sizeof(postdata));
+	sprintf((char*)postdata,"{\"time\": { \"utc\":\"%d-%d-%dT%02d:%02d:%02dZ\" }}", (utcTime->tm_year+1900), (utcTime->tm_mon+1), (utcTime->tm_mday), (utcTime->tm_hour) % 24, utcTime->tm_min, utcTime->tm_sec);
+	//sprintf(postdata,"{\"time\": { \"utc\":\"%d-%d-%dT%02d:%02d:%02dZ\" }}", 2021, (utcTime->tm_mon+1), (utcTime->tm_mday), (utcTime->tm_hour) % 24, utcTime->tm_min, utcTime->tm_sec); 
+	
+		PR("Local time and date: %s\n", postdata);
+	
+	switch(meterModel)
+	{
+		case METER_MODEL_LEM_L18005A:
+		default:
+
+			if(httpPut((uint8_t*)host,postdata, data)!= FAIL)
+			{
+				json_object *livemeasure;
+				livemeasure = json_tokener_parse((char*)data);
+				
+				if(!is_error(livemeasure))
+				{							
+					PR("PutConfingTimeGet %s\n",data);
+					PR("\n\n\n\n\n\n\n\n");
+					
+					if(json_object_object_get(livemeasure, "result") != NULL)
+					{
+						PR("configure_meter_time resul: %d \n",json_object_get_int(json_object_object_get(livemeasure, "result")));
+					}
+				 	
+				 	result = PASS;
+				}
+			json_object_put(livemeasure);
+				
+			}
+			break;
+	}
+	
 	return result;
+	
 }
 

+ 129 - 6
EVSE/Modularization/DcMeter/meterComm.h

@@ -44,20 +44,143 @@ typedef struct METER_INFO
 	double presentPower;						// resolution: 1.000kw
 	double totlizeImportEnergy;			// resolution: 1.000kwh
 	double totlizeExportEnergy;			// resolution: 1.000kwh
-	uint8_t LinkStatus;								// 0 = unknow ,1 = link , 2 miss link
+	unsigned char timestamp[32];
+	unsigned char LinkStatus;								// 0 = unknow ,1 = link , 2 miss link
 }Meter_Info;
 
+
+typedef union
+{
+				unsigned char Status;
+        struct
+        {
+	    			unsigned char suLinkStatusIsOk:1;
+            unsigned char muFatalErrorOccured:1;
+            unsigned char transactionIsOnGoing:1;
+            unsigned char tamperingIsDetected:1;
+            unsigned char timeSyncStatusIsOk:1;
+            unsigned char overTemperatureIsDetected:1;
+            unsigned char reversedVoltage:1;
+            unsigned char suMeasureFailureOccurred:1;
+        }bits;
+        
+}StatusFlag;
+
+typedef union
+{
+        unsigned char Errors;
+        struct
+        {
+            unsigned char muInitIsFailed:1;
+            unsigned char suStateIsInvalid:1;
+            unsigned char versionCheckIsFailed:1;
+            unsigned char muRngInitIsFailed:1;
+            unsigned char muDataIntegrityIsFailed:1;
+            unsigned char muFwIntegrityIsFailed:1;
+            unsigned char suIntegrityIsFailed:1;
+            unsigned char logbookIntegrityIsFailed:1;
+            unsigned char logbookIsFull:1;
+            unsigned char memoryAccessIsFailed:1;
+            unsigned char muStateIsFailed:1;
+            unsigned char res:5;
+        }bits;
+        
+}ErrorFlag;
+   
+typedef struct METER_STATUS_INFO
+{
+	 	unsigned short StatusValue;
+		StatusFlag MeterStatusFlag;
+    
+		unsigned char applicationFirmwareVersion[16];
+    unsigned char applicationFirmwareAuthTag[32];
+    unsigned char legalFirmwareVersion[16];
+    unsigned char legalFirmwareAuthTag[32];
+    unsigned char sensorFirmwareVersion[16];
+    unsigned char sensorFirmwareCrc[4];
+
+    unsigned char Systime[32];
+    unsigned char ipAddress[32];
+    unsigned char meterId[32];
+
+		unsigned short ErrorValue;
+ 		ErrorFlag MeterErrorFlag;
+   
+   unsigned char publicKey[140];
+   unsigned char publicKeyOcmf[200];
+   unsigned short indexOfLastTransaction;
+   unsigned short numberOfStoredTransactions;
+}Meter_Status_Info;
+
+typedef struct METER_TRANSACTION_HEAD
+{
+    unsigned char evseId[32];
+    unsigned char transactionId[32];
+    unsigned char clientId[32];
+    unsigned short tariffId;
+    unsigned short cableId;
+    unsigned short userData[32];
+    
+}Meter_transaction_Head;
+
+
+typedef struct METER_TRANSACTION_ACTION
+{
+		Meter_transaction_Head head;
+		unsigned char transactionOCMF[512];
+		unsigned char OcmfInfoReady;               // 0 = nothing, 1 = ocmp info ready
+    unsigned char ActionCmd;                   //  0 = nothing ,1 = transaction Start , 2 transaction Stop , sync time
+    
+}Meter_transaction_Action;
+
+
+typedef union
+{
+				unsigned char Status;
+        struct
+        {
+	    			unsigned char intermediateRead:1;
+            unsigned char res:7;
+        }bits;
+        
+}TransactionReadlevel;
+
+typedef struct METER_TRANSACTION_RESULT
+{
+		unsigned short paginationCounter;
+		Meter_transaction_Head head;
+    unsigned char timestampStart[32];
+    unsigned char timestampStop[32];
+    unsigned int transactionDuration;
+    TransactionReadlevel intermediateRead;
+    unsigned int  transactionStatus;
+    unsigned char energyUnit[8];
+    double energyImport;
+    double energyImportTotalStart;
+    double energyImportTotalStop;
+    double energyExport;
+    double energyExportTotalStart;
+    double energyExportTotalStop;
+    unsigned char signature[140];
+    //unsigned char transactionOCMF[512];
+}Meter_transaction_Result;
+
+
+
 enum METER_MODEL
 {
 	METER_MODEL_LEM_L18005A=0,
 };
 
 extern void meterInitialize(uint8_t model);
-extern void meterApiAssign(uint8_t meterIndex);
-extern int readVoltage(Meter_Info *meter_info);
-extern int readCurrent(Meter_Info *meter_info);
-extern int readPower(Meter_Info *meter_info);
-extern int readEnergy(Meter_Info *meter_info);
+extern int readMeterLivemeasure(uint8_t meterIndex, Meter_Info *meter_info);
+extern int readMeterStatusInfo(uint8_t meterIndex, Meter_Status_Info *meter_status_info);
+extern int startMeterTransaction(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action);
+extern int stopMeterTransaction(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action,Meter_transaction_Result *meter_transaction_Result);
+extern int readMeterTransactionOCMF(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action);
+extern int readMeterLegal(uint8_t meterIndex, Meter_transaction_Action *meter_transaction_Action);
+extern int configure_meter_time(uint8_t meterIndex);
+
 
 extern unsigned char 	meterModel;
 extern char				meterApiAddress[];

+ 50 - 6
EVSE/Modularization/Module_4g.c

@@ -112,7 +112,7 @@ void substr(char *dest, const char* src, unsigned int start, unsigned int cnt);
 
 char *portName[3] 				= {"/dev/ttyUSB2", "/dev/ttyACM2", "/dev/ttyACM2"};
 char *valid_Internet[2] 		= {"8.8.8.8", "180.76.76.76"};
-char *Version_And_Date[2]		= {"V0.13","2022-04-21"};
+char *Version_And_Date[2]		= {"V0.14","2022-09-12"};
 pid_t	pid;
 
 struct dongle_info
@@ -644,6 +644,7 @@ int isReadInfo(int connectStep)
 							if(sscanf(rx, "%*[^:]:%*[^,],%d,%*[^,],%*[^,],%*[^,],%*[^,],%[^,]", &Dongle.channel, Dongle.operator) == 2)
 							{
 								Dongle.MODE = NET_MODE_GSM_WCDMA;
+
 								memset(Dongle.band, 0x00, ARRAY_SIZE(Dongle.band));
 								memset(Dongle.act, 0x00, ARRAY_SIZE(Dongle.act));
 							}
@@ -1362,7 +1363,47 @@ void configNetworkMode(uint8_t actReq)
 	}
 	else if(Dongle.Model == DONGLE_THALES)
 	{
-		system("cp /root/ppp/ppp-on-dialer-org /root/ppp/ppp-on-dialer");
+		while (fgets(str, ARRAY_SIZE(str), fpOrg) != NULL)
+		{
+			fprintf(fpDst,"%s", str);
+
+			if(strstr(str, "ATE1") != NULL)
+			{
+				switch(actReq)
+				{
+					case NETWORK_MODE_GSM:
+						fprintf(fpDst, "	OK		\"AT\\^SCFG=\\\"Radio\\/Band\\/2G\\\",\\\"0000000f\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/3G\\\",\\\"0\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/4G\\\",\\\"0\\\",\\\"0\\\"\"	\\\n");
+						break;
+					case NETWORK_MODE_UMTS:
+						fprintf(fpDst, "	OK		\"AT\\^SCFG=\\\"Radio\\/Band\\/2G\\\",\\\"0\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/3G\\\",\\\"000400bf\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/4G\\\",\\\"0\\\",\\\"0\\\"\"	\\\n");
+						break;
+					case NETWORK_MODE_LTE:
+						fprintf(fpDst, "	OK		\"AT\\^SCFG=\\\"Radio\\/Band\\/2G\\\",\\\"0\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/3G\\\",\\\"0\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/4G\\\",\\\"0a0e18df\\\",\\\"00000002000001a0\\\"\"	\\\n");
+						break;
+					case NETWORK_MODE_AUTO:
+						fprintf(fpDst, "	OK		\"AT\\^SCFG=\\\"Radio\\/Band\\/2G\\\",\\\"0000000f\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/3G\\\",\\\"000400bf\\\"\"	\\\n");
+						fprintf(fpDst, "	OK		\\\\d\\\\d\\\\d				\\\n");
+						fprintf(fpDst, "	\"\"	\"AT\\^SCFG=\\\"Radio\\/Band\\/4G\\\",\\\"0a0e18df\\\",\\\"00000002000001a0\\\"\"	\\\n");
+					default:
+						break;
+				}
+			}
+			memset(str, 0x00, ARRAY_SIZE(str));
+		}
 	}
 
 	fclose(fpOrg);
@@ -1672,10 +1713,13 @@ int main(void)
 						DEBUG_INFO("Device Channel: %d\n", Dongle.channel);
 					}
 
-					DEBUG_INFO("TX counter: %d bytes\n", Dongle.bytesTx);
-					DEBUG_INFO("RX counter: %d bytes\n", Dongle.bytesRx);
-					DEBUG_INFO("Delta counter: %d bytes\n", (Dongle.bytesTx+Dongle.bytesRx)-Dongle.lastCounter);
-					Dongle.lastCounter = (Dongle.bytesTx+Dongle.bytesRx);
+					if(Dongle.Model == DONGLE_QUECTEL)
+					{
+						DEBUG_INFO("TX counter: %d bytes\n", Dongle.bytesTx);
+						DEBUG_INFO("RX counter: %d bytes\n", Dongle.bytesRx);
+						DEBUG_INFO("Delta counter: %d bytes\n", (Dongle.bytesTx+Dongle.bytesRx)-Dongle.lastCounter);
+						Dongle.lastCounter = (Dongle.bytesTx+Dongle.bytesRx);
+					}
 					DEBUG_INFO("++++++++++++++++++++++++++++++++++++++++\n");
 
 					break;

+ 15 - 16
EVSE/Modularization/Module_PowerSharing.c

@@ -14,9 +14,11 @@
 //#define MODPS_FW_VER_NUM	(1)    //V/T0.01
 //#define MODPS_FW_DATE		("20220730")
 
-#define MODPS_FW_VER_NUM	(2)    //V/T0.02
-#define MODPS_FW_DATE		("20220815")
+//#define MODPS_FW_VER_NUM	(2)    //V/T0.02
+//#define MODPS_FW_DATE		("20220815")
 
+#define MODPS_FW_VER_NUM	(3)    //V/T0.03
+#define MODPS_FW_DATE		("20220908")
 
 //-----------------------------------------------------------------------------
 #if (MODPS_FW_VER_NUM >= 1)
@@ -28,10 +30,11 @@
 #define MODIFY_MODPS_LET_ON_HAND_ALL_USED
 #define MODIFY_MODPS_REDUCE_DEBUG_LOG
 #define FUNC_MODPS_WATCH_MODE
-#define FIX_MODPS_CONN_UPDATE_STATUS_LOOP_INDEX_INIT_VAL
 #endif
 //-----------------------------------------------------------------------------
-
+#if (MODPS_FW_VER_NUM >= 3)
+//Fix: Variable used by DC Model (PresentChargingPower), unit of it is kW, not W
+#endif
 //-----------------------------------------------------------------------------
 
 #define HTK_USE_XPRINT
@@ -743,11 +746,7 @@ int conn_update_status(int socketFd, Connector_Info *connectorInfo, uint8_t conn
 		if(ShmPowerSharing->Connection_Info[idx].socketFd == socketFd)
 		{
 			ShmPowerSharing->Connection_Info[idx].connectorCount = connectorCount;
-#ifdef FIX_MODPS_CONN_UPDATE_STATUS_LOOP_INDEX_INIT_VAL
 			for(uint8_t gun_index=0;gun_index<connectorCount;gun_index++)
-#else
-			for(uint8_t gun_index;gun_index<connectorCount;gun_index++)
-#endif
 			{
 				if(!ShmPowerSharing->Connection_Info[idx].connectorInfo[gun_index].isGunConnected && connectorInfo[gun_index].isGunConnected)
 				{
@@ -1185,8 +1184,8 @@ int tcpSocketClient(void)
 											output.buffer[4+(gun_index*6)+1] = ShmSysConfigAndInfo->SysInfo.ChademoChargingData[tempIndex].ConnectorPlugIn;
 											output.buffer[4+(gun_index*6)+2] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>8)&0xff;
 											output.buffer[4+(gun_index*6)+3] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>0)&0xff;
-											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.ChademoChargingData[gun_index].PresentChargingPower/220)>>8)&0xff;
-											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.ChademoChargingData[gun_index].PresentChargingPower/220)>>0)&0xff;
+											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.ChademoChargingData[gun_index].PresentChargingPower*1000/220)>>8)&0xff;
+											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.ChademoChargingData[gun_index].PresentChargingPower*1000/220)>>0)&0xff;
 										}
 									}
 									break;
@@ -1208,8 +1207,8 @@ int tcpSocketClient(void)
 											output.buffer[4+(gun_index*6)+1] = ShmSysConfigAndInfo->SysInfo.CcsChargingData[tempIndex].ConnectorPlugIn;
 											output.buffer[4+(gun_index*6)+2] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>8)&0xff;
 											output.buffer[4+(gun_index*6)+3] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>0)&0xff;
-											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.CcsChargingData[gun_index].PresentChargingPower/220)>>8)&0xff;
-											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.CcsChargingData[gun_index].PresentChargingPower/220)>>0)&0xff;
+											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.CcsChargingData[gun_index].PresentChargingPower*1000/220)>>8)&0xff;
+											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.CcsChargingData[gun_index].PresentChargingPower*1000/220)>>0)&0xff;
 										}
 									}
 									break;
@@ -1231,8 +1230,8 @@ int tcpSocketClient(void)
 											output.buffer[4+(gun_index*6)+1] = ShmSysConfigAndInfo->SysInfo.GbChargingData[tempIndex].ConnectorPlugIn;
 											output.buffer[4+(gun_index*6)+2] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>8)&0xff;
 											output.buffer[4+(gun_index*6)+3] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>0)&0xff;
-											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.GbChargingData[gun_index].PresentChargingPower/220)>>8)&0xff;
-											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.GbChargingData[gun_index].PresentChargingPower/220)>>0)&0xff;
+											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.GbChargingData[gun_index].PresentChargingPower*1000/220)>>8)&0xff;
+											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.GbChargingData[gun_index].PresentChargingPower*1000/220)>>0)&0xff;
 										}
 									}
 									break;
@@ -1247,8 +1246,8 @@ int tcpSocketClient(void)
 											output.buffer[4+(gun_index*6)+1] = ShmSysConfigAndInfo->SysInfo.ConnectorInfo[tempIndex].GeneralChargingData.ConnectorPlugIn;
 											output.buffer[4+(gun_index*6)+2] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>8)&0xff;
 											output.buffer[4+(gun_index*6)+3] = (ShmSysConfigAndInfo->SysInfo.localSharingInfo.AvailableShargingCurrent[gun_index]>>0)&0xff;
-											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].GeneralChargingData.PresentChargingPower/220)>>8)&0xff;
-											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].GeneralChargingData.PresentChargingPower/220)>>0)&0xff;
+											output.buffer[4+(gun_index*6)+4] = ((int)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].GeneralChargingData.PresentChargingPower*1000/220)>>8)&0xff;
+											output.buffer[4+(gun_index*6)+5] = ((int)(ShmSysConfigAndInfo->SysInfo.ConnectorInfo[gun_index].GeneralChargingData.PresentChargingPower*1000/220)>>0)&0xff;
 										}
 									}
 									break;

+ 34 - 0
EVSE/Modularization/WebService.c

@@ -1956,6 +1956,8 @@ int main(int argc, char *argv[]) {
 		struct json_object *PowerSharingServerIP;
 		struct json_object *OcppReceiptrURL;
 		struct json_object *MaintainServerURL;
+		struct json_object *Private_Key;
+		struct json_object *Certificate;
 		/*for TTIA*/
 		struct json_object *isEnableTTIA;
 		struct json_object *server_addr;
@@ -2642,6 +2644,36 @@ int main(int argc, char *argv[]) {
 		MaintainServerSecurityPassword = json_object_new_string((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerSecurityPassword);
 		chargePointVendor = json_object_new_string((char *)&ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 		MaintainServerURL = json_object_new_string((char *)&ShmSysConfigAndInfo->SysConfig.MaintainServerURL);
+		FILE *file;
+		char line[0];
+		Private_Key = json_object_new_string("");
+		file = popen("sha256sum /Storage/OCPP/certCP.key", "r");
+		if (NULL != file)
+		{
+			int i=0;
+			while (fgets(line, 65, file) != NULL)
+			{
+				if(i==0){
+					Private_Key = json_object_new_string(line);
+				}
+				i++;
+			}
+		}
+		pclose(file);
+		Certificate = json_object_new_string("");
+		file = popen("sha256sum /Storage/OCPP/certCP.pem", "r");
+		if (NULL != file)
+		{
+			int i=0;
+			while (fgets(line, 65, file) != NULL)
+			{
+				if(i==0){
+					Certificate = json_object_new_string(line);
+				}
+				i++;
+			}
+		}
+		pclose(file);
 		if(strcmp(IsDO, "AX") == 0 || strcmp(IsDO, "AW") == 0 || strcmp(IsAcDc, "D") == 0){
 			isEnableLocalPowerSharging = json_object_new_int(ShmSysConfigAndInfo->SysConfig.isEnableLocalPowerSharing);
 			PowerSharingCapacity = json_object_new_int(ShmSysConfigAndInfo->SysConfig.PowerSharingCapacityPower);
@@ -3076,6 +3108,8 @@ int main(int argc, char *argv[]) {
 		json_object_object_add(jobj4,"MaintainServerSecurityProfile",MaintainServerSecurityProfile);
 		json_object_object_add(jobj4,"MaintainServerSecurityPassword",MaintainServerSecurityPassword);
 		json_object_object_add(jobj4,"MaintainServerURL",MaintainServerURL);
+		json_object_object_add(jobj4,"Private_Key",Private_Key);
+		json_object_object_add(jobj4,"Certificate",Certificate);
 		if(strcmp(IsDO, "AX") == 0 || strcmp(IsDO, "AW") == 0 || strcmp(IsAcDc, "D") == 0){
 			json_object_object_add(jobj4,"isEnableLocalPowerSharging",isEnableLocalPowerSharging);
 			json_object_object_add(jobj4,"PowerSharingCapacity",PowerSharingCapacity);

+ 215 - 272
EVSE/Modularization/ocppfiles/MessageHandler.c

@@ -1618,6 +1618,140 @@ int syncDateTimeRTC(uint8_t *data)
 	return result.result;
 }
 
+//==========================================
+// Parse certificate content
+//==========================================
+int parseCertInfo(char *certPath, int parseType, char *data)
+{
+	int result = FAIL;
+	if(access(certPath,F_OK) != -1)
+	{
+		char temp[512] = {0};
+		char capturedData[256] = {0};
+		char hashType[10] = "SHA256";
+		FILE *fp;
+
+		// Need to get hash type first
+		sprintf(temp ,"openssl x509 -noout -text -in %s", certPath);
+		fp = popen(temp, "r");
+		if(fp)
+		{
+			while(fgets(temp, sizeof(temp), fp) != NULL)
+			{
+				if(strstr(temp, "Signature Algorithm:") != NULL)
+				{
+					result = PASS;
+					if(strstr(temp, "sha256") != NULL || strstr(temp, "SHA256") != NULL)
+						sprintf((char*)hashType, "SHA256");
+					else if(strstr(temp, "sha384") != NULL || strstr(temp, "SHA384") != NULL)
+						sprintf((char*)hashType, "SHA384");
+					else if(strstr(temp, "sha512") != NULL || strstr(temp, "SHA512") != NULL)
+						sprintf((char*)hashType, "SHA512");
+					else
+					{
+						DEBUG_INFO("Error: hashAlgorithm is illegal or missing.\n");
+						result = FAIL;
+					}
+					break;
+				}
+			}
+			sprintf((char*)data, hashType);
+		}
+
+		switch(parseType)
+		{
+		case CERT_PARSE_HashAlgorithm:
+			// Already parsed
+			DEBUG_INFO("hashAlgorithm: %s\n", hashType);
+			break;
+
+		case CERT_PARSE_SerialNumber:
+			sprintf(temp ,"openssl x509 -noout -serial -in %s", certPath);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "serial=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						result = PASS;
+						break;
+					}
+				}
+				DEBUG_INFO("serialNumber: %s\n", capturedData);
+				sprintf((char*)data, capturedData);
+			}
+			break;
+
+		case CERT_PARSE_IssuerNameHash:
+			sprintf(temp ,"openssl x509 -noout -issuer -in %s | openssl dgst -%s", certPath, (char*)hashType);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "(stdin)=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						result = PASS;
+						break;
+					}
+				}
+				stringtrimspace(capturedData);
+				DEBUG_INFO("issuerNameHash: %s\n", capturedData);
+				sprintf((char*)data, capturedData);
+			}
+			break;
+
+		case CERT_PARSE_IssuerKeyHash:
+			sprintf(temp ,"openssl x509 -noout -pubkey -in %s | openssl dgst -%s", certPath, (char*)hashType);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "(stdin)=") != NULL)
+					{
+						sscanf(temp, "%*[^=]=%s", capturedData);
+						result = PASS;
+						break;
+					}
+				}
+				stringtrimspace(capturedData);
+				DEBUG_INFO("issuerKeyHash: %s\n", capturedData);
+				sprintf((char*)data, capturedData);
+			}
+			break;
+
+		case CERT_PARSE_OcspUrl:
+			sprintf(temp ,"openssl x509 -noout -ocsp_uri -in %s", certPath);
+			fp = popen(temp, "r");
+			if(fp)
+			{
+				while(fgets(temp, sizeof(temp), fp) != NULL)
+				{
+					if(strstr(temp, "://") != NULL)
+					{
+						strcpy((char*)data, temp);
+						result = PASS;
+						break;
+					}
+				}
+			}
+			break;
+
+		default:
+			DEBUG_INFO("Parse type is invalid.\n");
+			break;
+		}
+
+		pclose(fp);
+	}
+
+	return result;
+}
+
 //==========================================
 // GetCompositeSchedule logic related function
 //==========================================
@@ -5753,6 +5887,7 @@ void CheckSystemValue(void)
 		if(isWebsocketSendable && (server_sign == TRUE) && (ShmOCPP16Data->v2g_extend.AuthorizeReq == 1))
 		{
 			memset(&ShmOCPP16Data->v2g_extend.Authorize.Response_idTokenInfo,0,sizeof(struct IdTokenInfoType));
+			int parseCertResult = FAIL;
 
 			json_object *data = json_object_new_object();
 			json_object *idToken = json_object_new_object();
@@ -5765,6 +5900,22 @@ void CheckSystemValue(void)
 			json_object_object_add(idToken, "idToken", json_object_new_string((char*)ShmOCPP16Data->v2g_extend.Authorize.idToken.idToken));
 			json_object_object_add(data, "idToken", idToken);
 
+			char parseData[512] = {0};
+			if(parseCertInfo(CERTIFICATE_PnCAuth, CERT_PARSE_HashAlgorithm, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[0].hashAlgorithm, parseData);
+
+			if(parseCertInfo(CERTIFICATE_PnCAuth, CERT_PARSE_SerialNumber, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[0].serialNumber, parseData);
+
+			if(parseCertInfo(CERTIFICATE_PnCAuth, CERT_PARSE_IssuerNameHash, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[0].issuerNameHash, parseData);
+
+			if(parseCertInfo(CERTIFICATE_PnCAuth, CERT_PARSE_IssuerKeyHash, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[0].issuerKeyHash, parseData);
+
+			if(parseCertInfo(CERTIFICATE_PnCAuth, CERT_PARSE_OcspUrl, parseData) == PASS)
+				strcpy((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[0].responderURL, parseData);
+
 			for(int idx=0; idx < 4; idx++)
 			{
 				if(strlen((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[idx].responderURL) >= 7)
@@ -5777,17 +5928,28 @@ void CheckSystemValue(void)
 					json_object_object_add(OCSPRequestDataType, "responderURL", json_object_new_string((char*)ShmOCPP16Data->v2g_extend.Authorize.iso15118CertificateHashData[idx].responderURL));
 
 					json_object_array_add(iso15118CertificateHashData, OCSPRequestDataType);
+					parseCertResult = PASS;
 				}
 			}
-			json_object_object_add(data, "iso15118CertificateHashData", iso15118CertificateHashData);
 
-			sprintf((char*)ShmOCPP16Data->DataTransfer[0].VendorId, "org.openchargealliance.iso15118pnc");
-			sprintf((char*)ShmOCPP16Data->DataTransfer[0].MessageId,"Authorize");
-			sprintf((char*)ShmOCPP16Data->DataTransfer[0].Data, "%s", json_object_to_json_string_ext(data, JSON_C_TO_STRING_PLAIN));
-			json_object_put(data);
+			if(parseCertResult == PASS)
+			{
+				json_object_object_add(data, "iso15118CertificateHashData", iso15118CertificateHashData);
 
-			ShmOCPP16Data->CsMsg.bits[0].DataTransferReq = 1;
-			ShmOCPP16Data->v2g_extend.AuthorizeReq = 0;
+				sprintf((char*)ShmOCPP16Data->DataTransfer[0].VendorId, "org.openchargealliance.iso15118pnc");
+				sprintf((char*)ShmOCPP16Data->DataTransfer[0].MessageId,"Authorize");
+				sprintf((char*)ShmOCPP16Data->DataTransfer[0].Data, "%s", json_object_to_json_string_ext(data, JSON_C_TO_STRING_PLAIN));
+				json_object_put(data);
+
+				ShmOCPP16Data->CsMsg.bits[0].DataTransferReq = 1;
+				ShmOCPP16Data->v2g_extend.AuthorizeReq = 0;
+			}
+			else
+			{
+				sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.Response_certificateStatus, "NoCertificateAvailable");
+				sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.Response_idTokenInfo.status, "Invalid");
+				ShmOCPP16Data->v2g_extend.AuthorizeConf = 1;
+			}
 		}
 
 		if(isWebsocketSendable && (server_sign == TRUE) && (ShmOCPP16Data->v2g_extend.Get15118EVCertificateReq == 1))
@@ -12034,13 +12196,17 @@ int handleDataTransferRequest(char *uuid, char *payload)
 		{
 			json_object *data;
 			data = json_tokener_parse(tempdata);
-
+			DEBUG_INFO("DeleteCertificate processing...\n");
 			if(!is_error(data))
 			{
-				sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.hashAlgorithm, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "hashAlgorithm")));
-				sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerNameHash, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "issuerNameHash")));
-				sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerKeyHash, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "issuerKeyHash")));
-				sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.serialNumber, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "serialNumber")));
+				if(json_object_object_get(json_object_object_get(data, "certificateHashData"), "hashAlgorithm") != NULL)
+					sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.hashAlgorithm, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "hashAlgorithm")));
+				if(json_object_object_get(json_object_object_get(data, "certificateHashData"), "issuerNameHash") != NULL)
+					sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerNameHash, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "issuerNameHash")));
+				if(json_object_object_get(json_object_object_get(data, "certificateHashData"), "issuerKeyHash") != NULL)
+					sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerKeyHash, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "issuerKeyHash")));
+				if(json_object_object_get(json_object_object_get(data, "certificateHashData"), "serialNumber") != NULL)
+					sprintf((char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.serialNumber, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "certificateHashData"), "serialNumber")));
 
 				DEBUG_INFO("hashAlgorithm: %s\n", ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.hashAlgorithm);
 				DEBUG_INFO("issuerNameHash: %s\n", ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerNameHash);
@@ -12050,58 +12216,25 @@ int handleDataTransferRequest(char *uuid, char *payload)
 				char temp[256] = {0};
 				char compareData[256] = {0};
 				int  isMatch = TRUE;
-				FILE *fp;
 
 				// Check certV2G
 				if(access(CERTIFICATE_V2G,F_OK) != -1)
 				{
-					isMatch = FALSE;
-					sprintf(temp ,"openssl x509 -noout -serial -in %s", CERTIFICATE_V2G);
-					fp = popen(temp, "r");
-					if(fp)
-					{
-						while(fgets(temp, sizeof(temp), fp) != NULL)
-						{
-							if(strstr(temp, "serial=") != NULL)
-							{
-								DEBUG_INFO("Certificate enddate info: %s\n", temp);
-								sscanf(temp, "%*[^=]=%s", compareData);
-								break;
-							}
-						}
-					}
-					if(strcmp(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) != 0)
+					parseCertInfo(CERTIFICATE_V2G, CERT_PARSE_SerialNumber, compareData);
+					if(strcmp(compareData, (char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.serialNumber) != 0)
 						isMatch = FALSE;
 
 					if(isMatch == TRUE)
 					{
-						memset(compareData, 0, ARRAY_SIZE(compareData));
-						sprintf(temp ,"openssl x509 -noout -issuer -in %s | openssl dgst -%s", CERTIFICATE_V2G, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-						fp = popen(temp, "r");
-						if(fp)
-						{
-							while(fgets(temp, sizeof(temp), fp) != NULL)
-							{
-								strcat(compareData, temp);
-							}
-						}
-						if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) == NULL)
+						parseCertInfo(CERTIFICATE_V2G, CERT_PARSE_IssuerNameHash, compareData);
+						if(strstr(compareData, (char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerNameHash) == NULL)
 							isMatch = FALSE;
 					}
 
 					if(isMatch == TRUE)
 					{
-						memset(compareData, 0, ARRAY_SIZE(compareData));
-						sprintf(temp ,"openssl x509 -noout -pubkey -in %s | openssl dgst -%s", CERTIFICATE_V2G, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-						fp = popen(temp, "r");
-						if(fp)
-						{
-							while(fgets(temp, sizeof(temp), fp) != NULL)
-							{
-								strcat(compareData, temp);
-							}
-						}
-						if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
+						parseCertInfo(CERTIFICATE_V2G, CERT_PARSE_IssuerKeyHash, compareData);
+						if(strstr(compareData, (char*)ShmOCPP16Data->v2g_extend.DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
 							isMatch = FALSE;
 					}
 
@@ -12181,7 +12314,9 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			{
 				char tempCert[] = "/Storage/OCPP/tempInstallCertificate.pem";
 
-				sprintf((char*)ShmOCPP16Data->v2g_extend.InstallCertificate.certificateType, "%s", json_object_get_string(json_object_object_get(data, "certificateType")));
+				if(json_object_object_get(data, "certificateType") != NULL)
+					sprintf((char*)ShmOCPP16Data->v2g_extend.InstallCertificate.certificateType, "%s", json_object_get_string(json_object_object_get(data, "certificateType")));
+				if(json_object_object_get(data, "certificate") != NULL)
 				sprintf((char*)ShmOCPP16Data->v2g_extend.InstallCertificate.certificate, "%s", json_object_get_string(json_object_object_get(data, "certificate")));
 				DEBUG_INFO("certificateType: %s\n", (char*)ShmOCPP16Data->v2g_extend.InstallCertificate.certificateType);
 				DEBUG_INFO("certificate: %s\n", (char*)ShmOCPP16Data->v2g_extend.InstallCertificate.certificate);
@@ -15832,51 +15967,20 @@ int handleDeleteCertificateRequest(char *uuid, char *payload)
 		{
 			// Check CentralSystemRootCertificate
 			DEBUG_INFO("Checking CentralSystemRootCertificate...\n");
-			sprintf(temp ,"openssl x509 -noout -serial -in %s", ROOTCA_CS);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "serial=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", compareData);
-						break;
-					}
-				}
-				DEBUG_INFO("SerialNumber= %s...\n", compareData);
-			}
+			parseCertInfo(ROOTCA_CS, CERT_PARSE_SerialNumber, compareData);
 			if(strcmp(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) != 0)
 				isMatch = FALSE;
 
 			if(isMatch == TRUE)
 			{
-				memset(compareData, 0, ARRAY_SIZE(compareData));
-				sprintf(temp ,"openssl x509 -noout -issuer -in %s | openssl dgst -%s", ROOTCA_CS, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-				fp = popen(temp, "r");
-				if(fp)
-				{
-					while(fgets(temp, sizeof(temp), fp) != NULL)
-					{
-						strcat(compareData, temp);
-					}
-				}
-				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) == NULL)
+				parseCertInfo(ROOTCA_CS, CERT_PARSE_IssuerNameHash, compareData);
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerNameHash) == NULL)
 					isMatch = FALSE;
 			}
 
 			if(isMatch == TRUE)
 			{
-				memset(compareData, 0, ARRAY_SIZE(compareData));
-				sprintf(temp ,"openssl x509 -noout -pubkey -in %s | openssl dgst -%s", ROOTCA_CS, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-				fp = popen(temp, "r");
-				if(fp)
-				{
-					while(fgets(temp, sizeof(temp), fp) != NULL)
-					{
-						strcat(compareData, temp);
-					}
-				}
+				parseCertInfo(ROOTCA_CS, CERT_PARSE_IssuerKeyHash, compareData);
 				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
 					isMatch = FALSE;
 			}
@@ -15893,52 +15997,21 @@ int handleDeleteCertificateRequest(char *uuid, char *payload)
 		// Check ManufacturerRootCertificate
 		if(access(ROOTCA_MFG,F_OK) != -1)
 		{
-			isMatch = FALSE;
-			sprintf(temp ,"openssl x509 -noout -serial -in %s", ROOTCA_MFG);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "serial=") != NULL)
-					{
-						DEBUG_INFO("Certificate enddate info: %s\n", temp);
-						sscanf(temp, "%*[^=]=%s", compareData);
-						break;
-					}
-				}
-			}
+			isMatch = TRUE;
+			parseCertInfo(ROOTCA_MFG, CERT_PARSE_SerialNumber, compareData);
 			if(strcmp(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) != 0)
 				isMatch = FALSE;
 
 			if(isMatch == TRUE)
 			{
-				memset(compareData, 0, ARRAY_SIZE(compareData));
-				sprintf(temp ,"openssl x509 -noout -issuer -in %s | openssl dgst -%s", ROOTCA_MFG, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-				fp = popen(temp, "r");
-				if(fp)
-				{
-					while(fgets(temp, sizeof(temp), fp) != NULL)
-					{
-						strcat(compareData, temp);
-					}
-				}
-				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.serialNumber) == NULL)
+				parseCertInfo(ROOTCA_MFG, CERT_PARSE_IssuerNameHash, compareData);
+				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerNameHash) == NULL)
 					isMatch = FALSE;
 			}
 
 			if(isMatch == TRUE)
 			{
-				memset(compareData, 0, ARRAY_SIZE(compareData));
-				sprintf(temp ,"openssl x509 -noout -pubkey -in %s | openssl dgst -%s", ROOTCA_MFG, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.hashAlgorithm);
-				fp = popen(temp, "r");
-				if(fp)
-				{
-					while(fgets(temp, sizeof(temp), fp) != NULL)
-					{
-						strcat(compareData, temp);
-					}
-				}
+				parseCertInfo(ROOTCA_MFG, CERT_PARSE_IssuerKeyHash, compareData);
 				if(strstr(compareData, (char*)ShmOCPP16Data->DeleteCertificate.certificateHashData.issuerKeyHash) == NULL)
 					isMatch = FALSE;
 			}
@@ -16159,89 +16232,21 @@ int handleGetInstalledCertificateIdsRequest(char *uuid, char *payload)
 		DEBUG_INFO("Requested Certificate: %s\n", (char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType);
 		sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_status, "Accepted");
 
-		char temp[512] = {0};
-		char capturedData[256] = {0};
-		char hashType[10] = {0};
-		FILE *fp;
-
 		// Check CentralSystemRootCertificate
 		if((strstr((char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType, "CentralSystemRootCertificate")!= NULL) && (access(ROOTCA_CS,F_OK) != -1))
 		{
-			memset(hashType, 0, ARRAY_SIZE(hashType));
-			sprintf(temp ,"openssl x509 -noout -text -in %s", ROOTCA_CS);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "Signature Algorithm:") != NULL)
-					{
-						if(strstr(temp, "sha256") != NULL)
-							sprintf((char*)hashType, "SHA256");
-						if(strstr(temp, "sha384") != NULL)
-							sprintf((char*)hashType, "SHA384");
-						if(strstr(temp, "sha512") != NULL)
-							sprintf((char*)hashType, "SHA512");
+			char parseData[512] = {0};
+			if(parseCertInfo(ROOTCA_MFG, CERT_PARSE_HashAlgorithm, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].hashAlgorithm, parseData);
 
-						break;
-					}
-				}
-				DEBUG_INFO("hashAlgorithm: %s\n", hashType);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].hashAlgorithm, hashType);
-			}
+			if(parseCertInfo(ROOTCA_MFG, CERT_PARSE_SerialNumber, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].serialNumber, parseData);
 
-			memset(capturedData, 0, ARRAY_SIZE(capturedData));
-			sprintf(temp ,"openssl x509 -noout -serial -in %s", ROOTCA_CS);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "serial=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", capturedData);
-						break;
-					}
-				}
-				DEBUG_INFO("serialNumber: %s\n", capturedData);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].serialNumber, capturedData);
-			}
-
-			memset(capturedData, 0, ARRAY_SIZE(capturedData));
-			sprintf(temp ,"openssl x509 -noout -issuer -in %s | openssl dgst -%s", ROOTCA_CS, (char*)hashType);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "(stdin)=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", capturedData);
-						break;
-					}
-				}
-				stringtrimspace(capturedData);
-				DEBUG_INFO("issuerNameHash: %s\n", capturedData);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerNameHash, capturedData);
-			}
+			if(parseCertInfo(ROOTCA_MFG, CERT_PARSE_IssuerNameHash, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerNameHash, parseData);
 
-			memset(capturedData, 0, ARRAY_SIZE(capturedData));
-			sprintf(temp ,"openssl x509 -noout -pubkey -in %s | openssl dgst -%s", ROOTCA_CS, (char*)hashType);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "(stdin)=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", capturedData);
-						break;
-					}
-				}
-				stringtrimspace(capturedData);
-				DEBUG_INFO("issuerKeyHash: %s\n", capturedData);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerKeyHash, capturedData);
-			}
+			if(parseCertInfo(ROOTCA_MFG, CERT_PARSE_IssuerKeyHash, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerKeyHash, parseData);
 		}
 		else
 		{
@@ -16252,81 +16257,18 @@ int handleGetInstalledCertificateIdsRequest(char *uuid, char *payload)
 		// Check ManufacturerRootCertificate
 		if((strstr((char*)ShmOCPP16Data->GetInstalledCertificateIds.certificateType, "ManufacturerRootCertificate") != NULL) && (access(ROOTCA_MFG,F_OK) != -1))
 		{
-			memset(hashType, 0, ARRAY_SIZE(hashType));
-			sprintf(temp ,"openssl x509 -noout -text -in %s", ROOTCA_MFG);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "Signature Algorithm:") != NULL)
-					{
-						if(strstr(temp, "sha256") != NULL)
-							sprintf((char*)hashType, "SHA256");
-						if(strstr(temp, "sha384") != NULL)
-							sprintf((char*)hashType, "SHA384");
-						if(strstr(temp, "sha512") != NULL)
-							sprintf((char*)hashType, "SHA512");
+			char parseData[512] = {0};
+			if(parseCertInfo(ROOTCA_MFG, 1, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].hashAlgorithm, parseData);
 
-						break;
-					}
-				}
-				DEBUG_INFO("hashAlgorithm: %s\n", hashType);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].hashAlgorithm, hashType);
-			}
+			if(parseCertInfo(ROOTCA_MFG, 1, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].serialNumber, parseData);
 
-			memset(capturedData, 0, ARRAY_SIZE(capturedData));
-			sprintf(temp ,"openssl x509 -noout -serial -in %s", ROOTCA_MFG);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "serial=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", capturedData);
-						break;
-					}
-				}
-				DEBUG_INFO("serialNumber: %s\n", capturedData);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].serialNumber, capturedData);
-			}
+			if(parseCertInfo(ROOTCA_MFG, 1, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerNameHash, parseData);
 
-			memset(capturedData, 0, ARRAY_SIZE(capturedData));
-			sprintf(temp ,"openssl x509 -noout -issuer -in %s | openssl dgst -%s", ROOTCA_MFG, (char*)hashType);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "(stdin)=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", capturedData);
-						break;
-					}
-				}
-				stringtrimspace(capturedData);
-				DEBUG_INFO("issuerNameHash: %s\n", capturedData);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerNameHash, capturedData);
-			}
-
-			memset(capturedData, 0, ARRAY_SIZE(capturedData));
-			sprintf(temp ,"openssl x509 -noout -pubkey -in %s | openssl dgst -%s", ROOTCA_MFG, (char*)hashType);
-			fp = popen(temp, "r");
-			if(fp)
-			{
-				while(fgets(temp, sizeof(temp), fp) != NULL)
-				{
-					if(strstr(temp, "(stdin)=") != NULL)
-					{
-						sscanf(temp, "%*[^=]=%s", capturedData);
-						break;
-					}
-				}
-				stringtrimspace(capturedData);
-				DEBUG_INFO("issuerKeyHash: %s\n", capturedData);
-				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerKeyHash, capturedData);
-			}
+			if(parseCertInfo(ROOTCA_MFG, 1, parseData) == PASS)
+				sprintf((char*)ShmOCPP16Data->GetInstalledCertificateIds.Response_certificateHashData[0].issuerKeyHash, parseData);
 		}
 		else
 		{
@@ -16739,6 +16681,7 @@ int handleInstallCertificateRequest(char *uuid, char *payload)
 					if(strstr(temp, "://") != NULL)
 					{
 						strcpy(ocspUrl, temp);
+						break;
 					}
 				}
 			}

+ 9 - 0
EVSE/Modularization/ocppfiles/MessageHandler.h

@@ -442,6 +442,15 @@ enum DIAGNOSTIC_NOTIFICATION_STATUS
 	DIAGNOSTIC_STATUS_UPLOADING =3
 };
 
+enum CERTIFICATE_PARSE_TYPE
+{
+	CERT_PARSE_HashAlgorithm = 0,
+	CERT_PARSE_SerialNumber = 1,
+	CERT_PARSE_IssuerNameHash = 2,
+	CERT_PARSE_IssuerKeyHash = 3,
+	CERT_PARSE_OcspUrl = 4
+};
+
 struct StructPeriod
 {
 	int		StartPeriod;

+ 1 - 1
EVSE/Modularization/ocppfiles/Module_OcppBackend.c

@@ -1361,7 +1361,7 @@ int main(void)
 	queueOpInfo.TransactionMessageResend = 0;
 
 	DEBUG_INFO("Module_OcppBackend task initialization...\n");
-	DEBUG_INFO("Git update date: 2022/09/02 \n");
+	DEBUG_INFO("Git update date: 2022/09/07 \n");
 	//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(ProcessShareMemory()== FAIL)

+ 1 - 0
EVSE/Modularization/ocppfiles/Module_OcppBackend.h

@@ -56,6 +56,7 @@
 
 #define		CERTIFICATE_CP			"/Storage/OCPP/certCP.pem"							// for security profile 3
 #define		CERTIFICATE_V2G			"/Storage/OCPP/certV2G.pem"							// for 15118
+#define		CERTIFICATE_PnCAuth		"/Storage/OCPP/certPnCAuth.pem"						// for PnC authorization
 
 #define		PRIVATE_KEY_CP			"/Storage/OCPP/certCP.key"							// for security profile 3
 #define		PRIVATE_KEY_V2G			"/Storage/OCPP/certV2G.key"							// for 15118

+ 133 - 9
EVSE/Projects/define.h

@@ -925,12 +925,126 @@ typedef union
 
 struct DC_METER_INFO
 {
-    double presetVoltage;                       // resolution: 1.000v
-    double presentCurrent;                      // resolution: 1.000a
-    double presentPower;                        // resolution: 1.000kw
-    double totlizeImportEnergy;                 // resolution: 1.000kwh
-    double totlizeExportEnergy;                 // resolution: 1.000kwh
-    unsigned char LinkStatus;                   // 0 = unknow ,1 = link , 2 miss link
+    double presetVoltage;						// resolution: 1.000v
+	double presentCurrent;					// resolution: 1.000a
+	double presentPower;						// resolution: 1.000kw
+	double totlizeImportEnergy;			// resolution: 1.000kwh
+	double totlizeExportEnergy;			// resolution: 1.000kwh
+	unsigned char timestamp[32];
+	unsigned char LinkStatus;								// 0 = unknow ,1 = link , 2 miss link
+};
+
+typedef union
+{
+		unsigned char Status;
+        struct
+        {
+	    			unsigned char suLinkStatusIsOk:1;
+            unsigned char muFatalErrorOccured:1;
+            unsigned char transactionIsOnGoing:1;
+            unsigned char tamperingIsDetected:1;
+            unsigned char timeSyncStatusIsOk:1;
+            unsigned char overTemperatureIsDetected:1;
+            unsigned char reversedVoltage:1;
+            unsigned char suMeasureFailureOccurred:1;
+        }bits;
+        
+}DcmbStatusFlag;
+
+typedef union
+{
+        unsigned char Errors;
+        struct
+        {
+            unsigned char muInitIsFailed:1;
+            unsigned char suStateIsInvalid:1;
+            unsigned char versionCheckIsFailed:1;
+            unsigned char muRngInitIsFailed:1;
+            unsigned char muDataIntegrityIsFailed:1;
+            unsigned char muFwIntegrityIsFailed:1;
+            unsigned char suIntegrityIsFailed:1;
+            unsigned char logbookIntegrityIsFailed:1;
+            unsigned char logbookIsFull:1;
+            unsigned char memoryAccessIsFailed:1;
+            unsigned char muStateIsFailed:1;
+            unsigned char res:5;
+        }bits;
+        
+}DcmbErrorFlag;
+   
+struct DC_METER_STATUS_INFO
+{
+	unsigned short StatusValue;
+	DcmbStatusFlag MeterStatusFlag;
+    
+	unsigned char applicationFirmwareVersion[16];
+    unsigned char applicationFirmwareAuthTag[32];
+    unsigned char legalFirmwareVersion[16];
+    unsigned char legalFirmwareAuthTag[32];
+    unsigned char sensorFirmwareVersion[16];
+    unsigned char sensorFirmwareCrc[4];
+
+    unsigned char Systime[32];
+    unsigned char ipAddress[32];
+    unsigned char meterId[32];
+
+	unsigned short ErrorValue;
+ 	DcmbErrorFlag MeterErrorFlag;
+   
+    unsigned char publicKey[140];
+    unsigned char publicKeyOcmf[200];
+    unsigned short indexOfLastTransaction;
+    unsigned short numberOfStoredTransactions;
+};
+
+struct DC_METER_TRANSACTION_HEAD
+{
+    unsigned char evseId[32];
+    unsigned char transactionId[32];
+    unsigned char clientId[32];
+    unsigned short tariffId;
+    unsigned short cableId;
+    unsigned short userData[32];
+    
+};
+
+struct DC_METER_TRANSACTION_ACTION
+{
+	struct DC_METER_TRANSACTION_HEAD head;
+	unsigned char transactionOCMF[512];
+	unsigned char OcmfInfoReady;                // 0 = nothing, 1 = ocmp info ready
+	unsigned char ActionCmd;                   // 1 = transaction Start, 2 transaction Stop, sync time
+};
+
+typedef union
+{
+				unsigned char Status;
+        struct
+        {
+	    			unsigned char intermediateRead:1;
+            unsigned char res:7;
+        }bits;
+        
+}DcmbTransactionReadlevel;
+
+struct DC_METER_TRANSACTION_RESULT
+{
+	unsigned short paginationCounter;
+	struct DC_METER_TRANSACTION_HEAD head;
+    unsigned char timestampStart[32];
+    unsigned char timestampStop[32];
+    unsigned int transactionDuration;
+    DcmbTransactionReadlevel intermediateRead;
+    unsigned int  transactionStatus;
+    unsigned char energyUnit[8];
+    double energyImport;
+    double energyImportTotalStart;
+    double energyImportTotalStop;
+    double energyExport;
+    double energyExportTotalStart;
+    double energyExportTotalStop;
+    unsigned char signature[140];
+    //unsigned char transactionOCMF[512];
 };
 
 typedef struct Bazel8Command
@@ -1081,6 +1195,10 @@ struct SysInfoData
     CabinetSettingFlag      CabinetSetting;
     struct LocalSharingInfo localSharingInfo;           // Local power sharing info structure
     struct DC_METER_INFO    DcMeterInfo[4];
+    struct DC_METER_STATUS_INFO DcMeterStatusInfo[4];
+    struct DC_METER_TRANSACTION_ACTION DcMeterReadTransactionRecord[4];
+    struct DC_METER_TRANSACTION_ACTION DcMeterTransactionAction[4];
+    struct DC_METER_TRANSACTION_RESULT DcMeterTransactionResult[4];
     unsigned char           OTPTemp;                    // OTP Temperature
     unsigned char           OTPTempR;                   // OTP Recovery Temperature
     struct LCD_OVERRIDE     LcdOveride;                 // LCD override info (no use anymore)
@@ -1414,7 +1532,7 @@ char AlarmStatusCode[160][6]=
     "012340",   // reserved
     "012341",   // reserved
     "012342",   // reserved
-    "012343",   // reserved
+    "012343",   // Tilt sensor self-test failed
     "012344",   // AC: Meter IC communication timeout
     "012345",   // AC: Pilot negative error
     "012346",   // Psu Communication error with CSU
@@ -1593,7 +1711,8 @@ struct AlarmCodeData
             unsigned char PsuPhaseOvp:1;                            //bit 5
             unsigned char :2;                                       //reserved bit 6 ~ bit 7
             //AlarmVal[17]
-            unsigned char :8;                                       //reserved bit 0 ~ bit 7
+            unsigned char :7;                                       //reserved bit 0 ~ bit 6
+            unsigned char TiltSensorStestFail:1;                    //reserved bit 7
             //AlarmVal[18]
             unsigned char MeterIcCommTimeout:1;                     //bit 0
             unsigned char PilotNegativeError:1;                     //bit 1
@@ -1603,7 +1722,12 @@ struct AlarmCodeData
 			unsigned char :3;                                       //reserved bit 4 ~ bit 7
             //AlarmVal[19]
             unsigned char PaymentCommTimeout:1;                     //Payment system communication timeout
-            unsigned char :7;                                       //reserved bit 1 ~ bit 7
+           	unsigned char MeterSlaveLosLink:1;                     	//DCMB meter slave module los link
+            unsigned char MeterSyncTimeError:1;            					//DCMB meter Sync Time Error
+            unsigned char MetertStartTransactionError:1;            //DCMB meter Start Transaction Error
+            unsigned char MetertStopTransactionError:1;             //DCMB meter Stop Transaction Error
+            unsigned char MetertGetTransactionOcmfError:1;          //DCMB meter Get OCMF Error        	
+            unsigned char :2;                                       //reserved bit 1 ~ bit 7
 		}bits;
 	}AlarmEvents;
 };

+ 4 - 2
EVSE/rootfs/root/ppp/ppp-on-dialer-org

@@ -39,7 +39,8 @@ exec /root/ppp/chat -v						\
 	""              "ATZ" 				\
 	OK              "ATE1" 				\
 	OK              "AT+CGDCONT=1,\"IP\",\"$APN\" " \
-        OK              "AT+CFUN=1"                     \
+	OK              \\d\\d\\d                       \
+        ""              "AT+CFUN=1"                     \
         OK              "AT+CGDATA=\"ppp\",1"         	\
 	TIMEOUT         22                              \
 	OK             	\\d\\d\\d			\
@@ -71,7 +72,8 @@ exec /root/ppp/chat -v						\
 	""              "ATZ" 				\
 	OK              "ATE1" 				\
 	OK              "AT+CGDCONT=1,\"IP\",\"$APN\" " \
-	OK              "AT+CFUN=1"                     \
+	OK              \\d\\d\\d                       \
+	""              "AT+CFUN=1"                     \
         OK              "AT+CGDATA=\"ppp\",1"         	\
         TIMEOUT         22                              \
 	OK             	\\d\\d\\d			\

+ 1 - 1
EVSE/rootfs/var/www/css/main.css

@@ -3610,7 +3610,7 @@ ul.envor-property-options li .fa {
 	width: 100%;
 }
 
-.envor-toggle article div {
+.envor-toggle article div:not(.file-upload):not(.file-input):not(.file-caption-main):not(.clearfix):not(.kv-fileinput-caption):not(.input-group-btn):not(.btn-file){
 /*	background-color: #f2f2f2;*/
 	padding: 10px;
     margin-bottom: 30px;

BIN
EVSE/rootfs/var/www/lang.db


+ 71 - 32
EVSE/rootfs/var/www/set_backend.php

@@ -239,11 +239,11 @@ CORE STYLES ABOVE - NO TOUCHY
 										</div>
 										<div class="form-group" style="display:<?php echo $am101;?>">
 											<label>Charge Box Id</label>
-											<input type="text" name="ChargeBoxId" id="ChargeBoxId" class="form-control" value="<?php echo $obj->{'ChargeBoxId'};?>">
+											<input type="text" name="ChargeBoxId" id="ChargeBoxId" class="form-control" value="<?php echo htmlspecialchars($obj->{'ChargeBoxId'});?>">
 										</div>
 										<div class="form-group" style="display:<?php echo $am101;?>">
 											<label><?php echo $lang->showWord("charge_point_vendor"); ?></label>
-											<input type="text" name="chargePointVendor" id="chargePointVendor" class="form-control" value="<?php echo $obj->{'chargePointVendor'};?>">
+											<input type="text" name="chargePointVendor" id="chargePointVendor" class="form-control" value="<?php echo htmlspecialchars($obj->{'chargePointVendor'});?>">
 										</div>
 										<div class="form-group" style="display:<?php echo $am101;?>">
 											<label><?php echo $lang->showWord("ocpp_security_profile"); ?></label>
@@ -256,7 +256,21 @@ CORE STYLES ABOVE - NO TOUCHY
 										</div>
 										<div id="OcppSecurityPasswordDiv" class="form-group" style="display:<?php echo $am101;?>">
 											<label><?php echo $lang->showWord("ocpp_security_password"); ?></label>
-											<input type="text" name="OcppSecurityPassword" id="OcppSecurityPassword" class="form-control" value="<?php echo $obj->{'OcppSecurityPassword'};?>">
+											<input type="text" name="OcppSecurityPassword" id="OcppSecurityPassword" class="form-control" value="<?php echo htmlspecialchars($obj->{'OcppSecurityPassword'});?>">
+										</div>
+										<div id="TLSwithClientSideCertificatesDiv" class="form-group file-upload" style="display:<?php echo $am101;?>">
+											<div class="file-upload">
+												<label><?php echo $lang->showWord("private_key_file"); ?> sha256 hash: <font color="#ff0000">(<?php echo strlen($obj->{'Private_Key'})>0?$obj->{'Private_Key'}:'File not found'?>)</font></label>
+												<div class="file-loading">
+													<input name="private_key" id="private_key" type="file" class="file" data-show-preview="false" data-show-upload="false">
+												</div>
+											</div>
+											<div class="file-upload">
+												<label><?php echo $lang->showWord("certificate_file"); ?> sha256 hash: <font color="#ff0000">(<?php echo strlen($obj->{'Certificate'})>0?$obj->{'Certificate'}:"File not found"?>)</font></label>
+												<div class="file-loading">
+													<input name="certificate" id="certificate" type="file" class="file" data-show-preview="false" data-show-upload="false">
+												</div>
+											</div>
 										</div>
 <?php if(substr($ModelName,0,2)=="AX" || substr($ModelName,0,2)=="AW" || substr($ModelName,0,1)=="D"){?>
 										<div class="form-group" style="display:block">
@@ -298,12 +312,12 @@ CORE STYLES ABOVE - NO TOUCHY
 												<option value="0" <?php echo $obj->{'MaintainServerSecurityProfile'}=="0"?"selected":""?>><?php echo $lang->showWord("none_security"); ?></option>
 												<option value="1" <?php echo $obj->{'MaintainServerSecurityProfile'}=="1"?"selected":""?>><?php echo $lang->showWord("unsecured_transport_with_basic_atuentication"); ?></option>
 												<option value="2" <?php echo $obj->{'MaintainServerSecurityProfile'}=="2"?"selected":""?>><?php echo $lang->showWord("tls_with_basic_authentication"); ?></option>
-												<option value="3" <?php echo $obj->{'MaintainServerSecurityProfile'}=="3"?"selected":""?>><?php echo $lang->showWord("tls_with_client_side_certificates"); ?></option>
+												<!--<option value="3" <?php echo $obj->{'MaintainServerSecurityProfile'}=="3"?"selected":""?>><?php echo $lang->showWord("tls_with_client_side_certificates"); ?></option>-->
 											</select>
 										</div>
 										<div id="MaintainServerSecurityPasswordDiv" class="form-group" style="display:<?php echo $am101;?>">
 											<label><?php echo $lang->showWord("maintain_server_security_password"); ?></label>
-											<input type="text" name="MaintainServerSecurityPassword" id="MaintainServerSecurityPassword" class="form-control" value="<?php echo $obj->{'MaintainServerSecurityPassword'};?>">
+											<input type="text" name="MaintainServerSecurityPassword" id="MaintainServerSecurityPassword" class="form-control" value="<?php echo htmlspecialchars($obj->{'MaintainServerSecurityPassword'});?>">
 										</div>
 									</section>
 								</article>
@@ -390,38 +404,46 @@ CORE STYLES ABOVE - NO TOUCHY
 			request.open("POST", "set_backend_action.php");
 
 			// POST 參數須使用 send() 發送
-			var data =  "BackendConnTimeout=" + document.getElementById("BackendConnTimeout").value +
-						"&OfflinePolicy=" + document.getElementById("OfflinePolicy").value +
-						"&OfflineMaxChargeEnergy=" + document.getElementById("OfflineMaxChargeEnergy").value+
-						"&OfflineMaxChargeDuration=" + document.getElementById("OfflineMaxChargeDuration").value+
-//						"&OcppConnStatus=" + document.getElementById("OcppConnStatus").value+
-						"&OcppServerURL=" + escape(document.getElementById("OcppServerURL").value)+
-						"&MaintainServerURL=" + escape(document.getElementById("MaintainServerURL").value)+
-						"&ChargeBoxId=" + escape(document.getElementById("ChargeBoxId").value)+
-						"&chargePointVendor=" + escape(document.getElementById("chargePointVendor").value)+
-						"&OcppSecurityProfile=" + document.getElementById("OcppSecurityProfile").value+
-						"&OcppSecurityPassword=" + escape(document.getElementById("OcppSecurityPassword").value)+
-						"&MaintainServerSecurityProfile=" + document.getElementById("MaintainServerSecurityProfile").value+
-						"&MaintainServerSecurityPassword=" + escape(document.getElementById("MaintainServerSecurityPassword").value);
+			var formData = new FormData();
+			var fileInput = document.getElementById('private_key');
+			var file = fileInput.files[0];
+			formData.append("private_key", file);
+			var fileInput = document.getElementById('certificate');
+			var file = fileInput.files[0];
+			formData.append("certificate", file);
+			formData.append("BackendConnTimeout", document.getElementById("BackendConnTimeout").value);
+			formData.append("OfflinePolicy", document.getElementById("OfflinePolicy").value);
+			formData.append("OfflineMaxChargeEnergy", document.getElementById("OfflineMaxChargeEnergy").value);
+			formData.append("OfflineMaxChargeDuration", document.getElementById("OfflineMaxChargeDuration").value);
+			formData.append("OcppServerURL", escapeHtml(document.getElementById("OcppServerURL").value));
+			formData.append("MaintainServerURL", escapeHtml(document.getElementById("MaintainServerURL").value));
+			formData.append("ChargeBoxId", escapeHtml(document.getElementById("ChargeBoxId").value));
+			formData.append("chargePointVendor", escapeHtml(document.getElementById("chargePointVendor").value));
+			formData.append("OcppSecurityProfile", document.getElementById("OcppSecurityProfile").value);
+			formData.append("OcppSecurityPassword", escapeHtml(document.getElementById("OcppSecurityPassword").value));
+			//formData.append("file", file);
+			formData.append("MaintainServerSecurityProfile", document.getElementById("MaintainServerSecurityProfile").value);
+			formData.append("MaintainServerSecurityPassword", escapeHtml(document.getElementById("MaintainServerSecurityPassword").value));
 <?php if(substr($ModelName,0,2)=="AX" || substr($ModelName,0,2)=="AW" || substr($ModelName,0,1)=="D"){?>
-				data += "&isEnableLocalPowerSharging=" + document.getElementById("isEnableLocalPowerSharging").value;
-				data += "&PowerSharingServerIP=" + document.getElementById("PowerSharingServerIP").value;
-				data += "&PowerSharingCapacity=" + document.getElementById("PowerSharingCapacity").value;
-				data += "&OcppReceiptrURL=" + document.getElementById("OcppReceiptrURL").value;
+			formData.append("isEnableLocalPowerSharging", document.getElementById("isEnableLocalPowerSharging").value);
+			formData.append("PowerSharingServerIP", document.getElementById("PowerSharingServerIP").value);
+			formData.append("PowerSharingCapacity", document.getElementById("PowerSharingCapacity").value);
+			formData.append("OcppReceiptrURL", escapeHtml(document.getElementById("OcppReceiptrURL").value));
 <?php } ?>
 <?php if(substr($ModelName,0,1)=="D" && substr($ModelName,3,1)=="C"){?>
-				data += "&isEnableTTIA=" + (document.getElementById("isEnableTTIA").checked?"1":"0")+
-						"&server_addr=" + document.getElementById("server_addr").value+
-						"&server_port=" + document.getElementById("server_port").value+
-						"&busVenderId=" + document.getElementById("busVenderId").value+
-						"&EquipmentProvider=" + document.getElementById("EquipmentProvider").value+
-						"&TransportationCompanyNo=" + document.getElementById("TransportationCompanyNo").value+
-						"&TTIAChargeBoxId=" + document.getElementById("TTIAChargeBoxId").value+
-						"&evseStation=" + document.getElementById("evseStation").value;
+			formData.append("isEnableTTIA", (document.getElementById("isEnableTTIA").checked?"1":"0"));
+			formData.append("server_addr", document.getElementById("server_addr").value);
+			formData.append("server_port", document.getElementById("server_port").value);
+			formData.append("busVenderId", document.getElementById("busVenderId").value);
+			formData.append("EquipmentProvider", document.getElementById("EquipmentProvider").value);
+			formData.append("TransportationCompanyNo", document.getElementById("TransportationCompanyNo").value);
+			formData.append("TTIAChargeBoxId", document.getElementById("TTIAChargeBoxId").value);
+			formData.append("evseStation", document.getElementById("evseStation").value);
 <?php } ?>
+
 			// POST 請求必須設置表頭在 open() 下面,send() 上面
-			request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
-			request.send(data);
+//			request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+			request.send(formData);
 
 			request.onreadystatechange = function() {
 				// 伺服器請求完成
@@ -530,9 +552,16 @@ CORE STYLES ABOVE - NO TOUCHY
 	function OcppSecurityProfile_changed(){
 		if(document.getElementById("OcppSecurityProfile").value == "1" || document.getElementById("OcppSecurityProfile").value == "2" || document.getElementById("OcppSecurityProfile").value == "3"){
 			document.getElementById("OcppSecurityPasswordDiv").style.display="block";
+			if(document.getElementById("OcppSecurityProfile").value == "3"){
+				document.getElementById("TLSwithClientSideCertificatesDiv").style.display="block";
+			}
+			else{
+				document.getElementById("TLSwithClientSideCertificatesDiv").style.display="none";
+			}
 		}
 		else{
 			document.getElementById("OcppSecurityPasswordDiv").style.display="none";
+			document.getElementById("TLSwithClientSideCertificatesDiv").style.display="none";
 		}
 	}
 	function MaintainServerSecurityProfile_changed(){
@@ -613,6 +642,16 @@ CORE STYLES ABOVE - NO TOUCHY
 		len = str.replace(/%[A-F\d]{2}/g, 'U').length;
 		return len;
 	}
+	function escapeHtml(text) {
+		var map = {
+			'&': '&amp;',
+			'<': '&lt;',
+			'>': '&gt;',
+			'"': '&quot;',
+			"'": '&#039;'
+		};
+		return text.replace(/[&<>"']/g, function(m) { return map[m]; });
+	}
 </script>
 
 

+ 23 - 2
EVSE/rootfs/var/www/set_backend_action.php

@@ -14,7 +14,8 @@
 	function create() {
 		$pattern="/^(ws|wss):\/\/((([0-9]{1,3}\.){3}[0-9]{1,3})|(([a-zA-Z0-9]+(([\-]?[a-zA-Z0-9]+)*\.)+)*[a-zA-Z]{2,}))+/";
 		if($_REQUEST['OcppServerURL']!=""){
-			if(!preg_match($pattern, $_REQUEST['OcppServerURL'])){
+			$json['OcppServerURL']				= str_replace("&amp;","&",str_replace("&quot;",'"',str_replace("&#039;","'",str_replace("&lt;","<",str_replace("&gt;",">",$_REQUEST['OcppServerURL'])))));
+			if(!preg_match($pattern, $json['OcppServerURL'])){
 				$jsone['result'] = "Fail";
 				$jsone['message'] = "OcppServerURL format error, fill it with 'ws://' or 'wss://'";
 				echo json_encode($jsone);
@@ -22,7 +23,8 @@
 			}
 		}
 		if($_REQUEST['MaintainServerURL']!=""){
-			if(!preg_match($pattern, $_REQUEST['MaintainServerURL'])){
+			$json['MaintainServerURL']			= str_replace("&amp;","&",str_replace("&quot;",'"',str_replace("&#039;","'",str_replace("&lt;","<",str_replace("&gt;",">",$_REQUEST['MaintainServerURL'])))));
+			if(!preg_match($pattern, $json['MaintainServerURL'])){
 				$jsone['result'] = "Fail";
 				$jsone['message'] = "MaintainServerURL format error, fill it with 'ws://' or 'wss://'";
 				echo json_encode($jsone);
@@ -114,6 +116,25 @@
 			checkLength("evseStation",15);
 			$json['evseStation']				= str_replace("&amp;","&",str_replace("&quot;",'"',str_replace("&#039;","'",str_replace("&lt;","<",str_replace("&gt;",">",$_REQUEST['evseStation'])))));
 		}
+		$fCount = count($_FILES['private_key']['name']);
+		if($fCount>0){
+			if ($_FILES["private_key"]["error"] > 0)
+			{
+				echo "Return Code: " . $_FILES["private_key"]["error"] . "<br />";
+			}
+			sleep(1);
+			move_uploaded_file($_FILES["private_key"]["tmp_name"],"/Storage/OCPP/certCP.key");
+		}
+		$fCount = count($_FILES['certificate']['name']);
+		if($fCount>0){
+			if ($_FILES["certificate"]["error"] > 0)
+			{
+				echo "Return Code: " . $_FILES["certificate"]["error"] . "<br />";
+			}
+			sleep(1);
+			move_uploaded_file($_FILES["certificate"]["tmp_name"],"/Storage/OCPP/certCP.pem");
+		}
+
 //		ob_start();
 		
 		shell_exec('sync;sync;sync');