Browse Source

2022-06-07/Jerry Wang
[OCPP 1.6][OCPP 1.6PH]
Action:
1. Add DMS v2.0 logic.
2. Add configuration key 'OffLineMaxChargingPower'.

File:
1. EVSE/Modularization/ocppfiles/MessageHandler.c
--> Action 1,2
2. EVSE/Modularization/ocppfiles/MessageHandler.h
--> Action 2
3. EVSE/Modularization/ocppph/MessageHandler.c
--> Action 1,2
4. EVSE/Modularization/ocppph/MessageHandler.h
--> Action 2
5. EVSE/Projects/define.h
--> Action 1,2

Jerry Wang 2 years ago
parent
commit
da59952afd

+ 312 - 106
EVSE/Modularization/ocppfiles/MessageHandler.c

@@ -97,11 +97,16 @@ static struct OCPPAuthLocalElemet
 uint8_t reqSampleMeter[CONNECTOR_QUANTITY]={0};
 uint8_t reqClockAlignMeter[CONNECTOR_QUANTITY]={0};
 
-//=============================================
+//============================================
 // OCPP HeartBeat Response Not Receive Counts
 //============================================
 static int HeartBeatWithNOResponse = 0;
 
+//============================================
+// OCPP California Pricing Requirements
+//============================================
+static char dmsVersion[21]	= {0};
+
 extern sqlite3 *db;
 
 int TransactionMessageAttemptsGet(void);
@@ -2096,6 +2101,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 
 	uint8_t limitMax=0;
 	int compositePeriodIdx = 0;
+	//uint8_t isDurationNull = FALSE;
 
 	CurrentTime = time(NULL);
 	tmComposite=localtime(&CurrentTime);
@@ -2252,6 +2258,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 								else
 								{
 									maxProfile.ChargingSchedule.Duration = 86400;
+									//isDurationNull = TRUE;
 								}
 
 								if(json_object_object_get(json_object_object_get(json_object_object_get(obj, "csChargingProfiles"), "chargingSchedule"), "startSchedule") != NULL)
@@ -2364,6 +2371,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 						else
 						{
 							maxProfile.ChargingSchedule.Duration = 86400;
+							//isDurationNull = TRUE;
 						}
 
 						if(json_object_object_get(json_object_object_get(json_object_object_get(obj, "csChargingProfiles"), "chargingSchedule"), "startSchedule") != NULL)
@@ -2424,7 +2432,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 	{
 		if(strstr((char*)maxProfile.ChargingProfileKind, "Absolute") != NULL)
 		{
-			if(maxProfile.ChargingSchedule.Duration != -1)
+			if((maxProfile.ChargingSchedule.Duration != -1)/* && (isDurationNull)*/)
 			{
 				maxProfile.ChargingSchedule.Duration = ((maxProfile.ChargingSchedule.Duration-getStartStop(maxProfile.ChargingSchedule.StartSchedule, compositeProfile.ChargingSchedule.StartSchedule))<0?
 														0:
@@ -5099,7 +5107,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "org.openchargealliance.costmsg");
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -5162,7 +5173,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "org.openchargealliance.costmsg");
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -5225,7 +5239,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "org.openchargealliance.costmsg");
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -5280,7 +5297,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "org.openchargealliance.costmsg");
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -5342,7 +5362,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "org.openchargealliance.costmsg");
 							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16Data->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -10976,20 +10999,34 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			if(!is_error(data))
 			{
 				memset(&ShmOCPP16Data->Cost.SetUserPrice, 0x00, sizeof(struct StrcutSetUserPrice));
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 
 				if(json_object_object_get(data, "idToken") != NULL)
 				{
 					sprintf((char*)ShmOCPP16Data->Cost.SetUserPrice.idToken, "%s", json_object_get_string(json_object_object_get(data, "idToken")));
 					DEBUG_INFO("idToken: %s\n", json_object_get_string(json_object_object_get(data, "idToken")));
 				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("idToken not found."));
+				}
 
-				if(json_object_object_get(data, "price") != NULL)
+				if(json_object_object_get(data, "price") != NULL) //v1.0
 				{
 					sprintf((char*)ShmOCPP16Data->Cost.SetUserPrice.price, "%s", json_object_get_string(json_object_object_get(data, "price")));
 					DEBUG_INFO("price: %s\n", json_object_get_string(json_object_object_get(data, "price")));
 				}
