/* Title:       bss_hb.cpp
 * Description: init and refresh BSS(BSC+BTS) status. 
 * Author:      Steven Wong
 * Date:        2001/09/24
 * Modified by: CTC
 */

#include "bss_hb.h"

/*
 *  UDP socket variable
 */
#define HEARTBEAT_PORT	4957  //snmp
//#define BROADCAST_IP	"155.226.202.63"
char OMC_0_IP[16];
char OMC_1_IP[16];

MYSQL omcDbConn,*omcDb_sock;
MYSQL_RES *result;
MYSQL_ROW row;
char sqlstring[128];

static int udp_sockfd;
static struct sockaddr_in udp_cli_addr;
static struct sockaddr_in udp_serv_addr;

static BYTE sendbuf[SNMP_MSG_LEN];

static tHeartbeat bsc_heartbeat[NO_OF_BSS];
static tHeartbeat bts_heartbeat[NO_OF_BSS*NO_OF_BTSMgr];

struct tBssLed bts_led[NO_OF_BSS*NO_OF_BTSMgr];
struct tBssLed bsc_led[NO_OF_BSS];

static char snmphead[SNMP_HEADER_LEN] = {
	0x30, VAR,				/* length 1 (1)		*/
	0x02, 0x01, 0x01, 0x04, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,0xa7,
	VAR,					/* length 2 (14)		*/
	0x02, 0x01, 0x8e, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x30,
	VAR,					/* length 3 (25)		*/
	0x30, VAR,				/* length 4 (27)		*/
	0x06, OBJID_LEN,		/* OBJID_LEN:(29)			*/
	0x2b, 0x06, 0x01, 0x04, 0x01,
	0x8a, 0x5d, 0x01, 0x05, VAR, 0x01,0x00,		/* oid offset (39)*/
	0x04, VAR					/* value length(43)		*/
};

/*
 * Return the index for LED display.
 * signal_element is defined according to OMCR_BSSTREE MySQL table
 * return -1 if error
 *
 * LED assignment:
 *          ________________________________________________________________________________________
 *     LED:[0  |1   |2   |3   |4   |5   |6   |7   |8   |9     |10    |11   |12   |13   |14   |15   ]
 * BTS --> [IWP|S1E1|TRX2|TRX3|TRX4|TRX5|TRX6|TRX7|TRX8|TRX9  |TRX10 |TRX11|TRX12|TRX13|ABIS |     ]
 * BSC --> [IWP|S1E1|S2E1|S3E1|S4E1|S5E1|S6E1|S7E1|S8E1|S9E1  |S10E1 |S11E1|S12E1|S13E1|S14E1|S15E1]
 */
int object2LedId(int btsid,int signal_element)
{
    int led_index;
    
    if (btsid!=99)//BTS
    {
        switch (signal_element)
        {
            case 0:        // IWP
                led_index = 0;break;
            case 10:    // Slot1 E1
                led_index = 1;break;
            case 20:    // TRX 2
                led_index = 2;break;
            case 30:    // TRX 3
                led_index = 3;break;
            case 40:    // TRX 4
                led_index = 4;break;
            case 50:    // TRX 5
                led_index = 5;break;
            case 60:    // TRX 6
                led_index = 6;break;
            case 70:    // TRX 7
                led_index = 7;break;
            case 80:    // TRX 8
                led_index = 8;break;
            case 90:    // TRX 9
                led_index = 9;break;
            case 100:    // TRX 10
                led_index = 10;break; 
            case 110:    // TRX 11
                led_index = 11;break;
            case 120:    // TRX 12
                led_index = 12;break;
            case 130:    // TRX 13
                led_index = 13;break;
            case 11:    // AbisMgr
                led_index = 14;break;
            default:
                led_index = -1;break;
        }
    }
    else
    {
        switch (signal_element)
        {
            case 0:        // IWP
                led_index = 0;break;
            case 10:    // Slot1 E1
                led_index = 1;break;
            case 20:    // Slot2 E1
                led_index = 2;break;
            case 30:    // Slot3 E1
                led_index = 3;break;
            case 40:    // Slot4 E1
                led_index = 4;break;
            case 50:    // Slot5 E1
                led_index = 5;break;
            case 60:    // Slot6 E1
                led_index = 6;break;
            case 70:    // Slot7 E1
                led_index = 7;break;
            case 80:    // Slot8 E1
                led_index = 8;break;
            case 90:    // Slot9 E1
                led_index = 9;break;
            case 100:    // Slot10 E1
                led_index = 10;break;
            case 110:    // Slot11 E1
                led_index = 11;break;
            case 120:    // Slot12 E1
                led_index = 12;break;
            case 130:    // Slot13 E1
                led_index = 13;break;
            case 140:    // Slot14 E1
                led_index = 14;break;
            case 150:    // Slot15 E1
                led_index = 15;break;
            default:
                led_index = -1;break;
        }
    }
    return led_index;
}
void initOmcDbConn()
{ 
	mysql_init(&omcDbConn);
    omcDb_sock=mysql_real_connect(&omcDbConn,NULL,"application","noitacilpPA#68*","OMC_PUB",0,NULL,0);
    if (omcDb_sock == 0)
        exit(6);
}

