/*******************************************************************
Copyright (C):    
File name    :    Iec104.c
DESCRIPTION  :
AUTHOR       :
Version      :    1.0
Date         :    2014/07/31
Others       :
History      :
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1) Date: 2014/07/31         Author: ChenDajie
   content:

*******************************************************************/
#include <sys/ioctl.h> 
#include <sys/socket.h> 
#include <netinet/in.h> 
#include <net/if.h> 
#include <string.h> 
#include "Iec104.h"
#include "sys.h"
#include "huayun_common.h"

 /*
 * GLOABLE VARIALBLE
 */

uint8_t             Iec104_Sendbuf[IEC104_MAX_BUF_LEN];
/*
 * STATE
 * */
uint8_t             IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED;
uint8_t             IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CLOSED;
uint8_t             IEC104_STATE_FLAG_GROUP = IEC104_FLAG_CLOSED;
uint8_t             IEC104_STATE_FLAG_CLOCK = IEC104_FLAG_CLOSED;
uint8_t             IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE;
uint8_t             IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_CLOSED;
/*
 * receive and send serial number
 * */
int32_t             Iec104_BuildSendSn = 0;
int32_t             Iec104_BuildRecvSn = 0;
int32_t             Iec104_DealSendSn = -1;
int32_t             Iec104_DealRecvSn = 0;

uint8_t             IEC104_Call_AllQoi = 0;
uint8_t             IEC104_Call_GroupQoi = 0;


#define IEC104_CYCLE_TIME_MS             100                   /*100ms*/
#define IEC104_RESEND_TIME_MS            (30*1000)             /*30s*/
#define IEC104_S_ACK_TIMEOUT             (5*1000)              /*5s*/
#define IEC104_TESTER_IDLE_TIMEOUT       (20*1000)           /*2min*/
uint32_t            Iec104_TimeCount = 0;
uint32_t            Iec104_TimeCycle = IEC104_RESEND_TIME_MS;
uint32_t            Iec104_TimeCycle_S = 0;
uint32_t            Iec104_TimeCycle_TesterIdle = 0;
uint8_t             Iec104_TesterCount = 0;

uint32_t            Iec10x_Update_SeekAddr = 0;
uint16_t            FirmFlagCount = 0;
uint8_t	mac_addr[6] = {0};

int get_mac(void) 
{
	struct ifreq ifreq; 
    int sock; 
	
    if((sock=socket(AF_INET,SOCK_STREAM,0)) <0) 
    { 
        dy_syslog(LOG_DEBUG,"error get_mac socket "); 
        return 2; 
    } 
    strcpy(ifreq.ifr_name,"eth0"); 
    if(ioctl(sock,SIOCGIFHWADDR,&ifreq) <0) 
    { 
        perror("error get_mac ioctl ");
        close(sock);
        return 3; 
    } 
    dy_syslog(LOG_DEBUG,"%02x:%02x:%02x:%02x:%02x:%02x ",
            (unsigned   char)ifreq.ifr_hwaddr.sa_data[0], 
            (unsigned   char)ifreq.ifr_hwaddr.sa_data[1], 
            (unsigned   char)ifreq.ifr_hwaddr.sa_data[2], 
            (unsigned   char)ifreq.ifr_hwaddr.sa_data[3], 
            (unsigned   char)ifreq.ifr_hwaddr.sa_data[4], 
            (unsigned   char)ifreq.ifr_hwaddr.sa_data[5]); 
	
	mac_addr[0] = (unsigned   char)ifreq.ifr_hwaddr.sa_data[0];
	mac_addr[1] = (unsigned   char)ifreq.ifr_hwaddr.sa_data[1];
	mac_addr[2] = (unsigned   char)ifreq.ifr_hwaddr.sa_data[2];
	mac_addr[3] = (unsigned   char)ifreq.ifr_hwaddr.sa_data[3];
	mac_addr[4] = (unsigned   char)ifreq.ifr_hwaddr.sa_data[4];
	mac_addr[5] = (unsigned   char)ifreq.ifr_hwaddr.sa_data[5];
	
    close(sock);
    return   0; 
}


uint8_t IEC104_UploadAddr(void){

    uint8_t len = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = IEC104_ASDU_TYPE_M_DTU_INF_1;
    asdu->_num._sq = 0;
    asdu->_num._num = 1;
    asdu->_reason._reason = IEC10X_ASDU_COT_UNKNOW;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info*/
    ptr = info->_addr;
    Temp32 = 0;
    memcpy(ptr, &Temp32, 3);

    ptr = info->_element;
    Temp32 = IEC104_INFO_SIGNATURE;
    memcpy(ptr, &Temp32, 4);

    ptr+=4;
    Temp32 = Iec10x_Sta_Addr;
    memcpy(ptr, &Temp32, 2);

    ptr+=2;

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_INITLINK, NULL,NULL);

    return RET_SUCESS;
}
#if 1
uint8_t IEC104_Build_InitFin(void){

    uint8_t len = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = Iec10x_M_EI_NA_1;
    asdu->_num._sq = 0;
    asdu->_num._num = 1;
    asdu->_reason._reason = IEC10X_ASDU_REASON_INIT;
    asdu->_addr = Iec10x_Sta_Addr;//0x0A5C

    /*build info*/
    ptr = info->_addr;
    Temp32 = 0;
    memcpy(ptr, &Temp32, 3);

    ptr = info->_element;
    //Temp32 = 0;
    //memcpy(ptr, &Temp32, 4);
    info->_element[0] = 0x08;

    ptr++;

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_INITLINK, NULL,NULL);

    return RET_SUCESS;
}
uint8_t IEC104_BuildCallACK(uint8_t qoi,uint8_t Prio){

    uint8_t len = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = IEC10X_C_IC_NA_1;
    asdu->_num._sq = 0;
    asdu->_num._num = 1;
    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTCON;
    asdu->_addr = Iec10x_Sta_Addr;//Iec10x_Sta_Addr;//0x0A5C

    /*build info*/
    ptr = info->_addr;
    Temp32 = 0;
    memcpy(ptr, &Temp32, 3);

    ptr = info->_element;
    ptr[0] = 0x08;//qoi;

    ptr+=1;
    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;
    
    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}

#else
uint8_t IEC104_Build_InitFin(void){

    uint8_t len = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = Iec10x_M_EI_NA_1;
    asdu->_num._sq = 0;
    asdu->_num._num = 1;
    asdu->_reason._reason = IEC10X_ASDU_REASON_INIT;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info*/
    ptr = info->_addr;
    Temp32 = 0;
    memcpy(ptr, &Temp32, 3);

    ptr = info->_element;
    //Temp32 = 0;
    //memcpy(ptr, &Temp32, 4);
    info->_element[0] = 0;

    ptr++;

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_INITLINK, NULL,NULL);

    return RET_SUCESS;
}

uint8_t IEC104_BuildCallACK(uint8_t qoi,uint8_t Prio){

    uint8_t len = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = IEC10X_C_IC_NA_1;
    asdu->_num._sq = 0;
    asdu->_num._num = 1;
    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTCON;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info*/
    ptr = info->_addr;
    Temp32 = 0;
    memcpy(ptr, &Temp32, 3);

    ptr = info->_element;
    ptr[0] = qoi;

    ptr+=1;
    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;
    
    DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}