-
-				json_object_object_add(response, "status", json_object_new_string("Accepted"));
+				else if(json_object_object_get(data, "priceText") != NULL) //v2.0
+				{
+					sprintf((char*)ShmOCPP16Data->Cost.SetUserPrice.price, "%s", json_object_get_string(json_object_object_get(data, "priceText")));
+					DEBUG_INFO("priceText: %s\n", json_object_get_string(json_object_object_get(data, "priceText")));
+				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("price or priceText not found."));
+				}
 			}
 			else
 			{
@@ -11007,9 +11044,13 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			data = json_tokener_parse(tempdata);
 			if(!is_error(data))
 			{
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 				if(json_object_object_get(data, "txId") != NULL)
 				{
-					DEBUG_INFO("transaction id: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
+					// California pricing V1.0
+					DEBUG_INFO("California pricing V1.0\n");
+					DEBUG_INFO("txId: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
+					sprintf((char*)dmsVersion, "1.0");
 
 					for(int idx = 0;idx<gunTotalNumber;idx++)
 					{
@@ -11021,145 +11062,204 @@ int handleDataTransferRequest(char *uuid, char *payload)
 
 							if(json_object_object_get(data, "description") != NULL)
 							{
-								// California pricing V1.0
-								DEBUG_INFO("California pricing V1.0\n");
 								DEBUG_INFO("description: %s\n", json_object_get_string(json_object_object_get(data, "description")));
 								sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].description, "%s", json_object_get_string(json_object_object_get(data, "description")));
 							}
 							else
 							{
-								// California pricing V1.1
-								DEBUG_INFO("California pricing V1.1\n");
-								if(json_object_object_get(data, "timestamp") != NULL)
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("description not found."));
+							}
+						}
+					}
+				}
+				else if(json_object_object_get(data, "transactionId") != NULL)
+				{
+					// California pricing V2.0
+					DEBUG_INFO("California pricing V2.0\n");
+					DEBUG_INFO("transactionId: %d\n", json_object_get_int(json_object_object_get(data, "transactionId")));
+					sprintf((char*)dmsVersion, "2.0");
+
+					for(int idx=0;idx<gunTotalNumber;idx++)
+					{
+						if(ShmOCPP16Data->StartTransaction[idx].ResponseTransactionId == json_object_get_int(json_object_object_get(data, "transactionId")))
+						{
+
+							ShmOCPP16Data->Cost.RunningCost[idx].txId = json_object_get_int(json_object_object_get(data, "transactionId"));
+							if(json_object_object_get(data, "timestamp") != NULL)
+							{
+								DEBUG_INFO("timestamp: %s\n", json_object_get_string(json_object_object_get(data, "timestamp")));
+								sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].timestamp, "%s", json_object_get_string(json_object_object_get(data, "timestamp")));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("timestamp not found."));
+							}
+
+							if(json_object_object_get(data, "meterValue") != NULL)
+							{
+								DEBUG_INFO("meterValue: %d\n", json_object_get_int(json_object_object_get(data, "meterValue")));
+								ShmOCPP16Data->Cost.RunningCost[idx].meterValue = json_object_get_int(json_object_object_get(data, "meterValue"));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("meterValue not found."));
+							}
+
+							if(json_object_object_get(data, "cost") != NULL)
+							{
+								DEBUG_INFO("cost: %f\n", json_object_get_double(json_object_object_get(data, "cost")));
+								ShmOCPP16Data->Cost.RunningCost[idx].cost = json_object_get_double(json_object_object_get(data, "cost"));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("cost not found."));
+							}
+
+							if(json_object_object_get(data, "state") != NULL)
+							{
+								DEBUG_INFO("state: %s\n", json_object_get_string(json_object_object_get(data, "state")));
+								sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].state, "%s", json_object_get_string(json_object_object_get(data, "state")));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("state not found."));
+							}
+
+							if(json_object_object_get(data, "chargingPrice") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice") != NULL)
 								{
-									DEBUG_INFO("timestamp: %s\n", json_object_get_string(json_object_object_get(data, "timestamp")));
-									sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].timestamp, "%s", json_object_get_string(json_object_object_get(data, "timestamp")));
+									DEBUG_INFO("chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice")));
+									ShmOCPP16Data->Cost.RunningCost[idx].chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice"));
 								}
 
-								if(json_object_object_get(data, "meterValue") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice") != NULL)
 								{
-									DEBUG_INFO("meterValue: %d\n", json_object_get_int(json_object_object_get(data, "meterValue")));
-									ShmOCPP16Data->Cost.RunningCost[idx].meterValue = json_object_get_int(json_object_object_get(data, "meterValue"));
+									DEBUG_INFO("chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice")));
+									ShmOCPP16Data->Cost.RunningCost[idx].chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice"));
 								}
 
-								if(json_object_object_get(data, "cost") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee") != NULL)
 								{
-									DEBUG_INFO("cost: %f\n", json_object_get_double(json_object_object_get(data, "cost")));
-									ShmOCPP16Data->Cost.RunningCost[idx].cost = json_object_get_double(json_object_object_get(data, "cost"));
+									DEBUG_INFO("chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee")));
+									ShmOCPP16Data->Cost.RunningCost[idx].chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee"));
 								}
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("chargingPrice not found."));
+							}
 
-								if(json_object_object_get(data, "state") != NULL)
+							if(json_object_object_get(data, "idlePrice") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes") != NULL)
 								{
-									DEBUG_INFO("state: %s\n", json_object_get_string(json_object_object_get(data, "state")));
-									sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].state, "%s", json_object_get_string(json_object_object_get(data, "state")));
+									DEBUG_INFO("idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes")));
+									ShmOCPP16Data->Cost.RunningCost[idx].idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes"));
 								}
 
-								if(json_object_object_get(data, "chargingPrice") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice") != NULL)
 								{
-									if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice") != NULL)
-									{
-										DEBUG_INFO("chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice")));
-										ShmOCPP16Data->Cost.RunningCost[idx].chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice"));
-									}
+									DEBUG_INFO("idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice")));
+									ShmOCPP16Data->Cost.RunningCost[idx].idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice"));
+								}
+							}
 
-									if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice") != NULL)
-									{
-										DEBUG_INFO("chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice")));
-										ShmOCPP16Data->Cost.RunningCost[idx].chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice"));
-									}
+							if(json_object_object_get(data, "nextPeriod") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime") != NULL)
+								{
+									DEBUG_INFO("nextPeriod-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
+									sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
+								}
+								else
+								{
+									json_object_object_add(response, "status", json_object_new_string("Rejected"));
+									json_object_object_add(response, "data", json_object_new_string("atTime not found."));
+								}
 
-									if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice") != NULL)
+								{
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice") != NULL)
 									{
-										DEBUG_INFO("chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee")));
-										ShmOCPP16Data->Cost.RunningCost[idx].chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee"));
+										DEBUG_INFO("nextPeriod-chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice")));
+										ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice"));
 									}
