Browse Source

[Improve][Modularization][Module_OcppBackend / Module_OcppBackend20]

2021.08.22 / Folus Wen

Actions:
1. RemoteStartTransaction support request without connectorId if charger gun already connected.

Files:
1. As follow commit history

Image version: D0.00.XX.XXXX.XX
Image checksum: XXXXXXXX

Hardware PWB P/N : XXXXXXX
Hardware Version : XXXXXXX
FolusWen 3 years ago
parent
commit
41855dacbc

+ 78 - 69
EVSE/Modularization/ocpp20/MessageHandler.c

@@ -13867,7 +13867,7 @@ int handleRemoteStartTransactionRequest(char *uuid, char *payload)
 	uint8_t isPeriodOverMax = FALSE;
 	uint8_t isPeriodOverMax = FALSE;
 	uint8_t isProfileOverMax = FALSE;
 	uint8_t isProfileOverMax = FALSE;
 	uint8_t isConnectorMismatch = FALSE;
 	uint8_t isConnectorMismatch = FALSE;
-	uint8_t isTxProfile = FALSE;
+	uint8_t isTxProfile = TRUE;
 	uint8_t existProfileQuantity = 0;
 	uint8_t existProfileQuantity = 0;
 	uint8_t filename[128]={0};
 	uint8_t filename[128]={0};
 	uint8_t word[2048]={0};
 	uint8_t word[2048]={0};
@@ -13880,102 +13880,111 @@ int handleRemoteStartTransactionRequest(char *uuid, char *payload)
 	{
 	{
 		if(json_object_object_get(RemoteStartTransaction, "evseId") != NULL)
 		if(json_object_object_get(RemoteStartTransaction, "evseId") != NULL)
 		{
 		{
-			gun_index = json_object_get_int(json_object_object_get(RemoteStartTransaction, "evseId"));
+			gun_index = (json_object_get_int(json_object_object_get(RemoteStartTransaction, "evseId"))>0)?(json_object_get_int(json_object_object_get(RemoteStartTransaction, "evseId"))-1):-1;
 		}
 		}
 		else
 		else
 		{
 		{
-			/*
-			 * TODO:
-			 * 	1. Selected connector process
-			 */
-			gun_index = 0;
-		}
-
-		memset(&ShmOCPP20Data->RequestStartTransaction[gun_index], 0, sizeof(struct RequestStartTransaction_20));
-		memcpy(&ShmOCPP20Data->RequestStartTransaction[gun_index].guid, uuid, ARRAY_SIZE(ShmOCPP20Data->RequestStartTransaction[gun_index].guid));
-		// Required data
-		if(json_object_object_get(RemoteStartTransaction, "remoteStartId") != NULL)
-		{
-			ShmOCPP20Data->RequestStartTransaction[gun_index].remoteStartId = json_object_get_int(json_object_object_get(RemoteStartTransaction, "remoteStartId"));
-		}
-
-		if(json_object_object_get(RemoteStartTransaction, "idToken") != NULL)
-		{
-			if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "idToken") != NULL)
+			for(uint8_t idx=0;idx<gunTotalNumber;idx++)
 			{
 			{
-				sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].idToken.idToken, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "idToken")));
-			}
+				if(!cpinitateMsg.bits[idx].isOnCharging && (strstr((char*)ShmOCPP20Data->StatusNotification[idx].connectorStatus, ConnectorStatusEnumTypeStr[ConnectorStatusEnumType_Occupied]) != NULL))
+				{
+					gun_index = idx;
 
 
-			if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "type") != NULL)
-			{
-				sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].idToken.type, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "type")));
+					DEBUG_INFO("Remote start without connectorId but detect connector-%02d connected ready to start.\n", (gun_index+1));
+					break;
+				}
 			}
 			}
 		}
 		}
 
 