#endif
uint8_t IEC104_BuildSignal_Spon(uint8_t TimeFlag, uint8_t signalV, uint16_t addrV, uint16_t signalAddr){

    uint8_t len = 0, asdu_num = 0, i;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PCP56Time2a_T time = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /* check Time flag */
    if(TimeFlag != 1 && TimeFlag != 0){
        dy_syslog(LOG_ERR,"-%s-, error time flag(%d) ",__FUNCTION__,TimeFlag);
        return RET_ERROR;
    }
    dy_syslog(LOG_DEBUG,"-%s-, time flag(%d) signalV(%d) ",__FUNCTION__,TimeFlag,signalV);
    /*get value*/
    asdu_num = 1;

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    if(TimeFlag == 0)
        asdu->_type = IEC10X_M_SP_NA_1;
    else
        asdu->_type = IEC10X_M_SP_TB_1;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = IEC10X_COT_SPONT;
    asdu->_addr = addrV;

    /*build info addr*/
    ptr = info->_addr;
    Temp32 = signalAddr;
    memcpy(ptr, &Temp32, 3);

    /*build info value*/
    ptr = info->_element;
    for(i=0; i<asdu_num; i++){
        *ptr = signalV;
        ptr++;
    }
    if(TimeFlag == 1){
        time = (PCP56Time2a_T)ptr;
        IEC10X->GetTime(time, 0);
        ptr += sizeof(CP56Time2a_T);
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_SPON, NULL,NULL);

    return RET_SUCESS;
}
uint8_t IEC104_BuildDetect_Spont(uint8_t TimeFlag, PIEC10X_DETECT_T detectV, uint16_t addrV){

    uint8_t len = 0, asdu_num = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PIEC10X_DETECT_T detect = NULL;
    PCP56Time2a_T time = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);
	
    /* check Time flag */
    if(TimeFlag != 1 && TimeFlag != 0){
        dy_syslog(LOG_ERR,"-%s-, error time flag(%d) ",__FUNCTION__,TimeFlag);
        return RET_ERROR;
    }
    /*get value*/
    asdu_num = 1;

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    if(TimeFlag == 0)
        asdu->_type = IEC10X_M_ME_NA_1;
    else
        asdu->_type = IEC10X_M_ME_TD_1;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = IEC10X_COT_SPONT;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info addr*/
    ptr = info->_addr;
    Temp32 = addrV;
    memcpy(ptr, &Temp32, 3);

    /*build info value*/
    ptr = info->_element;
    detect = (PIEC10X_DETECT_T)ptr;
    detect->_detect = detectV->_detect;
    detect->_qds = detectV->_qds;
    ptr += sizeof(IEC10X_DETECT_T);
    if(TimeFlag == 1){
        time = (PCP56Time2a_T)ptr;
        IEC10X->GetTime(time, 0);
        ptr += sizeof(CP56Time2a_T);
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_SPON, NULL,NULL);

    return RET_SUCESS;
}
#if 1
uint8_t IEC104_BuildDetectF_Spont(uint8_t TimeFlag, uint16_t infoAddr, uint16_t addrV, int start, int end, IEC104_PACK_T* pack){

    uint8_t len = 0, i;//asdu_num = 0,
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PIEC10X_DETECT_F_T detect = NULL;
    PCP56Time2a_T ptime = NULL;
	time_t now = time(NULL);

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /* check Time flag */
    if(TimeFlag != 1 && TimeFlag != 0){
        dy_syslog(LOG_ERR,"-%s-, error time flag(%d) ",__FUNCTION__,TimeFlag);
        return RET_ERROR;
    }
    /*get value*/
	//asdu_num = 1;
    //IEC10X->GetInfoNum(&asdu_num, 0);
    //dy_syslog(LOG_DEBUG,"-%s- total info (%d) ",__FUNCTION__, asdu_num);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    if(TimeFlag == 0)
        asdu->_type = IEC10X_M_ME_NC_1;
    else
        asdu->_type = IEC10X_M_ME_TF_1;
    asdu->_num._sq = 1;
    asdu->_num._num = end - start;//asdu_num;
    asdu->_reason._reason = 1;//IEC10X_COT_SPONT;
    asdu->_addr = addrV;//Iec10x_Sta_Addr;

    /*build info addr*/
    ptr = info->_addr;
    Temp32 = infoAddr;//addrV;
    memcpy(ptr, &Temp32, 3);

	dy_syslog(LOG_DEBUG,"ASDU(0x%x) infoAddr(0x%x) cnt %d",addrV,infoAddr,asdu->_num._num);
    /*build info value*/
    ptr = info->_element;
	for(i=start; i<end; i++){
		detect = (PIEC10X_DETECT_F_T)ptr;
	    //detect->_detect = detectV;
		//float val = 0;
		//uint8_t qds = 0x80;
		//time_t time_stamp;
		tag_info_t tag_info;
		
		tag_info.val = 0;
		tag_info.quality = 0x80;		
		iec104_get_station_info(addrV, 0, i, &tag_info);
		detect->_detect = tag_info.val;
	    dy_syslog(LOG_DEBUG,"end %d %d _detect %g qds %d",end,i,detect->_detect,tag_info.quality);
	    detect->_qds = tag_info.quality;
	    ptr += sizeof(IEC10X_DETECT_F_T);
	    if(TimeFlag == 1){
	        ptime = (PCP56Time2a_T)ptr;
			memset(ptime, 0, sizeof(CP56Time2a_T));		
			if(tag_info.time_stamp && now - tag_info.time_stamp <= 300)
			{
				dy_syslog(LOG_DEBUG, "now %d time_stamp %d", now, tag_info.time_stamp);
				tag_info.time_stamp = 0;
			}
	        IEC10X->GetTime(ptime, tag_info.time_stamp);
	        ptr += sizeof(CP56Time2a_T);
	    }
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_SPON, NULL,NULL);
	memcpy(pack->pack, Iec104_Sendbuf, len);
	pack->len = len;

    return RET_SUCESS;
}

uint8_t IEC104_Send_Spont(uint8_t *buf, uint16_t len){

	/*PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
	
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;
    DumpHEX(buf,len);*/
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(buf, len ,IEC10X_PRIO_SPON, NULL,NULL);
}