-								}
 
-								if(json_object_object_get(data, "idlePrice") != NULL)
-								{
-									if(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice") != NULL)
 									{
-										DEBUG_INFO("idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes")));
-										ShmOCPP16Data->Cost.RunningCost[idx].idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes"));
+										DEBUG_INFO("nextPeriod-chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice")));
+										ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice"));
 									}
 
-									if(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee") != NULL)
 									{
-										DEBUG_INFO("idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice")));
-										ShmOCPP16Data->Cost.RunningCost[idx].idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice"));
+										DEBUG_INFO("nextPeriod-chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee")));
+										ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee"));
 									}
 								}
+								else
+								{
+									json_object_object_add(response, "status", json_object_new_string("Rejected"));
+									json_object_object_add(response, "data", json_object_new_string("chargingPrice not found."));
+								}
 
-								if(json_object_object_get(data, "nextPeriod") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice") != NULL)
 								{
-									if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes") != NULL)
 									{
-										DEBUG_INFO("nextPeriod-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
-										sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
+										DEBUG_INFO("nextPeriod-idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes")));
+										ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes"));
 									}
 
-									if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice") != NULL)
 									{
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice")));
-											ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice"));
-										}
-
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice")));
-											ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice"));
-										}
-
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee")));
-											ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee"));
-										}
+										DEBUG_INFO("nextPeriod-idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice")));
+										ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice"));
 									}
+								}
+							}
 
-									if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice") != NULL)
-									{
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes")));
-											ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes"));
-										}
-
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice")));
-											ShmOCPP16Data->Cost.RunningCost[idx].nextPeriod.idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice"));
-										}
-									}
+							if(json_object_object_get(data, "triggerMeterValue") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime") != NULL)
+								{
+									DEBUG_INFO("triggerMeterValue-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
+									sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
 								}
 
-								if(json_object_object_get(data, "triggerMeterValue") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh") != NULL)
 								{
-									if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime") != NULL)
-									{
-										DEBUG_INFO("triggerMeterValue-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
-										sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
-									}
+									DEBUG_INFO("triggerMeterValue-atEnergykWh: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh")));
+									ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atEnergykWh = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh"));
+								}
 
-									if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh") != NULL)
-									{
-										DEBUG_INFO("triggerMeterValue-atEnergykWh: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh")));
-										ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atEnergykWh = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh"));
-									}
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW") != NULL)
+								{
+									DEBUG_INFO("triggerMeterValue-atPowerkW: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW")));
+									ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atPowerkW = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW"));
+								}
 
-									if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW") != NULL)
-									{
-										DEBUG_INFO("triggerMeterValue-atPowerkW: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW")));
-										ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atPowerkW = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW"));
-									}
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atCPStatus") != NULL)
+								{
+									DEBUG_INFO("triggerMeterValue-atCPStatus: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atCPStatus")));
+									sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atCPStatus, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atCPStatus")));
 								}
 							}
 						}
 					}
 				}
-				json_object_object_add(response, "status", json_object_new_string("Accepted"));
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("txId or transactionId not found."));
+				}
 			}
 			else
 			{
@@ -11177,9 +11277,10 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			data = json_tokener_parse(tempdata);
 			if(!is_error(data))
 			{
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 				if(json_object_object_get(data, "txId") != NULL)
 				{
-					DEBUG_INFO("transaction id: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
+					DEBUG_INFO("v1.0 txId: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
 
 					for(int idx = 0;idx<gunTotalNumber;idx++)
 					{
@@ -11194,10 +11295,61 @@ int handleDataTransferRequest(char *uuid, char *payload)
 								DEBUG_INFO("description: %s\n", json_object_get_string(json_object_object_get(data, "description")));
 								sprintf((char*)ShmOCPP16Data->Cost.FinalCost[idx].description, "%s", json_object_get_string(json_object_object_get(data, "description")));
 							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("description not found."));
+							}
 						}
 					}
 				}
-				json_object_object_add(response, "status", json_object_new_string("Accepted"));
+				else if(json_object_object_get(data, "transactionId") != NULL)
+				{
+					DEBUG_INFO("v2.0 transactionId: %d\n", json_object_get_int(json_object_object_get(data, "transactionId")));
+
+					for(int idx = 0;idx<gunTotalNumber;idx++)
+					{
+						if(ShmOCPP16Data->StartTransaction[idx].ResponseTransactionId == json_object_get_int(json_object_object_get(data, "transactionId")))
+						{
+							memset(&ShmOCPP16Data->Cost.FinalCost[idx], 0x00, sizeof(struct StrcutFinalCost));
+
+							ShmOCPP16Data->Cost.FinalCost[idx].txId = json_object_get_int(json_object_object_get(data, "transactionId"));
+
+							if(json_object_object_get(data, "cost") != NULL)
+							{
+								DEBUG_INFO("cost: %s\n", json_object_get_string(json_object_object_get(data, "cost")));
+								ShmOCPP16Data->Cost.FinalCost[idx].cost = json_object_get_double(json_object_object_get(data, "cost"));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("cost not found."));
+							}
+
+							if(json_object_object_get(data, "priceText") != NULL)
+							{
+								DEBUG_INFO("priceText: %s\n", json_object_get_string(json_object_object_get(data, "priceText")));
+								sprintf((char*)ShmOCPP16Data->Cost.FinalCost[idx].priceText, "%s", json_object_get_string(json_object_object_get(data, "priceText")));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("priceText not found."));
+							}
+
+							if(json_object_object_get(data, "qrCodeText") != NULL)
+							{
+								DEBUG_INFO(": %s\n", json_object_get_string(json_object_object_get(data, "qrCodeText")));
+								sprintf((char*)ShmOCPP16Data->Cost.FinalCost[idx].qrCodeText, "%s", json_object_get_string(json_object_object_get(data, "qrCodeText")));
+							}
+						}
+					}
+				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("txId or transactionId not found."));
+				}
 			}
 			else
 			{
@@ -16176,7 +16328,7 @@ int initialConfigurationTable(void)
 	char sstr[256]={0};
 	int c = 0;
 	char *loc;
-	int	confVersion = 15;
+	int	confVersion = 16;
 
 	DEBUG_INFO("initialConfigurationTable...version: %d\n", confVersion);
 	//start_t = clock();
@@ -16620,6 +16772,13 @@ int initialConfigurationTable(void)
 
 		fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","EVCCID_PREFIX", "false", ShmOCPP16Data->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData);
 
+		// OffLineMaxChargingPower
+		ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility = 1;
+		strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemName, "OffLineMaxChargingPower");
+		strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "0" );
+
+		fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","OffLineMaxChargingPower", "false", ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData);
+
 		// Configuration Version
 		ShmOCPP16Data->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemAccessibility = 0;
 		strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemName, "ConfigurationVersion");
