#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/termios.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <linux/sockios.h> 
#include <linux/socket.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h> 
#include <sys/timeb.h> 
#include <math.h>//for pow
#include <unistd.h>
#include "../../define.h"

//#define Debug

struct SysConfigAndInfo			*ShmSysConfigAndInfo;
struct StatusCodeData 			*ShmStatusCodeData;


#ifdef SystemLogMessage
int StoreLogMsg(unsigned char *DataString)
{
	unsigned char Buf[256];
	time_t CurrentTime;
	struct tm *tm;
			
	memset(Buf,0,sizeof(Buf));
	CurrentTime = time(NULL);
	tm=localtime(&CurrentTime);
	sprintf(Buf,"echo \"%04d.%02d.%02d %02d:%02d:%02d - %s\" >> /Storage/SystemLog/[%04d.%02d]SystemLog",
			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
			DataString,
			tm->tm_year+1900,tm->tm_mon+1);
	system(Buf);
	#ifdef Debug
	printf("%s \n",DataString);
	#endif
}		
#endif

int StoreEventLogMsg(unsigned char *EventCodeString)
{
	unsigned char Buf[256];
	time_t CurrentTime;
	struct tm *tm;
			
	memset(Buf,0,sizeof(Buf));
	CurrentTime = time(NULL);
	tm=localtime(&CurrentTime);
	sprintf(Buf,"echo \"%04d.%02d.%02d %02d:%02d:%02d - %s\" >> /Storage/EventLog/[%04d.%02d]EventLog",
			tm->tm_year+1900,tm->tm_mon+1,tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec,
			EventCodeString,
			tm->tm_year+1900,tm->tm_mon+1);
	system(Buf);
	#ifdef Debug
	printf("%s \n",Buf);
	#endif
}		

int DiffTimeb(struct timeb ST, struct timeb ET)
{
	//return milli-second
	unsigned int StartTime,StopTime;
	
	StartTime=(unsigned int)ST.time;
	StopTime=(unsigned int)ET.time;
	return (StopTime-StartTime)*1000+ET.millitm-ST.millitm;
}	
	
/**************************************************************************************/
/**************************Init all share memory *********************************/
/**************************************************************************************/
int InitShareMemory()
{
	int MeterSMId;
	
	//creat ShmSysConfigAndInfo
	if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo),  0777)) < 0) 
    	{
		#ifdef SystemLogMessage	
		StoreLogMsg("[EventLogging]InitShareMemory:shmget ShmSysConfigAndInfo NG");
		#endif			
		return 0;
	}
    	else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) 
    	{
    		#ifdef SystemLogMessage	
		StoreLogMsg("[EventLogging]InitShareMemory:shmat ShmSysConfigAndInfo NG");
		#endif		
		return 0;
   	 }
   	 //creat ShmStatusCodeData
   	 if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData),  0777)) < 0) 
    	{
		#ifdef SystemLogMessage	
		StoreLogMsg("[EventLogging]InitShareMemory:shmget ShmStatusCodeData NG");
		#endif		
		return 0;	
	}
    	else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) 
    	{
    		#ifdef SystemLogMessage	
		StoreLogMsg("[EventLogging]InitShareMemory:shmat ShmStatusCodeData NG");
		#endif		
		return 0;
   	 }

    	return 1;
}

int main(int argc,char *argv[])
{
	int ByteCount,BitCount;
	unsigned char tmp, EventCodeTmp[7];
	
	//Initialization
	if(InitShareMemory()==0)
	{
		#ifdef SystemLogMessage	
		StoreLogMsg("[EventLogging]main:InitShareMemory NG");
		#endif		
		if(ShmStatusCodeData!=NULL)
		{
			ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FailToCreateShareMemory=1;
		}	
		sleep(5);
		return 0;
	}	
	
	while(1)
	{
		//check Fault Status
		for(ByteCount=0;ByteCount<4;ByteCount++)
		{
			if(ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[ByteCount] != ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount])
			{
				tmp=ShmStatusCodeData->FaultCode.FaultEvents.FaultVal[ByteCount]; //prevent be modified during following process
				for(BitCount=0;BitCount<8;BitCount++)
				{
					if(((tmp>>BitCount)&0x01) != ((ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount]>>BitCount)&0x01))
					{
						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
						memcpy(EventCodeTmp,FaultStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
						if(((tmp>>BitCount)&0x01)==0)//Recovered
						{	
							EventCodeTmp[0]=1;
							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount]&=(0<<BitCount);
						}
						else
							ShmStatusCodeData->FaultCode.PreviousFaultVal[ByteCount]|=(1<<BitCount);
						StoreEventLogMsg(EventCodeTmp);
					}
				}
			}
		}
		
		//check Alarm Status
		for(ByteCount=0;ByteCount<8;ByteCount++)
		{
			if(ShmStatusCodeData->AlarmCode.AlarmEvents.AlarmVal[ByteCount] != ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount])
			{
				tmp=ShmStatusCodeData->AlarmCode.AlarmEvents.AlarmVal[ByteCount]; //prevent be modified during following process
				for(BitCount=0;BitCount<8;BitCount++)
				{
					if(((tmp>>BitCount)&0x01) != ((ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount]>>BitCount)&0x01))
					{
						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
						memcpy(EventCodeTmp,AlarmStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
						if(((tmp>>BitCount)&0x01)==0)//Recovered
						{	
							EventCodeTmp[0]=1;
							ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount]&=(0<<BitCount);
						}
						else
							ShmStatusCodeData->AlarmCode.PreviousAlarmVal[ByteCount]|=(1<<BitCount);
						StoreEventLogMsg(EventCodeTmp);
					}
				}
			}
		}
		
		//check Info Status
		for(ByteCount=0;ByteCount<8;ByteCount++)
		{
			if(ShmStatusCodeData->InfoCode.InfoEvents.InfoVal[ByteCount] != ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount])
			{
				tmp=ShmStatusCodeData->InfoCode.InfoEvents.InfoVal[ByteCount]; //prevent be modified during following process
				for(BitCount=0;BitCount<8;BitCount++)
				{
					if(((tmp>>BitCount)&0x01) != ((ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount]>>BitCount)&0x01))
					{
						memset(EventCodeTmp,0,sizeof(EventCodeTmp));
						memcpy(EventCodeTmp,InfoStatusCode[ByteCount*8+BitCount],sizeof(EventCodeTmp)-1);
						if(((tmp>>BitCount)&0x01)==0)//Recovered
						{	
							EventCodeTmp[0]=1;
							ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount]&=(0<<BitCount);
						}
						else
							ShmStatusCodeData->InfoCode.PreviousInfoVal[ByteCount]|=(1<<BitCount);
						StoreEventLogMsg(EventCodeTmp);
					}
				}
			}
		}
		
	}//main while loop 
}