Przeglądaj źródła

2022-09-19/Jerry Wang
[OCPP 1.6]
Action:
1. Improve PnC Authorize function.
2. Add occupancy fee related fuctions.

File:
1. EVSE/Modularization/ocppfiles/MessageHandler.c
--> Action 1-2
2. EVSE/Modularization/ocppfiles/Module_OcppBackend.c
--> Action 2
3. EVSE/Projects/define.h
--> Action 2

Jerry Wang 2 lat temu
rodzic
commit
9f63dec0c8

+ 254 - 6
EVSE/Modularization/ocppfiles/MessageHandler.c

@@ -133,6 +133,7 @@ struct ClientTime
 	struct timespec MeterValues[CONNECTOR_QUANTITY];
 	struct timespec RemoteStartWait;
 	struct timespec TcciQueryDeduct;
+	struct timespec TcciQueryOccupancyDeduct;
 	struct timespec CharingProfileRefresh[CONNECTOR_QUANTITY];
 }clientTime;
 
@@ -1422,6 +1423,88 @@ void OCPP_query_deduct_info()
     }
 }
 
+// Occupancy fee deduct queue process
+int OCPP_insert_occupancyDeduct_info(char *occupancySN, char *creditNo, uint8_t deductResult, double amount, char *approvalNo)
+{
+	int result = PASS;
+	char* errMsg = NULL;
+	char sqlStr[8192];
+
+	sprintf(sqlStr, "insert or replace into report_occupancyDeduct_info(occupancySN, creditNo, deductResult, amount, approvalNo, isUploaded) values('%s', '%s', '%d', '%.2f', '%s', '0');",
+			occupancySN, creditNo, deductResult, amount, approvalNo);
+
+	if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+	{
+		result = FAIL;
+		DEBUG_WARN( "Insert local report_occupancyDeduct_info error message: %s\n", errMsg);
+	}
+
+	sprintf(sqlStr, "delete from report_occupancyDeduct_info where (idx < (select idx from report_occupancyDeduct_info order by idx desc limit 1)-5000);");
+	if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+	{
+		result = FAIL;
+		DEBUG_WARN( "delete local report_occupancyDeduct_info error message: %s\n", errMsg);
+	}
+
+	return result;
+}
+
+int OCPP_update_occupancyDeduct_info(char *occupancySN)
+{
+	int result = PASS;
+	char* errMsg = NULL;
+	char sqlStr[8192];
+
+	sprintf(sqlStr, "update report_occupancyDeduct_info set isUploaded='1' where occupancySN='%s';", occupancySN);
+
+	if (sqlite3_exec(db, sqlStr, 0, 0, &errMsg) != SQLITE_OK)
+	{
+		result = FAIL;
+		DEBUG_WARN( "Update local report_occupancyDeduct_info error message: %s\n", errMsg);
+	}
+
+	return result;
+}
+
+int queryOccupancyDeductCallBack(void *data, int columenCount, char **columnValue, char **columnName)
+{
+	json_object *dataBuf = json_object_new_object();
+
+	sprintf((char*)ShmOCPP16Data->DataTransfer[0].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
+	sprintf((char*)ShmOCPP16Data->DataTransfer[0].MessageId,"%s","ID_CreditDeductResult");
+
+	json_object_object_add(dataBuf, "occupancySN", json_object_new_string(columnValue[1]));
+	json_object_object_add(dataBuf, "creditNo", json_object_new_string(columnValue[2]));
+	json_object_object_add(dataBuf, "deductResult", json_object_new_boolean(atoi(columnValue[3])));
+	json_object_object_add(dataBuf, "amount", json_object_new_double(atof(columnValue[4])));
+	json_object_object_add(dataBuf, "approvalNo", json_object_new_string(columnValue[5]));
+
+	sprintf((char*)ShmOCPP16Data->DataTransfer[0].Data, "%s", json_object_to_json_string_ext(dataBuf, JSON_C_TO_STRING_PLAIN));
+	json_object_put(dataBuf);
+
+	ShmOCPP16Data->CsMsg.bits[0].DataTransferReq = 1;
+
+	return 0;
+}
+
+void OCPP_query_occupancyDeduct_info()
+{
+    int rc = 0;
+
+    char sql[100];
+    char zErrMsg[100];
+
+    sprintf(sql,"select * from report_occupancyDeduct_info where isUploaded='0' order by idx limit 1");
+
+    /* Execute SQL statement */
+    rc = sqlite3_exec(db, sql, queryOccupancyDeductCallBack, 0, (char **)&zErrMsg);
+
+    if( rc != SQLITE_OK )
+    {
+    	DEBUG_INFO("SQL error: %s\n", zErrMsg);
+    }
+}
+
 void reportReaderStatus(int gun_index)
 {
 	struct timeval tmnow;
@@ -1447,7 +1530,7 @@ void reportReaderStatus(int gun_index)
 	sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
 	sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId,"%s","ID_ReaderStatus");
 
-	json_object_object_add(dataBuf, "connectorId", json_object_new_int((gun_index+1)));
+	json_object_object_add(dataBuf, "ConnectorId", json_object_new_int((gun_index+1)));
 	json_object_object_add(dataBuf, "readerStatus", json_object_new_int(ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].readerStatus));
 	json_object_object_add(dataBuf, "timestamp", json_object_new_string(buf));
 	json_object_object_add(dataBuf, "SerialNo", json_object_new_string((char*)ShmOCPP16Data->TcciCustomData.SerialNo[gun_index]));