#else
uint8_t IEC104_BuildDetectF_Spont(uint8_t TimeFlag, uint16_t infoAddr, uint16_t addrV){

    uint8_t len = 0, asdu_num = 0, i;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PIEC10X_DETECT_F_T detect = NULL;
    PCP56Time2a_T time = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /* check Time flag */
    if(TimeFlag != 1 && TimeFlag != 0){
        dy_syslog(LOG_ERR,"-%s-, error time flag(%d) ",__FUNCTION__,TimeFlag);
        return RET_ERROR;
    }
    /*get value*/
	//asdu_num = 1;
    IEC10X->GetInfoNum(&asdu_num, 0);
    dy_syslog(LOG_DEBUG,"-%s- total info (%d) ",__FUNCTION__, asdu_num);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    if(TimeFlag == 0)
        asdu->_type = IEC10X_M_ME_NC_1;
    else
        asdu->_type = IEC10X_M_ME_TF_1;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = 1;//IEC10X_COT_SPONT;
    asdu->_addr = addrV;//Iec10x_Sta_Addr;

    /*build info addr*/
    ptr = info->_addr;
    Temp32 = infoAddr;//addrV;
    memcpy(ptr, &Temp32, 3);

    /*build info value*/
    ptr = info->_element;
	for(i=0; i<asdu_num; i++){
		detect = (PIEC10X_DETECT_F_T)ptr;
	    //detect->_detect = detectV;
		float val = 0;
	    iec104_get_station_info(addrV, 0, i, &val);
		detect->_detect = val;
	    dy_syslog(LOG_DEBUG,"i %d _detect %g",i,detect->_detect);
	    detect->_qds = 0;
	    ptr += sizeof(IEC10X_DETECT_F_T);
	    if(TimeFlag == 1){
	        time = (PCP56Time2a_T)ptr;
	        IEC10X->GetTime(time);
	        ptr += sizeof(CP56Time2a_T);
	    }
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_SPON, NULL,NULL);

    return RET_SUCESS;
}
#endif
uint8_t IEC104_BuildSignal(uint8_t reason,uint8_t Prio, uint8_t DevType){

    uint8_t len = 0, asdu_num = 0;
    uint16_t i = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*get value*/
    IEC10X->GetInfoNum(&asdu_num, DevType);
    dy_syslog(LOG_DEBUG,"-%s- total info (%d) ",__FUNCTION__, asdu_num);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = IEC10X_M_SP_NA_1;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = reason;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info addr*/
    ptr = info->_addr;
    if(DevType == ENDDEVICE_TYPE_HXTM){
        Temp32 = IEC104_INFOADDR_STATE_HXTM;
    }
    else if(DevType == ENDDEVICE_TYPE_HXGF){
        Temp32 = IEC104_INFOADDR_STATE_HXGF;
    }
    else{
        dy_syslog(LOG_ERR,"-%s-, error dev type:%d ",__FUNCTION__,DevType);
        return RET_ERROR;
    }

    memcpy(ptr, &Temp32, 3);

    /*build info value*/
    ptr = info->_element;
    for(i=0; i<asdu_num; i++){
        *ptr = IEC10X->GetStationState(i, DevType);
        ptr++;
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}
#if 1
uint8_t IEC104_BuildDetect(uint16_t Addr, uint8_t reason,uint8_t ValueType, uint8_t Prio, uint8_t DevType, uint16_t infoAddr, int start, int end){

    uint8_t len = 0, asdu_num = 0, i;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PIEC10X_DETECT_T detect = NULL;
    PIEC10X_DETECT_F_T detect_f = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*get value*/
    //IEC10X->GetInfoNum(&asdu_num, DevType);
	//iec104_get_station_cnt(Addr, DevType, &asdu_num);
    //dy_syslog(LOG_DEBUG,"-%s- total info (%d) ",__FUNCTION__, asdu_num);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = ValueType;
    asdu->_num._sq = 1;
    asdu->_num._num = end - start;
    asdu->_reason._reason = reason;
    asdu->_addr = Addr;

    /*build info addr*/
    ptr = info->_addr;
    /*if(DevType == ENDDEVICE_TYPE_HXTM){
        Temp32 = IEC104_INFOADDR_VALUE_HXTM;
    }
    else if(DevType == ENDDEVICE_TYPE_HXGF){
        Temp32 = IEC104_INFOADDR_VALUE_HXGF;
    }
    else{
        dy_syslog(LOG_ERR,"-%s-, error dev type:%d ",__FUNCTION__,DevType);
        return RET_ERROR;
    }*/
	Temp32 = infoAddr;//IEC104_INFOADDR_VALUE_HXGF
    memcpy(ptr, &Temp32, 3);

	dy_syslog(LOG_DEBUG,"-%s- ASDU(0x%x) infoAddr(0x%x) cnt %d",__FUNCTION__, Addr, infoAddr, asdu->_num._num);
    /*Build Detect value*/
    ptr = info->_element;
    for(i=start; i<end; i++){
        /*short int*/
        if(ValueType == IEC10X_M_ME_NA_1){
            detect = (PIEC10X_DETECT_T)ptr;
            detect->_detect = IEC10X->GetStaValue(i, DevType);
            detect->_qds = 0;
            ptr += sizeof(IEC10X_DETECT_T);
        }
        /*float*/
        else if(ValueType == IEC10X_M_ME_NC_1){
            detect_f = (PIEC10X_DETECT_F_T)ptr;
            //detect_f->_detect = IEC10X->GetStaValue(i, DevType);
			//float val = 0;
			//uint8_t qds = 0x80;
			//time_t time_stamp;
			tag_info_t tag_info;
		
			tag_info.val = 0;
			tag_info.quality = 0x80;
			iec104_get_station_info(Addr, DevType, i, &tag_info);
			detect_f->_detect = tag_info.val;
            dy_syslog(LOG_DEBUG,"-%s-, addr %x val %g ",__FUNCTION__,Addr,detect_f->_detect);
            detect_f->_qds = tag_info.quality;
            ptr += sizeof(IEC10X_DETECT_F_T);
        }
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}

#else
uint8_t IEC104_BuildDetect(uint16_t Addr, uint8_t reason,uint8_t ValueType, uint8_t Prio, uint8_t DevType){

    uint8_t len = 0, asdu_num = 0, i;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PIEC10X_DETECT_T detect = NULL;
    PIEC10X_DETECT_F_T detect_f = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*get value*/
    //IEC10X->GetInfoNum(&asdu_num, DevType);
	iec104_get_station_cnt(Addr, DevType, &asdu_num);
    dy_syslog(LOG_DEBUG,"-%s- total info (%d) ",__FUNCTION__, asdu_num);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = ValueType;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = reason;
    asdu->_addr = Addr;

    /*build info addr*/
    ptr = info->_addr;
    if(DevType == ENDDEVICE_TYPE_HXTM){
        Temp32 = IEC104_INFOADDR_VALUE_HXTM;
    }
    else if(DevType == ENDDEVICE_TYPE_HXGF){
        Temp32 = IEC104_INFOADDR_VALUE_HXGF;
    }
    else{
        dy_syslog(LOG_ERR,"-%s-, error dev type:%d ",__FUNCTION__,DevType);
        return RET_ERROR;
    }
    memcpy(ptr, &Temp32, 3);

    /*Build Detect value*/
    ptr = info->_element;
    for(i=0; i<asdu_num; i++){
        /*short int*/
        if(ValueType == IEC10X_M_ME_NA_1){
            detect = (PIEC10X_DETECT_T)ptr;
            detect->_detect = IEC10X->GetStaValue(i, DevType);
            detect->_qds = 0;
            ptr += sizeof(IEC10X_DETECT_T);
        }
        /*float*/
        else if(ValueType == IEC10X_M_ME_NC_1){
            detect_f = (PIEC10X_DETECT_F_T)ptr;
            //detect_f->_detect = IEC10X->GetStaValue(i, DevType);
			float val = 0;
			uint8_t qds = 0x80;
			iec104_get_station_info(Addr, DevType, i, &val, &qds);
			detect_f->_detect = val;
            dy_syslog(LOG_DEBUG,"-%s-, addr %x val %g ",__FUNCTION__,Addr,detect_f->_detect);
            detect_f->_qds = qds;
            ptr += sizeof(IEC10X_DETECT_F_T);
        }
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}
#endif
uint8_t IEC104_BuildUpload(uint8_t ValueType, uint8_t Prio, uint8_t DevType){

    uint8_t len = 0, asdu_num = 0, i;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;
    PIEC10X_DETECT_T detect = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*get value*/
    IEC10X->GetInfoNum(&asdu_num, DevType);
    dy_syslog(LOG_DEBUG,"-%s- total info (%d) ",__FUNCTION__, asdu_num);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = ValueType;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = AP_COT_BASE_INFO;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info addr*/
    ptr = info->_addr;
    
    Temp32 = IEC104_INFOADDR_BASE_DEVINFO;
    memcpy(ptr, &Temp32, 3);
    ptr += 3;
    /*Build Detect value*/
    ptr = info->_element;
    for(i=0; i<asdu_num; i++){

        detect = (PIEC10X_DETECT_T)ptr;
        detect->_detect = IEC10X->GetStaValue(i, DevType);
        detect->_qds = 0;
        ptr += sizeof(IEC10X_DETECT_T);
    }
    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}


uint8_t IEC104_BuildActFinish(uint8_t qoi, uint8_t Prio){

    uint8_t len = 0, asdu_num = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = IEC10X_C_IC_NA_1;
    asdu->_num._sq = 1;
    asdu->_num._num = asdu_num;
    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTTERM;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info addr*/
    ptr = info->_addr;
    Temp32 = IEC10X_INFO_ADDR_SIG_BASE+IEC10X_INFO_ADDR_SIG_TEMP_HX_OFF;
    memcpy(ptr, &Temp32, 3);

    /*Build Detect value*/
    ptr = info->_element;
    ptr[0] = qoi;

    ptr+=1;
    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;

    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}

uint8_t IEC104_Build_U(uint8_t UType, uint8_t Ack){

    uint8_t len = 0, Tester, Start, Stop;
    uint8_t *ptr = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;


    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    if(Ack){
        Tester = IEC104_U_FUNC_TESTER_ACK;
        Start = IEC104_U_FUNC_STARTDT_ACK;
        Stop = IEC104_U_FUNC_STOPDT_ACK;
    }else{
        Tester = IEC104_U_FUNC_TESTER;
        Start = IEC104_U_FUNC_STARTDT;
        Stop = IEC104_U_FUNC_STOPDT;
    }

    switch(UType){

        case IEC104_U_FUNC_STARTDT:
            Iec104Data->Ctrl.Func.Func = Start;
            break;
        case IEC104_U_FUNC_STOPDT:
            Iec104Data->Ctrl.Func.Func = Stop;
            break;
        case IEC104_U_FUNC_TESTER:
            Iec104Data->Ctrl.Func.Func = Tester;
            break;
        default:
            dy_syslog(LOG_ERR,">%s<, U Type Error(%d) !",__FUNCTION__,UType);
            return RET_ERROR;
    }


    /*build ASDU , COT ,Addr*/
    ptr=Iec104Data->Asdu;

    /*build info*/

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;
    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_INITLINK, NULL,NULL);

    return RET_SUCESS;
}


uint8_t IEC104_Build_S_Ack(void){

    uint8_t len = 0;
    uint8_t *ptr = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.S.Type1 = 1;
    Iec104Data->Ctrl.S.Type2 = 0;

    Iec104Data->Ctrl.S.Reserve = 0;
    Iec104Data->Ctrl.S.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    ptr=Iec104Data->Asdu;

    /*build info*/

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;
    //DumpHEX(Iec101_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_INITLINK, NULL,NULL);

    return RET_SUCESS;
}
uint8_t IEC104_ASDU_Call(PIEC10X_ASDU_T Iec10x_Asdu){

    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
    uint8_t qoi = asdu_info->_element[0];
    uint8_t Prio = 0;

    uint32_t InfoAddr = 0;

    /* check info addrest */
    memcpy(&InfoAddr, asdu_info->_addr, 3);
    if(InfoAddr != 0){
        dy_syslog(LOG_ERR,"-%s- call cmd active error addr(%x) " ,__FUNCTION__ ,InfoAddr);
        return RET_ERROR;
    }

    switch(Iec10x_Asdu->_reason._reason){

        case IEC10X_ASDU_REASON_ACT:
            switch(qoi){
                case IEC10X_CALL_QOI_TOTAL:
                    Prio = IEC10X_PRIO_CALLALL;
                    IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_CALL_ALLDATA;
                    IEC104_Call_AllQoi = qoi;
                    break;
                case IEC10X_CALL_QOI_GROUP1:
                case IEC10X_CALL_QOI_GROUP2:
                case IEC10X_CALL_QOI_GROUP9:
                case IEC10X_CALL_QOI_GROUP10:
                    Prio = IEC10X_PRIO_CALLGROUP;
                    IEC104_STATE_FLAG_GROUP = IEC101_FLAG_CALL_GROURPDATA;
                    IEC104_Call_GroupQoi = qoi;
                    break;
                default:
                    dy_syslog(LOG_ERR,"call cmd error qoi(%d) ", qoi);
                    return RET_ERROR;
            }
			
            IEC104_BuildCallACK(qoi,Prio);
            /**/
			//IEC10X->Delay_ms(1000);
			//dy_syslog(LOG_DEBUG,"-%s- %d ", __FUNCTION__,__LINE__);
            //IEC104_BuildSignal(qoi,Prio, ENDDEVICE_TYPE_HXTM);
			//dy_syslog(LOG_DEBUG,"-%s- %d ", __FUNCTION__,__LINE__);
            //Detect(qoi ,IEC10X_M_ME_NA_1,Prio, ENDDEVICE_TYPE_HXTM);
			//dy_syslog(LOG_DEBUG,"-%s- %d ", __FUNCTION__,__LINE__);
            /**/
			IEC10X->Delay_ms(1000);
            //IEC104_BuildSignal(qoi,Prio, ENDDEVICE_TYPE_HXGF);
			dy_syslog(LOG_DEBUG,"_addr 0x%x Prio %d", Iec10x_Asdu->_addr,Prio);
			iec104_call_process(Iec10x_Asdu->_addr, qoi ,IEC10X_M_ME_NC_1,Prio, ENDDEVICE_TYPE_HXGF);
			
            IEC104_BuildActFinish(qoi, Prio);
            break;

        default:
            dy_syslog(LOG_ERR,"call cmd error reason(%d) ", Iec10x_Asdu->_reason._reason);
            break;
    }
    return RET_SUCESS;
}
uint8_t Iec104_Aadu_Clock(PIEC10X_ASDU_T Iec10x_Asdu){

    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);

    memcpy(&IEC10X_Cp56time2a,asdu_info->_element, sizeof(CP56Time2a_T));

    if(asdu_info->_addr[0] != 0 || asdu_info->_addr[1] != 0 || asdu_info->_addr[2] != 0){
        dy_syslog(LOG_ERR,"-%s- Clock cmd error addr(0x%02x:%02x:%02x) ", __FUNCTION__,asdu_info->_addr[0],asdu_info->_addr[2],asdu_info->_addr[2]);
        return RET_ERROR;
    }

    switch(Iec10x_Asdu->_reason._reason){

        case IEC10X_COT_ACT:
            dy_syslog(LOG_DEBUG,"-%s- Clock cmd (20%d-%d-%d %d %d:%d:%d) ", __FUNCTION__,IEC10X_Cp56time2a._year._year,IEC10X_Cp56time2a._month._month,IEC10X_Cp56time2a._day._dayofmonth,
                    IEC10X_Cp56time2a._day._dayofweek,IEC10X_Cp56time2a._hour._hours,IEC10X_Cp56time2a._min._minutes,IEC10X_Cp56time2a._milliseconds);
            /*get time*/
            /*...*/
            IEC10X->SetTime(&IEC10X_Cp56time2a);
            IEC104_Build_S_Ack();

            break;
        case IEC10X_COT_SPONT:
            dy_syslog(LOG_DEBUG,"-%s- Clock cmd spont ", __FUNCTION__);
            break;
        default:
            dy_syslog(LOG_ERR,"-%s- Clock cmd error reason(%d) ", __FUNCTION__,Iec10x_Asdu->_reason._reason);
            break;
    }
    return RET_SUCESS;
}

uint8_t IEC104_ASDU_SetAct(PIEC10X_ASDU_T Iec10x_Asdu, uint8_t Type){

    PASDU_INFO_T asdu_info = (PASDU_INFO_T)(Iec10x_Asdu->_info);
    uint8_t *ptr = NULL;
    uint8_t n = Iec10x_Asdu->_num._num, Sq = Iec10x_Asdu->_num._sq, i;
    float Value = 0.0;
    uint32_t InfoAddr = 0;
            
    /* if sq == 1 */
    PIEC10X_DETECT_T detect = NULL;
    PIEC10X_DETECT_F_T detect_f = NULL;
  
    /* if sq == 0 */  
    PIEC10X_DETECT_SQ0_T detect_Sq0 = NULL;
    PIEC10X_DETECT_SQ0_F_T detect_Sq0_f = NULL;

    /* check info addrest */
    memcpy(&InfoAddr, asdu_info->_addr, 3);

    switch(Iec10x_Asdu->_reason._reason){

        case IEC10X_COT_ACT:
        
            switch(Type){
                case IEC10X_C_SE_NA_1:
                
                    if(Sq == 1){
                        ptr = asdu_info->_element;
                        for(i=0; i<n; i++){

                            detect = (PIEC10X_DETECT_T)ptr;
                            Value = (float)(detect->_detect);
                            ptr += sizeof(IEC10X_DETECT_T);
                            IEC10X->SetConfig(Value, InfoAddr+i);
                        }
                    }else if(Sq == 0){
                        ptr = Iec10x_Asdu->_info;
                        for(i=0; i<n; i++){

                            detect_Sq0 = (PIEC10X_DETECT_SQ0_T)ptr;
                            Value = (float)(detect_Sq0->_detect);
                            InfoAddr = 0;
                            memcpy(&InfoAddr, detect_Sq0->_addr, 3);
                            IEC10X->SetConfig(Value, InfoAddr);
                            ptr += sizeof(IEC10X_DETECT_SQ0_T);   
                        }
                        
                    }
                    break;
                case IEC10X_C_SE_NC_1:
                    if(Sq == 1){
                        ptr = asdu_info->_element;
                        for(i=0; i<n; i++){
                   
                            detect_f = (PIEC10X_DETECT_F_T)ptr;
                            Value = detect_f->_detect;
                            ptr += sizeof(IEC10X_DETECT_F_T);
                            IEC10X->SetConfig(Value, InfoAddr+i);
                        }
                    }else if(Sq == 0){
                        ptr = Iec10x_Asdu->_info;
                        for(i=0; i<n; i++){
                            detect_Sq0_f = (PIEC10X_DETECT_SQ0_F_T)ptr;
                            Value = (float)(detect_Sq0_f->_detect);
                            memcpy(&InfoAddr, detect_Sq0_f->_addr, 3);
                            IEC10X->SetConfig(Value, InfoAddr);
                            ptr += sizeof(IEC10X_DETECT_SQ0_F_T); 
                        }
                    }
                    break;
                default:
                    dy_syslog(LOG_ERR,"-%s-, Type error !",__FUNCTION__);
                    return RET_ERROR;
            }
            break;

        default:
            dy_syslog(LOG_ERR,"-%s- , error reason(%d) ", __FUNCTION__,Iec10x_Asdu->_reason._reason);
            return RET_ERROR;
    }
    return RET_SUCESS;
}

uint8_t IEC104_Build_SetAck(uint8_t Prio, uint8_t Type){

    uint8_t len = 0;
    uint8_t *ptr = NULL;

    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = Type;
    asdu->_num._sq = 0;
    asdu->_num._num = 0;
    asdu->_reason._reason = IEC10X_ASDU_REASON_ACTFIN;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info*/
    ptr = info->_addr;

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;
    
    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}

uint8_t Iec104_Deal_SN(uint16_t SendSn, uint16_t RecvSn){

    dy_syslog(LOG_DEBUG,"Receive Pakage I(%d,%d), Send(%d,%d)",SendSn,RecvSn, Iec104_BuildSendSn,Iec104_BuildRecvSn);
    
#if 0
    if(SendSn > Iec104_DealSendSn+1){
        dy_syslog(LOG_ERR,"-%s-, error,send last(%d),now(%d) ",__FUNCTION__,Iec104_DealSendSn,SendSn);
        IEC104_STATE_FLAG_INIT = IEC104_FLAG_SEND_CLOSED;
        return RET_ERROR;
    }else if(SendSn < Iec104_DealSendSn+1){
        dy_syslog(LOG_DEBUG,"-%s-, Retransmit,send last(%d),now(%d) ",__FUNCTION__,Iec104_DealSendSn,SendSn);
        return RET_ERROR;
    }
    if(RecvSn != Iec104_BuildSendSn){
        dy_syslog(LOG_ERR,"-%s-, error,receive last(%d),now(%d) ",__FUNCTION__,Iec104_BuildSendSn,RecvSn);
        IEC104_STATE_FLAG_INIT = IEC104_FLAG_SEND_CLOSED;
        return RET_ERROR;
    }
    if(RecvSn < Iec104_DealRecvSn){
        dy_syslog(LOG_ERR,"-%s-, error,receive2 last(%d),now(%d) ",__FUNCTION__,Iec104_DealRecvSn,RecvSn);
        return RET_ERROR;
    }
#endif

    if(SendSn < Iec104_DealSendSn || RecvSn < Iec104_DealRecvSn){

        dy_syslog(LOG_ERR,"-%s-, error,send last(%d),now(%d). recv last(%d),now(%d) ",__FUNCTION__,
                        Iec104_DealSendSn,SendSn, Iec104_DealRecvSn, RecvSn);
        return RET_ERROR;
    }
    Iec104_BuildRecvSn = SendSn+1;

    Iec104_DealSendSn = SendSn;
    Iec104_DealRecvSn = RecvSn;

    //Iec104_BuildRecvSn++;

    /* return S ACK */
    IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_S_ACK;
    Iec104_TimeCycle_S = 0;

    return RET_SUCESS;
}
int8_t Iec104_BuildDataAck(uint8_t TI, uint16_t COT, uint32_t InfoAddr, uint16_t Info, uint8_t Prio){

    uint8_t len = 0;
    uint8_t *ptr = NULL;
    uint32_t Temp32 = 0;

    /* build head */
    PIEC104_DATA_T Iec104Data = (PIEC104_DATA_T)Iec104_Sendbuf;
    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    /*build head*/
    Iec104Data->Head = IEC104_HEAD;

    /*build control code*/
    Iec104Data->Ctrl.I.Type = 0;
    Iec104Data->Ctrl.I.SendSn = Iec104_BuildSendSn++;
    Iec104Data->Ctrl.I.RecvSn = Iec104_BuildRecvSn;

    /*build ASDU , COT ,Addr*/
    asdu->_type = TI;
    asdu->_num._sq = 0;
    asdu->_num._num = 1;
    asdu->_reason._reason = COT;
    asdu->_addr = Iec10x_Sta_Addr;

    /*build info*/
    ptr = info->_addr;
    Temp32 = InfoAddr;
    memcpy(ptr, &Temp32, 3);

    ptr = info->_element;
    if(COT == IEC10X_COT_ACT_TERMINAL || COT == IEC10X_COT_ACTCON ||COT == IEC10X_COT_ACT_TERMINAL_ACK ||COT == IEC10X_TI_AP_FIRM_BACKOFF){
        ptr[0] = 0;
        ptr[1] = 0;
        ptr+=2;
    }else if(COT == IEC10X_COT_DATA_ACK || COT == IEC10X_COT_DATA_FIN_ACK){
        memcpy(ptr, &Info, 2);
        ptr+=2;
    }

    /*len*/
    len = ptr - Iec104_Sendbuf;
    Iec104Data->Len = len - 2;
    
    //DumpHEX(Iec104_Sendbuf,len);
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,Prio, NULL,NULL);

    return RET_SUCESS;
}