-		// Optional data
-		if(json_object_object_get(RemoteStartTransaction, "groupIdToken") != NULL)
+		if(gun_index >= 0)
 		{
 		{
-			if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "idToken") != NULL)
+			memset(&ShmOCPP20Data->RequestStartTransaction[gun_index], 0, sizeof(struct RequestStartTransaction_20));
+			memcpy(&ShmOCPP20Data->RequestStartTransaction[gun_index].guid, uuid, ARRAY_SIZE(ShmOCPP20Data->RequestStartTransaction[gun_index].guid));
+			// Required data
+			if(json_object_object_get(RemoteStartTransaction, "remoteStartId") != NULL)
 			{
 			{
-				sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].groupIdToken.idToken, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "idToken")));
+				ShmOCPP20Data->RequestStartTransaction[gun_index].remoteStartId = json_object_get_int(json_object_object_get(RemoteStartTransaction, "remoteStartId"));
 			}
 			}
 
 
-			if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "type") != NULL)
+			if(json_object_object_get(RemoteStartTransaction, "idToken") != NULL)
 			{
 			{
-				sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].groupIdToken.type, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "type")));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "idToken") != NULL)
+				{
+					sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].idToken.idToken, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "idToken")));
+				}
+
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "type") != NULL)
+				{
+					sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].idToken.type, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "idToken"), "type")));
+				}
 			}
 			}
-		}
 
 
-		if(json_object_object_get(RemoteStartTransaction, "chargingProfile") != NULL)
-		{
-			// Check periods is over max configuration
-			if(json_object_array_length(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod")) > 10)
+			// Optional data
+			if(json_object_object_get(RemoteStartTransaction, "groupIdToken") != NULL)
 			{
 			{
-				isPeriodOverMax = TRUE;
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "idToken") != NULL)
+				{
+					sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].groupIdToken.idToken, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "idToken")));
+				}
+
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "type") != NULL)
+				{
+					sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].groupIdToken.type, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "groupIdToken"), "type")));
+				}
 			}
 			}
 
 
-			// Check periods is over max configuration
-			if(strstr(json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfilePurpose")), ChargingProfilePurposeEnumTypeStr[ChargingProfilePurposeEnumType_TxProfile]) != NULL)
+			if(json_object_object_get(RemoteStartTransaction, "chargingProfile") != NULL)
 			{
 			{
-				if(gun_index > 0)
-					sprintf((char*)filename, "/Storage/OCPP/TxProfile_%d_OCPP20.json", gun_index);
-				else
-					isConnectorMismatch = TRUE;
+				// Check periods is over max configuration
+				if(json_object_array_length(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod")) > 10)
+				{
+					isPeriodOverMax = TRUE;
+				}
 
 
-				if(!isConnectorMismatch)
+				// Check periods is over max configuration
+				if(strstr(json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfilePurpose")), ChargingProfilePurposeEnumTypeStr[ChargingProfilePurposeEnumType_TxProfile]) != NULL)
 				{
 				{
-					filePtr = fopen((char*)filename, "r");
-					if (!filePtr)
-					{
-						DEBUG_INFO("%s not exist, create it.\n", filename);
-						filePtr = fopen((char*)filename, "w+");
-					}
+					if(gun_index >= 0)
+						sprintf((char*)filename, "/Storage/OCPP/TxProfile_%d_OCPP20.json", (gun_index+1));
 					else
 					else
+						isConnectorMismatch = TRUE;
+
+					if(!isConnectorMismatch)
 					{
 					{
-						//Check Charging Profile Count
-						while(fscanf(filePtr, "%s", word) != EOF)
+						filePtr = fopen((char*)filename, "r");
+						if (!filePtr)
 						{
 						{
-							//DEBUG_INFO("word=%s\n",word);
-							if(strstr((char*)word, "chargingProfileId")!= NULL)
+							DEBUG_INFO("%s not exist, create it.\n", filename);
+							filePtr = fopen((char*)filename, "w+");
+						}
+						else
+						{
+							//Check Charging Profile Count
+							while(fscanf(filePtr, "%s", word) != EOF)
 							{
 							{
-								existProfileQuantity += 1;
+								//DEBUG_INFO("word=%s\n",word);
+								if(strstr((char*)word, "chargingProfileId")!= NULL)
+								{
+									existProfileQuantity += 1;
+								}
 							}
 							}
 						}
 						}
+						fclose(filePtr);
 					}
 					}
-					fclose(filePtr);
 				}
 				}
-			}
-			else
-			{
+				else
+				{
+					isTxProfile = FALSE;
+				}
 
 
+				if(existProfileQuantity > 3)
+					isProfileOverMax = TRUE;
 			}
 			}
-
-			if(existProfileQuantity > 3)
-				isProfileOverMax = TRUE;
 		}
 		}
 
 
+
 		// Profile replace or add info
 		// Profile replace or add info
-		if((gun_index > 0) && !isPeriodOverMax && !isProfileOverMax && !isConnectorMismatch && !isTxProfile)
+		if((gun_index >= 0) && !isPeriodOverMax && !isProfileOverMax && !isConnectorMismatch && isTxProfile)
 		{
 		{
 			FILE *infile;
 			FILE *infile;
 			FILE *outfile;
 			FILE *outfile;
@@ -14043,7 +14052,7 @@ int handleRemoteStartTransactionRequest(char *uuid, char *payload)
 					}
 					}
 					json_object_put(tmpChargingProfile);
 					json_object_put(tmpChargingProfile);
 
 
-					if((tempconnectorIdInt == gun_index) &&
+					if((tempconnectorIdInt == (gun_index+1)) &&
 					   (tempchargingProfileIdInt == json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "csChargingProfiles"), "chargingProfileId"))))
 					   (tempchargingProfileIdInt == json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "csChargingProfiles"), "chargingProfileId"))))
 					{
 					{
 						if((tempstackLevelInt == json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "csChargingProfiles"), "stackLevel"))) &&
 						if((tempstackLevelInt == json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "csChargingProfiles"), "stackLevel"))) &&