@@ -17108,6 +17267,12 @@ int initialConfigurationTable(void)
 					sprintf((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData, "%s", valuestr);
 				}
 
+				if(strcmp(keystr, "OffLineMaxChargingPower") == 0)
+				{
+					ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility = (strcmp(readonlystr, "true")==0) ? 0 : 1;
+					sprintf((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "%s", valuestr);
+				}
+
 				if(strcmp(keystr, "ConfigurationVersion") == 0)
 				{
 					ShmOCPP16Data->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemAccessibility = (strcmp(readonlystr, "true")==0) ? 0 : 1;
@@ -17694,6 +17859,15 @@ void StoreConfigurationTable(void)
 
 	fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","EVCCID_PREFIX", "false", (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData);
 
+	// OffLineMaxChargingPower
+	/*
+	ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility = 1;
+	strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemName, "OffLineMaxChargingPower");
+	strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "" );
+	*/
+
+	fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","OffLineMaxChargingPower", "false", (char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData);
+
 	// ConfigurationVersion
 	/*
 	ShmOCPP16Data->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemAccessibility = 1;
@@ -18791,6 +18965,24 @@ void getKeyValue(char *keyReq)
 			  isKnowKey = TRUE;
 		  }
 
+		  if(isEmpty ||  strcmp(keyReq, "OffLineMaxChargingPower") == 0 )
+		  {
+			  strcpy((char *)ShmOCPP16Data->GetConfiguration.Key[GetConfiguration_OffLineMaxChargingPower].Item, "OffLineMaxChargingPower");
+			  strcpy((char *)ShmOCPP16Data->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].Key, "OffLineMaxChargingPower");
+
+			  if(ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility == 1)
+			  {
+				  strcpy((char *)ShmOCPP16Data->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].ReadOnly, "0"/*"FALSE"*/);
+			  }
+			  else
+			  {
+				  strcpy((char *)ShmOCPP16Data->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].ReadOnly, "1"/*"TRUE"*/);
+			  }
+
+			  strcpy((char *)ShmOCPP16Data->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].Value, (const char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData );
+			  isKnowKey = TRUE;
+		  }
+
 	      if(isEmpty ||  strcmp(keyReq, "ConfigurationVersion") == 0 )
 		  {
 			  strcpy((char *)ShmOCPP16Data->GetConfiguration.Key[GetConfiguration_ConfigurationVersion].Item, "ConfigurationVersion");
@@ -20142,6 +20334,20 @@ int setKeyValue(char *key, char *value)
 		}
 	}
 