int8_t Iec104_Deal_FirmUpdate(PIEC10X_ASDU_T asdu, uint8_t Len){
    
    uint16_t cot = asdu->_reason._reason;
    uint16_t FlagNum = 0, i;
    uint8_t DataLen = Len - IEC104_DATA_LEN - 3;        /* flag num 2, check sum 1 byte*/
    PASDU_INFO_T element = (PASDU_INFO_T)(asdu->_info);
    uint8_t *DataPtr = (uint8_t *)(element->_element) +3;
    uint8_t TI = asdu->_type, csum = 0, CsumTemp = 0;
    uint32_t FirmwareType = 0;
    int8_t ret = 0;
    
    PASDU_INFO_T info = (PASDU_INFO_T)(asdu->_info);

    FlagNum = *(uint16_t *)(info->_element);
    memcpy(&FirmwareType, asdu->_info,3);

    if(Len == 0){
        dy_syslog(LOG_ERR,"-%s-,data:%d,Len:%d error!",__FUNCTION__,FlagNum,DataLen);
        return RET_ERROR;
    }
    
    /* reset the flag counter */
    if(FlagNum == 1){
        FirmFlagCount = 0;
        Iec10x_Update_SeekAddr = 0;
    }

    switch(cot){
    
        case IEC10X_COT_DATA:
            
            if(FlagNum == FirmFlagCount+1){
            
                /* check sum */
                csum = info->_element[2];
                
                for(i=0; i<DataLen; i++){
                    CsumTemp += DataPtr[i];
                }
                if(CsumTemp == csum){
                    dy_syslog(LOG_DEBUG,"-%s-,data:%d,Len:%d,seek:%d ",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr);
                    for(i=0; i<3; i++){
                        ret = IEC10X->SaveFirmware(DataLen,DataPtr,FirmwareType, Iec10x_Update_SeekAddr);
                        if(ret == RET_SUCESS)
                            break;
                    }
                    if(ret == RET_ERROR){
                        dy_syslog(LOG_ERR,"save firmware error ");
                        break;
                    }

                    FirmFlagCount = FlagNum;
                    Iec10x_Update_SeekAddr+=DataLen;
                }else{
                    dy_syslog(LOG_ERR,"%s, check sum error:%d,need:%d,num:%d",__FUNCTION__,CsumTemp,csum,FlagNum);
                }
            }else if(FlagNum < FirmFlagCount+1){
                dy_syslog(LOG_DEBUG,"update flag resend,need:%d,flag:%d",FirmFlagCount+1,FlagNum);
            }else{
                dy_syslog(LOG_ERR,"update flag error! need:%d,flag:%d",FirmFlagCount+1,FlagNum);
                //Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1);
            }
            break;
            
        case IEC10X_COT_DATA_NEEDACK:
            if(FlagNum == FirmFlagCount+1){

                /* check sum */
                csum = info->_element[2];
                for(i=0; i<DataLen; i++){
                    CsumTemp += DataPtr[i];
                }
                if(CsumTemp == csum){
                    dy_syslog(LOG_DEBUG,"-%s-,data need ack:%d,Len:%d,seek:%d ",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr);
                    
                    for(i=0; i<3; i++){
                        ret = IEC10X->SaveFirmware(DataLen,DataPtr,FirmwareType,Iec10x_Update_SeekAddr);
                        if(ret == RET_SUCESS)
                            break;
                    }
                    
                    if(ret == RET_ERROR){
                        dy_syslog(LOG_ERR,"save firmware error ");
                        break;
                    }
                    Iec104_BuildDataAck(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum,1);
                    
                    FirmFlagCount = FlagNum;
                    Iec10x_Update_SeekAddr+=DataLen;
                }else{
                    dy_syslog(LOG_ERR,"%s,need ack check sum error:%d,need:%d,num...:%d",__FUNCTION__,CsumTemp,csum,FlagNum);
                    //Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1);
                }
            }else if(FlagNum < FirmFlagCount+1){
                dy_syslog(LOG_DEBUG,"update flag resend,need:%d,flag:%d",FirmFlagCount+1,FlagNum);
                Iec104_BuildDataAck(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum,1);
            }else{
                dy_syslog(LOG_ERR,"update flag error! need:%d,flag:%d",FirmFlagCount+1,FlagNum);
                //Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, FlagNum,1);
            }
            break;

        case IEC10X_COT_DATA_FIN:
            if(FirmFlagCount == FlagNum){
                dy_syslog(LOG_DEBUG,"-%s-,data finish:%d,Len:%d,Total Len:%d ",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr);
                ret = IEC10X->CheckFirmware(FirmwareType, Iec10x_Update_SeekAddr);
                if(ret == RET_SUCESS){
                    Iec104_BuildDataAck(TI, IEC10X_COT_DATA_FIN_ACK, FirmwareType, FlagNum,1);
                    IEC10X->UpdateFirmware(FirmwareType);
                }else{
                    /* check firmware error ,terminal update */
                    Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, 0,1);
                }
            }else{
                dy_syslog(LOG_ERR,"-%s-,data finish error:%d,Len:%d,Total Len:%d,FirmFlagCount:%d,FlagNum:%d, ",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr,FirmFlagCount,FlagNum);
                return RET_ERROR;
            }
            break;

        case IEC10X_COT_ACT_TERMINAL:
            dy_syslog(LOG_DEBUG,"-%s-, Terminal:%d,Len:%d ",__FUNCTION__,FlagNum,DataLen);
            Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL_ACK, FirmwareType, 0,1);
            break;
        case IEC10X_COT_ACT_TERMINAL_ACK:
            dy_syslog(LOG_DEBUG,"-%s-, Terminal Ack ",__FUNCTION__);
            break;
        default :
            dy_syslog(LOG_ERR,"-%s-,data:%d,Len:%d error cot: ",__FUNCTION__,FlagNum,Len);
            return RET_ERROR;
    }
    return RET_SUCESS;
}

