Browse Source

2022-07-18/Jerry Wang
[OCPP 2.0.1]

Action:
1. Add logic to check if the attributeValue of variable matches its dataType during SetVariables process.
2. Add logic to check if the contents of connectionData match rules and formats.
3. Correct the parsing logic in handleAuthorizeResponse function.

File:
1. EVSE/Modularization/ocpp20/MessageHandler.c
--> Action 1-3

Jerry Wang 2 years ago
parent
commit
df2c319ce0
1 changed files with 238 additions and 23 deletions
  1. 238 23
      EVSE/Modularization/ocpp20/MessageHandler.c

+ 238 - 23
EVSE/Modularization/ocpp20/MessageHandler.c

@@ -3335,6 +3335,128 @@ int DB_deleteNetworkProfile(int slot)
 	return result;
 }
 
+int isNumber(uint8_t *string, uint8_t isFloat)
+{
+	int result = NO;
+	int cntDecimal = 0;
+	float i;
+
+	for(int idx=0; idx<strlen((char*)string); idx++)
+	{
+		if((isdigit(string[idx])==0) && (string[idx] != '.'))
+		{
+			return result;
+		}
+		else if(string[idx] == '.')
+			cntDecimal++;
+
+		if(cntDecimal>1)
+			return result;
+	}
+
+	if((isFloat==FALSE) && (strstr((char*)string, ".") != NULL))
+	{
+		//DEBUG_INFO("%s is not pure integer!!\n", string);
+	}
+	else if((isFloat==TRUE) && (strstr((char*)string, ".") == NULL))
+	{
+		//DEBUG_INFO("%s is not float format!!\n", string);
+	}
+	else if(sscanf((char*)string, "%f", &i) != 0)
+	{
+		result = YES;
+	}
+
+	return result;
+}
+
+int isMatchTimeFormat(uint8_t *time)
+{
+	int result = NO;
+	struct ParsingResult
+	{
+		int result;
+		int scanedElement;
+		int year;
+		int month;
+		int mday;
+		int hour;
+		int min;
+		int sec;
+		int tz_hour;
+		int tz_min;
+		float minSec;
+	}parsingResult;
+
+	memset(&parsingResult, 0x00, sizeof(struct ParsingResult));
+
+	if(strstr((char*)time, ".") != NULL)
+	{
+		// Original data with mini second
+		if(strstr((char*)time, "Z") != NULL)
+		{
+			// Original data with Z
+			parsingResult.scanedElement = sscanf((char*)time, "%d-%d-%dT%d:%d:%d.%fZ",
+																&parsingResult.year,
+																&parsingResult.month,
+																&parsingResult.mday,
+																&parsingResult.hour,
+																&parsingResult.min,
+																&parsingResult.sec,
+																&parsingResult.minSec);
+		}
+		else
+		{
+			// Original data without Z
+			parsingResult.scanedElement = sscanf((char*)time, "%d-%d-%dT%d:%d:%d.%f%d:%d",
+												&parsingResult.year,
+												&parsingResult.month,
+												&parsingResult.mday,
+												&parsingResult.hour,
+												&parsingResult.min,
+												&parsingResult.sec,
+												&parsingResult.minSec,
+												&parsingResult.tz_hour,
+												&parsingResult.tz_min);
+		}
+	}
+	else
+	{
+		// Original data without mini second
+		if(strstr((char*)time, "Z") != NULL)
+		{
+			// Original data with Z
+			parsingResult.scanedElement = sscanf((char*)time, "%d-%d-%dT%d:%d:%dZ",
+												&parsingResult.year,
+												&parsingResult.month,
+												&parsingResult.mday,
+												&parsingResult.hour,
+												&parsingResult.min,
+												&parsingResult.sec);
+		}
+		else
+		{
+			// Original data without Z
+			parsingResult.scanedElement = sscanf((char*)time, "%d-%d-%dT%d:%d:%d%d:%d",
+												&parsingResult.year,
+												&parsingResult.month,
+												&parsingResult.mday,
+												&parsingResult.hour,
+												&parsingResult.min,
+												&parsingResult.sec,
+												&parsingResult.tz_hour,
+												&parsingResult.tz_min);
+		}
+	}
+
+	if(parsingResult.scanedElement >= 6)
+	{
+		result = YES;
+	}
+
+	return result;
+}
+
 int getCurrentYear()
 {
 	int result = 0;
@@ -6878,15 +7000,31 @@ void CheckSystemValue(void)
 		sendAuthorizeRequest(0);
 	}
 