@@ -14138,13 +14147,13 @@ int handleRemoteStartTransactionRequest(char *uuid, char *payload)
 				rename((char*)tmpProfileName, (char*)filename);
 				rename((char*)tmpProfileName, (char*)filename);
 			}
 			}
 
 
-			sprintf((char*)ShmOCPP20Data->RequestStartTransaction[(gun_index==0?gun_index:gun_index-1)].Response_status, "%s", RequestStartStopStatusEnumTypeStr[RequestStartStopStatusEnumType_Accepted] );
-			random_uuid((char*)ShmOCPP20Data->RequestStartTransaction[(gun_index==0?gun_index:gun_index-1)].Response_transactionId);
+			sprintf((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].Response_status, "%s", RequestStartStopStatusEnumTypeStr[RequestStartStopStatusEnumType_Accepted] );
+			random_uuid((char*)ShmOCPP20Data->RequestStartTransaction[gun_index].Response_transactionId);
 			result = PASS;
 			result = PASS;
 		}
 		}
 		else
 		else
 		{
 		{
-			if(gun_index <= 0)
+			if(gun_index < 0)
 				DEBUG_WARN("Connector id is wrong.\n");
 				DEBUG_WARN("Connector id is wrong.\n");
 
 
 			if(isConnectorMismatch)
 			if(isConnectorMismatch)
@@ -14159,12 +14168,12 @@ int handleRemoteStartTransactionRequest(char *uuid, char *payload)
 			if(!isTxProfile)
 			if(!isTxProfile)
 				DEBUG_WARN("Profile purpose is not TxProfile.\n");
 				DEBUG_WARN("Profile purpose is not TxProfile.\n");
 
 
-			sprintf((char*)ShmOCPP20Data->RequestStartTransaction[(gun_index==0?gun_index:gun_index-1)].Response_status, "%s", RequestStartStopStatusEnumTypeStr[RequestStartStopStatusEnumType_Rejected] );
+			sprintf((char*)ShmOCPP20Data->RequestStartTransaction[(gun_index<0?0:gun_index)].Response_status, "%s", RequestStartStopStatusEnumTypeStr[RequestStartStopStatusEnumType_Rejected] );
 		}
 		}
 	}
 	}
 	json_object_put(RemoteStartTransaction);
 	json_object_put(RemoteStartTransaction);
 
 