@@ -1460,6 +1543,40 @@ void reportReaderStatus(int gun_index)
 	ShmOCPP16Data->CsMsg.bits[gun_index].DataTransferReq = 1;
 }
 
+void getOccupancyFee(int gun_index)
+{
+	struct timeval tmnow;
+	struct tm *tm;
+	char buf[28];//, usec_buf[6];
+	gettimeofday(&tmnow, NULL);
+
+	time_t t;
+	t = time(NULL);
+	/*UTC time and date*/
+	tm = gmtime(&t);
+	strftime(buf,28,"%Y-%m-%dT%H:%M:%SZ", tm);
+
+	#if 0 // remove temporally
+		strftime(buf,30,"%Y-%m-%dT%H:%M:%S", tm);
+		strcat(buf,".");
+		sprintf(usec_buf,"%dZ",(int)tmnow.tv_usec);
+		strcat(buf,usec_buf);
+	#endif
+
+	json_object *dataBuf = json_object_new_object();
+
+	sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].VendorId, "%s", ShmSysConfigAndInfo->SysConfig.chargePointVendor);
+	sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].MessageId,"%s","ID_GetOccupancyFee");
+
+	json_object_object_add(dataBuf, "ConnectorId", json_object_new_int((gun_index+1)));
+	json_object_object_add(dataBuf, "occupancySN", json_object_new_string((char*)ShmOCPP16Data->TcciCustomData.GetOccupancyFee[gun_index].occupancySN));
+
+	sprintf((char*)ShmOCPP16Data->DataTransfer[gun_index].Data, "%s", json_object_to_json_string_ext(dataBuf, JSON_C_TO_STRING_PLAIN));
+	json_object_put(dataBuf);
+
+	ShmOCPP16Data->CsMsg.bits[gun_index].DataTransferReq = 1;
+}
+
 //==========================================
 // Check time passed since today
 //==========================================
@@ -5056,7 +5173,7 @@ void CheckSystemValue(void)
 	}
 
 	//===============================
-	// Credit deduct report
+	// Tcci credit deduct report
 	//===============================
 	if(ShmOCPP16Data->TcciCustomData.ReportCreditDeductReq)
 	{
@@ -5069,12 +5186,27 @@ void CheckSystemValue(void)
 		ShmOCPP16Data->TcciCustomData.ReportCreditDeductReq = FALSE;
 	}
 
-	if(getDiffSecNow(clientTime.TcciQueryDeduct) > 5)
+	if(isWebsocketSendable && (server_sign == TRUE) && (ShmOCPP16Data->CsMsg.bits[0].DataTransferReq != TRUE) && getDiffSecNow(clientTime.TcciQueryDeduct) > 5)
 	{
 		OCPP_query_deduct_info();
 		refreshStartTimer(&clientTime.TcciQueryDeduct);
 	}
 