-
+	//===============================
+	// NotifyMonitoringReportRequest
+	//===============================
 	if(isWebsocketSendable &&
-		   (server_sign == TRUE) &&
-		   (ShmOCPP20Data->GetMonitoringReport.requestId > 0))
+	   (server_sign == TRUE) &&
+	   (ShmOCPP20Data->GetMonitoringReport.requestId > 0))
 	{
 		for(uint8_t idxCriterion=0;idxCriterion<ARRAY_SIZE(ShmOCPP20Data->GetMonitoringReport.monitoringCriteria);idxCriterion++)
 		{
+			if((strcmp((char*)ShmOCPP20Data->GetMonitoringReport.monitoringCriteria[idxCriterion],  MonitoringCriterionEnumTypeStr[MonitoringCriterionEnumType_ThresholdMonitoring]) == 0) ||
+			   (strcmp((char*)ShmOCPP20Data->GetMonitoringReport.monitoringCriteria[idxCriterion], MonitoringCriterionEnumTypeStr[MonitoringCriterionEnumType_DeltaMonitoring]) == 0) ||
+			   (strcmp((char*)ShmOCPP20Data->GetMonitoringReport.monitoringCriteria[idxCriterion], MonitoringCriterionEnumTypeStr[MonitoringCriterionEnumType_PeriodicMonitoring]) == 0))
+			{
+				/*for(uint8_t idxVarMonitoring=0; idxVarMonitoring<10; idxVarMonitoring++)
+				{
+					if(strcmp((char*)ShmOCPP20Data->ControllerVariableMonitoring[idxVarMonitoring].variableMonitoring[idxVarMonitoring].type, (char*)ShmOCPP20Data->GetMonitoringReport.monitoringCriteria[idxCriterion]))
+					{
+						strcpy(ShmOCPP20Data->NotifyMonitoringReport.monitor[idxVarMonitoring].component, ShmOCPP20Data->ControllerVariableMonitoring[idxVarMonitoring].
+					}
+				}*/
+			}
+
 			if(strcmp((char*)ShmOCPP20Data->GetMonitoringReport.monitoringCriteria[idxCriterion],  MonitoringCriterionEnumTypeStr[MonitoringCriterionEnumType_ThresholdMonitoring]) == 0)
 			{
+
 				/*
 				 * TODO:
 				 * 	1. Report component that are ThresholdMonitoring
@@ -6918,6 +7056,7 @@ void CheckSystemValue(void)
 		ShmOCPP20Data->GetMonitoringReport.requestId = 0;
 	}
 
+
 	if(isWebsocketSendable &&
 	   (server_sign == TRUE) &&
 	   (ShmOCPP20Data->GetReport.requestId > 0))
@@ -17781,13 +17920,53 @@ int handleSetNetworkProfileRequest(char *uuid, char *payload)
 				sprintf((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppVersion, "%s", json_object_get_string(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppVersion")));
 
 			if(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppTransport") != NULL)
-				sprintf((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppTransport, "%s", json_object_get_string(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppTransport")));
+			{
+				if(strcmp(json_object_get_string(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppTransport")), "JSON") == 0)
+				{
+					sprintf((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppTransport, "%s", json_object_get_string(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppTransport")));
+				}
+				else
+				{
+					strcpy((char*)ShmOCPP20Data->SetNetworkProfile.Response_status, SetNetworkProfileStatusEnumTypeStr[SetNetworkProfileStatusEnumType_Rejected]);
+					goto end;
+				}
+			}
 
 			if(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppCsmsUrl") != NULL)
 			{
 				sprintf((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl, "%s", json_object_get_string(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "ocppCsmsUrl")));
 
-				memcpy((char*)ShmOCPP20Data->OcppServerURL, (char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl, ARRAY_SIZE(ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl));
+				if((strncmp((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl,"wss", 3) == 0) || (strncmp((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl,"ws", 2) == 0))
+				{
+					char protocol[10], host[128], path[512], port[10];
+					int check = sscanf((char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl,"%[^:]:%*2[/]%[^:]:%[^/]/%199[^\n]", protocol, host, port, path);
+
+					if(check >= 3)
+					{
+						DEBUG_INFO("URL: %s\n", ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl);
+						DEBUG_INFO("protocol: %s\n",protocol);
+						DEBUG_INFO("host: %s\n",host);
+						DEBUG_INFO("port: %s\n",port);
+						DEBUG_INFO("path: %s\n",path);
+
+						memcpy((char*)ShmOCPP20Data->OcppServerURL, (char*)ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl, ARRAY_SIZE(ShmOCPP20Data->SetNetworkProfile.connectionData.ocppCsmsUrl));
+					}
+					else
+					{
+						strcpy((char*)ShmOCPP20Data->SetNetworkProfile.Response_status, SetNetworkProfileStatusEnumTypeStr[SetNetworkProfileStatusEnumType_Rejected]);
+						goto end;
+					}
+				}
+				else
+				{
+					strcpy((char*)ShmOCPP20Data->SetNetworkProfile.Response_status, SetNetworkProfileStatusEnumTypeStr[SetNetworkProfileStatusEnumType_Rejected]);
+					goto end;
+				}
+			}
+			else
+			{
+				strcpy((char*)ShmOCPP20Data->SetNetworkProfile.Response_status, SetNetworkProfileStatusEnumTypeStr[SetNetworkProfileStatusEnumType_Rejected]);
+				goto end;
 			}
 
 			if(json_object_object_get(json_object_object_get(SetNetworkProfile, "connectionData"), "messageTimeout") != NULL)
@@ -17981,7 +18160,10 @@ int handleSetNetworkProfileRequest(char *uuid, char *payload)
 
 
 	strcpy((char*)ShmOCPP20Data->SetNetworkProfile.Response_status, SetNetworkProfileStatusEnumTypeStr[SetNetworkProfileStatusEnumType_Accepted]);
-	sendSetNetworkProfileConfirmation(uuid);
+
+
+end:
+    sendSetNetworkProfileConfirmation(uuid);
 
 	return result;
 }
@@ -18180,19 +18362,52 @@ int handleSetVariablesRequest(char *uuid, char *payload)
 						   (strlen((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].variable.instance)>0?(strstr((char*)ShmOCPP20Data->ControllerComponentVariable[idx_var].variable.instance, (char*)ShmOCPP20Data->SetVariables.setVariableData[idx].variable.instance) != NULL):TRUE))
 						{
 							isUnknownComponent = FALSE;
+							//DEBUG_INFO("Checking variable...[%s][%s], dataType: %s\n",ShmOCPP20Data->ControllerComponentVariable[idx_var].component.name, ShmOCPP20Data->ControllerComponentVariable[idx_var].variable.name, ShmOCPP20Data->ControllerComponentVariable[idx_var].variableCharacteristics.dataType);
 
-							// To make sure all boolean value is in uppercase
-							if((strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"true") != NULL) ||
-							   (strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"True") != NULL) ||
-							   (strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"TRUE") != NULL))
+							if(strcmp((char*)ShmOCPP20Data->ControllerComponentVariable[idx_var].variableCharacteristics.dataType,DataEnumTypeStr[DataEnumType_decimal]) == 0)
 							{
-								strcpy((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"true");
+								if(isNumber(ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,TRUE)!=YES)
+								{
+									strcpy((char*)ShmOCPP20Data->SetVariables.Response_setVariableResult[idx].attributeStatus, SetVariableStatusEnumTypeStr[SetVariableStatusEnumType_Rejected]);
+									break;
+								}
 							}
-							else if((strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"false") != NULL) ||
-									(strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"False") != NULL) ||
-									(strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"FALSE") != NULL))
+							else if(strcmp((char*)ShmOCPP20Data->ControllerComponentVariable[idx_var].variableCharacteristics.dataType,DataEnumTypeStr[DataEnumType_integer]) == 0)
 							{
-								strcpy((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"false");
+								if(isNumber(ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue, FALSE)!=YES)
+								{
+									strcpy((char*)ShmOCPP20Data->SetVariables.Response_setVariableResult[idx].attributeStatus, SetVariableStatusEnumTypeStr[SetVariableStatusEnumType_Rejected]);
+									break;
+								}
+							}
+							else if(strcmp((char*)ShmOCPP20Data->ControllerComponentVariable[idx_var].variableCharacteristics.dataType,DataEnumTypeStr[DataEnumType_dateTime]) == 0)
+							{
+								if(isMatchTimeFormat(ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue)!=YES)
+								{
+									strcpy((char*)ShmOCPP20Data->SetVariables.Response_setVariableResult[idx].attributeStatus, SetVariableStatusEnumTypeStr[SetVariableStatusEnumType_Rejected]);
+									break;
+								}
+							}
+							else if(strcmp((char*)ShmOCPP20Data->ControllerComponentVariable[idx_var].variableCharacteristics.dataType,DataEnumTypeStr[DataEnumType_boolean]) == 0)
+							{
+								// To make sure all boolean value is in uppercase
+								if((strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"true") != NULL) ||
+								   (strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"True") != NULL) ||
+								   (strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"TRUE") != NULL))
+								{
+									strcpy((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"true");
+								}
+								else if((strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"false") != NULL) ||
+										(strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"False") != NULL) ||
+										(strstr((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"FALSE") != NULL))
+								{
+									strcpy((char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeValue,"false");
+								}
+								else
+								{
+									strcpy((char*)ShmOCPP20Data->SetVariables.Response_setVariableResult[idx].attributeStatus, SetVariableStatusEnumTypeStr[SetVariableStatusEnumType_Rejected]);
+									break;
+								}
 							}
 
 							if((strstr((char*)ShmOCPP20Data->ControllerComponentVariable[idx_var].variableAttribute[0].type, (char*)ShmOCPP20Data->SetVariables.setVariableData[idx].attributeType) == NULL) &&
@@ -19049,29 +19264,29 @@ void handleAuthorizeResponse(char *payload, int gun_index)
 			sprintf((char *)(char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.status, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "status")));
 
 			// Optional data
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "cacheExpiryDateTime") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "cacheExpiryDateTime") != NULL)
 				sprintf((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.cacheExpiryDateTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "cacheExpiryDateTime")));
 			else
 				memset(ShmOCPP20Data->Authorize.Response_idTokenInfo.cacheExpiryDateTime, 0x00, ARRAY_SIZE(ShmOCPP20Data->Authorize.Response_idTokenInfo.cacheExpiryDateTime));
 
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "chargingPriority") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "chargingPriority") != NULL)
 				ShmOCPP20Data->Authorize.Response_idTokenInfo.chargingPriority = json_object_get_int(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "chargingPriority"));
 
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "language1") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "language1") != NULL)
 				sprintf((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.language1, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "language1")));
 
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "evseId") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "evseId") != NULL)
 			{
-				for(int idx=0;idx<json_object_array_length(json_object_object_get(json_object_object_get(Authorize, "idTagInfo"), "evseId"));idx++)
+				for(int idx=0;idx<json_object_array_length(json_object_object_get(json_object_object_get(Authorize, "idTokenInfo"), "evseId"));idx++)
 				{
 					ShmOCPP20Data->Authorize.Response_idTokenInfo.evseId[idx] = json_object_get_int(json_object_array_get_idx(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "evseId"), idx));
 				}
 			}
 
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "language2") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "language2") != NULL)
 				sprintf((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.language2, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "language2")));
 
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "groupIdToken") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "groupIdToken") != NULL)
 			{
 				if(json_object_object_get(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "groupIdToken"), "idToken") != NULL)
 					sprintf((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.groupIdToken.idToken, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "groupIdToken"), "idToken")));
@@ -19082,7 +19297,7 @@ void handleAuthorizeResponse(char *payload, int gun_index)
 					sprintf((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.groupIdToken.type, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "groupIdToken"), "type")));
 			}
 
-			if(json_object_object_get(json_object_object_get(Authorize,"idTagInfo"), "personalMessage") != NULL)
+			if(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "personalMessage") != NULL)
 			{
 				if(json_object_object_get(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "personalMessage"), "format") != NULL)
 					sprintf((char *)ShmOCPP20Data->Authorize.Response_idTokenInfo.personalMessage.format, "%s", json_object_get_string(json_object_object_get(json_object_object_get(json_object_object_get(Authorize,"idTokenInfo"), "personalMessage"), "format")));