+	if(strcmp(key, "OffLineMaxChargingPower") == 0)
+	{
+		if(ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility == 1)
+		{
+			strcpy(str, (const char*)value);
+			sprintf((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "%s", str );
+			isSuccess = ConfigurationStatus_Accepted;
+		}
+		else
+		{
+			isSuccess = ConfigurationStatus_Rejected;
+		}
+	}
+
 #if 0
     //For OCPP Test Case
     if(strcmp(key, "LocalAuthorizationListEnabled") == 0)

+ 308 - 103
EVSE/Modularization/ocppph/MessageHandler.c

@@ -98,11 +98,16 @@ static struct OCPPAuthLocalElemet
 uint8_t reqSampleMeter[CONNECTOR_QUANTITY]={0};
 uint8_t reqClockAlignMeter[CONNECTOR_QUANTITY]={0};
 
-//=============================================
+//============================================
 // OCPP HeartBeat Response Not Receive Counts
 //============================================
 static int HeartBeatWithNOResponse = 0;
 
+//============================================
+// OCPP California Pricing Requirements
+//============================================
+static char dmsVersion[21]	= {0};
+
 extern sqlite3 *db;
 
 int TransactionMessageAttemptsGet(void);
@@ -1601,6 +1606,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 
 	uint8_t limitMax=0;
 	int compositePeriodIdx = 0;
+	//uint8_t isDurationNull = FALSE;
 
 	CurrentTime = time(NULL);
 	tmComposite=localtime(&CurrentTime);
@@ -1757,6 +1763,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 								else
 								{
 									maxProfile.ChargingSchedule.Duration = 86400;
+									//isDurationNull = TRUE;
 								}
 
 								if(json_object_object_get(json_object_object_get(json_object_object_get(obj, "csChargingProfiles"), "chargingSchedule"), "startSchedule") != NULL)
@@ -1869,6 +1876,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 						else
 						{
 							maxProfile.ChargingSchedule.Duration = 86400;
+							//isDurationNull = TRUE;
 						}
 
 						if(json_object_object_get(json_object_object_get(json_object_object_get(obj, "csChargingProfiles"), "chargingSchedule"), "startSchedule") != NULL)
@@ -2008,7 +2016,7 @@ void checkChargePointMaxProfile(uint32_t durationReq, struct StructChargingProfi
 			}
 			else
 			{
-				if(maxProfile.ChargingSchedule.Duration != -1)
+				if((maxProfile.ChargingSchedule.Duration != -1)/* && (isDurationNull)*/)
 				{
 					maxProfile.ChargingSchedule.Duration = ((maxProfile.ChargingSchedule.Duration-getStartSinceRecurring(maxProfile.ChargingSchedule.StartSchedule, compositeProfile.ChargingSchedule.StartSchedule, TRUE))<0?
 															0:
@@ -4619,7 +4627,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -4682,7 +4693,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -4745,7 +4759,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -4800,7 +4817,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -4862,7 +4882,10 @@ void CheckSystemValue(void)
 							getNowDatetime(ts);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].MessageId, "ConnectorUnplugged");
-							sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							if(strcmp((char*)dmsVersion, "2.0")==0)
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"transactionId\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
+							else
+								sprintf((char*)ShmOCPP16DataPH->DataTransfer[gun_index].Data, "{\\\"idTx\\\":%d,\\\"timestamp\\\":\\\"%s\\\"}", ShmOCPP16DataPH->StartTransaction[gun_index].ResponseTransactionId, ts);
 							sendUnplugByDataTransferRequest(gun_index);
 							interLock.isSentUnplug[gun_index] = 1;
 						}
@@ -10514,20 +10537,36 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			if(!is_error(data))
 			{
 				memset(&ShmOCPP16DataPH->Cost.SetUserPrice, 0x00, sizeof(struct StrcutSetUserPrice));
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 
 				if(json_object_object_get(data, "idToken") != NULL)
 				{
 					sprintf((char*)ShmOCPP16DataPH->Cost.SetUserPrice.idToken, "%s", json_object_get_string(json_object_object_get(data, "idToken")));
 					DEBUG_INFO("idToken: %s\n", json_object_get_string(json_object_object_get(data, "idToken")));
 				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("idToken not found."));
+				}
 
-				if(json_object_object_get(data, "price") != NULL)
+				if(json_object_object_get(data, "price") != NULL) //v1.0
 				{
 					sprintf((char*)ShmOCPP16DataPH->Cost.SetUserPrice.price, "%s", json_object_get_string(json_object_object_get(data, "price")));
 					DEBUG_INFO("price: %s\n", json_object_get_string(json_object_object_get(data, "price")));
 				}
+				else if(json_object_object_get(data, "priceText") != NULL) //v2.0
+				{
+					sprintf((char*)ShmOCPP16DataPH->Cost.SetUserPrice.price, "%s", json_object_get_string(json_object_object_get(data, "priceText")));
+					DEBUG_INFO("priceText: %s\n", json_object_get_string(json_object_object_get(data, "priceText")));
+				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("price or priceText not found."));
+				}
+
 
-				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 			}
 			else
 			{
@@ -10545,9 +10584,13 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			data = json_tokener_parse(tempdata);
 			if(!is_error(data))
 			{
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 				if(json_object_object_get(data, "txId") != NULL)
 				{
-					DEBUG_INFO("transaction id: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
+					// California pricing V1.0
+					DEBUG_INFO("California pricing V1.0\n");
+					DEBUG_INFO("txId: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
+					sprintf((char*)dmsVersion, "1.0");
 
 					for(int idx = 0;idx<gunTotalNumber;idx++)
 					{
@@ -10564,140 +10607,196 @@ int handleDataTransferRequest(char *uuid, char *payload)
 								DEBUG_INFO("description: %s\n", json_object_get_string(json_object_object_get(data, "description")));
 								sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].description, "%s", json_object_get_string(json_object_object_get(data, "description")));
 							}
+
+						}
+
+					}
+				}
+				else if(json_object_object_get(data, "transactionId") != NULL)
+				{
+					// California pricing V2.0
+					DEBUG_INFO("California pricing V2.0\n");
+					DEBUG_INFO("transactionId: %d\n", json_object_get_int(json_object_object_get(data, "transactionId")));
+					sprintf((char*)dmsVersion, "2.0");
+
+					for(int idx=0;idx<gunTotalNumber;idx++)
+					{
+						if(ShmOCPP16DataPH->StartTransaction[idx].ResponseTransactionId == json_object_get_int(json_object_object_get(data, "transactionId")))
+						{
+							if(json_object_object_get(data, "timestamp") != NULL)
+							{
+								DEBUG_INFO("timestamp: %s\n", json_object_get_string(json_object_object_get(data, "timestamp")));
+								sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].timestamp, "%s", json_object_get_string(json_object_object_get(data, "timestamp")));
+							}
 							else
 							{
-								// California pricing V1.1
-								DEBUG_INFO("California pricing V1.1\n");
-								if(json_object_object_get(data, "timestamp") != NULL)
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("timestamp not found."));
+							}
+
+							if(json_object_object_get(data, "meterValue") != NULL)
+							{
+								DEBUG_INFO("meterValue: %d\n", json_object_get_int(json_object_object_get(data, "meterValue")));
+								ShmOCPP16DataPH->Cost.RunningCost[idx].meterValue = json_object_get_int(json_object_object_get(data, "meterValue"));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("meterValue not found."));
+							}
+
+							if(json_object_object_get(data, "cost") != NULL)
+							{
+								DEBUG_INFO("cost: %f\n", json_object_get_double(json_object_object_get(data, "cost")));
+								ShmOCPP16DataPH->Cost.RunningCost[idx].cost = json_object_get_double(json_object_object_get(data, "cost"));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("cost not found."));
+							}
+
+							if(json_object_object_get(data, "state") != NULL)
+							{
+								DEBUG_INFO("state: %s\n", json_object_get_string(json_object_object_get(data, "state")));
+								sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].state, "%s", json_object_get_string(json_object_object_get(data, "state")));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("state not found."));
+							}
+
+							if(json_object_object_get(data, "chargingPrice") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice") != NULL)
 								{
-									DEBUG_INFO("timestamp: %s\n", json_object_get_string(json_object_object_get(data, "timestamp")));
-									sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].timestamp, "%s", json_object_get_string(json_object_object_get(data, "timestamp")));
+									DEBUG_INFO("chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice"));
 								}
 