-	sendRemoteStartTransactionConfirmation(uuid, gun_index);
+	sendRemoteStartTransactionConfirmation(uuid, (gun_index<0?0:gun_index));
 
 
 	return result;
 	return result;
 }
 }

+ 59 - 43
EVSE/Modularization/ocppfiles/MessageHandler.c

@@ -10309,7 +10309,7 @@ int handleRemoteStartRequest(char *uuid, char *payload)
 {
 {
 	mtrace();
 	mtrace();
 	int result = FAIL;
 	int result = FAIL;
-	int connectorIdInt=0;
+	int connectorIdInt=-1;
 	int tempIndex = 0;
 	int tempIndex = 0;
 	int connectorIdIsNULL, chargingProfileIsNULL;
 	int connectorIdIsNULL, chargingProfileIsNULL;
 	char comfirmstr[20]={0};
 	char comfirmstr[20]={0};
@@ -10331,69 +10331,85 @@ int handleRemoteStartRequest(char *uuid, char *payload)
 		if(json_object_object_get(RemoteStartTransaction, "connectorId") != NULL)
 		if(json_object_object_get(RemoteStartTransaction, "connectorId") != NULL)
 		{
 		{
 			connectorIdInt = json_object_get_int(json_object_object_get(RemoteStartTransaction, "connectorId"));
 			connectorIdInt = json_object_get_int(json_object_object_get(RemoteStartTransaction, "connectorId"));
-
-			if(connectorIdInt <= gunTotalNumber)
+		}
+		else
+		{
+			connectorIdIsNULL = TRUE;
+			for(uint8_t gun_index=0;gun_index<gunTotalNumber;gun_index++)
 			{
 			{
-				memset(&ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1], 0x00, sizeof(struct StructRemoteStartTransaction));
-				// Required data
-				sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].IdTag, "%s", json_object_get_string(json_object_object_get(RemoteStartTransaction, "idTag")));
-
-				// Optional data
-				if(json_object_object_get(RemoteStartTransaction, "chargingProfile") != NULL)
+				if(!cpinitateMsg.bits[gun_index].isOnCharging && (strstr((char*)ShmOCPP16Data->StatusNotification[gun_index].Status, "Preparing") != NULL))
 				{
 				{
-					ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileId"));
-					ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.StackLevel = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "stackLevel"));
-					sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfilePurpose, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfilePurpose")));
-					sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileKind, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileKind")));
+					connectorIdIsNULL = FALSE;
+					connectorIdInt = (gun_index+1);
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId") != NULL)
-						ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.TransactionId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId"));
+					DEBUG_INFO("Remote start without connectorId but detect connector-%02d connected ready to start.\n", connectorIdInt);
+					break;
+				}
+			}
+		}
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind") != NULL)
-						sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.RecurrencyKind , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind")));
+		if((connectorIdInt <= gunTotalNumber) && (connectorIdInt != -1))
+		{
+			memset(&ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1], 0x00, sizeof(struct StructRemoteStartTransaction));
+			// Required data
+			sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].IdTag, "%s", json_object_get_string(json_object_object_get(RemoteStartTransaction, "idTag")));
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom") != NULL)
-						sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidFrom , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom")));
+			// Optional data
+			if(json_object_object_get(RemoteStartTransaction, "chargingProfile") != NULL)
+			{
+				ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileId"));
+				ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.StackLevel = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "stackLevel"));
+				sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfilePurpose, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfilePurpose")));
+				sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileKind, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileKind")));
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo") != NULL)
-						sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidTo , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo")));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId") != NULL)
+					ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.TransactionId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId"));
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule") != NULL)
-					{
-						sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingRateUnit , "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingRateUnit")));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind") != NULL)
+					sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.RecurrencyKind , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind")));
+
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom") != NULL)
+					sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidFrom , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom")));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration") != NULL)
-							ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.Duration = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration"));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo") != NULL)
+					sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidTo , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo")));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate") != NULL)
-							ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.MinChargingRate = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate"));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule") != NULL)
+				{
+					sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingRateUnit , "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingRateUnit")));
+
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration") != NULL)
+						ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.Duration = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration"));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule") != NULL)
-							sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.StartSchedule, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule")));
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate") != NULL)
+						ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.MinChargingRate = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate"));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod") != NULL)
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule") != NULL)
+						sprintf((char*)ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.StartSchedule, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule")));
+
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod") != NULL)
+					{
+						for(int idxPeriod=0;idxPeriod<json_object_array_length(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"));idxPeriod++)
 						{
 						{
-							for(int idxPeriod=0;idxPeriod<json_object_array_length(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"));idxPeriod++)
-							{
-								ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].StartPeriod = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "startPeriod"));
-								ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].Limit = json_object_get_double(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "limit"));
+							ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].StartPeriod = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "startPeriod"));
+							ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].Limit = json_object_get_double(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "limit"));
 
 
-								if(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases") != NULL)
-									ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].NumberPhases = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases"));
-							}
+							if(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases") != NULL)
+								ShmOCPP16Data->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].NumberPhases = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases"));
 						}
 						}
 					}
 					}
 				}
 				}