+	if(ShmOCPP16Data->TcciCustomData.ReportOccupancyDeductReq)
+	{
+		OCPP_insert_occupancyDeduct_info((char*)ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.occupancySN, (char*)ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.creditNo,
+								         ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.deductResult, ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.amount,
+								         (char*)ShmOCPP16Data->TcciCustomData.OccupancyDeductResult.approvalNo);
+
+		ShmOCPP16Data->TcciCustomData.ReportOccupancyDeductReq = FALSE;
+	}
+
+	if(isWebsocketSendable && (server_sign == TRUE) && (ShmOCPP16Data->CsMsg.bits[0].DataTransferReq != TRUE) && getDiffSecNow(clientTime.TcciQueryOccupancyDeduct) > 5)
+	{
+		OCPP_query_occupancyDeduct_info();
+		refreshStartTimer(&clientTime.TcciQueryOccupancyDeduct);
+	}
+
 	for(int gun_index=0;gun_index < gunTotalNumber;gun_index++)
 	{
 		// ClockAlign MeterValue
@@ -5609,7 +5741,7 @@ void CheckSystemValue(void)
 		}
 
 		//==============================================
-		// TCCI reader status report
+		// TCCI related DataTransfer messages
 		//==============================================
 		if(isWebsocketSendable && (server_sign == TRUE) && (ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].ReportReaderStatusReq == 1))
 		{
@@ -5617,6 +5749,11 @@ void CheckSystemValue(void)
 			//ShmOCPP16Data->TcciCustomData.ReaderStatus[gun_index].ReportReaderStatusReq = 0;
 		}
 
+		if(isWebsocketSendable && (server_sign == TRUE) && (ShmOCPP16Data->TcciCustomData.GetOccupancyFee[gun_index].GetOccupancyFeeReq == 1))
+		{
+			getOccupancyFee(gun_index);
+		}
+
 		//==============================================
 		// CSU Trigger or timer timeout refresh Smart Charging Profile
 	    //==============================================
@@ -12165,6 +12302,92 @@ int handleDataTransferRequest(char *uuid, char *payload)
 			sprintf(message,"[%d,\"%s\",%s]",MESSAGE_TYPE_CALLRESULT, uuid, json_object_to_json_string_ext(response, JSON_C_TO_STRING_PLAIN));
 			json_object_put(response);
 		}
+		else if(strstr(tempmessageId, "ID_OccupancyFeeDisplay") != NULL)
+		{
+			json_object *data;
+			data = json_tokener_parse(tempdata);
+			if(!is_error(data))
+			{
+				json_object_object_add(response, "status", json_object_new_string("Accepted"));
+				int gun_index = 0;
+
+				if(json_object_object_get(data, "ConnectorId") != NULL)
+				{
+					gun_index = json_object_get_int(json_object_object_get(data, "ConnectorId"));
+					if(json_object_object_get(data, "occupancySN") != NULL)
+					{
+						sprintf((char *)ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].occupancySN, "%s", json_object_get_string(json_object_object_get(data,"occupancySN")));
+					}
+					else
+					{
+						json_object_object_add(response, "status", json_object_new_string("Rejected"));
+						json_object_object_add(response, "data", json_object_new_string("occupancySN data can not get."));
+					}
+
+					if(json_object_object_get(data, "actionId") != NULL)
+					{
+						ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].actionId = json_object_get_int(json_object_object_get(data,"actionId"));
+					}
+					else
+					{
+						json_object_object_add(response, "status", json_object_new_string("Rejected"));
+						json_object_object_add(response, "data", json_object_new_string("actionId data can not get."));
+					}
+				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("ConnectorId data can not get."));
+				}
+
+				if(strcmp(json_object_get_string(json_object_object_get(response,"status")),"Accepted")==0)
+				{
+					ShmOCPP16Data->TcciCustomData.OccupancyFeeDisplay[gun_index].OccupancyFeeDisplayReq = 1;
+				}
+			}
+			else
+			{
+				json_object_object_add(response, "status", json_object_new_string("Rejected"));
+				json_object_object_add(response, "data", json_object_new_string("OccupancyFeeDisplay content got something wrong."));
+			}
+			json_object_put(data);
+
+			sprintf(message,"[%d,\"%s\",%s]",MESSAGE_TYPE_CALLRESULT, uuid, json_object_to_json_string_ext(response, JSON_C_TO_STRING_PLAIN));
+			json_object_put(response);
+		}
+		else if(strstr(tempmessageId, "ID_SetOccupancyPrice") != NULL)
+		{
+			json_object *data;
+			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, "price") != NULL)
+				{
+					ShmOCPP16Data->TcciCustomData.SetOccupancyPrice.price = json_object_get_double(json_object_object_get(data,"price"));
+				}
+				else
+				{
+					json_object_object_add(response, "status", json_object_new_string("Rejected"));
+					json_object_object_add(response, "data", json_object_new_string("price data can not get."));
+				}
+
+				if(strcmp(json_object_get_string(json_object_object_get(response,"status")),"Accepted")==0)
+				{
+					ShmOCPP16Data->TcciCustomData.SetOccupancyPrice.SetOccupancyPriceReq = 1;
+				}
+			}
+			else
+			{
+				json_object_object_add(response, "status", json_object_new_string("Rejected"));
+				json_object_object_add(response, "data", json_object_new_string("SetOccupancyPrice content got something wrong."));
+			}
+			json_object_put(data);
+
+			sprintf(message,"[%d,\"%s\",%s]",MESSAGE_TYPE_CALLRESULT, uuid, json_object_to_json_string_ext(response, JSON_C_TO_STRING_PLAIN));
+			json_object_put(response);
+		}
 		// Support ISO-15118 related message
 		else if(strstr(tempmessageId, "TriggerMessage") != NULL)
 		{
@@ -17318,11 +17541,14 @@ void handleDataTransferResponse(char *payload, int gun_index)
 
 					if(json_object_object_get(Data, "idTokenInfo") != NULL)
 					{
-						sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.Response_idTokenInfo.status, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Data, "certificateStatus"), "status")));
+						if(json_object_object_get(json_object_object_get(Data, "idTokenInfo"), "status") != NULL)
+						{
+							sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.Response_idTokenInfo.status, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Data, "idTokenInfo"), "status")));
+						}
 
 						if(json_object_object_get(json_object_object_get(Data, "idTokenInfo"), "cacheExpiryDateTime") != NULL)
 						{
-							sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.Response_idTokenInfo.cacheExpiryDateTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Data, "certificateStatus"), "cacheExpiryDateTime")));
+							sprintf((char*)ShmOCPP16Data->v2g_extend.Authorize.Response_idTokenInfo.cacheExpiryDateTime, "%s", json_object_get_string(json_object_object_get(json_object_object_get(Data, "idTokenInfo"), "cacheExpiryDateTime")));
 						}
 					}
 					ShmOCPP16Data->v2g_extend.AuthorizeConf = 1;