void initHeartbeatStruct(tHeartbeat *heartbeat)
{
	int i;
	    
	heartbeat->system_id=0;
	heartbeat->timestamp=0;
	for (i=0; i<HB_LED_CONTROL_LEN; i++)
	{
		heartbeat->led_control[i]=0;
	}
	heartbeat->component_id=0;
	heartbeat->alarmlevel=0;
	heartbeat->alarmcode=0;
	heartbeat->reserved=0;
	for (i=0; i<HB_EXTENDED_LEN; i++)
	{
		heartbeat->extended[i]=0;
	}
}


//set which was is install and set all is ok
void initBssStatusTransmitter(void)
{
	int i,j;
	int on;
	bzero((char *) &udp_serv_addr, sizeof(udp_serv_addr));
	udp_serv_addr.sin_family = AF_INET;
	//udp_serv_addr.sin_addr.s_addr = inet_addr(BROADCAST_IP);
	udp_serv_addr.sin_port = htons(HEARTBEAT_PORT);

	
	if ((udp_sockfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0 )
	{
		exit (errno);
	}

	bzero((char *) &udp_cli_addr, sizeof(udp_cli_addr));
	udp_cli_addr.sin_family = AF_INET;
	udp_cli_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	udp_cli_addr.sin_port = htons(0);

    	if (setsockopt(udp_sockfd, SOL_SOCKET, SO_RCVBUF, sendbuf, SNMP_MSG_LEN) < 0)
    	{
			perror("setsockopt\n");      
	    }
	on=1;
    
	if (setsockopt(udp_sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
    	{
		perror("setsockopt\n");
	}
	if (fcntl(udp_sockfd, F_SETFL,O_NONBLOCK)<0)
	{
        perror("fcntl()\n");
	}
	if (setsockopt(udp_sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
    	{
        perror("setsockopt\n");
	}
	
	
	if (bind(udp_sockfd, (struct sockaddr *) &udp_cli_addr, sizeof(udp_cli_addr)) < 0)
	{
	
		exit (errno);
	}

	for (i=0; i<NO_OF_BSS; i++)
	{
		initHeartbeatStruct(&(bsc_heartbeat[i]));
		for (j=0; j<NO_OF_BTSMgr; j++)
		{
			initHeartbeatStruct(&(bts_heartbeat[NO_OF_BTSMgr*i+j]));
		}
	}
	initOmcDbConn();
} //end of function initBscStatus()


/*
 * 0xFF is group alarm clear (refer to Meng XZ's heartbeat format document
 */
void format_alarmcode(int *alarmcode)
{

	*alarmcode=0;   // set it to zero anyway as it is not processed by TS_OMC
	return;
}

/*
 * alarm level = component type + ID
 * For example: E1port.0.1.1, 
 *
 * 0x4 -> E1
 * 0x5 -> TRX
 * 0x6 -> Clock
 * 0x7 -> Shelf
 * 0x8 -> Software
 * 0x9 -> Environment
 * 0xa -> Lapd
 * 0xb -> Bts
 * 0xc -> Bsc
 * 0xd -> Aif
 * 0xe -> Bbu
 * 0xf -> Rfd
 *
 */
void format_alarmlevel(int *alarmlevel)
{
	*alarmlevel=0;   // set it to zero anyway as it is not processed by TS_OMC
	return;
}


void send_heartbeat(int index, struct tBssLed *pbsc_led,struct tBssLed *pbts_led, int component_id, int alarmcode, int alarmlevel,int bsType)
{
	int retval,i,offset;
	tHeartbeat *pHeartbeat;
	BYTE *psendbuf;
	int bts_code;
	int bsc_code;
	char tmpHb[256];
	
	int bssid = index / NO_OF_BTSMgr;
	int btsid = index % NO_OF_BTSMgr;

	time_t unix_time;

	format_alarmcode(&alarmcode);
	format_alarmlevel(&alarmlevel);
	
	sprintf(OMC_0_IP,"");
	sprintf(OMC_1_IP,"");
	sprintf(sqlstring, "select sysNo,ip FROM OMC_PUB.sysInfo WHERE sysTypeNo='0'");
    mysql_query(omcDb_sock, sqlstring);
	if(mysql_errno(omcDb_sock) > 0) 
	{
		printf("\n Error number:%d", mysql_errno(omcDb_sock));
		printf("\n Description: %s", mysql_error(omcDb_sock));
		exit(16);
	}

	result = mysql_use_result(omcDb_sock);
	while((row = mysql_fetch_row(result))){
		if(atoi(row[0])==0){
			sprintf(OMC_0_IP,row[1]);
		}else if(atoi(row[0])==1){
			sprintf(OMC_1_IP,row[1]);
		}
	}
	mysql_free_result(result);

	/*
	 * Insert the length field in SNMP header
	 */
	snmphead[LENGTH1] = SNMP_MSG_LEN - LENGTH1 - 1;
	snmphead[LENGTH2] = SNMP_MSG_LEN - LENGTH2 - 1;
	snmphead[LENGTH3] = SNMP_MSG_LEN - LENGTH3 - 1;
	snmphead[LENGTH4] = SNMP_MSG_LEN - LENGTH4 - 1;
	snmphead[VALUE_LEN] = SNMP_MSG_LEN - VALUE_LEN - 1;
	
	
	// BSC
	psendbuf = &sendbuf[0];
	snmphead[SNMP_OBJID] = BSC_OBJID;
	pHeartbeat = &(bsc_heartbeat[bssid]);

	unix_time = time((time_t *)0);
	pHeartbeat->timestamp = ((unix_time & 0xff000000) >> 24)
					| ((unix_time & 0xff0000) >> 8)
					| ((unix_time & 0xff00) << 8)
					| ((unix_time & 0xff) << 24);

	if(pbsc_led->led[0] !=  0xf){ //installed
		
		bsc_code = bssid*256;
		pHeartbeat->system_id = ((bsc_code & 0xff00) >> 8) | ((bsc_code & 0xff) << 8);
		
		for(i=0;i<8;i++){
			pHeartbeat->led_control[i]=((pbsc_led->led[2*i] & 0x0f)<<4) | (pbsc_led->led[2*i+1] & 0x0f);
		}
	    
	    /*
	    pHeartbeat->component_id = component_id;
		pHeartbeat->alarmlevel = alarmlevel;
		pHeartbeat->alarmcode = alarmcode;
		*/
		
		pHeartbeat->component_id = 0;
		pHeartbeat->alarmlevel = 0;
		pHeartbeat->alarmcode = 0;

		/*
		 * Copy message to message buffer
		 */
		offset = 0;
		//memcpy(psendbuf, snmphead, SNMP_HEADER_LEN);//snmp head
		//offset += SNMP_HEADER_LEN;
		memcpy(psendbuf+offset, &pHeartbeat->system_id,HB_SYSTEM_ID_LEN);//system id
		offset += HB_SYSTEM_ID_LEN;
		memcpy(psendbuf+offset, &pHeartbeat->timestamp,HB_TIMESTAMP_LEN);//time
		offset += HB_TIMESTAMP_LEN;
		memcpy(psendbuf+offset, pHeartbeat->led_control,HB_LED_CONTROL_LEN);//len control
		offset += HB_LED_CONTROL_LEN;
		memcpy(psendbuf+offset, &pHeartbeat->component_id,HB_COMPONENT_ID_LEN);//component id
		offset += HB_COMPONENT_ID_LEN;
		memcpy(psendbuf+offset, &pHeartbeat->alarmlevel,HB_ALARMLEVEL_LEN);//alarmlevel
		offset += HB_ALARMLEVEL_LEN;
		memcpy(psendbuf+offset, &pHeartbeat->alarmcode,HB_ALARMCODE_LEN);//alarmcode
		offset += HB_ALARMCODE_LEN;
		memcpy(psendbuf+offset, &pHeartbeat->reserved,HB_RESERVED_LEN);
		offset += HB_RESERVED_LEN;
		memcpy(psendbuf+offset, pHeartbeat->extended,HB_EXTENDED_LEN);
		
		omc_RbcdToAscii(tmpHb, sendbuf, (offset + HB_EXTENDED_LEN)*2);
		sprintf(sqlstring, "REPLACE INTO sysStat SET sysTypeNo='510',sysNo=%d,subSysNo='0',detailStat='%s',updateTime=CURRENT_TIMESTAMP",
							bssid,tmpHb);
		mysql_query(omcDb_sock, sqlstring);
		/*if(strlen(OMC_0_IP)>0){		
			udp_serv_addr.sin_addr.s_addr = inet_addr(OMC_0_IP);
			retval = sendto(udp_sockfd, sendbuf, SNMP_MSG_LEN, 0,
						(const struct sockaddr *)&udp_serv_addr,  sizeof(udp_serv_addr));
			//printf("Bsc heartbeat is sent~~~~~~~~~~~~~~~~\n\n");
		}
		
		if(strlen(OMC_1_IP)>0){	
			udp_serv_addr.sin_addr.s_addr = inet_addr(OMC_1_IP);
			retval = sendto(udp_sockfd, sendbuf, SNMP_MSG_LEN, 0,
				(const struct sockaddr *)&udp_serv_addr,  sizeof(udp_serv_addr));
			//printf("Bsc_hb LEN=%d:",retval);
		
		}*/		
		//for ( n=0;n<SNMP_MSG_LEN;n++)
		//	printf("%x ",(int) sendbuf[n]);
		//printf("\n");

		if (retval < 0)
		{
			perror("BSS <Bsc> heartbeat send fail!\n");
		}
		
	}//end of if(installed)
	
	
	//check the device is BSC+BTS or BS+
	if(btsid==0&&bsType==0){
		return;	
	}

	psendbuf = &sendbuf[0];
	snmphead[SNMP_OBJID] = BTS_OBJID;
	
	pHeartbeat = &(bts_heartbeat[btsid]);
		
	//bts_code=bssid*256 + btsid - 1;
	bts_code=bssid*256 + btsid;
	pHeartbeat->system_id = ((bts_code & 0xff00) >> 8) | ((bts_code & 0xff) << 8);
		
	unix_time = time((time_t *)0);
	pHeartbeat->timestamp = ((unix_time & 0xff000000) >> 24)
					| ((unix_time & 0xff0000) >> 8)
					| ((unix_time & 0xff00) << 8)
					| ((unix_time & 0xff) << 24);
	for(i=0;i<8;i++){
		pHeartbeat->led_control[i]=((pbts_led->led[2*i] & 0x0f)<<4) | (pbts_led->led[2*i+1] & 0x0f);
	}

	/*
	pHeartbeat->component_id = component_id;
	pHeartbeat->alarmlevel = alarmlevel;
	pHeartbeat->alarmcode = alarmcode;
	*/
	pHeartbeat->component_id = 0;
	pHeartbeat->alarmlevel = 0;
	pHeartbeat->alarmcode = 0;
	
	/*
	 * Copy message to message buffer
	 */
	//memcpy(psendbuf, snmphead, SNMP_HEADER_LEN);
	//psendbuf += SNMP_HEADER_LEN;
	memcpy(psendbuf, &pHeartbeat->system_id,HB_SYSTEM_ID_LEN);
	psendbuf += HB_SYSTEM_ID_LEN;
	memcpy(psendbuf, &pHeartbeat->timestamp,HB_TIMESTAMP_LEN);
	psendbuf += HB_TIMESTAMP_LEN;
	memcpy(psendbuf, pHeartbeat->led_control,HB_LED_CONTROL_LEN);
	psendbuf += HB_LED_CONTROL_LEN;
	memcpy(psendbuf, &pHeartbeat->component_id,HB_COMPONENT_ID_LEN);
	psendbuf += HB_COMPONENT_ID_LEN;
	memcpy(psendbuf, &pHeartbeat->alarmlevel,HB_ALARMLEVEL_LEN);
	psendbuf += HB_ALARMLEVEL_LEN;
	memcpy(psendbuf, &pHeartbeat->alarmcode,HB_ALARMCODE_LEN);
	psendbuf += HB_ALARMCODE_LEN;
	memcpy(psendbuf, &pHeartbeat->reserved,HB_RESERVED_LEN);
	psendbuf += HB_RESERVED_LEN;
	memcpy(psendbuf, pHeartbeat->extended,HB_EXTENDED_LEN);
	
	omc_RbcdToAscii(tmpHb, sendbuf, (psendbuf - sendbuf+ HB_EXTENDED_LEN)*2);
	sprintf(sqlstring, "REPLACE INTO sysStat SET sysTypeNo='520',sysNo=%d,subSysNo='%d',detailStat='%s',updateTime=CURRENT_TIMESTAMP",
						bssid,btsid,tmpHb);
	//printf("sqlstring=%s\n",sqlstring);
	mysql_query(omcDb_sock, sqlstring);

/*	if(strlen(OMC_0_IP)>0){		
		udp_serv_addr.sin_addr.s_addr = inet_addr(OMC_0_IP);
		retval = sendto(udp_sockfd, sendbuf, SNMP_MSG_LEN, 0,
			(const struct sockaddr *)&udp_serv_addr,  sizeof(udp_serv_addr));
	}
	if(strlen(OMC_1_IP)>0){			
		udp_serv_addr.sin_addr.s_addr = inet_addr(OMC_1_IP);
		retval = sendto(udp_sockfd, sendbuf, SNMP_MSG_LEN, 0,
			(const struct sockaddr *)&udp_serv_addr,  sizeof(udp_serv_addr));
		//printf("\33[36m\nBts heartbeat is sent!!!!!!!!!!!!!!!!!!!\n\n");
    	//printf("Bts_hb LEN=%d:",retval);
	}*/
	//		for (n=0;n<SNMP_MSG_LEN;n++)
	//			printf("%x ",(int) sendbuf[n]);
	//		printf("\n\n");
	if (retval < 0)
	{
		perror("BSS <Bts> heartbeat send fail!\n");
	}
	
}//end of function

void clearBssStatus(void)
{
	close(udp_sockfd);
}

void omc_RbcdToAscii(char *ascii_buf, const unsigned char *bcd_buf,
                                         int len)
{
        int i;
        char ch;
        //if(sizeof(*ascii_buf) < len*2){
        //  len = sizeof(*ascii_buf)/2;
        //}
        for (i = 0; i < len; i++) {
                if ((len - i) & 1) {
                        ch = *(bcd_buf++) & 0x0f;
                } else {
                        //ch = (*bcd_buf & 0xf0) >> 4;
                        ch = *bcd_buf >> 4;
                }
                ascii_buf[i] = ch + ((ch > 9) ? 'A' - 10 : '0');
        }
        ascii_buf[i] = '\0';
}