-								if(json_object_object_get(data, "meterValue") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice") != NULL)
 								{
-									DEBUG_INFO("meterValue: %d\n", json_object_get_int(json_object_object_get(data, "meterValue")));
-									ShmOCPP16DataPH->Cost.RunningCost[idx].meterValue = json_object_get_int(json_object_object_get(data, "meterValue"));
+									DEBUG_INFO("chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice"));
 								}
 
-								if(json_object_object_get(data, "cost") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee") != NULL)
 								{
-									DEBUG_INFO("cost: %f\n", json_object_get_double(json_object_object_get(data, "cost")));
-									ShmOCPP16DataPH->Cost.RunningCost[idx].cost = json_object_get_double(json_object_object_get(data, "cost"));
+									DEBUG_INFO("chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee"));
 								}
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("chargingPrice not found."));
+							}
 
-								if(json_object_object_get(data, "state") != NULL)
+							if(json_object_object_get(data, "idlePrice") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes") != NULL)
 								{
-									DEBUG_INFO("state: %s\n", json_object_get_string(json_object_object_get(data, "state")));
-									sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].state, "%s", json_object_get_string(json_object_object_get(data, "state")));
+									DEBUG_INFO("idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes"));
 								}
 
-								if(json_object_object_get(data, "chargingPrice") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice") != NULL)
 								{
-									if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice") != NULL)
-									{
-										DEBUG_INFO("chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "kWhPrice"));
-									}
+									DEBUG_INFO("idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice"));
+								}
+							}
 
-									if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice") != NULL)
-									{
-										DEBUG_INFO("chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "hourPrice"));
-									}
+							if(json_object_object_get(data, "nextPeriod") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime") != NULL)
+								{
+									DEBUG_INFO("nextPeriod-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
+									sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
+								}
+								else
+								{
+									json_object_object_add(response, "status", json_object_new_string("Rejected"));
+									json_object_object_add(response, "data", json_object_new_string("atTime not found."));
+								}
 
-									if(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice") != NULL)
+								{
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice") != NULL)
 									{
-										DEBUG_INFO("chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(data, "chargingPrice"), "flatFee"));
+										DEBUG_INFO("nextPeriod-chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice")));
+										ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice"));
 									}
-								}
 
-								if(json_object_object_get(data, "idlePrice") != NULL)
-								{
-									if(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice") != NULL)
 									{
-										DEBUG_INFO("idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(data, "idlePrice"), "graceMinutes"));
+										DEBUG_INFO("nextPeriod-chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice")));
+										ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice"));
 									}
 
-									if(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee") != NULL)
 									{
-										DEBUG_INFO("idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(data, "idlePrice"), "hourPrice"));
+										DEBUG_INFO("nextPeriod-chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee")));
+										ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee"));
 									}
 								}
+								else
+								{
+									json_object_object_add(response, "status", json_object_new_string("Rejected"));
+									json_object_object_add(response, "data", json_object_new_string("chargingPrice not found."));
+								}
 
-								if(json_object_object_get(data, "nextPeriod") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice") != NULL)
 								{
-									if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes") != NULL)
 									{
-										DEBUG_INFO("nextPeriod-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
-										sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "nextPeriod"), "atTime")));
+										DEBUG_INFO("nextPeriod-idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes")));
+										ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes"));
 									}
 
-									if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice") != NULL)
+									if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice") != NULL)
 									{
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-chargingPrice-kWhPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice")));
-											ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.chargingPrice.kWhPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "kWhPrice"));
-										}
-
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-chargingPrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice")));
-											ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.chargingPrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "hourPrice"));
-										}
-
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-chargingPrice-flatFee: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee")));
-											ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.chargingPrice.flatFee = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "chargingPrice"), "flatFee"));
-										}
+										DEBUG_INFO("nextPeriod-idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice")));
+										ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice"));
 									}
+								}
+							}
 