void Iec104_Tester_Timer(void){

    IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE;
    Iec104_TimeCycle_TesterIdle = 0;
}

uint8_t Iec104_Deal_I(PIEC104_DATA_T Iec104Data, uint16_t len){

    uint8_t Type;
    uint16_t RecvSn,SendSn;
    uint32_t FirmwareType = 0;

    PIEC10X_ASDU_T asdu = (PIEC10X_ASDU_T)(Iec104Data->Asdu);

    SendSn = Iec104Data->Ctrl.I.SendSn;
    RecvSn = Iec104Data->Ctrl.I.RecvSn;

    /* check asdu addrest */
    if(Iec10x_Sta_Addr != asdu->_addr){
        dy_syslog(LOG_ERR,"-%s-, error asdu addr(%x)(%x) " ,__FUNCTION__ ,Iec10x_Sta_Addr,asdu->_addr);
        //return RET_ERROR;
    }
    
    /* deal the receive and send serial number */
    if(Iec104_Deal_SN(SendSn, RecvSn) == RET_ERROR){
        return RET_ERROR;
    }
    /* Start tester timer */
    Iec104_Tester_Timer();

    Type = asdu->_type;
    switch(Type){

        case IEC10X_C_IC_NA_1:
            dy_syslog(LOG_DEBUG,"++++Asdu Type Call cmd... ");
            IEC104_ASDU_Call(asdu);
            IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_IDLE;
            break;
        case IEC10X_C_CS_NA_1:
            dy_syslog(LOG_DEBUG,"++++Asdu Type Clock syc cmd... ");
            Iec104_Aadu_Clock(asdu);
            break;
            
        case IEC10X_C_SE_NA_1:
        case IEC10X_C_SE_NC_1:
            dy_syslog(LOG_DEBUG,"++++Asdu Type Set type(%d)... ",Type);
            IEC104_ASDU_SetAct(asdu, Type);
            IEC104_Build_SetAck(1, Type);
            break;
        case IEC10X_TI_FIRM_UPDATE:
            dy_syslog(LOG_DEBUG,"++++Asdu Type Firmware Update... ");
            Iec104_Deal_FirmUpdate(asdu, len);
            break;
        case IEC10X_TI_AP_FIRM_BACKOFF:
            dy_syslog(LOG_DEBUG,"++++Asdu Type Firmware Backoff... ");
            memcpy(&FirmwareType, asdu->_info,3);
            Iec104_BuildDataAck(IEC10X_TI_AP_FIRM_BACKOFF, IEC10X_COT_ACTCON, FirmwareType, 0,1);
            IEC10X->BackoffFirmware(FirmwareType);
            break;
        default:
            dy_syslog(LOG_ERR,"-%s-, error Type(%d) ", __FUNCTION__,Type);
            return RET_ERROR;
    }
    return RET_SUCESS;
}