-				else
-					chargingProfileIsNULL = TRUE;
+			}
+			else
+			{
+				chargingProfileIsNULL = TRUE;
 			}
 			}
 		}
 		}
-		else
-			connectorIdIsNULL = TRUE;
 	}
 	}
 	else
 	else
+	{
 		connectorIdIsNULL = TRUE;
 		connectorIdIsNULL = TRUE;
-
+	}
 
 
 	if(connectorIdIsNULL == TRUE)  // Number of the connector on which to start the transaction. connectorId SHALL be > 0
 	if(connectorIdIsNULL == TRUE)  // Number of the connector on which to start the transaction. connectorId SHALL be > 0
 	{
 	{

+ 59 - 43
EVSE/Modularization/ocppph/MessageHandler.c

@@ -10061,7 +10061,7 @@ int handleRemoteStartRequest(char *uuid, char *payload)
 {
 {
 	mtrace();
 	mtrace();
 	int result = FAIL;
 	int result = FAIL;
-	int connectorIdInt=0;
+	int connectorIdInt=-1;
 	int tempIndex = 0;
 	int tempIndex = 0;
 	int connectorIdIsNULL, chargingProfileIsNULL;
 	int connectorIdIsNULL, chargingProfileIsNULL;
 	char comfirmstr[20]={0};
 	char comfirmstr[20]={0};
@@ -10083,69 +10083,85 @@ int handleRemoteStartRequest(char *uuid, char *payload)
 		if(json_object_object_get(RemoteStartTransaction, "connectorId") != NULL)
 		if(json_object_object_get(RemoteStartTransaction, "connectorId") != NULL)
 		{
 		{
 			connectorIdInt = json_object_get_int(json_object_object_get(RemoteStartTransaction, "connectorId"));
 			connectorIdInt = json_object_get_int(json_object_object_get(RemoteStartTransaction, "connectorId"));
-
-			if(connectorIdInt <= gunTotalNumber)
+		}
+		else
+		{
+			connectorIdIsNULL = TRUE;
+			for(uint8_t gun_index=0;gun_index<gunTotalNumber;gun_index++)
 			{
 			{
-				memset(&ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1], 0x00, sizeof(struct StructRemoteStartTransaction));
-				// Required data
-				sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].IdTag, "%s", json_object_get_string(json_object_object_get(RemoteStartTransaction, "idTag")));
-
-				// Optional data
-				if(json_object_object_get(RemoteStartTransaction, "chargingProfile") != NULL)
+				if(!cpinitateMsg.bits[gun_index].isOnCharging && (strstr((char*)ShmOCPP16DataPH->StatusNotification[gun_index].Status, "Preparing") != NULL))
 				{
 				{
-					ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileId"));
-					ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.StackLevel = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "stackLevel"));
-					sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfilePurpose, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfilePurpose")));
-					sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileKind, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileKind")));
+					connectorIdIsNULL = FALSE;
+					connectorIdInt = (gun_index+1);
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId") != NULL)
-						ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.TransactionId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId"));
+					DEBUG_INFO("Remote start without connectorId but detect connector-%02d connected ready to start.\n", connectorIdInt);
+					break;
+				}
+			}
+		}
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind") != NULL)
-						sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.RecurrencyKind , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind")));
+		if((connectorIdInt <= gunTotalNumber) && (connectorIdInt != -1))
+		{
+			memset(&ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1], 0x00, sizeof(struct StructRemoteStartTransaction));
+			// Required data
+			sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].IdTag, "%s", json_object_get_string(json_object_object_get(RemoteStartTransaction, "idTag")));
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom") != NULL)
-						sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidFrom , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom")));
+			// Optional data
+			if(json_object_object_get(RemoteStartTransaction, "chargingProfile") != NULL)
+			{
+				ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileId"));
+				ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.StackLevel = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "stackLevel"));
+				sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfilePurpose, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfilePurpose")));
+				sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingProfileKind, "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingProfileKind")));
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo") != NULL)
-						sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidTo , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo")));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId") != NULL)
+					ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.TransactionId = json_object_get_int(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "transactionId"));
 
 
-					if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule") != NULL)
-					{
-						sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingRateUnit , "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingRateUnit")));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind") != NULL)
+					sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.RecurrencyKind , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "recurrencyKind")));
+
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom") != NULL)
+					sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidFrom , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validFrom")));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration") != NULL)
-							ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.Duration = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration"));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo") != NULL)
+					sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ValidTo , "%s", json_object_get_string(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "validTo")));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate") != NULL)
-							ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.MinChargingRate = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate"));
+				if(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule") != NULL)
+				{
+					sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingRateUnit , "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingRateUnit")));
+
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration") != NULL)
+						ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.Duration = json_object_get_int(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "duration"));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule") != NULL)
-							sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.StartSchedule, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule")));
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate") != NULL)
+						ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.MinChargingRate = json_object_get_double(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "minChargingRate"));
 
 
-						if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod") != NULL)
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule") != NULL)
+						sprintf((char*)ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.StartSchedule, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "startSchedule")));
+
+					if(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod") != NULL)
+					{
+						for(int idxPeriod=0;idxPeriod<json_object_array_length(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"));idxPeriod++)
 						{
 						{
-							for(int idxPeriod=0;idxPeriod<json_object_array_length(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"));idxPeriod++)
-							{
-								ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].StartPeriod = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "startPeriod"));
-								ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].Limit = json_object_get_double(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "limit"));
+							ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].StartPeriod = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "startPeriod"));
+							ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].Limit = json_object_get_double(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "limit"));
 
 
-								if(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases") != NULL)
-									ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].NumberPhases = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases"));
-							}
+							if(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases") != NULL)
+								ShmOCPP16DataPH->RemoteStartTransaction[connectorIdInt -1].ChargingProfile.ChargingSchedule.ChargingSchedulePeriod[idxPeriod].NumberPhases = json_object_get_int(json_object_object_get(json_object_array_get_idx(json_object_object_get(json_object_object_get(json_object_object_get(RemoteStartTransaction, "chargingProfile"), "chargingSchedule"), "chargingSchedulePeriod"), idxPeriod), "numberPhases"));
 						}
 						}
 					}
 					}
 				}
 				}
-				else
-					chargingProfileIsNULL = TRUE;
+			}
+			else
+			{
+				chargingProfileIsNULL = TRUE;
 			}
 			}
 		}
 		}
-		else
-			connectorIdIsNULL = TRUE;
 	}
 	}
 	else
 	else
+	{
 		connectorIdIsNULL = TRUE;
 		connectorIdIsNULL = TRUE;
-
+	}
 
 
 	if(connectorIdIsNULL == TRUE)  // Number of the connector on which to start the transaction. connectorId SHALL be > 0
 	if(connectorIdIsNULL == TRUE)  // Number of the connector on which to start the transaction. connectorId SHALL be > 0
 	{
 	{