-									if(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice") != NULL)
-									{
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-idlePrice-graceMinutes: %d\n", json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes")));
-											ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.idlePrice.graceMinutes = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "graceMinutes"));
-										}
-
-										if(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice") != NULL)
-										{
-											DEBUG_INFO("nextPeriod-idlePrice-hourPrice: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice")));
-											ShmOCPP16DataPH->Cost.RunningCost[idx].nextPeriod.idlePrice.hourPrice = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(data, "nextPeriod"), "idlePrice"), "hourPrice"));
-										}
-									}
+							if(json_object_object_get(data, "triggerMeterValue") != NULL)
+							{
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime") != NULL)
+								{
+									DEBUG_INFO("triggerMeterValue-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
+									sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].triggerMeterValue.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
 								}
 
-								if(json_object_object_get(data, "triggerMeterValue") != NULL)
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh") != NULL)
 								{
-									if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime") != NULL)
-									{
-										DEBUG_INFO("triggerMeterValue-atTime: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
-										sprintf((char*)ShmOCPP16DataPH->Cost.RunningCost[idx].triggerMeterValue.atTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atTime")));
-									}
+									DEBUG_INFO("triggerMeterValue-atEnergykWh: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].triggerMeterValue.atEnergykWh = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh"));
+								}
 
-									if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh") != NULL)
-									{
-										DEBUG_INFO("triggerMeterValue-atEnergykWh: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].triggerMeterValue.atEnergykWh = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atEnergykWh"));
-									}
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW") != NULL)
+								{
+									DEBUG_INFO("triggerMeterValue-atPowerkW: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW")));
+									ShmOCPP16DataPH->Cost.RunningCost[idx].triggerMeterValue.atPowerkW = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW"));
+								}
 
-									if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW") != NULL)
-									{
-										DEBUG_INFO("triggerMeterValue-atPowerkW: %f\n", json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW")));
-										ShmOCPP16DataPH->Cost.RunningCost[idx].triggerMeterValue.atPowerkW = json_object_get_double(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atPowerkW"));
-									}
+								if(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atCPStatus") != NULL)
+								{
+									DEBUG_INFO("triggerMeterValue-atCPStatus: %s\n", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atCPStatus")));
+									sprintf((char*)ShmOCPP16Data->Cost.RunningCost[idx].triggerMeterValue.atCPStatus, "%s", json_object_get_string(json_object_object_get(json_object_object_get(data, "triggerMeterValue"), "atCPStatus")));
 								}
 							}
 						}
 					}
 				}
-				json_object_object_add(response, "status", json_object_new_string("Accepted"));
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("txId or transactionId not found."));
+				}
 			}
 			else
 			{
@@ -10715,9 +10814,10 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			data = json_tokener_parse(tempdata);
 			if(!is_error(data))
 			{
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
 				if(json_object_object_get(data, "txId") != NULL)
 				{
-					DEBUG_INFO("transaction id: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
+					DEBUG_INFO("v1.0 txId: %d\n", json_object_get_int(json_object_object_get(data, "txId")));
 
 					for(int idx = 0;idx<gunTotalNumber;idx++)
 					{
@@ -10732,10 +10832,61 @@ int handleDataTransferRequest(char *uuid, char *payload)
 								DEBUG_INFO("description: %s\n", json_object_get_string(json_object_object_get(data, "description")));
 								sprintf((char*)ShmOCPP16DataPH->Cost.FinalCost[idx].description, "%s", json_object_get_string(json_object_object_get(data, "description")));
 							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("description not found."));
+							}
 						}
 					}
 				}