@@ -17372,6 +17598,28 @@ void handleDataTransferResponse(char *payload, int gun_index)
 							if(json_object_object_get(Data, "ConnectorId") != NULL)
 								ShmOCPP16Data->TcciCustomData.ReaderStatus[json_object_get_int(json_object_object_get(Data, "ConnectorId"))-1].ReportReaderStatusReq = 0;
 						}
+
+						if(strstr(json_object_get_string(json_object_object_get(Data, "msgId")), "ID_GetOccupancyFee") != NULL)
+						{
+							if(json_object_object_get(Data, "ConnectorId") != NULL)
+							{
+								if(json_object_object_get(Data, "occupancySN") != NULL)
+									sprintf((char*)ShmOCPP16Data->TcciCustomData.GetOccupancyFee[json_object_get_int(json_object_object_get(Data, "ConnectorId"))-1].response_occupancySN, "%s", json_object_get_string(json_object_object_get(Data, "occupancySN")));
+								if(json_object_object_get(Data, "startTime") != NULL)
+									sprintf((char*)ShmOCPP16Data->TcciCustomData.GetOccupancyFee[json_object_get_int(json_object_object_get(Data, "ConnectorId"))-1].response_startTime, "%s", json_object_get_string(json_object_object_get(Data, "startTime")));
+								if(json_object_object_get(Data, "duration") != NULL)
+									ShmOCPP16Data->TcciCustomData.GetOccupancyFee[json_object_get_int(json_object_object_get(Data, "ConnectorId"))-1].response_duration = json_object_get_int(json_object_object_get(Data, "duration"));
+								if(json_object_object_get(Data, "occupancyFee") != NULL)
+									ShmOCPP16Data->TcciCustomData.GetOccupancyFee[json_object_get_int(json_object_object_get(Data, "ConnectorId"))-1].response_occupancyFee = json_object_get_double(json_object_object_get(Data, "occupancyFee"));
+							}
+							ShmOCPP16Data->TcciCustomData.GetOccupancyFee[gun_index].GetOccupancyFeeReq = 0;
+						}
+
+						if(strstr(json_object_get_string(json_object_object_get(Data, "msgId")), "ID_OccupancyFeeResult") != NULL)
+						{
+							if(json_object_object_get(Data, "occupancySN") != NULL)
+								OCPP_update_occupancyDeduct_info((char*)json_object_get_string(json_object_object_get(Data, "occupancySN")));
+						}
 					}
 				}
 			}

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

