
/*
 * wifi.c
 *
 *  Created on: 13-Jan-2020
 *      Author: aed
 */
/**************INCLUDE BLOCK**************/

#include "stdio.h"
#include "OCPP.h"
#include "ProcessOCPP.h"
#include "modbus.h"
#include "rng.h"
#include "w25qxx.h"
#include <string.h>

/***********INCLUDE BLOCK END*************/

/***** Data Type, Constant, and Macro Definitions *****/

/* Global variables*/

volatile char DC001_OCPP_timestamp1[30];
char websocket_success,boot_success;
char Bootnotification[15];
char Statusnotification[15];
char metervalue[15];
unsigned char WaitForResponse;  //v4.x.7
char HeartBeat_Res[15];         //4.x.7 change

/* Extern Data Declarations */

extern char internal_rtc_read;
extern uint8_t status;
volatile extern uint32_t energy,energy2,energy3;
extern uint8_t Time_Zone;
extern char otp_ocpp[14];
extern char offset[8];
extern RNG_HandleTypeDef hrng;

/* Static Data Declarations */

static int SEC;
static uint32_t RendomNumber;
static volatile int hertbeat=0;//interval=300;
char gafw_status[30]={0};

/***** Data Type, Constant, and Macro Definitions END *****/


/***** Public Function Bodies *****/

int StateFlowOCPP(OCPP_States OCPP_State_ACType2);

/***** Public Function Bodies END *****/
/**
 * @brief State flow for DC001 protocol.
 *
 * This function represents the state flow for the DC001 protocol.
 *
 * @param None
 * @return None
 */
void OCPPProtocol(void)
{
	//StateFlowOCPP();			/* Main State flow of DC001 protocol */
}
/**
 * @brief Check OCPP state for DC001 and perform the operation.
 *
 * This function checks the OCPP state for DC001 and performs the corresponding operation.
 *
 * @param OCPP_State_ACType2 The OCPP state for DC001.
 * @return None
 */