uint8_t Iec104_Deal_S(PIEC104_DATA_T Iec104Data, uint16_t len){


    return RET_SUCESS;
}
uint8_t test_cnt = 1;
uint8_t Iec104_Deal_U(PIEC104_DATA_T Iec104Data, uint16_t len){

    switch(Iec104Data->Ctrl.Func.Func){

        case IEC104_U_FUNC_STARTDT:
            dy_syslog(LOG_DEBUG,">%s<, function STARTDT ",__FUNCTION__);
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_LINK_INIT;
            Iec104_TimeCycle = 0;
            Iec104_TimeCount = 0;
            //IEC104_Build_U(IEC104_U_FUNC_STARTDT,1);
            //IEC104_Build_InitFin();
			test_cnt = 1;
            break;
        case IEC104_U_FUNC_STOPDT:
            dy_syslog(LOG_DEBUG,">%s<, function STOPDT ",__FUNCTION__);
            IEC10X->CloseLink();
            IEC104_Build_U(IEC104_U_FUNC_STOPDT,1);
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_RECV_CLOSED;
            break;
        case IEC104_U_FUNC_TESTER:
            dy_syslog(LOG_DEBUG,">%s<, function TESTER ",__FUNCTION__);
            IEC104_Build_U(IEC104_U_FUNC_TESTER,1);
            break;

        /* U ACK */
        case IEC104_U_FUNC_STARTDT_ACK:
            dy_syslog(LOG_DEBUG,">%s<, function STARTDT ACK",__FUNCTION__);
            break;
        case IEC104_U_FUNC_STOPDT_ACK:
            dy_syslog(LOG_DEBUG,">%s<, function STOPDT ACK",__FUNCTION__);
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_RECV_CLOSED;
            break;
        case IEC104_U_FUNC_TESTER_ACK:
            dy_syslog(LOG_DEBUG,">%s<, function TESTER ACK",__FUNCTION__);
            Iec104_TesterCount = 0;
            break;
        default:
            dy_syslog(LOG_ERR,">%s<, function ERROR ",__FUNCTION__);
            break;
    }
    return RET_SUCESS;
}
#if 0
void Iex104_send_test(void){

	uint32_t Temp32 = 0x001020;
	uint8_t TimeFlag = 1;
	PIEC10X_DETECT_T detect;
	//dy_syslog(LOG_DEBUG,"##%s line %d##",__FUNCTION__,__LINE__);
    detect->_detect = 13;//IEC10X->GetStaValue(1, IEC10X_M_ME_NC_1);
	//dy_syslog(LOG_DEBUG,"##%s line %d##",__FUNCTION__,__LINE__);
    detect->_qds = 0;

	float detectV = 11.0;
	uint16_t addrV = 0x010203;

	//IEC104_BuildDetect_Spont(TimeFlag, detect, Temp32);
	IEC104_BuildDetectF_Spont(TimeFlag, detectV, addrV);
}
#else
void Iex104_send_login(void)
{
	uint8_t len = 16;
	uint8_t *ptr = Iec104_Sendbuf;

	//68 0E 00 00 00 00 46 01 04 00 XX XX XX XX XX XX
	ptr[0] = 0x68; //68 0E 00 00 00 00 46 01 04 00 XX XX XX XX XX XX
	ptr[1] = 0x0E;
	ptr[2] = 0x00;
	ptr[3] = 0x00;
	ptr[4] = 0x00;
	ptr[5] = 0x00;
	ptr[6] = 0x46;
	ptr[7] = 0x01;
	ptr[8] = 0x04;
	ptr[9] = 0x00;
	ptr[10] = mac_addr[0];//0x08;//08:00:3E:26:0A:5C
	ptr[11] = mac_addr[1];
	ptr[12] = mac_addr[2];
	ptr[13] = mac_addr[3];
	ptr[14] = mac_addr[4];
	ptr[15] = mac_addr[5];
	
    /* enqueue to the transmisson queue */
    IEC10X_Enqueue(Iec104_Sendbuf, len ,IEC10X_PRIO_SPON, NULL,NULL);
}


