/*****************************************************/
/*Title:    heartbeat.c	                             */
/*Descr:    Generate flatform's heartbeart           */
/*Author:   Liang Hanxi                              */
/*Create:   2002-06-24                               */
/*Modify:                                            */
/*****************************************************/
#include "./include/heartbeat.h"

// by simon at 23/9/25
DWORD		ExistIP[64];
DWORD		ExistIPNum;

heartbeat_shm			*HbShm=NULL;
static DWORD			ObjID[20]=FLATFORM_HB_OID;
static snmp_addr		HBAddr;
static BYTE				InitOnce=0;
static DWORD			latestAlmCmp=0;
static BYTE				latestAlmCod=0;


static void send_alarm();
static void send_heartbeat();

void heartbeat_init(u_short sys_id)
{
	int 				shmid;
	struct shmid_ds		shm_info;
	memset(&shm_info, 0, sizeof(struct shmid_ds));
	if(InitOnce == 0)
	{
		ExistIPNum = 0;
		HBAddr.local_port = HBAddr.remote_port = HB_PORT;
		HBAddr.remote_ip = inet_addr(HB_IP);
		HBAddr.broadcast = 1;
		sysctrl_init();
	}

	if(HbShm==NULL)
	{
		/*open share memory*/
		if((shmid=shmget(HEARTBEAT_SHM_KEY,sizeof(heartbeat_shm),HEARTBEAT_SHM_PERM))==-1)
		{
			if((shmid=shmget(HEARTBEAT_SHM_KEY,sizeof(heartbeat_shm),HEARTBEAT_SHM_PERM|IPC_CREAT))==-1)
			{
				printf("fail to open share memory");
				exit(1);
			}
		}
		if((HbShm=(heartbeat_shm *)shmat(shmid,0,0))==(heartbeat_shm *)-1)
		{
			printf("fail to attach share memory");
			exit(1);
		}

		shmctl(shmid,IPC_STAT,&shm_info);
		if(shm_info.shm_nattch==1)
		{
			memset(HbShm,0,sizeof(heartbeat_shm));
			HbShm->msg.sys_id=0xFF;
			HbShm->msg.subsys_id=0xFF;
		}
	}
	
	if((sys_id & 0xFF)!=0xFF)
	{
		HbShm->msg.sys_id =HbShm->sys_id=sys_id>>8;
		HbShm->msg.subsys_id =HbShm->subsys_id=sys_id & 0xFF;
		snmp_debug_hb(2);
	}

	InitOnce=1;
}

void heartbeat_timer() //called per 20ms
{
	static time_t	l_oldtime = 0,l_time;
	static int counter=0;

	l_time = time(NULL);

	if(l_time - l_oldtime >= 10)
		counter = 500;

	system_report();
	switch(counter)
	{
	case 500:
		
		send_heartbeat();
		counter=0;
		l_oldtime = l_time;
		break;
	default:
		
		if(HbShm->alarm_num >0)
		{
			//system_report();
			send_alarm();
			counter=0;
		}
		else
			counter++;
		break;
	}
}


void send_heartbeat()
{
	int			i;
	short		len,msglen=0;
	snmp_pdu	pdu;
	DWORD		curtime;
	curtime=htonl(time(NULL));
	memcpy(HbShm->msg.timestamp,(BYTE *)&curtime,4);
	for(i=0;i<8;i++)
		HbShm->msg.led_color[i]=(HbShm->led[2*i]<<4) | HbShm->led[2*i+1];
	
	for(i=0;i<COMPONENT_NUM;i++)
	{
#if _CDMA_SNMP
		HbShm->msg.info[msglen++]=0;
#endif
		HbShm->msg.info[msglen++]=i;
		len=HbShm->component[i].status_len;
#if _CDMA_SNMP
		HbShm->msg.info[msglen++]=len >> 8;
#endif
		HbShm->msg.info[msglen++]=len & 255; 
		memcpy(HbShm->msg.info+msglen,HbShm->component[i].status,len);
		msglen+=len;
	}
#if _CDMA_SNMP
	HbShm->msg.length[0] = msglen >> 8;
	HbShm->msg.length[1] = msglen & 255;
	msglen++;
	msglen+=19;
#else
	HbShm->msg.length =msglen;
	msglen+=18;
#endif

#if _CDMA_SNMP
/* daniel modify on 2005-7-24 */	
	HbShm->msg.component_id[0]=latestAlmCmp >> 8;
	HbShm->msg.component_id[1]=latestAlmCmp & 255;
/* daniel modify on 2005-7-24 */
#else
	HbShm->msg.component_id=latestAlmCmp;
#endif
	HbShm->msg.alarm_code =latestAlmCod;
	/*send out---->*/
	pdu.error_index =pdu.error_status =0;
	pdu.pdu_type =PDU_TRAP;
	pdu.request_id =0;
	memcpy(pdu.var[0].msg,(BYTE *)&HbShm->msg,msglen);
	pdu.var_num=1;
	pdu.var[0].msglen =msglen;
	pdu.var[0].vartype =4;
	memcpy(pdu.var[0].oid,ObjID,14*sizeof(DWORD));
	pdu.var[0].oidlen =14;

	HBAddr.local_port =HBAddr.remote_port =HB_PORT;
	HBAddr.remote_ip =inet_addr(HB_IP);

	for(i = 0; i < ExistIPNum; i++)
	{
		HBAddr.remote_ip = ExistIP[i];
		HBAddr.broadcast = 0;
		snmp_plat_send(&pdu, &HBAddr);
	}
}