int StateFlowOCPP(OCPP_States OCPP_State_ACType2)
{
	HAL_StatusTypeDef status;
	status = HAL_RNG_GenerateRandomNumber(&hrng, &RendomNumber);
	//char ocpp_reson[20];
	if(status != HAL_OK)
	{
		return 0xff;
	}

	 switch (OCPP_State_ACType2)
	 {
	    case idle_ocpp:
	    {
	    	 break;
	    }
	    case initialisation_ocpp:
	    {
	    	//if(AC001_OCPP_Charger_Status == 0u)
	    	{
	    	    if(websocket_success == 1u)  /* if wifi and web socket connection is successful */
	    	    {
	    	    	sprintf(Bootnotification,"\"%lu\"",RendomNumber);

	    	    	//AC001_OCPP_Charger_Status = 0u;/* Assign status */
	     	    	BootNotification("LUBI","LUBI","LUBI-BS",1,1,RendomNumber,"AC");/* send boot notification to server */
	    	    }
	    	    OCPP_State_ACType2 = idle_ocpp;
	    	}
    	    break;
	    }
#ifdef DATATRANSFER
	    case datatansfer:
		{
			DataTransfer(RendomNumber,"LUBI-AEPL","PRE-AUTH-RFID");
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case DataTransferChargingType_G1_ocpp:
	    {
	    	if(charger_status_G1.charge_by_automatic == 1)
	    	{
	    		DataTransferChargingType(RendomNumber,charger_status_G1.transaction_id,"LUBI-AEPL","DataTransferChargingType","Automatic");
	    	}
	    	else if(charger_status_G1.charging_time != 0)
	    	{
	    		DataTransferChargingType(RendomNumber,charger_status_G1.transaction_id,"LUBI-AEPL","DataTransferChargingType","Time",charger_status_G1.charging_time);
	    	}
	    	else
	    	{
	    		DataTransferChargingType(RendomNumber,charger_status_G1.transaction_id,"LUBI-AEPL","DataTransferChargingType","Unit",charger_status_G1.charge_by_energy);
	    	}
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case DataTransferChargingType_G2_ocpp:
			{
				if(charger_status_G2.charge_by_automatic == 1)
				{
					DataTransferChargingType(RendomNumber,charger_status_G2.transaction_id,"LUBI-AEPL","DataTransferChargingType","Automatic");
				}
				else if(charger_status_G2.charging_time != 0)
				{
					DataTransferChargingType(RendomNumber,charger_status_G2.transaction_id,"LUBI-AEPL","DataTransferChargingType","Time",charger_status_G2.charging_time);
				}
				else
				{
					DataTransferChargingType(RendomNumber,charger_status_G2.transaction_id,"LUBI-AEPL","DataTransferChargingType","Unit",charger_status_G2.charge_by_energy);
				}
				OCPP_State_ACType2 = idle_ocpp;
				break;
			}
	    case DataTransferChargingType_G3_ocpp:
			{
				if(charger_status_G3.charge_by_automatic == 1)
				{
					DataTransferChargingType(RendomNumber,charger_status_G3.transaction_id,"LUBI-AEPL","DataTransferChargingType","Automatic");
				}
				else if(charger_status_G3.charging_time != 0)
				{
					DataTransferChargingType(RendomNumber,charger_status_G3.transaction_id,"LUBI-AEPL","DataTransferChargingType","Time",charger_status_G3.charging_time);
				}
				else
				{
					DataTransferChargingType(RendomNumber,charger_status_G3.transaction_id,"LUBI-AEPL","DataTransferChargingType","Unit",charger_status_G3.charge_by_energy);
				}
				OCPP_State_ACType2 = idle_ocpp;
				break;
			}
#endif
	    case G1_Authorization_ocpp :
		{
			sprintf(charger_status_G1.Authorised,"\"%lu\"",RendomNumber);
			Authorizereq(charger_status_G1.start_tagid,1,1,RendomNumber);
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G2_Authorization_ocpp :
		{
			sprintf(charger_status_G2.Authorised,"\"%lu\"",RendomNumber);
			Authorizereq(charger_status_G2.start_tagid,1,1,RendomNumber);
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G3_Authorization_ocpp :
		{
			 sprintf(charger_status_G3.Authorised,"\"%lu\"",RendomNumber);
			 Authorizereq(charger_status_G3.start_tagid,1,1,RendomNumber);
			 OCPP_State_ACType2 = idle_ocpp;
			 break;
		}
	    case G1_charging_ocpp:
	    {

			sprintf(charger_status_G1.start_transaction,"\"%lu\"",RendomNumber);

			{
				StartTransactionreq(RendomNumber,1,1,charger_status_G1.start_tagid,(energy+OCPP.acc_enery1),0,charger_status_G1.start_time);//RM=2
			}
			OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case  G1_MeterValue_Periodic_ocpp:
	    {
	    	Get_Time();
	    	sprintf(charger_status_G1.metervalue,"\"%lu\"",RendomNumber);
	    	Metervalue_Periodic(1,1,RendomNumber,charger_status_G1.transaction_id,(float)charger_status_G1.current,(float)charger_status_G1.voltage,(float)charger_status_G1.power,(float)(energy+OCPP.acc_enery1),DC001_OCPP_timestamp1);//RM=voltage3
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case  G1_MeterValue_ClockAlign_ocpp :
		{
			Get_Time();
			sprintf(charger_status_G1.metervalue,"\"%lu\"",RendomNumber);
			Metervalue_ClockAlign(1,1,RendomNumber,0,(float)charger_status_G1.current,(float)charger_status_G1.voltage,(float)charger_status_G1.power,(float)(energy+OCPP.acc_enery1),DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case  G1_MeterValue_Began_ocpp :
		{
			Get_Time();
			sprintf(charger_status_G1.metervalue,"\"%lu\"",RendomNumber);
			Metervalue_Began(1,1,RendomNumber,charger_status_G1.transaction_id,(float)charger_status_G1.current,(float)charger_status_G1.voltage,(float)charger_status_G1.power,(float)(energy+OCPP.acc_enery1),DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case  G1_MeterValue_End_ocpp :
		{
			Get_Time();
			sprintf(charger_status_G1.metervalue,"\"%lu\"",RendomNumber);
			Metervalue_End(1,1,RendomNumber,charger_status_G1.transaction_id,(float)charger_status_G1.current,(float)charger_status_G1.voltage,(float)charger_status_G1.power,(float)(energy+OCPP.acc_enery1),DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case Heartbeat_ocpp:
		{
			sprintf(HeartBeat_Res,"\"%lu\"",RendomNumber); //4.x.7 change
			WaitForResponse = true; ///////////////V4.x.7 ////////////////
			Heartbeat(1,1,RendomNumber);
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G1_StatusNotification_ocpp:
	    {
	    	Get_Time();
	    	sprintf(charger_status_G1.Statusnotification,"\"%lu\"",RendomNumber);
	    	char *charger_error = ocpp_error(charger_status_G1.error);
	    	char *EVSE_status = ocpp_statuse(charger_status_G1.charging_status);

	        StatusNotification(RendomNumber, 1, 1, EVSE_status, DC001_OCPP_timestamp1, charger_error);//RM=11
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G1_discharging_ocpp:
	    {
	    	//char ocpp_reson[20];
	    	sprintf(charger_status_G1.stop_transaction,"\"%lu\"",RendomNumber);
	    	char *ocpp_reson = ocpp_resone(charger_status_G1.reson);
	    	StopTransactionreq(RendomNumber, charger_status_G1.start_tagid, (energy+OCPP.acc_enery1), ocpp_reson,charger_status_G1.transaction_id,1, 4, charger_status_G1.stop_time);
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G2_charging_ocpp:
	    {

			sprintf(charger_status_G2.start_transaction,"\"%lu\"",RendomNumber);
			{
				StartTransactionreq(RendomNumber,1,2,charger_status_G2.start_tagid,(energy2+OCPP.acc_enery2),0,charger_status_G2.start_time);//RM=2
			}
			OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G2_MeterValue_Periodic_ocpp:
	    {
	    	Get_Time();
	    	sprintf(charger_status_G2.metervalue,"\"%lu\"",RendomNumber);
	    	Metervalue_Periodic(1,2,RendomNumber,charger_status_G2.transaction_id,charger_status_G2.current,(float)charger_status_G2.voltage,charger_status_G2.power,(float)(energy2+OCPP.acc_enery2),DC001_OCPP_timestamp1);//RM=voltage3
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G2_MeterValue_ClockAlign_ocpp:
		{
			Get_Time();
			sprintf(charger_status_G2.metervalue,"\"%lu\"",RendomNumber);
			Metervalue_ClockAlign(1,2,RendomNumber,charger_status_G2.transaction_id,charger_status_G2.current,(float)charger_status_G2.voltage,charger_status_G2.power,(float)(energy2+OCPP.acc_enery2),DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G2_MeterValue_Began_ocpp:
		{
			Get_Time();
			sprintf(charger_status_G2.metervalue,"\"%lu\"",RendomNumber);
			Metervalue_Began(1,2,RendomNumber,charger_status_G2.transaction_id,charger_status_G2.current,(float)charger_status_G2.voltage,charger_status_G2.power,(float)(energy2+OCPP.acc_enery2),DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G2_MeterValue_End_ocpp:
		{
			Get_Time();
			sprintf(charger_status_G2.metervalue,"\"%lu\"",RendomNumber);
			Metervalue_End(1,2,RendomNumber,charger_status_G2.transaction_id,charger_status_G2.current,(float)charger_status_G2.voltage,charger_status_G2.power,(float)(energy2+OCPP.acc_enery2),DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}

	    case G2_StatusNotification_ocpp:
	    {
	    	Get_Time();
	    	sprintf(charger_status_G2.Statusnotification,"\"%lu\"",RendomNumber);
	    	char *charger_error = ocpp_error(charger_status_G2.error);
	    	char *EVSE_status = ocpp_statuse(charger_status_G2.charging_status);

	        StatusNotification(RendomNumber, 1, 2, EVSE_status, DC001_OCPP_timestamp1, charger_error);//RM=11
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G2_discharging_ocpp:
	    {
	    	//char ocpp_reson[20];
	    	sprintf(charger_status_G2.stop_transaction,"\"%lu\"",RendomNumber);
	    	char *ocpp_reson = ocpp_resone(charger_status_G2.reson);
//	    	if(StopTransactionreq(RendomNumber, charger_status_G2.start_tagid, (energy2+OCPP.acc_enery2), ocpp_reson,charger_status_G2.transaction_id,1, 2, charger_status_G2.stop_time) == 1)//RM=8
//			{
//
//			}
	    	StopTransactionreq(RendomNumber, charger_status_G2.start_tagid, (energy2+OCPP.acc_enery2), ocpp_reson,charger_status_G2.transaction_id, 1, 2, charger_status_G2.stop_time);
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
#ifdef GUN3
	    case G3_charging_ocpp:
	    {

			sprintf(charger_status_G3.start_transaction,"\"%u\"",RendomNumber);

			/*if(charger_status_G3.reson == Remote)
			{
				StartTransactionreq(RendomNumber,1,3,charger_status_G3.start_tagid,voltage,1,charger_status_G3.start_time,0);//RM=2
			}
			else*/
			{
				StartTransactionreq(RendomNumber,1,3,charger_status_G3.start_tagid,energy3,0,charger_status_G3.start_time);//RM=2
			}
			OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G3_MeterValue_Periodic_ocpp:
	    {
	    	Get_Time();
	    	sprintf(charger_status_G3.metervalue,"\"%u\"",RendomNumber);
	    	Metervalue_Periodic(1,3,RendomNumber,charger_status_G3.transaction_id,charger_status_G3.current,charger_status_G3.voltage,charger_status_G3.power,(float)energy3,DC001_OCPP_timestamp1);//RM=voltage3
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G3_MeterValue_ClockAlign_ocpp:
		{
			Get_Time();
			sprintf(charger_status_G3.metervalue,"\"%u\"",RendomNumber);
			Metervalue_ClockAlign(1,3,RendomNumber,charger_status_G3.transaction_id,charger_status_G3.current,charger_status_G3.voltage,charger_status_G3.power,(float)energy3,DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G3_MeterValue_Began_ocpp:
		{
			Get_Time();
			sprintf(charger_status_G3.metervalue,"\"%u\"",RendomNumber);
			Metervalue_Began(1,3,RendomNumber,charger_status_G3.transaction_id,charger_status_G3.current,charger_status_G3.voltage,charger_status_G3.power,(float)energy3,DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G3_MeterValue_End_ocpp:
		{
			Get_Time();
			sprintf(charger_status_G3.metervalue,"\"%u\"",RendomNumber);
			Metervalue_End(1,3,RendomNumber,charger_status_G3.transaction_id,charger_status_G3.current,charger_status_G3.voltage,charger_status_G3.power,(float)energy3,DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case G3_StatusNotification_ocpp:
	    {
	    	Get_Time();

	    	char *charger_error = ocpp_error(charger_status_G3.error);
	    	char *EVSE_status = ocpp_statuse(charger_status_G3.charging_status);

	    	sprintf(charger_status_G3.Statusnotification,"\"%u\"",RendomNumber);

	        StatusNotification(RendomNumber,1,3,EVSE_status,DC001_OCPP_timestamp1,charger_error);//RM=11
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case G3_discharging_ocpp:
	    {
	    	char *ocpp_reson = ocpp_resone(charger_status_G3.reson);
	    	//char ocpp_reson[20];
	    	sprintf(charger_status_G3.stop_transaction,"\"%u\"",RendomNumber);
	    	StopTransactionreq(RendomNumber,charger_status_G3.start_tagid,energy3,ocpp_reson,charger_status_G3.transaction_id,1,2,charger_status_G3.stop_time);

	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
#endif
	    case power_ON_available_ocpp:	//v4.x.8
		{
			Get_Time();
			char *charger_error = ocpp_error(6);
			char *EVSE_status = ocpp_statuse(0);
			sprintf(charger_status_G1.Statusnotification,"\"%lu\"",RendomNumber);
			StatusNotification(RendomNumber, 1, 3, EVSE_status, DC001_OCPP_timestamp1, charger_error); //RM=11
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case  G_MeterValue_ClockAlign_ocpp :
		{
			Get_Time();
			sprintf(charger_status_G1.metervalue,"\"%lu\"", RendomNumber);
			Metervalue_ClockAlign(1, 0, RendomNumber, 0, (float)(charger_status_G1.current+charger_status_G2.current+charger_status_G3.current), (float)(charger_status_G1.voltage*1.73), (float)((charger_status_G1.power+charger_status_G2.power+charger_status_G3.power)/1000), (float)((OCPP.acc_enery1 + OCPP.acc_enery2 + OCPP.acc_enery3)/1000), DC001_OCPP_timestamp1);//RM=voltage3
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case Stop_Tx_On_Cach_Memory :
		{
			//char *ocpp_reson = ocpp_resone(Cash_Memory.Reson[Cash_Memory.dummy]);
//			StopTransactionreq(RendomNumber, Cash_Memory.Tag_Id[Cash_Memory.dummy], Cash_Memory.Metervalue[Cash_Memory.dummy], ocpp_reson, Cash_Memory.transaction_id[Cash_Memory.dummy] , 1, 2, Cash_Memory.StopTxTime[Cash_Memory.dummy]);
			OCPP_State_ACType2 = idle_ocpp;
			break;
		}
	    case FirmwareNotification_Req:
	    {
	    	FirmwareStatusNotificationreq(RendomNumber,gafw_status);
	    			OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }

	    /*case emergency_ocpp:
	    {
	    	if(OCPP_ACType2_val == 1u)
    	    {
	    		Get_Time();
	    		StopTransactionreq(RendomNumber,"lubi-1",(float)ocpp_energy,"userstop",charger_status.transaction_id,1,4,DC001_OCPP_timestamp1,0);//RM=8
	    		OCPP_ACType2_val = 0u; Reset value
	    		//OCPP_State_ACType2 = idle_ocpp;
    	    }
	    	OCPP_ACType2_val = 0u; Reset value
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case RemotStartResponse:
	    {
	    	RemoteStartTransaction("1233","Accepted",1);
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
	    case RemotRejectResponse:
	    {
	    	RemoteStartTransaction("1233","Rejected",1);
	    	OCPP_State_ACType2 = idle_ocpp;
	    	break;
	    }
*/
	    default:
	    {
	    	break;
	    }
	 }

}
/**
 * @brief Set the RTC (Real-Time Clock) with the provided date and time.
 *
 * This function sets the RTC with the specified year, month, day, hour, minute,
 * second, and day of the week.
 *
 * @param year: Year (0-99).
 * @param month: Month (1-12).
 * @param day: Day of the month (1-31).
 * @param hour: Hour (0-23).
 * @param min: Minute (0-59).
 * @param sec: Second (0-59).
 * @param dow: Day of the week (1-7, where 1 is Monday and 7 is Sunday).
 * @return 0 on success, -1 if setting the date fails, -2 if setting the time fails.
 */
int RTC_Set(
        uint8_t year, uint8_t month, uint8_t day,
        uint8_t hour, uint8_t min, uint8_t sec,
        uint8_t dow) {
    HAL_StatusTypeDef res;
    RTC_TimeTypeDef time;
    RTC_DateTypeDef date;
 //   uint8_t buff[200];


    memset(&time, 0, sizeof(time));
    memset(&date, 0, sizeof(date));

    date.WeekDay = dow;
    date.Year = year;
    date.Month = month;
    date.Date = day;

    res = HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN);
    if(res != HAL_OK) {
        //UART_Printf("HAL_RTC_SetDate failed: %d\r\n", res);
        return -1;
    }

    time.Hours = hour;
    time.Minutes = min;
    time.Seconds = sec;

    res = HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN);
    if(res != HAL_OK) {
      //  UART_Printf("HAL_RTC_SetTime failed: %d\r\n", res);
        return -2;
    }

    return 0;
}
/**
 * @brief Process OCPP data and perform heartbeat operations.
 *
 * This function increments the heartbeat counter and checks if the websocket connection
 * is successful. If successful, it checks if the heartbeat interval has passed, and if so,
 * enqueues a heartbeat task. It also processes any pending tasks in the queue.
 *
 * @return Nothing.
 */
char OCPP_data(void)
{
	hertbeat++;
	if(websocket_success)
	{
		if(++SEC > Ocpp_Setting.HeartbeatIntvl)
		{
			SEC = 0;
			//StateFlowOCPP(Heartbeat_ocpp);//heart
			enQueue(Heartbeat_ocpp);
			//AC001_OCPP_Charger_Status = idle_EVSE;
		}

		if( isEmpty() == true )
		{
			//  val = -1;
		}
		else
		{
			StateFlowOCPP(deQueue());//heart
		}
	}
	 if(hertbeat> 600) //V4.x.8
	{
		hertbeat=0;
		internal_rtc_read = 1;
	}


}
/**
 * @brief Get the current time from the RTC and format it into DC001 OCPP timestamp.
 *
 * This function retrieves the current time from the RTC and formats it into the DC001 OCPP timestamp
 * based on the configured time zone.
 * The formatted timestamp is stored in the global variable `DC001_OCPP_timestamp1`.
 *
 * @return Nothing.
 */
int Get_Time(void)
{
	RTC_TimeTypeDef time;
	RTC_DateTypeDef date;
	HAL_StatusTypeDef res;
 //	char buff[512];
	//internal_rtc_read = 1;

	res = HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);

	if(res != HAL_OK) {
		//UART_Printf("HAL_RTC_GetTime failed: %d\r\n", res);
		return 0;
	}

	//sprintf(buff,"HAL_RTC_GetTime: %02d: %02d: %02d\r\n",time.Hours,time.Minutes,time.Seconds);
	//UART_Printf(buff);

	//UART_Printf("test.........\r\n");
	res = HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);


	if(res != HAL_OK) {
		UART_Printf("HAL_RTC_GetDate failed: %d\r\n", res);
		return 0;
	}

	if(Time_Zone == 1)
	{
		sprintf(DC001_OCPP_timestamp1,"20%02d-%02d-%02dT%02d:%02d:%02dZ",date.Year,date.Month,date.Date,time.Hours,time.Minutes,time.Seconds);
	}
	else
	{
		sprintf(DC001_OCPP_timestamp1,"20%02d-%02d-%02dT%02d:%02d:%02d%s",date.Year,date.Month,date.Date,time.Hours,time.Minutes,time.Seconds,offset);
	}
	//UART_Printf(DC001_OCPP_timestamp1);

//	UART_Printf("\r\n");
}
/**
 * @brief Get the string representation of the OCPP reason.
 *
 * This function returns the string representation of the specified OCPP reason code.
 *
 * @param reson The OCPP reason code.
 * @return A pointer to the string representation of the OCPP reason.
 */
char *ocpp_resone(char reson)
{
	char *ptr;
	if(reson == EVDisconnected)
	{
		//strcpy(ocpp_reson,"EVDisconnected");
		ptr = "EVDisconnected";
	}
	else if(reson == Other)
	{
		ptr = "Other";
	}
	else if(reson == Remote)
	{
		//strcpy(ocpp_reson,"Remote");
		ptr = "Remote";
	}
	else if(reson == Local)
	{
		ptr = "Local";
	}
	else if(reson == EmergencyStop)
	{
		ptr = "EmergencyStop";
	}
	else if(reson == HardReset)
	{
		ptr = "HardReset";
	}
	else if(reson == PowerLoss)
	{
		ptr = "PowerLoss";
	}
	else if(reson == SoftReset)
	{
		ptr = "SoftReset";
	}
	else if(reson == DeAuthorized)
	{
		ptr = "DeAuthorized";
	}

	return ptr;

}
/**
 * @brief Get the string representation of the OCPP error.
 *
 * This function returns the string representation of the specified OCPP error code.
 *
 * @param error The OCPP error code.
 * @return A pointer to the string representation of the OCPP error.
 */
char *ocpp_error(char error)
{
	char *ptr;
	if(error == NoError_ChargerPoint)
	{
		//strcpy(charger_error,"NoError");

		ptr = "NoError";
	}
	else if(error == UnderVoltage)
	{
		ptr = "UnderVoltage";
	}
	else if(error == OverVoltage)
	{
		ptr = "OverVoltage";
	}
	else if(error == OverCurrentFailure)
	{
		ptr = "OverCurrentFailure";
	}
	else if(error == PowerMeterFailure)
	{
		ptr = "PowerMeterFailure";
	}
	else if(error == PowerSwitchFailure)
	{
		ptr = "PowerSwitchFailure";
	}
	else if(error == ReaderFailure)
	{
		ptr = "ReaderFailure";
	}
	else if(error == ResetFailure)
	{
		ptr = "ResetFailure";
	}
	else if(error == LocalListConflict)
	{
		ptr = "LocalListConflict";
	}
	else if(error == InternalError)
	{
		ptr = "InternalError";
	}
	else if(error == GroundFailure)
	{
		ptr = "GroundFailure";
	}

	return ptr;

}
/**
 * @brief Get the string representation of the OCPP charging status.
 *
 * This function returns the string representation of the specified OCPP charging status code.
 *
 * @param charging_status The OCPP charging status code.
 * @return A pointer to the string representation of the OCPP charging status.
 */
char *ocpp_statuse(char charging_status)
{
	char *ptr;

	if(charging_status == SuspendedEVSE_ChargerPoint)
	{
		ptr = "SuspendedEVSE";
	}
	else if(charging_status == SuspendedEV_ChargerPoint)
	{
		ptr = "SuspendedEV";
	}
	else if(charging_status == Faulted_ChargerPoint)
	{
		ptr = "Faulted";
	}
	else if(charging_status == Charging_ChargerPoint)
	{
		ptr = "Charging";
	}
	else if(charging_status == Available_ChargerPoint)
	{
		ptr = "Available";
	}
	else if(charging_status == Preparing_ChargerPoint)
	{
		ptr = "Preparing";
	}
	else if(charging_status == Finishing_ChargerPoint)
	{
		ptr = "Finishing";
	}
	else if(charging_status == Unavailable_ChargerPoint)
	{
		ptr = "Unavailable";
	}
	return ptr;
}
/**
 * @brief Add a value to the queue.
 *
 * This function adds the specified value to the queue.
 *
 * @param value The value to be added to the queue.
 */
void enQueue(unsigned char value)
{
  if( isFull() == true )
  {
    //printf("ERROR: Queue is Overflow!!!\n");
	  FRONT = 0;
		  REAR=0;
  }
  else
  {
    if( FRONT == -1 )
    {
      FRONT = 0;
    }

    REAR++;

    //int value;
    // printf("Enter a value to be add: ");
    //scanf("%d",&value);
    queue_data[REAR] = value;
   // printf("%d is added to the Queue\n", value);
  }
}
/**
 * @brief Delete an element from the queue.
 *
 * This function deletes an element from the queue and returns the deleted value.
 *
 * @return The value deleted from the queue.
 */
char deQueue()
{
int8_t val;

  //else
  {
    //printf("%d is deleted\r\n",
	  val = queue_data[FRONT];

    FRONT++;

    /* Reset it, if we reached the end */
    if(FRONT > REAR)
    {
      FRONT = REAR = -1;
    }
  }
  return val;
}
/**
 * @brief Check if the queue is empty.
 *
 * @return True if the queue is empty, false otherwise.
 */
char isEmpty()
{
  char isQueueEmpty = false;

  if( FRONT == -1 )
  {
    isQueueEmpty = true;
  }

  return (isQueueEmpty);
}
/**
 * @brief Check if the queue is full.
 *
 * @return True if the queue is full, false otherwise.
 */
char isFull()
{
  char isQueueFull = false;

  if( REAR == MAX-1 )
  {
    isQueueFull = true;
  }

  return (isQueueFull);
}
/**
 * @brief Peek at the top element of the queue.
 *
 * This function checks and prints the top element of the queue if it is not empty.
 */
void peek()
{
  if( isEmpty() == true )
  {
  //  printf("Queue is Empty!!!\n");
  }
  else
  {
    //printf("Top Element is %d\n", queue[FRONT]);
  }
}
void qClear(void)
{
	REAR = FRONT = 0;
}