#endif
void Iex104_Receive(uint8_t *buf, uint16_t len){

    uint8_t *BufTemp = NULL;
    int16_t LenRemain,LenTmp;
    PIEC104_DATA_T Iec104Data = NULL;

    if(buf == NULL){
        dy_syslog(LOG_ERR,"-%s-,buffer (null)",__FUNCTION__);
        return;
    }
#if 0
    if(len <= 0 || len>IEC104_MAX_BUF_LEN || len<BufTemp[0]+2){
        dy_syslog(LOG_ERR,"-%s-,buffer len error(%d) ",__FUNCTION__,len);
        return;
    }
#endif

    BufTemp = buf;
    LenRemain = len;

    while(BufTemp<buf+len){

        Iec104Data = (PIEC104_DATA_T)BufTemp;
        Iec10x_Lock();
        if(Iec104Data->Head == IEC104_HEAD){

            LenTmp = Iec104Data->Len + 2;
            if(LenRemain < IEC104_HEAD_LEN){
                dy_syslog(LOG_ERR,"_%s_,len error(%d) ",__FUNCTION__,len);
                Iec10x_UnLock();
                return;
            }
            if(Iec104Data->Ctrl.Type.Type1 == 0){
                dy_syslog(LOG_DEBUG,"-%s-,Frame Type I ",__FUNCTION__);
                Iec104_Deal_I(Iec104Data, LenTmp);

            }else if(Iec104Data->Ctrl.Type.Type1 == 1 && Iec104Data->Ctrl.Type.Type2 == 0){
                dy_syslog(LOG_DEBUG,"-%s-,Frame Type S ",__FUNCTION__);
                Iec104_Deal_S(Iec104Data, LenTmp);

            }else if(Iec104Data->Ctrl.Type.Type1 == 1 && Iec104Data->Ctrl.Type.Type2 == 1){
                dy_syslog(LOG_DEBUG,"-%s-,Frame Type U ",__FUNCTION__);
                Iec104_Deal_U(Iec104Data, LenTmp);
            }
        }else{
            dy_syslog(LOG_ERR,"-%s-,head type error(%d) ",__FUNCTION__,BufTemp[0]);
            Iec10x_UnLock();
            return;
        }
        Iec10x_UnLock();
        BufTemp+=LenTmp;
        LenRemain-=LenTmp;
    }
    return;
}