@@ -113,6 +113,14 @@ static char *sqlReportDeduct = "create table if not exists report_deduct_info (
 		                       "storeId text,"
 							   "isUploaded text);";
 
+static char *sqlReportOccupancyDeduct = "create table if not exists report_occupancyDeduct_info ( idx integer primary key,"
+		                       "occupancySN text,"
+							   "creditNo text,"
+							   "deductResult text,"
+							   "amount text,"
+							   "approvalNo text,"
+							   "isUploaded text);";
+
 //=================================
 // Common routine
 //=================================
@@ -1361,7 +1369,7 @@ int main(void)
 	queueOpInfo.TransactionMessageResend = 0;
 
 	DEBUG_INFO("Module_OcppBackend task initialization...\n");
-	DEBUG_INFO("Git update date: 2022/09/07 \n");
+	DEBUG_INFO("Git update date: 2022/09/19 \n");
 	//lws_set_log_level(LLL_PARSER | LLL_HEADER | LLL_ERR | LLL_WARN | LLL_NOTICE | LLL_INFO | LLL_DEBUG | LLL_EXT | LLL_CLIENT | LLL_LATENCY  , NULL);
 
 	if(ProcessShareMemory()== FAIL)
@@ -1464,6 +1472,17 @@ int main(void)
 		DEBUG_INFO( "Opened report_deduct_info table successfully\n");
 	}
 
+	// Create occupancy deduct info
+	if(sqlite3_exec(db, sqlReportOccupancyDeduct, 0, 0, &errMsg) != SQLITE_OK)
+	{
+		DEBUG_INFO( "Create Table report_occupancyDeduct_info error %s\n",errMsg);
+		return 0;
+	}
+	else
+	{
+		DEBUG_INFO( "Opened report_occupancyDeduct_info table successfully\n");
+	}
+
 	if(initialConfigurationTable() != PASS)
 	{
 		DEBUG_WARN("OCPPConfiguration version mismatch, upgrade it.\n");

+ 40 - 1
EVSE/Projects/define.h

@@ -6014,12 +6014,50 @@ struct StructReaderStatus
     unsigned char ReportReaderStatusReq:1;
 };
 
+struct StructOccupancyFeeDisplay
+{
+	unsigned char occupancySN[64];
+	int   actionId;
+    unsigned char OccupancyFeeDisplayReq:1;
+};
+
+struct StructSetOccupancyPrice
+{
+	float   price;
+    unsigned char SetOccupancyPriceReq:1;
+};
+
+struct StructGetOccupancyFee
+{
+	unsigned char occupancySN[64];
+
+	int   response_duration;
+	float response_occupancyFee;
+    unsigned char response_occupancySN[37];
+    unsigned char response_startTime[64];
+
+    unsigned char GetOccupancyFeeReq:1;
+};
+
+struct StructOccupancyDeductResult
+{
+	unsigned char deductResult:1;
+	float amount;
+	unsigned char occupancySN[37];
+	unsigned char creditNo[64];
+	unsigned char approvalNo[20];
+};
+
 struct StructTcciCustomData
 {
     struct StructChargerInfo ChargerInfo;
     struct StructWeatherInfo WeatherInfo;
     struct StructCreditDeductResult DeductInfo;
     struct StructReaderStatus ReaderStatus[CONNECTOR_QUANTITY];
+    struct StructOccupancyFeeDisplay OccupancyFeeDisplay[CONNECTOR_QUANTITY];
+    struct StructSetOccupancyPrice SetOccupancyPrice;
+    struct StructGetOccupancyFee GetOccupancyFee[CONNECTOR_QUANTITY];
+    struct StructOccupancyDeductResult OccupancyDeductResult;
     unsigned char TriggerReaderReq[3];
     unsigned char SerialNo[CONNECTOR_QUANTITY][37];
     unsigned char VEMData[CONNECTOR_QUANTITY][65];
@@ -6029,7 +6067,8 @@ struct StructTcciCustomData
     unsigned char ChargerInfoConf:1;
     unsigned char WeatherInfoReq:1;
     unsigned char WeatherInfoConf:1;
-    unsigned char :3;                  // bit 5-7 , reserved
+    unsigned char ReportOccupancyDeductReq:1;
+    unsigned char :2;                  // bit 6-7 , reserved
 };
 
 struct OCMFData