void send_alarm()
{
	int			i;
	short		len,msglen=0;
	snmp_pdu	pdu;
	DWORD	curtime;
	curtime=htonl(time(NULL));
	memcpy(HbShm->msg.timestamp,(BYTE *)&curtime,4);
	for(i=0;i<8;i++)
		HbShm->msg.led_color[i]=(HbShm->led[2*i]<<4) | HbShm->led[2*i+1];
	
	if(HbShm->alarm_num<=0)
		return;

	for(i=0;i<ALARM_COMPONENT_NUM;i++)
	{
		if(HbShm->alarm[i].flag)
		{
#if _CDMA_SNMP
			HbShm->msg.component_id[0] = i >> 8;
			HbShm->msg.component_id[1] = i & 255;
#else
			HbShm->msg.component_id= i;
#endif
			HbShm->msg.alarm_code =HbShm->alarm[i].alarm_code;
			
			HbShm->alarm[i].flag =0;
			
/* daniel add on 2005-7-24 */			
			latestAlmCmp = i;
			latestAlmCod = HbShm->msg.alarm_code;
/* daniel add on 2005-7-24 */
			break;
		}
	}

	for(i=0;i<COMPONENT_NUM;i++)
	{
#if _CDMA_SNMP
		HbShm->msg.info[msglen++]=0;
#endif
		HbShm->msg.info[msglen++]=i;
		len=HbShm->component[i].status_len;
#if _CDMA_SNMP
		HbShm->msg.info[msglen++]=len >> 8;
#endif
		HbShm->msg.info[msglen++]=len&255;
		memcpy(HbShm->msg.info+msglen,HbShm->component[i].status,len);
		msglen+=len;
	}
	
#if _CDMA_SNMP
	HbShm->msg.length[0] = msglen >> 8;
	HbShm->msg.length[1] = msglen & 255;
	msglen++;
	msglen+=19;
#else
	HbShm->msg.length =msglen;
	msglen+=18;
#endif

	if(HbShm->alarm_num >=1)
		HbShm->alarm_num--;
	
	/*send out---->*/
	pdu.error_index =pdu.error_status =0;
	pdu.pdu_type =PDU_TRAP;
	pdu.request_id =0;
	memcpy(pdu.var[0].msg,(BYTE *)&HbShm->msg,msglen);
	pdu.var_num=1;
	pdu.var[0].msglen =msglen;
	pdu.var[0].vartype =4;
	memcpy(pdu.var[0].oid,ObjID,14*sizeof(DWORD));
	pdu.var[0].oidlen =14;

	HBAddr.local_port =HBAddr.remote_port =HB_PORT;
	HBAddr.remote_ip =inet_addr(HB_IP);

	for(i = 0; i < ExistIPNum; i++)
	{
		HBAddr.broadcast = 0;
		HBAddr.remote_ip = ExistIP[i];

		snmp_plat_send(&pdu, &HBAddr);
	}
}


void set_led(BYTE nled,BYTE ncolor)
{
	if(HbShm==NULL)
		heartbeat_init(0xFF);
	HbShm->led[nled]=ncolor;
}

void set_alarm(WORD component_id,BYTE alarm_code)
{
	if(HbShm==NULL)
		heartbeat_init(0xFF);
	if(component_id>ALARM_COMPONENT_NUM)
	{
		snmp_debug(SNMPDB_ALARM | SNMPDB_ERR, "Fail to send Alarm:No Such component id(%d)",component_id);
		return;
	}
	snmp_debug(SNMPDB_ALARM, "set alarm.component id=%d,alarm_code=%d",component_id,alarm_code);

	if(HbShm->alarm[component_id].alarm_code !=alarm_code)
	{
		HbShm->alarm[component_id].flag=1;
		HbShm->alarm_num ++;
	}
	HbShm->alarm[component_id].alarm_code =alarm_code;
}

void set_status(BYTE component_id,BYTE info_len,BYTE *info)
{
	if(HbShm == NULL)
		heartbeat_init(0xFF);

	if(component_id > COMPONENT_NUM)
	{
		snmp_debug(SNMPDB_ERR, "Fail to set status of component %d:No Such component id",component_id);
		return;
	}
	/*
	if(info_len>=256)
	{
		snmp_debug(SNMPDB_ERR, "Fail to set status of component %d:the length(%d) of status part exceed limit(256Byte)",component_id,info_len);
		return;
	}*/
	HbShm->component[component_id].status_len =info_len;
	memcpy(HbShm->component[component_id].status,info,info_len);
}