void Iec104_ResetFlag(void){

    IEC104_STATE_FLAG_CALLALL = IEC104_FLAG_IDLE;
    IEC104_STATE_FLAG_GROUP = IEC104_FLAG_IDLE;
    IEC104_STATE_FLAG_CLOCK = IEC104_FLAG_IDLE;
    IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE;

    Iec104_BuildSendSn = 0;
    Iec104_BuildRecvSn = 0;
    Iec104_DealSendSn = -1;
    Iec104_DealRecvSn = 0;

    Iec104_TesterCount = 0;
	test_cnt = 1;

}

uint32_t TestCount_Temp = 0;
uint8_t Iec104_StateMachine(void){
    /*Init link*/
    switch(IEC104_STATE_FLAG_INIT){

        case IEC104_FLAG_CLOSED:
#if defined(IEC104_STM32_FUJIAN_HX)
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_UPLOAD_ADDR;
#else
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_START_LINK;
            IEC10X_ClearQ();
            Iec104_ResetFlag();
#endif  /* IEC104_STM32_FUJIAN_HX */
            break;
        case IEC104_FLAG_SEND_CLOSED:
            Iec104_TimeCycle += IEC104_CYCLE_TIME_MS;
            if(Iec104_TimeCycle > IEC104_RESEND_TIME_MS){
                Iec104_TimeCycle = 0;
                Iec104_TimeCount++;
                IEC104_Build_U(IEC104_U_FUNC_STOPDT,0);
            }
            if(Iec104_TimeCount>=3){
                Iec104_TimeCount = 0;
                IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE;
                IEC10X->CloseLink();
            }
            break;
        case IEC104_FLAG_RECV_CLOSED:
            Iec104_ResetFlag();
            IEC10X_ClearQ();
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS;
            break;
        case IEC104_FLAG_LINK_INIT:
            dy_syslog(LOG_DEBUG,"Iec104 machine state :IEC104_FLAG_LINK_INIT ");
            Iec104_ResetFlag();
            Iec10x_Sta_Addr = IEC10X->GetLinkAddr();
            IEC104_Build_U(IEC104_U_FUNC_STARTDT,1);
            IEC104_Build_InitFin();
			test_cnt = 1;
            //IEC104_BuildUpload(IEC10X_TI_AP_BASE_INFO, IEC10X_PRIO_INITLINK, AP_TYPE_BASE_INFO);
            IEC104_STATE_FLAG_INIT = IEC104_FLAG_CONNECT_SUCESS;
            break;
        case IEC104_FLAG_UPLOAD_ADDR:
            Iec104_TimeCycle += IEC104_CYCLE_TIME_MS;
            if(Iec104_TimeCycle > IEC104_RESEND_TIME_MS){
                Iec10x_Sta_Addr = IEC10X->GetLinkAddr();
                Iec104_TimeCycle = 0;
                Iec104_TimeCount++;
                IEC104_UploadAddr();
            }
            if(Iec104_TimeCount>=3){
                Iec104_TimeCount = 0;
                IEC104_STATE_FLAG_INIT = IEC104_FLAG_IDLE;
                IEC10X->CloseLink();
            }
            break;

        case IEC104_FLAG_CONNECT_SUCESS:
        case IEC104_FLAG_IDLE:
        default:
            break;
    }
    if(IEC104_STATE_FLAG_INIT == IEC104_FLAG_CONNECT_SUCESS){

        /* Return s ack */
        switch(IEC104_STATE_FLAG_S_ACK){

            case IEC104_FLAG_S_ACK:
                Iec104_TimeCycle_S += IEC104_CYCLE_TIME_MS;
                if(Iec104_TimeCycle_S > IEC104_S_ACK_TIMEOUT){
                    Iec104_TimeCycle_S = 0;
                    IEC104_Build_S_Ack();
                    IEC104_STATE_FLAG_S_ACK = IEC104_FLAG_IDLE;
                }
                break;
            case IEC104_FLAG_IDLE:
                break;
            default:
                break;
        }
        /* test spon */
#if 0
        if(TestCount_Temp++>(10*60*20)){
            TestCount_Temp = 0;
            IEC104_BuildSignal_Spon(1, 1, IEC104_INFOADDR_STATE_HXGF+2);
            IEC104_BuildDetectF_Spont(1, 60.2, IEC104_INFOADDR_VALUE_HXTM+2);
            IEC104_BuildDetectF_Spont(1, 61.1, IEC104_INFOADDR_VALUE_HXGF+2);
        }
#endif
    }
	
    /* Tester */
    switch(IEC104_STATE_FLAG_TESTER){
        case IEC104_FLAG_TESTER:
			#if 0
			if(cnt_test++ % 100 == 0)
				Iex104_send_test();
            IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE;
			#else
			if(test_cnt <= 2)
				IEC104_Build_U(IEC104_U_FUNC_STARTDT,0);
			else 
				IEC104_Build_U(IEC104_U_FUNC_TESTER,0);
			//if(cnt_test++ % 40 == 0)
				//Iex104_send_test();
            IEC104_STATE_FLAG_TESTER = IEC104_FLAG_IDLE;
            Iec104_TesterCount++;
            //dy_syslog(LOG_DEBUG,"Tester Count(%d)... ",Iec104_TesterCount);
            if(Iec104_TesterCount>3){
                Iec104_TesterCount = 0;
                //dy_syslog(LOG_WARNING,"Tester error(%d)... ",Iec104_TesterCount);
                //IEC104_STATE_FLAG_INIT = IEC104_FLAG_CLOSED;
                //IEC10X->CloseLink();
            }
			#endif
            break;
        case IEC104_FLAG_TESTER_STOP:
            break;
        case IEC104_FLAG_IDLE:
            Iec104_TimeCycle_TesterIdle += IEC104_CYCLE_TIME_MS;
            if(test_cnt == 1 || Iec104_TimeCycle_TesterIdle > IEC104_TESTER_IDLE_TIMEOUT){
                Iec104_TimeCycle_TesterIdle = 0;
                IEC104_STATE_FLAG_TESTER = IEC104_FLAG_TESTER;
				if(test_cnt < 5)
					test_cnt++;
            }
			//dy_syslog(LOG_DEBUG,"Iec104_TimeCycle_TesterIdle %d %d",Iec104_TimeCycle_TesterIdle,IEC104_TESTER_IDLE_TIMEOUT);
			IEC10X->Delay_ms(100);
            break;
        default:
            break;
    }
    return RET_SUCESS;
}