-				json_object_object_add(response, "status", json_object_new_string("Accepted"));
+				else if(json_object_object_get(data, "transactionId") != NULL)
+				{
+					DEBUG_INFO("v2.0 transactionId: %d\n", json_object_get_int(json_object_object_get(data, "transactionId")));
+
+					for(int idx = 0;idx<gunTotalNumber;idx++)
+					{
+						if(ShmOCPP16DataPH->StartTransaction[idx].ResponseTransactionId == json_object_get_int(json_object_object_get(data, "transactionId")))
+						{
+							memset(&ShmOCPP16DataPH->Cost.FinalCost[idx], 0x00, sizeof(struct StrcutFinalCost));
+
+							ShmOCPP16DataPH->Cost.FinalCost[idx].txId = json_object_get_int(json_object_object_get(data, "transactionId"));
+
+							if(json_object_object_get(data, "cost") != NULL)
+							{
+								DEBUG_INFO("cost: %s\n", json_object_get_string(json_object_object_get(data, "cost")));
+								ShmOCPP16DataPH->Cost.FinalCost[idx].cost = json_object_get_double(json_object_object_get(data, "cost"));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("cost not found."));
+							}
+
+							if(json_object_object_get(data, "priceText") != NULL)
+							{
+								DEBUG_INFO("priceText: %s\n", json_object_get_string(json_object_object_get(data, "priceText")));
+								sprintf((char*)ShmOCPP16DataPH->Cost.FinalCost[idx].priceText, "%s", json_object_get_string(json_object_object_get(data, "priceText")));
+							}
+							else
+							{
+								json_object_object_add(response, "status", json_object_new_string("Rejected"));
+								json_object_object_add(response, "data", json_object_new_string("priceText not found."));
+							}
+
+							if(json_object_object_get(data, "qrCodeText") != NULL)
+							{
+								DEBUG_INFO(": %s\n", json_object_get_string(json_object_object_get(data, "qrCodeText")));
+								sprintf((char*)ShmOCPP16DataPH->Cost.FinalCost[idx].qrCodeText, "%s", json_object_get_string(json_object_object_get(data, "qrCodeText")));
+							}
+						}
+					}
+				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("txId or transactionId not found."));
+				}
 			}
 			else
 			{
@@ -15671,7 +15822,7 @@ int initialConfigurationTable(void)
 	char sstr[256]={0};
 	int c = 0;
 	char *loc;
-	int	confVersion = 14;
+	int	confVersion = 15;
 
 	DEBUG_INFO("initialConfigurationTable...version: %d\n", confVersion);
 	//start_t = clock();
@@ -16087,6 +16238,13 @@ int initialConfigurationTable(void)
 
 		fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","EVCCID_PREFIX", "false", ShmOCPP16DataPH->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData);
 
+		// OffLineMaxChargingPower
+		ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility = 1;
+		strcpy((char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemName, "OffLineMaxChargingPower");
+		strcpy((char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "0" );
+
+		fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","OffLineMaxChargingPower", "false", ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData);
+
 		// Configuration Version
 		ShmOCPP16DataPH->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemAccessibility = 0;
 		strcpy((char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemName, "ConfigurationVersion");
@@ -16552,6 +16710,12 @@ int initialConfigurationTable(void)
 					sprintf((char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData, "%s", valuestr);
 				}
 
+				if(strcmp(keystr, "OffLineMaxChargingPower") == 0)
+				{
+					ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility = (strcmp(readonlystr, "true")==0) ? 0 : 1;
+					sprintf((char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "%s", valuestr);
+				}
+
 				if(strcmp(keystr, "ConfigurationVersion") == 0)
 				{
 					ShmOCPP16DataPH->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemAccessibility = (strcmp(readonlystr, "true")==0) ? 0 : 1;
@@ -17101,6 +17265,15 @@ void StoreConfigurationTable(void)
 
 	fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","EVCCID_PREFIX", "false", (char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[EVCCID_PREFIX].ItemData);
 
+	// OffLineMaxChargingPower
+	/*
+	ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility = 1;
+	strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemName, "OffLineMaxChargingPower");
+	strcpy((char *)ShmOCPP16Data->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "" );
+	*/
+
+	fprintf(outfile,"{\"key\":\"%s\",\"readonly\":%s,\"value\":\"%s\"}\n","OffLineMaxChargingPower", "false", (char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData);
+
 	// ConfigurationVersion
 	/*
 	ShmOCPP16DataPH->ConfigurationTable.CoreProfile[ConfigurationVersion].ItemAccessibility = 1;
@@ -18126,6 +18299,24 @@ void getKeyValue(char *keyReq)
 			  isKnowKey = TRUE;
 		  }
 
+		  if(isEmpty ||  strcmp(keyReq, "OffLineMaxChargingPower") == 0 )
+		  {
+			  strcpy((char *)ShmOCPP16DataPH->GetConfiguration.Key[GetConfiguration_OffLineMaxChargingPower].Item, "OffLineMaxChargingPower");
+			  strcpy((char *)ShmOCPP16DataPH->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].Key, "OffLineMaxChargingPower");
+
+			  if(ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility == 1)
+			  {
+				  strcpy((char *)ShmOCPP16DataPH->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].ReadOnly, "0"/*"FALSE"*/);
+			  }
+			  else
+			  {
+				  strcpy((char *)ShmOCPP16DataPH->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].ReadOnly, "1"/*"TRUE"*/);
+			  }
+
+			  strcpy((char *)ShmOCPP16DataPH->GetConfiguration.ResponseConfigurationKey[GetConfiguration_OffLineMaxChargingPower].Value, (const char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData );
+			  isKnowKey = TRUE;
+		  }
+
 	      if(isEmpty ||  strcmp(keyReq, "ConfigurationVersion") == 0 )
 		  {
 			  strcpy((char *)ShmOCPP16DataPH->GetConfiguration.Key[GetConfiguration_ConfigurationVersion].Item, "ConfigurationVersion");
@@ -19420,6 +19611,20 @@ int setKeyValue(char *key, char *value)
 		}
 	}
 
+	if(strcmp(key, "OffLineMaxChargingPower") == 0)
+	{
+		if(ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemAccessibility == 1)
+		{
+			strcpy(str, (const char*)value);
+			sprintf((char *)ShmOCPP16DataPH->ConfigurationTable.CoreProfile[OffLineMaxChargingPower].ItemData, "%s", str );
+			isSuccess = ConfigurationStatus_Accepted;
+		}
+		else
+		{
+			isSuccess = ConfigurationStatus_Rejected;
+		}
+	}
+
 #if 0
     //For OCPP Test Case
     if(strcmp(key, "LocalAuthorizationListEnabled") == 0)

+ 1 - 0
EVSE/Modularization/ocppph/MessageHandler.h

@@ -402,6 +402,7 @@ enum GetConfigurationKey {
 	GetConfiguration_isEnableLocalPowerSharing,
 	GetConfiguration_PowerSharingServerIP,
 	GetConfiguration_EVCCID_PREFIX,
+	GetConfiguration_OffLineMaxChargingPower,
 	GetConfiguration_LocalAuthListEnabled,
 	GetConfiguration_LocalAuthListMaxLength,
 	GetConfiguration_SendLocalListMaxLength,

+ 6 - 0
EVSE/Projects/define.h

@@ -332,6 +332,7 @@ enum CoreProfile {
      isEnableLocalPowerSharing,
      PowerSharingServerIP,
      EVCCID_PREFIX,
+	 OffLineMaxChargingPower,
      ConfigurationVersion,
 	 _CoreProfile_CNT
 };
@@ -4479,6 +4480,7 @@ struct Triggers
                                                     // be used to trigger a meter value when vehicle stops charging or when vehicle charges at a high power that requires a
                                                     // different tariff.
                                                     // It is recommended to implement a hysteresis around this value to avoid repetitive triggers when the power fluctuates around this level.
+    unsigned char atCPStatus[100];
 };
 
 struct StrcutRunningCost
@@ -4499,6 +4501,10 @@ struct StrcutFinalCost
 {
     int             txId;
     unsigned char   description[1024];
+
+    float           cost;
+    unsigned char   priceText[1024];
+    unsigned char   qrCodeText[1024];
 };
 
 struct StructCost