/********************************************************************
版权所有：	
文件版本： V1.00
文件名称： IECComm.c
生成日期： 2007年04月26日
作    者：王建军
使用范围：

功    能： 外部通信处理函数
更新信息：
更新日志1：
修改者:
修改日期:
修改内容:
修改原因:
*********************************************************************/
#include "head.h"
#ifdef LINUX_KERNEL_APP
#include "uart_user.h"
#include <linux/delay.h>
#else
#include <sys/prctl.h>
#include <errno.h>
#endif


u8 rmt_str_cnt=0;
para_chg_queque g_para_chg_queque[COMM_CHANNEL_NUM];	
DWORD dTpartime;

//#define SEC_BOX_CODE  1

bool g_bCommLed;             //通信灯状态
bool g_bCommStatus;
u32 g_comm_link_status;    	//通信连接状态，每个通道用一个bit表示
bool byc_filter;	//遥测滤波，防止遥测没有稳定下来突发上送


BYTE g_arrIECBuf[IEC_TBUF_LEN];  	// 通信规约处理时使用的数据缓冲区

SERIAL_COMM 	g_tRsComm[CFG_UART_NUM_MAX]; 	// 4个串行通信口的通信结构定义
union u_RsIEC 	g_tRsIEC[CFG_UART_NUM_MAX];		// 串口规约共用结构buf区，目前有101 104规约
s8 UART_CHANNEL[CFG_UART_NUM_MAX] = {CFG_UART_485_0, CFG_UART_485_1,
                                     CFG_UART_232_0, CFG_UART_232_1,
                                     CFG_UART_GPS, CFG_UART_BK_0,
                                     CFG_UART_BK_1, CFG_UART_CHIP_S1};

u8 uart_test_begin=0;
u8 uart_test_flag[CFG_UART_NUM_MAX][2];

//定义预置/固化参数时用于比较的数组及变量
BYTE buf_forCompare[256]={0};	//预置报文和固化报文的比较存储数组
int i_forCompare=0,j_forCompare=0;	//比较数组存储时计数用
bool bfirst_sel=false;	//预置标志

#ifdef FUNC_ENCRY_IN_ONE_SERIAL
bool gb_bready = true;
#endif


#ifdef CPU_FUXI
int g_uart_isr_thread_create_flag[CFG_UART_NUM_MAX] = {0};
static struct task_struct * ts[CFG_UART_NUM_MAX];
static struct sched_param sp[CFG_UART_NUM_MAX];
static int l_ch[CFG_UART_NUM_MAX];
#endif


int g_link_uart_chnl=-1;		//级联串口号
static void IEC_Recv(BYTE cDat,BYTE chnl);
#ifdef FUN_GPRS	// modfiy for xxxxxx 20220706 GPRS没有使用。	
extern void (*g_IEC_Recv)(unsigned char cDat, unsigned char chnl);
extern int gprs_net_init(void);
extern int g_gh_vs_is_idle;
extern int g_update_dz; 
#else
//接收数据处理回调函数
void (*g_IEC_Recv)(unsigned char cDat, unsigned char chnl);
#endif

#ifdef LINUX_USER_APP
 static int l_ch[CFG_UART_NUM_MAX];
 static pthread_t l_id[CFG_UART_NUM_MAX];
 
 extern int main_mod_is_exit(void);
 extern void mainloop_wakeup(void);
#endif


#ifdef CPU_FUXI
int uart_isr_thread_create(int ch);
extern int main_mod_is_exit(void);
#endif
extern void FaultComm_Init(IEC101_DEF *pt,BYTE chnl);
extern void FaultComm_Applay(IEC101_DEF *pt);
extern void FaultComm_Recv(IEC101_DEF *pt,BYTE byRevData) ;
#define CFG_LINK_EQU_SOE_NUM	10	// 级联装置保存SOE数量
u8 g_ti_select[]=
{
	0x2d, // 单点命令(45)
	0x2e, // 双点命令(46)
	0xcb, // 写参数和定值(203)  报文格式不同，若需要，应特殊处理
	0xd3, // 软件升级(211)
};

u8 TI_SELECT_NUM= (sizeof(g_ti_select));


// 文件，信息体对应表
typedef struct DI_DIR
{
	DWORD	di;   					//485 波特	
	char *    dir;      				// 串口校验方式无奇偶校验等
}DI_DIR;

DI_DIR di_dir[]=
{
	{0x0000,				" "},
	{0x6804, HF_SOE_101_DIR},    // 6804
	{0x6805,	HF_CO_101_DIR},
	{0x0cea,	HF_EXV_101_DIR},  // 6802
	{0x6805,	HF_FIXPT_101_DIR},
	{0x680A,	HF_WAVE_DIR},
};

const int DI_DIR_NUMBER  = sizeof( di_dir ) / sizeof(di_dir[0]);  //  个数

#ifdef GEN_QUEUE	
s32 queue_init(QTYPE *queque, s32 maxsize,void *data,s32 s_size)
{
	
	queque->count = 0;
	queque->front = 0;
	queque->rear = 0;
	queque->maxsize = maxsize;
	queque->s_size = s_size;
	queque->data = data;	/*元素实体*/
 
	return 0;
}

s32 get_queue_count(QTYPE *queue)
{
	return queue->count;
}

/*函数功能说明：队列操作的通用写接口*/ 
s32 add_data_queque(QTYPE *queue,u8 *data, u8 op_type)
{
	s32 rear=0;
	u32 pos=0;
	
	if((queue->count >= queue->maxsize)	&& (op_type == KEEP_QUEUE))	/*队列满,保持原数据*/
	{
		return -1;
	}	
		
	rear = queue->rear;
	pos  = rear*queue->s_size;	
	memcpy(&queue->data[pos], data, queue->s_size);

	queue->rear = (queue->rear+1)%queue->maxsize;	
	queue->count ++;;	
	
/*************/	
	if((queue->count > queue->maxsize)&& (op_type == OVER_QUEUE))		
	{
		queue->count = queue->maxsize;
		queue->front = (queue->front+1)%queue->maxsize; 
	}
/*************/ 

	return 0;
}


/*队列操作的通用读接口*/ 
s32 get_data_queque(QTYPE *queue,u8 *data)
{	
	u32 pos=0;

	if(queue->count == 0) return -1;	/*无数据*/

	pos = queue->front * queue->s_size;
	memcpy(data, &queue->data[pos], queue->s_size);

	queue->front = (queue->front+1)%queue->maxsize; 
	queue->count--;	
	return 0;	
}

/*队列操作的通用检查接口*/ 
s32 check_data_queque(QTYPE *queue,u8 *data)
{	
	u32 pos=0;

	if(queue->count == 0) return -1;	/*无数据*/

	pos = queue->front * queue->s_size;
	memcpy(data, &queue->data[pos], queue->s_size);	
	return 0;	
}

/*队列操作的通用减接口*/ 
void del_data_queue(QTYPE *queue)
{
	if(queue->count > 0)
	{
		queue->front = (queue->front+1)%queue->maxsize; 
		queue->count--;	
	}	
}


s32 print_queque(QTYPE *queue,u8 type)
{
	s32 i=0;
	s32 pos=0;
	s32 ret=0;	
	s32 front=0;

	rt_printf("queue------count=%d,s_size=%d,maxsize=%d,front=%d,rear=%d\r\n",(int)queue->count,(int)queue->s_size
					,(int)queue->maxsize,(int)queue->front,(int)queue->rear);	

	for(i=0;i<queue->count;i++)
	{
		front = (queue->front+i)%queue->maxsize;
		pos = front*queue->s_size;

		if(type == RCD_PRINT)
		{			
			newrcd_m_struct *data;
			data = (newrcd_m_struct *)&queue->data[pos];
			
			rt_printf("---data[%x][%x]:%s,addr=%d\r\n",(int)front,(int)pos,data->filename,data->addr);
		}
		else if(type == PARA_PRINT)
		{
			para_chg_single *data;		
			data = (para_chg_single *)&queue->data[pos];
			rt_printf("---data[%x][%x]:%f,parId=%x\r\n",(int)front,(int)pos,data->val,data->parId);					
		}

	}

	return ret;
}


#endif 

#ifdef RCD_STRAN_S
void iec_commadd_rcd(char *filename)
{
	int i=0;
	char data[128]={0};
	IEC101_DEF *pt101;
	IEC104_DEF *pt104;
	
	for(i=0;i<CFG_UART_NUM_MAX;i++)
	{		
		 if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_101)  // 串口级联规约
		 {
		 	pt101 = (IEC101_DEF *)g_tRsComm[i].ptBuf;
			strncpy(data,filename,sizeof(data));
			add_data_queque(&pt101->rcd_qt.queue,data,OVER_QUEUE);		
		 }
	}
	

	for(i=0;i<CFG_ETH_MAX_LOGIC;i++)
	{		
		pt104=&g_t104[i];		
		strncpy(data,filename,sizeof(data));
		add_data_queque(&pt104->rcd_qt.queue,data,OVER_QUEUE);		
	}

}

#endif

char * IEC_Getdir(DWORD di)
{
	int i;
	for(i=0;i<DI_DIR_NUMBER;i++)
	{
		if(di==di_dir[i].di)return di_dir[i].dir;

	}
	return di_dir[0].dir;
}

bool getCommStatus(void)
{
	int i;
	for(i=0;i<CFG_UART_NUM_MAX+CFG_ETH_NUM_MAX;i++)
	{
		if(soe_check(EV_COMM1_ERR+i))
			return true;
	}
	return false;
}
//获取101级联通信状态
bool getIecLink101Status(void)
{
	int i;
	for(i=EV_LINK_EQU1;i<EV_LINK_EQU10;i++)
	{
		if( soe_check(i))
			return true;
	}
	return false;
}

/**************************************************************************
函数名称：IEC_CommInit
函数版本：1.00 
作者：   
创建日期：2008.9.1     
函数功能说明：外部通信初始化
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
void IEC_CommInit(void)                     // 外部通信初始化 
{
	int i, ret;
	
	s_stat_reset(1);//初始串口统计信息
	
	//相关通道规约应用初始化
	g_link_uart_chnl=-1;
	
	for(i=0;i<CFG_UART_NUM_MAX;i++)
	{
		// 不管硬件通道是否存在，都将参数设置放入串口统计信息中
		s_stat_protocol(i, (int)tRunPara.tUartPara[i].wProtocol);	//统计规约
		
		// 如果硬件通道不存在，跳过
		if(UART_CHANNEL[i]<0)continue;		

		// 如果没有初始化标志，意味着设置没有更新，不重新初始化
		if(!tRunPara.tUartPara[i].bInit)continue;
		
		tRunPara.tUartPara[i].bInit=false;		//清初始化标志
		
		memset(&g_tRsComm[i],0,sizeof(g_tRsComm[i]));
		g_tRsComm[i].ptBuf=(BYTE*)&g_tRsIEC[i];
		
		if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_101
			||tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_PH
			||tRunPara.tUartPara[i].wProtocol == PROTOCOL_MAINTAIN
		#ifdef FUNC_ENCRY_IN_ONE_SERIAL
			|| tRunPara.tUartPara[i].wProtocol == PROTOCOL_WED_ENC
		#endif
			) //  103
		{
			IEC101_Init((IEC101_DEF *)g_tRsComm[i].ptBuf,i);
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_M||tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_PH_M) //  101级联
		{
			lnk_101_init((IECLINK_DEF *)g_tRsComm[i].ptBuf,i,(tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_PH_M));
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_104)  // 104规约
		{
			IEC104_Init_RS((IEC104_DEF *)g_tRsComm[i].ptBuf,i);
		}
		else if(tRunPara.tUartPara[i].wProtocol == PROTOCOL_HMI)  // 面板规约
		{
			uart_comm_init((UART_COMM_STRUCT *)g_tRsComm[i].ptBuf, i);
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_FAULT) //  状态板通信
		{
			FaultComm_Init((IEC101_DEF *)g_tRsComm[i].ptBuf,i);
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_SXYB)  //数显仪表
		{
			sxyb_init();
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_MODBUS) //  modbus主站规约
		{
			modbus_Init((MODBUS_DEF *)g_tRsComm[i].ptBuf,i);
		}
	#if defined(ADD_ATGM366_GPS_FUN) || defined(DEV_GPS_ATGM366) || defined(DEV_GPS_ATGM332D)
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_GPS) //  GPS模块
		{
			GPSCommInit((GPS_COMM *)g_tRsComm[i].ptBuf,i);
		}
	#endif
		else if (tRunPara.tUartPara[i].wProtocol==PROTOCOL_AUTHOR_BL) //  蓝牙模块)
		{
			bluetooth_init((BLUETOOTH_DEF *)g_tRsComm[i].ptBuf,i);
		}
	#ifdef BATTERY_WITH_COMM
		else if(tRunPara.tUartPara[i].wProtocol == PROTOCOL_POWER_MOD){
			PowerModuleCommInit((COMM_POW_MOD*)g_tRsComm[i].ptBuf,i);
		}
		#ifdef FUNC_SEL_BAT_MODULE
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_PWRM)
		{			
			pwrm_Init((pwdmodlue_def *)g_tRsComm[i].ptBuf,i);
		}
		#endif	
	#endif
		
	#ifdef FUN_GPRS	// modfiy for xxxxxx 20220706 GPRS没有使用。	
		if(UART_CHANNEL[i] == CFG_UART_GPRS_IN)
		{ 
			g_gh_vs_is_idle = 1;//置为空闲.如果不空闲,后续代码会改变此变量的值. 
		}
	#endif		
		
			
		// 如果此串口不是系统控制台串口，协议也不是空闲，初始化串口
		if(UART_CHANNEL[i] != g_con_uart_index && tRunPara.tUartPara[i].wProtocol != PROTOCOL_IDLE)
		{
		#ifdef FUN_GPRS	// modfiy for xxxxxx 20220706 GPRS没有使用。	
			if(UART_CHANNEL[i] == CFG_UART_GPRS_IN)
			{ 
				g_gh_vs_is_idle = 0; //置为不空闲
				continue;
			}
		#endif	
	#ifdef	FUN_FUXI_ESAM
			else if(UART_CHANNEL[i] == CFG_UART_CHIP_S1)
			{ 
				continue;
			}
	#endif
			

			// 如果GPS对时打开，必须关闭串口。
			if(g_clock_mode_gps && UART_CHANNEL[i] == CFG_UART_GPS)
			{
				continue;
			}
		#ifdef IECCOM_DEBUG
			rt_printf("UART_CHANNEL[%d]=%d,tRunPara.tUartPara[%d].wProtocol=%d,tRunPara.tUartPara[%d].wBaud=%d tUartPara[%d].wParity=%d\r\n",\
					i,UART_CHANNEL[i],i,tRunPara.tUartPara[i].wProtocol,i,tRunPara.tUartPara[i].dBaud,i,tRunPara.tUartPara[i].wParity);
		#endif
			ret = uart_open(UART_CHANNEL[i],tRunPara.tUartPara[i].dBaud,tRunPara.tUartPara[i].wParity);
			if (ret < 0)
			{
				printf("%s: outside uart %d open failed!\n", __FUNCTION__, UART_CHANNEL[i]);
			}
			

			RS_Ena_Init(i);
			RS_Recv_Enable(i);
#if defined CPU_FUXI
			uart_isr_thread_create(i);
#endif		
		}

		//串口打开后，再初始化
		if(tRunPara.tUartPara[i].wProtocol == PROTOCOL_HMI)  // 面板规约
		{
			g_h_boj[0].fd = UART_CHANNEL[i];
			user_conf_init(); //用户配置初始化(面板)
		}
	}
	
	//回调函数
	g_IEC_Recv=IEC_Recv;
#ifdef FUN_GPRS	// modfiy for xxxxxx 20220706 GPRS没有使用。
	g_update_dz = 1;//置标志,要求任务重新初始化虚拟串口
#endif	
	//内部GPRS初始化
	//gprs_net_init();
}
/**************************************************************************
函数名称：IEC_Recv
函数版本：1.00 
作者：   
创建日期：2008.9.1     
函数功能说明：通信口接收处理，根据不同的规约类型，调用不同的接收函数
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/

static void IEC_Recv(BYTE cDat,BYTE chnl)
{
	if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_101
		||tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_101_PH
		||tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_MAINTAIN
	#ifdef FUNC_ENCRY_IN_ONE_SERIAL
		|| tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_WED_ENC
	#endif
		)  // 101规约
	{
		IEC101_Recv_Int((IEC101_DEF *)g_tRsComm[chnl].ptBuf,cDat);
	}
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_101_M||tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_101_PH_M)  // 级联
	{
		lnk_101_recv((IECLINK_DEF *)g_tRsComm[chnl].ptBuf,cDat);
	}
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_104) //104规约
	{
		IEC104_Recv((IEC104_DEF *)g_tRsComm[chnl].ptBuf,cDat);
	}	
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_FAULT) // 状态板
	{
		FaultComm_Recv((IEC101_DEF *)g_tRsComm[chnl].ptBuf,cDat);
	}		
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_MODBUS) //modbus主站规约
	{
		modbus_Recv((MODBUS_DEF *)g_tRsComm[chnl].ptBuf,cDat);
	}	
#if defined(ADD_ATGM366_GPS_FUN) || defined(DEV_GPS_ATGM366) || defined(DEV_GPS_ATGM332D)
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_GPS) //GPS模块
	{
		GPS_Recv((GPS_COMM *)g_tRsComm[chnl].ptBuf,cDat);
	}
#endif
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_AUTHOR_BL) //加密蓝牙模块
	{
		bluetooth_recv((BLUETOOTH_DEF *)g_tRsComm[chnl].ptBuf,cDat);
	}
#ifdef BATTERY_WITH_COMM
	else if(tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_POWER_MOD){
		PowerModuleCommRecv((COMM_POW_MOD*)g_tRsComm[chnl].ptBuf,cDat);
	}
	#ifdef FUNC_SEL_BAT_MODULE
	else if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_PWRM) //电源模块规约
	{	
		pwrm_Recv((pwdmodlue_def *)g_tRsComm[chnl].ptBuf,cDat);
	}
	#endif
#endif
}


#ifdef FUN_FUXI_ESAM
void commtask_recv(u8 chnl)
{
	int ret=0,i=0;
	BYTE buf[256];
	
	s1_process();
	ret = read_chip_s1(buf,256);
	if(ret > 0) /*收到报文收据*/	
	{		
		//rt_printf("s1_tclrecv:::");
		for(i=0;i<ret;i++)
		{
			if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_104) //104规约
			{
				//rt_printf("[%02x] ",buf[i]);				
				IEC104_Recv_Int((IEC104_DEF *)g_tRsComm[chnl].ptBuf,buf[i]);								
			}
			else  if(tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_101
					||tRunPara.tUartPara[chnl].wProtocol==PROTOCOL_101_PH
			   )
			{
				IEC101_Recv_Int((IEC101_DEF *)g_tRsComm[chnl].ptBuf,buf[i]);
			}			
			
		}	
		
		//rt_printf("\r\n");
	}
}
#endif


/**************************************************************************
函数名称：IEC_485_Task
函数版本：1.00 
作者：   
创建日期：2008.9.1     
函数功能说明：RS485接受处理任务
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/

void IECCommTask(void)
{
	int i,equNum;
	int commErrTab[CFG_UART_NUM_MAX];
	//int equErrTab[]={true};
	// 串口规约处理

	g_bCommStatus=FALSE;
	
	for(i=0;i<CFG_UART_NUM_MAX;i++)
	{
		// 如果串口不存在，跳过
		if(UART_CHANNEL[i]< 0 )
		{
			continue;
		}
	#ifdef FUN_FUXI_ESAM
		else if(UART_CHANNEL[i] == CFG_UART_CHIP_S1)
		{
			commtask_recv(i);
		}
	#endif
				
		commErrTab[i] = true;//初始化通信端口状态为异常
		//外部通信报文处理
		if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_101
			||tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_PH
			||tRunPara.tUartPara[i].wProtocol == PROTOCOL_MAINTAIN
		#ifdef FUNC_ENCRY_IN_ONE_SERIAL
			||tRunPara.tUartPara[i].wProtocol == PROTOCOL_WED_ENC
		#endif
			)  // 101规约
		{
			IEC101_DEF *pt;
			IEC101_Applay((IEC101_DEF *)g_tRsComm[i].ptBuf);
			IEC101_AutoTimer((IEC101_DEF *)g_tRsComm[i].ptBuf); //101 规约定时处理
			pt = (IEC101_DEF *)g_tRsComm[i].ptBuf;
			if(pt->st101 == IEC101_ST_DATA)
			{
				commErrTab[i] = false;
				g_bCommStatus=true;
			}
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_M||tRunPara.tUartPara[i].wProtocol==PROTOCOL_101_PH_M)  // 串口级联规约
		{
			IECLINK_DEF *pt;
			pt = (IECLINK_DEF *)g_tRsComm[i].ptBuf;
			lnk_101_app((IECLINK_DEF *)g_tRsComm[i].ptBuf);
			//equNum = pt->slave_current;//按级联地址不同开始计数开始算级联个数 MAX=CFG_LINK_101_NUM
			equNum = pt->slave_addr;//按级联地址开始算级联个数               MAX=32
			commErrTab[i] = false;//不监视装置状态的时候，通道默认为正常
			if(equNum && equNum<=pt->slave_num)
			{
				if(tRunPara.dLinkStateCh==i)//监测该通道级联装置信息
				{
					if(equNum<=CFG_LINK_EQU_SOE_NUM && soe_check(EV_LINK_EQU1+equNum-1) != (!pt->tlnk.bLinkOK))
						soe_record_ev(EV_LINK_EQU1+equNum-1, (!pt->tlnk.bLinkOK), 0,0,0 ); //级联装置状态
					//rt_printf("slave_current = %d slave_addr=%d slave_num=%d\r\n",pt->slave_current,pt->slave_addr,pt->slave_num);
					
					for(equNum=0;(equNum<pt->slave_num&&equNum<=CFG_LINK_EQU_SOE_NUM);equNum++)
					{
						if(soe_check(EV_LINK_EQU1+equNum))//当前有一装置异常
						{
							commErrTab[i] = true;//该通信端口异常
							break;
						}
					}
				}
				//else //if(soe_check(EV_LINK_EQU1+equNum))//当前有一装置异常
				{
					//commErrTab[i] = true;//该通信端口异常
					//break;
				}								
			}
			
		}	
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_104)  // 104规约
		{
			IEC104_DEF *pt104;
			IEC104_App((IEC104_DEF *)g_tRsComm[i].ptBuf);	
			pt104 = (IEC104_DEF *)g_tRsComm[i].ptBuf;
			if(pt104->state == IEC104_ST_STARTED)
			{
				commErrTab[i] = false;
			}
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_HMI)  // 面板规约
		{
			Uart_Comm_Recv();
			HMI_Comm_App();		
			PDA_app();
		#ifdef FUN_GPRS	// modfiy for xxxxxx 20220706 GPRS没有使用。	
			gprs_comm_app();
		#endif	
			//发送面板,PDA等数据
			Uart_Comm_Send();

			if(hmi_status)
				commErrTab[i] =false;
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_FAULT)  // 状态版
		{
			FaultComm_Applay((IEC101_DEF *)g_tRsComm[i].ptBuf);		
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_SXYB) //数显仪表
		{
			sxyb_App();	
		}
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_MODBUS)  // modbus主站规约
		{
			modbus_Applay((MODBUS_DEF *)g_tRsComm[i].ptBuf);	
			modbus_AutoTimer((MODBUS_DEF *)g_tRsComm[i].ptBuf);
		}
#if defined(ADD_ATGM366_GPS_FUN) || defined(DEV_GPS_ATGM366) || defined(DEV_GPS_ATGM332D)
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_GPS)  // GPS模块
		{
			GPS_Comm_App((GPS_COMM *)g_tRsComm[i].ptBuf);
		}
#endif
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_AUTHOR_BL)  // 蓝牙模块
		{
			bluetooth_app((BLUETOOTH_DEF *)g_tRsComm[i].ptBuf);
			bluetooth_timer((BLUETOOTH_DEF *)g_tRsComm[i].ptBuf);
		}
	#ifdef BATTERY_WITH_COMM
		else if(tRunPara.tUartPara[i].wProtocol == PROTOCOL_POWER_MOD)
		{
			PowerModuleCommRun((COMM_POW_MOD*)g_tRsComm[i].ptBuf);
		}
		#ifdef FUNC_SEL_BAT_MODULE	
		else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_PWRM)	// 电源模块规约
		{
			pwrm_recv_proc((pwdmodlue_def *)g_tRsComm[i].ptBuf);
			pwrm_send_entry((pwdmodlue_def *)g_tRsComm[i].ptBuf);
		}
		#endif
	#endif
		else //if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_NULL)
		{
			commErrTab[i] =false;
			//continue;
		}
		if(soe_check(EV_COMM1_ERR+i) != commErrTab[i])
		{
			soe_record_ev(EV_COMM1_ERR+i, commErrTab[i], 0,0,0 ); //记录该端口通信状态
		}

	}

	// 以太网级联从设备
	for(i=0;i<CFG_LINK_104_NUM;i++)
	{
		if(tRunPara.ip104Link[i])
		{
			//if(tRunPara.dLinkStateCh==8)//监测该通道级联装置信息
			{
				if(!net_104link_is_connect(i))
				{
					if(soe_check(EV_LINK_EQU1+i) != 1)
					{
						//rt_printf("级联装置状态改变产生异常SOE,断开连接\n\r");
						soe_record_ev(EV_LINK_EQU1+i,1,0,0,0 ); //级联装置状态
					}
				}
				else if (net_104link_is_connect(i) && g_link_104[i].bData)
				{
					if(soe_check(EV_LINK_EQU1+i) != 0)
					{
						//rt_printf("级联装置状态改变产生恢复SOE,建立连接\n\r");
						soe_record_ev(EV_LINK_EQU1+i,0,0,0,0 ); //级联装置状态
					}
				}
			}
			lnk_104_app(i);
		}
	}
	
}
u8 get_is_invert(u16 no)
{
	int i;
	for(i=0;i<g_table_head->di_num;i++)
	{
		if(g_di_table[i].cp == no) 
			return g_di_table[i].is_inverse;
	}
	return 0;
}
#ifdef IECTABLE_NEWDPI_V106

u8 get_is_dpi(u16 no)
{
	int i;
	for(i=0;i<g_table_head->di_num;i++)
	{
		if(g_di_table[i].cp == no) 
			return g_di_table[i].dpi;
	}
	return 0;
}
#endif

#ifdef SOE_RELINK_DISCOS
bool is_resume_soe(u8 ch)
{
	if(g_soe_queue.bSoeRelink[ch])	/*发生续传中*/
	{
		if(g_soe_queue.tail_send[ch].n != g_soe_queue.relink_tail_bak[ch].n)
		{
			rt_printf("------通讯续传中tail_send:%d,bak:%d\r\n",g_soe_queue.tail_send[ch].n,g_soe_queue.relink_tail_bak[ch].n);
			return true;
		}
		else
		{			
			rt_printf("------通讯续传结束\r\n");
			g_soe_queue.bSoeRelink[ch]=false;	/*续传结束*/					
		}	
	}

	return false;
}
#endif


int asdu_get_event(u8 ch,u16 head,u8* pcos,u8 *psoe,u8* pcos1,u8 *psoe1,u16*psoe_sno,u16*psoe_dno,	int baddr3,bool *bf,EVENT_STRUCT *ev,u16 *extarg,u8 *yxtype,u8 *pcosnum,u8 *pcosnum1)
{
	bool b_siq=false;
	int soe_no=0,cnt_s=0,cnt_d=0,cnt_evp=0;
	u8 SIQ,week;
	u8 soe_type;
	u16 no,index=0;
	EVENT_STRUCT event;
	struct rtc_time_t rt;
	u8 isInverse=0;
	u8 ditype=0;
	*pcosnum = 0;
	*pcosnum1 = 0;
	
	while(g_soe_queue.tail_send[ch].n != head)	// 有SOE产生
	{
#ifdef SOE_RELINK_DISCOS
		bool bresuming = false;		
		bresuming = is_resume_soe(ch);
#endif
		
		// 得到一个事件
		index=g_soe_queue.tail_send[ch].n;
		soe_no = soe_get(ch,&event);
		
		if(soe_no < 0)
		{
			rt_printf_time("soe_get(%d):ret=%d.\r\n",ch,soe_no);
			break;
		}
		
		// 得到检查通讯点号，如果为0，则此事件不需要发送
		// 此处会滤除不需发送的事件的，例如操作事件。
		no = soe_lp2cp(event.ev_type,event.ev_code,event.ev_arg[1]);
		if(no == 0)
		{
			continue;
		}

	#ifdef IEC_JXYB_DEAL
		if(g_run_stu.bjx)
		{
			u8 yx_slot=(u8)(event.ev_code>>8);	//板卡号
			u8 yx_no=(u8)(event.ev_code);		//遥信号
			u8 yx_type = equ_pub_di_type(yx_slot,yx_no);

			{
				if(yx_type>0)
				{
					yx_type-=1;
					
					if(yx_type != PUB_DI_JX)
					{
						continue;
					}
				}
				else
				{
					continue;
				}
			}			
		}
	#endif
		
#ifdef IECTABLE_NEWDPI_V106
	{
		int k;
		u8 owner=0;
		isInverse = get_is_invert(no);
		ditype=get_is_dpi(no);
		// 整理好SIQ,单双点需要转换
		soe_type = event.ev_type&SOE_TYPE_MASK;
		SIQ = event.ev_value;

		for(k=0;k<g_table_head->di_num;k++)
		{
			if(g_di_table[k].cp == no)
			{
				owner =  g_di_table[k].owner;
				break;
			}
		}


		if(tRunPara.bSDPI)
		{			
			if(soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK)
			{
				if(ditype==0)  // 单点上送
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息
				}
			}
			else
			{
				if(ditype==1)  //双点上送
				{
					SIQ +=1;//转为双点点信息
				}
			}
		}
		else
		{
			ditype=tRunPara.bDPI?1:0;
			if(ditype==1) // 双点上送
			{
				if(soe_type!= SOE_TYPE_DPI && soe_type!= SOE_TYPE_LNK)
				{
					SIQ +=1;//转为双点点信息
				}
			}
			else
			{
				if(soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK)
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息
				}
			}
		}
		if(isInverse)
		{
			if(ditype==1)  //双点取反
			{
				if(SIQ == 2)
				{
					SIQ = 1;
				}
				else if(SIQ == 1)
				{
					SIQ = 2;
				}
			}
			else  // 单点取反
			{
				SIQ = (SIQ == 0)?1:0;
			}
		}	
	}
#else
	{
		u8 owner=0;
		int j,k,id1,id2;
		bool db_special = 0;//特殊双点
		static u8 bh_fa_keep[SWITCH_NUM_EXT] = {0};

		for(k=0;k<g_table_head->di_num;k++)
		{
			if(g_di_table[k].cp == no)
			{
				owner =  g_di_table[k].owner;
				break;
			}
		}

		for(j=0;j<g_table_head->di_db_num;j++)	
		{
			db_special = false;
			if(no == g_di_db_table[j].cp)  
			{
				id1 = g_di_db_table[j].no[0]&0xff;
				id2 = g_di_db_table[j].no[1]&0xff;
				
				if(((id1 == (SW_DI_BHTT+1))&&(id2 == (SW_DI_FA_TT+1)))
					||((id2 == (SW_DI_BHTT+1))&&(id1 == (SW_DI_FA_TT+1))))
				{
					//rt_printf("%s:cp=0x%04x,id1=0x%04x,id2=0x%04x\r\n",__func__,g_di_db_table[j].cp,g_di_db_table[j].no[0],g_di_db_table[j].no[1]);	
					db_special = true;
					break;
				}					
			}
		}
		isInverse = get_is_invert(no);
		// 整理好SIQ,单双点需要转换
		soe_type = event.ev_type&SOE_TYPE_MASK;
		SIQ = event.ev_value;
		//级联上送的SOE带品质描述
		if(SIQ&0x80)
		{
		#ifdef IEC_QDS_HAVE
				b_siq=true;
				SIQ=(SIQ&0x7f);
		#endif
			
		}

		if(db_special)
		{
			if(g_sw[owner].di[SW_DI_BHTT] == 1 && g_sw[owner].di[SW_DI_FA_TT] == 1)
				SIQ = bh_fa_keep[owner];
			else
			{
				if(g_sw[owner].di[SW_DI_FA_TT] == 2)
					SIQ = 1;
				else if(g_sw[owner].di[SW_DI_BHTT] == 2)
					SIQ = 0;
				bh_fa_keep[owner] = SIQ;
			}
			if(SIQ==0)
			{
				SIQ = 1;
			}
			else
			{
				SIQ = 2;
			}
		}
		
		//rt_printf("%s(2):soe_type=%d,SIQ=0x%02x,owner=%d,no=0x%04x,indexno=%d,isInverse=%d\r\n",__func__,soe_type,SIQ,owner,no,g_di_table[k].indexno,isInverse);
	
		if(tRunPara.bSDPI)
		{
			ditype=(soe_type == SOE_TYPE_DPI)?1:0;

			if(soe_type == SOE_TYPE_LNK)
			{
				if(SWITCH_NUM_EXT == owner) 	//将默认开关31当成级联双点
				{
					ditype = 1;   
					
				}
				else
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息

					if(isInverse)
					{
						SIQ = (SIQ == 0)?1:0;
					}
				}
			}
			else
			{
	
				if(soe_type != SOE_TYPE_DPI)
				{
					if(isInverse)
					{
						SIQ = (SIQ == 0)?1:0;
					}
				}
				else
				{
					
					if(isInverse)
					{
						if(SIQ == 2)
						{
							SIQ = 1;
						}
						else if(SIQ == 1)
						{
							SIQ = 2;
						}
					}
				}
				
			}

		
			/*
			if((soe_type == SOE_TYPE_DPI)&&(isInverse))
			{
				SIQ =((~SIQ)&0x03);
			}
			*/
			
		}
		else
		{
			if(tRunPara.bDPI)
			{
				if(soe_type != SOE_TYPE_DPI && soe_type != SOE_TYPE_LNK)
				{
					SIQ+=1; //转为双点信息
				}

				if(isInverse)
				{
					if(SIQ == 2)
					{
						SIQ = 1;
					}
					else if(SIQ == 1)
					{
						SIQ = 2;
					}
		
				}

			}
			else
			{
				if(soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK)
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息
				}

				if(soe_type != SOE_TYPE_PLC)
				{
					if(isInverse)
					{
						SIQ = (SIQ == 0)?1:0;
					}
				}

			}
			ditype=tRunPara.bDPI?1:0;
		}
	}

#endif
		*yxtype=ditype;
		if(g_run_stu.bToolRmtTest||g_run_stu.bHmiRmtTest)	//测试模式，遥信置为无效
		{
			if(pRunSet->bTT_RmtTest)SIQ|=0x80;
		}	

	#if !defined IEC_JXYB_DEAL && !defined FUNC_JX_YC_SIQ00
		if(g_run_stu.bjx||b_siq)
			SIQ|=0x80;
	#endif

		//单点
		if(*yxtype==0)
		{
			//COS
			
	#ifdef SOE_RELINK_DISCOS
			if(!bresuming)
	#endif	
			{
				*pcos++=(u8)no;		//信息体地址L
				*pcos++=(u8)(no>>8);	//信息体地址H
				if(baddr3)
				{
					*pcos++=0;			//信息体地址H2
				}
				*pcos++=SIQ;			//遥信			
				*pcosnum += 1;
			}
				
			 //SOE
			timespec_to_rtc(event.ts,&rt,1);
			week = WEEK_DAY(event.ts.tv_sec); 
			
			*psoe++=(u8)no;		// 信息体地址L
			*psoe++=(u8)(no>>8);	// 信息体地址H
			if(baddr3)
			{
				*psoe++=0;			// 信息体地址H2
			}
			*psoe++=SIQ;			// 遥信
			*psoe++=(u8)rt.ms;
			*psoe++=(u8)(rt.ms>>8);
			*psoe++=(u8)rt.min;
			*psoe++=(u8)rt.hour;
			*psoe++=((week<<5) | rt.day);
			*psoe++=(u8)rt.month;
			*psoe++=(u8)rt.year;	

			cnt_s++;
			*psoe_sno = soe_no;

		}
		else
		{
	#ifdef SOE_RELINK_DISCOS
			if(!bresuming)	
	#endif
			{			
				*pcos1++=(u8)no; 	//信息体地址L
				*pcos1++=(u8)(no>>8);	//信息体地址H
				if(baddr3)
				{
					*pcos1++=0;			//信息体地址H2
				}
				*pcos1++=SIQ;			//遥信		
				*pcosnum1 +=1;
			}
			
			 //SOE
			timespec_to_rtc(event.ts,&rt,1);
			week = WEEK_DAY(event.ts.tv_sec); 
			
			*psoe1++=(u8)no; 	// 信息体地址L
			*psoe1++=(u8)(no>>8);	// 信息体地址H
			if(baddr3)
			{
				*psoe1++=0;			// 信息体地址H2
			}
			*psoe1++=SIQ;			// 遥信
			*psoe1++=(u8)rt.ms;
			*psoe1++=(u8)(rt.ms>>8);
			*psoe1++=(u8)rt.min;
			*psoe1++=(u8)rt.hour;
			*psoe1++=((week<<5) | rt.day);
			*psoe1++=(u8)rt.month;
			*psoe1++=(u8)rt.year;	
			
			cnt_d++;		
			*psoe_dno = soe_no;
		}

		 
		if(event.ev_type&SOE_TYPE_FAULT)  // 该事件需上送故障信息
		{
			if(ev!=NULL)
			{
				*ev++=event;				
				*extarg++=index;	
				
				cnt_evp++;
			}
			//*bf=(num_p>0)&&tRunPara.bEvPara;
		}
		if(cnt_s>=MAX_SOE_PER_FRAME)
		{
			break;
		}

		if(cnt_d>=MAX_SOE_PER_FRAME)
		{
			break;
		}
		
		//if(tRunPara.bSDPI)break;  // 单双点配置，SOE逐条上送
	}

	

	return (cnt_s+(cnt_d<<8)+(cnt_evp<<16));
}




int asdu_get_event_104(u8 ch,u16 head,u8* pcos,u8 *psoe,u16 *psoe_no,int baddr3,bool *bf,EVENT_STRUCT *ev,u16 *extarg,u8 *yxtype)
{
	bool b_siq=false;
	int soe_no=0,cnt=0;
	u8 SIQ,week;
	u8 soe_type;
	u16 no,index=0;
	EVENT_STRUCT event;
	struct rtc_time_t rt;
	u8 isInverse=0;
	u8 ditype=0;	
	while(g_soe_queue.tail_send[ch].n != head)  // 有SOE产生
	{
		// 得到一个事件
		index=g_soe_queue.tail_send[ch].n;
		soe_no = soe_get(ch,&event);
		if(soe_no < 0)
		{
			rt_printf_time("soe_get(%d):ret=%d.\r\n",ch,soe_no);
			break;
		}
		
		// 得到检查通讯点号，如果为0，则此事件不需要发送
		// 此处会滤除不需发送的事件的，例如操作事件。
		no = soe_lp2cp(event.ev_type,event.ev_code,event.ev_arg[1]);
		if(no == 0)
		{
			continue;

		}

	#ifdef IEC_JXYB_DEAL

		if(g_run_stu.bjx)
		{
			u8 yx_slot=(u8)(event.ev_code>>8);	//板卡号
			u8 yx_no=(u8)(event.ev_code);		//遥信号
			u8 yx_type = equ_pub_di_type(yx_slot,yx_no);

			{
				if(yx_type>0)
				{
					yx_type-=1;
					
					if(yx_type != PUB_DI_JX)
					{
						continue;
					}
				}
				else
				{
					continue;
				}
			}			
		}
		
	#endif

		
#ifdef IECTABLE_NEWDPI_V106
{
		int k;
		u8 owner=0;
		isInverse = get_is_invert(no);
		ditype=get_is_dpi(no);
		// 整理好SIQ,单双点需要转换
		soe_type = event.ev_type&SOE_TYPE_MASK;
		SIQ = event.ev_value;

		for(k=0;k<g_table_head->di_num;k++)
		{
			if(g_di_table[k].cp == no)
			{
				owner =  g_di_table[k].owner;
				break;
			}
		}


		if(tRunPara.bSDPI)
		{			
			if(soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK)
			{
				if(ditype==0)  // 单点上送
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息
				}
			}
			else
			{
				if(ditype==1)  //双点上送
				{
					SIQ +=1;//转为双点点信息
				}
			}
		}
		else
		{
			ditype=tRunPara.bDPI?1:0;
			if(ditype==1) // 双点上送
			{
				if(soe_type!= SOE_TYPE_DPI && soe_type!= SOE_TYPE_LNK)
				{
					SIQ +=1;//转为双点点信息
				}
			}
			else
			{
				if(soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK)
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息
				}
			}
		}
		if(isInverse)
		{
			if(ditype==1)  //双点取反
			{
				if(SIQ == 2)
				{
					SIQ = 1;
				}
				else if(SIQ == 1)
				{
					SIQ = 2;
				}
			}
			else  // 单点取反
			{
				SIQ = (SIQ == 0)?1:0;
			}
		}	
	}
#else
	{
		u8 owner=0;
		int j,k,id1,id2;
		bool db_special = 0;//特殊双点
		static u8 bh_fa_keep[SWITCH_NUM_EXT] = {0};

		for(k=0;k<g_table_head->di_num;k++)
		{
			if(g_di_table[k].cp == no)
			{
				owner =  g_di_table[k].owner;
				break;
			}
		}

		for(j=0;j<g_table_head->di_db_num;j++)  
		{
			db_special = false;
			if(no == g_di_db_table[j].cp)  
			{
				id1 = g_di_db_table[j].no[0]&0xff;
				id2 = g_di_db_table[j].no[1]&0xff;
				
				if(((id1 == (SW_DI_BHTT+1))&&(id2 == (SW_DI_FA_TT+1)))
					||((id2 == (SW_DI_BHTT+1))&&(id1 == (SW_DI_FA_TT+1))))
				{
					//rt_printf("%s:cp=0x%04x,id1=0x%04x,id2=0x%04x\r\n",__func__,g_di_db_table[j].cp,g_di_db_table[j].no[0],g_di_db_table[j].no[1]);	
					db_special = true;
					break;
				}					
			}
		}
		isInverse = get_is_invert(no);
		// 整理好SIQ,单双点需要转换
		soe_type = event.ev_type&SOE_TYPE_MASK;
		SIQ = event.ev_value;
		//级联上送的SOE带品质描述
		if(SIQ&0x80)
		{
			#ifdef IEC_QDS_HAVE
				b_siq=true;
				SIQ=(SIQ&0x7f);
			#endif
			
		}

		if(db_special)
		{
			if(g_sw[owner].di[SW_DI_BHTT] == 1 && g_sw[owner].di[SW_DI_FA_TT] == 1)
				SIQ = bh_fa_keep[owner];
			else
			{
				if(g_sw[owner].di[SW_DI_FA_TT] == 2)
					SIQ = 1;
				else if(g_sw[owner].di[SW_DI_BHTT] == 2)
					SIQ = 0;
				bh_fa_keep[owner] = SIQ;
			}
			if(SIQ==0)
			{
				SIQ = 1;
			}
			else
			{
				SIQ = 2;
			}
		}
		
		//rt_printf("%s(2):soe_type=%d,SIQ=0x%02x,owner=%d,no=0x%04x,indexno=%d,isInverse=%d\r\n",__func__,soe_type,SIQ,owner,no,g_di_table[k].indexno,isInverse);
	
		if(tRunPara.bSDPI)
		{
			ditype=(soe_type == SOE_TYPE_DPI)?1:0;

			if(soe_type == SOE_TYPE_LNK)
			{
				if(SWITCH_NUM_EXT == owner)		//将默认开关31当成级联双点
				{
					ditype = 1;   
					
				}
				else
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息

					if(isInverse)
					{
						SIQ = (SIQ == 0)?1:0;
					}
				}
			}
			else
			{
	
				if(soe_type != SOE_TYPE_DPI)
				{
					if(isInverse)
					{
						SIQ = (SIQ == 0)?1:0;
					}
				}
				else
				{
					
					if(isInverse)
					{
						if(SIQ == 2)
						{
							SIQ = 1;
						}
						else if(SIQ == 1)
						{
							SIQ = 2;
						}
					}
				}
				
			}

		
			/*
			if((soe_type == SOE_TYPE_DPI)&&(isInverse))
			{
				SIQ =((~SIQ)&0x03);
			}
			*/
			
		}
		else
		{
			if(tRunPara.bDPI)
			{
				if(soe_type != SOE_TYPE_DPI && soe_type != SOE_TYPE_LNK)
				{
					SIQ+=1;	//转为双点信息
				}

				if(isInverse)
				{
					if(SIQ == 2)
					{
						SIQ = 1;
					}
					else if(SIQ == 1)
					{
						SIQ = 2;
					}
		
				}

			}
			else
			{
				if(soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK)
				{
					SIQ = (SIQ == SW_DI_TYPE_ON);//转为单点信息
				}

				if(soe_type != SOE_TYPE_PLC)
				{
					if(isInverse)
					{
						SIQ = (SIQ == 0)?1:0;
					}
				}

			}
			ditype=tRunPara.bDPI?1:0;
		}
	}

#endif
		*yxtype=ditype;
		if(g_run_stu.bToolRmtTest||g_run_stu.bHmiRmtTest)	//测试模式，遥信置为无效
		{
			if(pRunSet->bTT_RmtTest)SIQ|=0x80;
		}	

	#if !defined IEC_JXYB_DEAL && !defined FUNC_JX_YC_SIQ00
		if(g_run_stu.bjx||b_siq)
			SIQ|=0x80;
	#endif

		

		//COS
		*pcos++=(u8)no;		//信息体地址L
		*pcos++=(u8)(no>>8);	//信息体地址H
		if(baddr3)
		{
			*pcos++=0;			//信息体地址H2
		}
		*pcos++=SIQ;			//遥信

		 //SOE
		timespec_to_rtc(event.ts,&rt,1);
		week = WEEK_DAY(event.ts.tv_sec); 
		
		*psoe++=(u8)no;		// 信息体地址L
		*psoe++=(u8)(no>>8);	// 信息体地址H
		if(baddr3)
		{
			*psoe++=0;			// 信息体地址H2
		}
		*psoe++=SIQ;			// 遥信
		*psoe++=(u8)rt.ms;
		*psoe++=(u8)(rt.ms>>8);
		*psoe++=(u8)rt.min;
		*psoe++=(u8)rt.hour;
		*psoe++=((week<<5) | rt.day);
		*psoe++=(u8)rt.month;
		*psoe++=(u8)rt.year;	

		cnt++; 
		if(event.ev_type&SOE_TYPE_FAULT)  // 该事件需上送故障信息
		{
			if(ev!=NULL)
			{
				*ev=event;
				*bf=true&&tRunPara.bEvPara;
				*extarg=index;
				break;
			}			
		}
		if(cnt>=MAX_SOE_PER_FRAME)
		{
			break;
		}
		
		if(tRunPara.bSDPI)break;  // 单双点配置，SOE逐条上送
	}
	*psoe_no = soe_no;

	return cnt;
}

 
int asdu_get_event_yc(BYTE *dat,int baddr3,u16 arg_index)
{
	int evsw;
	int i,j;
	BYTE indexno;
	BYTE ycnum=0;
	EVENT_EXT_ARG *pArg;
	pArg=&g_soe_queue.tExtArg[arg_index];  //附加参数

	for(i=0;i<EXT_ARG_NUMBER;i++)
	{
		 if(pArg->type[i]==SW_AC_IA
			||pArg->type[i]==SW_AC_IB
			||pArg->type[i]==SW_AC_IC
			||pArg->type[i]==SW_AC_I0)
		{
			evsw=pArg->sw+1;
		}
		else
		{
			evsw=0;
		}
		indexno=(pArg->type[i]&0x7f)+1;

		for(j=0;j<g_table_head->ac_num;j++)
		{
			u8 no=g_ac_table[j].indexno;
			if(g_ac_table[j].owner==evsw&&no==indexno) // soe参数在转发表中有配置获取点号 
			{
				WORD di=g_ac_table[j].cp;
				union{

					float ff;
					u8 tt[4];
				}ff;
				if(pRunSet->bTT_EV_YCRate)
				{
					ff.ff=(float)pArg->arg[i]/65536*((float)g_ac_table[j].rate/65536.0);
				}
				else
				{
					ff.ff=(float)pArg->arg[i]/65536;
				}
				*dat++=(BYTE)di;
				*dat++=(BYTE)(di>>8);
				if(baddr3)*dat++=0;

				dat += CopySwap(dat,ff.tt,sizeof(ff.tt),true);
				ycnum++;
			}
		}
	}
	return ycnum;

}
 
#ifdef CPU_AM335X

void uart_isr(void)  /* 串口处理*/
{
	int ret = 0;
	int i = 0;
	//static unsigned char buf[256];
	unsigned char buf[10]; //sunxi for test

	int ch = 0;
	volatile SERIAL_COMM *prc;


	for(ch=0;ch<CFG_UART_NUM_MAX;ch++)
	{

		if( UART_CHANNEL[ch] < 0
			|| UART_CHANNEL[ch] == g_con_uart_index 
			|| tRunPara.tUartPara[ch].wProtocol == PROTOCOL_IDLE)
		{
			continue;
		}

		//如果是使用内部GPRS，则不用再走下面的代码流程
		if(UART_CHANNEL[ch]==CFG_UART_GPRS_IN )
		{
			continue;	
		}

#ifdef FUN_FUXI_ESAM
		else if(UART_CHANNEL[ch]==CFG_UART_CHIP_S1 )
		{
			continue;	
		}
#endif

		//面板做特殊处理
		if(tRunPara.tUartPara[ch].wProtocol==PROTOCOL_HMI)
		{
			//规约处理
			protocol_proc_task(ch);
			continue;	
		}

		prc=&g_tRsComm[ch];
		

	#if 1	
		//接收 start

		//ret = uart_select(UART_CHANNEL[ch]);
		//有数据可读
		if(1)
		{
			unsigned char c;
			int jj;
			//读取数据
			memset(buf,0,sizeof(buf));
			// sunxi 20221202 ret = uart_read(UART_CHANNEL[ch], buf, sizeof(buf));
			for(jj = 0; jj < 3; jj ++)
			{
				ret = uart_read(UART_CHANNEL[ch], &c, 1);
				if(ret > 0)
				{

					//处理101规约报文
					if(g_IEC_Recv)
					{
						for(i=0; i<ret ;i++)
						{

						#ifdef FLOW_CALC_FUNC
							if(ch == tRunPara.flow_port)
							{
								g_sw_pub.ac_in[PUB_AC_IN_FLOW]+=Q16_BASE;
							}
						#endif
							g_IEC_Recv(c, ch);

						}

						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						{
							//rt_printf("ch_%d have rev len =%d ",ch,ret);
							for(i = 0; i < ret; i++)
							{
								rt_printf("%02x ", (unsigned char)c);
							}
							//rt_printf("\r\n");

						}		

						s_stat_rx(ch, ret);//接收字节数计数
						prc->us0_recv = ustimer_get_origin();//记录接收数据的时间戳

					}
				}
				else if(ret < 0)
				{
					//rt_printf("\nch_%d read err!\n",ch);
					s_stat_rx_err(ch, 1);//接收错误计数

					if( ustimer_get_duration(prc->us0_recv) > prc->us_recv_timeout)
					{
						prc->b_recv_reset = 1;
					}
				}
				else
				{
					if( ustimer_get_duration(prc->us0_recv) > prc->us_recv_timeout)
					{
						prc->b_recv_reset = 1;
					}
				}
			}
		}

//接收 end		
#endif

#if 1
		//发送 start
		if(prc->bextsend)
		{
			// 规约要求帧与帧之间间隔必须大于33位。
			if((prc->extsendcnt== 0 // 帧头
				)
				&& ((ustimer_get_duration(prc->us0_recv) < 5*USTIMER_MS) // 与接收帧之间的间隔
				||  (ustimer_get_duration(prc->us0_send) < 5*USTIMER_MS))) // 与发送帧之间的间隔
			{		
				continue;
			}
			if(prc->extsendlen > 0)
			{
				if(prc->extsendcnt < prc->extsendlen) 					// 发送没完成,继续发送
				{	
		
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf[prc->extsendcnt], 1);					
					if(ret > 0)
					{

						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						{
							if(prc->extsendcnt == 0)
							{
								rt_printf("\r\nTX[%d] len=%d:",ch,prc->extsendlen);
							}
						
							for(i=0; i<ret ;i++)
							{
								rt_printf("%02x ",prc->extsendbuf[prc->extsendcnt + i]);
							}
							if(prc->extsendcnt >= (prc->extsendlen - 1))
							{
								rt_printf("\r\n");
							}
						}
						
						s_stat_tx(ch, ret);//发送字节数计数				
						prc->extsendcnt += ret;
						
						if(prc->extsendcnt >= prc->extsendlen)
						{	
							prc->bextsend=false;
							prc->extsendcnt = 0;
							mainloop_wakeup();
							prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
						}


					}

				} 

			}
		}
		else if(prc->bSend) 		// 发送
		{
			// 规约要求帧与帧之间间隔必须大于33位。
			if(prc->nSendCnt <= 1 // 帧头
				&& ((ustimer_get_duration(prc->us0_recv) < 5*USTIMER_MS) // 与接收帧之间的间隔
				|| (ustimer_get_duration(prc->us0_send) < 5*USTIMER_MS))) // 与发送帧之间的间隔
			{	
				continue;
			}

			if(prc->sendbuf[0] > 0)
			{
				if(prc->nSendCnt <= prc->sendbuf[0])
				{				
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->sendbuf[prc->nSendCnt], 1);					
					if(ret > 0)
					{
						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						{
							if(prc->nSendCnt ==0)
							{
								rt_printf("\r\nTX[ch:%d len=%d]:",ch,prc->sendbuf[0]);
							}
							for(i=0; i<ret ;i++)
							{
								rt_printf("%02x ",prc->sendbuf[prc->nSendCnt + i]);
							}
							if(prc->nSendCnt > (prc->sendbuf[0] - 1))
							{
								rt_printf("\r\n");
							}
						}	
						s_stat_tx(ch, ret);//发送字节数计数
						
						if (uart_test_begin)
						{
							uart_test_flag[ch][0] = 1;
						}
						
						if(prc->nSendCnt > prc->sendbuf[0])
						{	
							prc->bSend=false;
							prc->nSendCnt = 0;
							RS_Recv_Enable(ch);
							if(tRunPara.tUartPara[ch].wProtocol==PROTOCOL_HMI)
							{
								Reset_Uart_Link((UART_COMM_STRUCT *)g_tRsComm[ch].ptBuf);
							}
							mainloop_wakeup();
							prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
						}
						prc->nSendCnt += ret;
				
					}
				
				}

			}

		}
//发送 end
#endif	

	}


}

#elif defined CPU_FUXI

static int uart_isr_thread(void *arg)
{
	int ret = 0;
	int i = 0;
	int send_fail_cnt = 0;
	int send_len = 0;
	static unsigned char buf[256];
#ifdef LINUX_USER_APP
	char thread_name[25];
#endif
	int ch = *((int *)arg);
	volatile SERIAL_COMM *prc;
	prc=&g_tRsComm[ch];
#ifdef RT_THREAD_DEBUG
	rt_printf("uart_isr_thread---%d\r\n", ch);
#endif

#ifdef CPU_FUXI
	 memset(thread_name,0,sizeof(thread_name));
	 sprintf(thread_name, "uart_isr_%d", ch);

	 prctl(PR_SET_NAME, thread_name);

	uint32_t wdt_id[20];
    int rc = watchdog_add_item(thread_name, &wdt_id[ch],120);
    if(rc != 0) {
        printf("can not add %s task to wdt\r\n",thread_name);
        return -1;
    }
#endif	
	 while(1)
	 {
	#ifdef CPU_FUXI
		 msleep(5);

		 watchdog_feed(wdt_id[ch]);
	#else
		msleep(1);//noted by sunxi: 20220706 面板切换太慢，5ms->1ms,以提高速度
	#endif
		 
		 //检查是否退出
		 if(main_mod_is_exit())
		 {
			 uart_close(UART_CHANNEL[ch]);

			 break;
		 }
 
		 if( UART_CHANNEL[ch] < 0
			 || UART_CHANNEL[ch] == g_con_uart_index
			 || tRunPara.tUartPara[ch].wProtocol == PROTOCOL_IDLE)
		 {
			 continue;
		 }
 
#if 0
		 // 如果GPS对时打开，必须关闭串口。
		 if(g_clock_mode_gps && chnl == CFG_UART_GPS)
		 {
			 continue;
		 }
#endif	
 
		 //如果是使用内部GPRS，则不用再走下面的代码流程
		 if(UART_CHANNEL[ch]==CFG_UART_GPRS_IN )
		 {
			 continue;	 
		 }
		 
#ifdef FUN_FUXI_ESAM
		else if(UART_CHANNEL[ch]==CFG_UART_CHIP_S1 )
		{
			continue;	
		}
#endif
 
 
		 //面板做特殊处理
		 if(tRunPara.tUartPara[ch].wProtocol==PROTOCOL_HMI)
		 {
			 //规约处理
			 protocol_proc_task(ch);
			 continue;	 
		 }
 
 /*
 //sunxi for test: 暂不支持
 
		 //如果是数显仪表
		 if(tRunPara.tUartPara[ch].wProtocol==PROTOCOL_SXYB)
		 {
			 //数显仪表处理
			 //sxyb_proc(chnl); 	 
			 continue;	 
		 }
 */
 
#if 1	
 //接收 start
 
		 ret = uart_select(UART_CHANNEL[ch]);
		 //有数据可读
		 if(ret > 0)
		 {
			 //rt_printf("\nch_%d have select.\n",ch);
		 
			 //读取数据
			 memset(buf,0,sizeof(buf));
			 ret = uart_read(UART_CHANNEL[ch], buf, sizeof(buf)); 		 
			 if(ret > 0)
			 {
 
				 //处理101规约报文
				 if(g_IEC_Recv)
				 {
			  	 //rt_printf("ch_%d have rev:\n",ch);
					 for(i=0; i<ret ;i++)
					 {
 
#ifdef FLOW_CALC_FUNC
						 if(ch == tRunPara.flow_port)
						 {
							 g_sw_pub.ac_in[PUB_AC_IN_FLOW]+=Q16_BASE;
						 }
#endif
						 g_IEC_Recv(buf[i], ch);
 
						 if(g_print_comm_raw && (g_print_port & (1<<ch)))
						 {
							 if(UART_CHANNEL[ch] == CFG_UART_232_0)
							 {
								 rt_printf("%c",buf[i]);
							 }
							 else
							 {
								 rt_printf("%02x ",buf[i]);
							 }
						 }
						 
					 }
			  	 //rt_printf("\n");
					 
					 s_stat_rx(ch, ret);//接收字节数计数
					 prc->us0_recv = ustimer_get_origin();//记录接收数据的时间戳	 
					 
				 }
 
#if 0
				 //测试代码
				 rt_printf("\nch_%d RECV num=%d frame:",ch,ret);
				 for(i = 0; i < ret; i++)
				 {
					 rt_printf("%02x ", (unsigned char)buf[i]);  
				 }		 
				 rt_printf("\n");
 
				 uart_write(ch, (const char *)buf, ret);//sunxi for test
#endif	 
 
			 }
			 else if(ret < 0)
			 {
				 //rt_printf("\nch_%d read err!\n",ch);
				 s_stat_rx_err(ch, 1);//接收错误计数
			 }
	 
		 }
		 else
		 {
			 msleep(5);
 
			 if(ret < 0)
			 {
				 //rt_printf("\nch_%d select err!\n",ch);
				 s_stat_rx_err(ch, 1);//接收错误计数
			 }
			 
			 if( ustimer_get_duration(prc->us0_recv) > prc->us_recv_timeout) 
			 {
				 prc->b_recv_reset = 1;
			 }
 
		 }
 
 //接收 end		 
#endif

#if 1
		//发送 start

		if(prc->bextsend
#ifdef FUNC_ENCRY_IN_ONE_SERIAL
			|| prc->bextsend_1
			|| prc->bextsend_2
			|| prc->bextsend_3
#endif
		)
		{
			// 规约要求帧与帧之间间隔必须大于33位。
			if((prc->extsendcnt== 0 // 帧头
#ifdef FUNC_ENCRY_IN_ONE_SERIAL
				|| prc->extsendcnt_1 == 0
				|| prc->extsendcnt_2 == 0
				|| prc->extsendcnt_3 == 0
#endif	
				)
				&& ((ustimer_get_duration(prc->us0_recv) < 5*USTIMER_MS) // 与接收帧之间的间隔
				||  (ustimer_get_duration(prc->us0_send) < 5*USTIMER_MS))) // 与发送帧之间的间隔
			{				 
				continue;
			}

			if(prc->extsendlen > 0)
			{
				send_fail_cnt = 0;
				send_len = 0;
				while(send_len<prc->extsendlen) 					// 发送没完成,继续发送
				{	
					if(g_print_comm_raw && (g_print_port & (1<<ch)))
					{
						rt_printf("\r\nTX[%d]:",ch);
					}				
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf[prc->extsendcnt + send_len], (prc->extsendlen - send_len));					
					if(ret > 0)
					{
						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						
						{
							for(i=0; i<ret ;i++)
							{
								rt_printf("%02x ",prc->extsendbuf[prc->extsendcnt + send_len + i]);
							}

						}
						send_len += ret;

						s_stat_tx(ch, ret);//发送字节数计数

					}
					else if(send_fail_cnt++ > 5)
					{
						send_fail_cnt = 0;
				//		rt_printf("\nch_%d send fail!!!\n",ch);
						break;
					}

				} 
				if(g_print_comm_raw && (g_print_port & (1<<ch)))
				{
						rt_printf("\r\n");
				}
				{	
					prc->bextsend=false;
					prc->extsendcnt = 0;
					mainloop_wakeup();
					prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
				}
			}
#ifdef FUNC_ENCRY_IN_ONE_SERIAL

			else if(prc->extsendlen_1 > 0)
			{
				send_fail_cnt = 0;
				send_len = 0;
				while(send_len<prc->extsendlen_1) 					// 发送没完成,继续发送
				{	
					if(g_print_comm_raw && (g_print_port & (1<<ch)))
					{
						rt_printf("\r\nTX[%d]:",ch);
					}				
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf_1[prc->extsendcnt_1 + send_len], (prc->extsendlen_1 - send_len));					
					if(ret > 0)
					{
						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						
						{
							for(i=0; i<ret ;i++)
							{
								rt_printf("%02x ",prc->extsendbuf_1[prc->extsendcnt_1 + send_len + i]);
							}
			
						}
						send_len += ret;
			
						s_stat_tx(ch, ret);//发送字节数计数
			
					}
					else if(send_fail_cnt++ > 5)
					{
						send_fail_cnt = 0;
				//		rt_printf("\nch_%d send fail!!!\n",ch);
						break;
					}
			
				} 

				if(g_print_comm_raw && (g_print_port & (1<<ch)))
				{
						rt_printf("\r\n");
				}
				{	
					prc->bextsend_1=false;
					prc->extsendcnt_1 = 0;
					mainloop_wakeup();
					prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
				}				
			}

			else if(prc->extsendlen_2 > 0)
			{
				send_fail_cnt = 0;
				send_len = 0;
				while(send_len<prc->extsendlen_2)					// 发送没完成,继续发送
				{	
					if(g_print_comm_raw && (g_print_port & (1<<ch)))
					{
						rt_printf("\r\nTX[%d]:",ch);
					}				
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf_2[prc->extsendcnt_2 + send_len], (prc->extsendlen_2 - send_len)); 				
					if(ret > 0)
					{
						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						
						{
							for(i=0; i<ret ;i++)
							{
								rt_printf("%02x ",prc->extsendbuf_2[prc->extsendcnt_2 + send_len + i]);
							}
			
						}
						send_len += ret;
			
						s_stat_tx(ch, ret);//发送字节数计数
			
					}
					else if(send_fail_cnt++ > 5)
					{
						send_fail_cnt = 0;
				//		rt_printf("\nch_%d send fail!!!\n",ch);
						break;
					}
			
				} 
			
				if(g_print_comm_raw && (g_print_port & (1<<ch)))
				{
						rt_printf("\r\n");
				}
				{	
					prc->bextsend_2=false;
					prc->extsendcnt_2 = 0;
					mainloop_wakeup();
					prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
				}				
			}

			else if(prc->extsendlen_3 > 0)
			{
				send_fail_cnt = 0;
				send_len = 0;
				while(send_len<prc->extsendlen_3)					// 发送没完成,继续发送
				{	
					if(g_print_comm_raw && (g_print_port & (1<<ch)))
					{
						rt_printf("\r\nTX[%d]:",ch);
					}				
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf_3[prc->extsendcnt_3 + send_len], (prc->extsendlen_3 - send_len)); 				
					if(ret > 0)
					{
						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						
						{
							for(i=0; i<ret ;i++)
							{
								rt_printf("%02x ",prc->extsendbuf_3[prc->extsendcnt_3 + send_len + i]);
							}
			
						}
						send_len += ret;
			
						s_stat_tx(ch, ret);//发送字节数计数
			
					}
					else if(send_fail_cnt++ > 5)
					{
						send_fail_cnt = 0;
				//		rt_printf("\nch_%d send fail!!!\n",ch);
						break;
					}
			
				} 
			
				if(g_print_comm_raw && (g_print_port & (1<<ch)))
				{
						rt_printf("\r\n");
				}
				{	
					prc->bextsend_3=false;
					prc->extsendcnt_3 = 0;
					mainloop_wakeup();
					prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
				}				
			}		
#endif

		}
		else if(prc->bSend) 		// 发送
		{
			// 规约要求帧与帧之间间隔必须大于33位。
			if(prc->nSendCnt <= 1 // 帧头
				&& ((ustimer_get_duration(prc->us0_recv) < 5*USTIMER_MS) // 与接收帧之间的间隔
				|| (ustimer_get_duration(prc->us0_send) < 5*USTIMER_MS))) // 与发送帧之间的间隔
			{				 
				continue;
			}

			if(prc->sendbuf[0] > 0)
			{
				send_fail_cnt = 0;
				send_len = 0;
				while(send_len<prc->sendbuf[0])					// 发送没完成,继续发送
				{	
					//TODO. noted by sunxi 这里也需要加select,并且write的select与read的select 的参数不一样。
					ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->sendbuf[prc->nSendCnt+send_len], (prc->sendbuf[0] - send_len));					
					if(ret > 0)
					{
						if(g_print_comm_raw && (g_print_port & (1<<ch)))
						{
							if(send_len == 0)
							{
								rt_printf("\r\nTX[%d]:",ch);	
							}
							for(i=0; i<ret ;i++)
							{
								if((ch+1) == CFG_UART_GPS)
								{
									rt_printf("%c",prc->sendbuf[prc->nSendCnt + send_len + i]);
								}
								else
								{
									rt_printf("%02x ",prc->sendbuf[prc->nSendCnt + send_len + i]);
								}
							}
						}
						send_len += ret; 
						s_stat_tx(ch, ret);//发送字节数计数
				
					}
					else if(send_fail_cnt++ > 5)
					{
						send_fail_cnt = 0;
						rt_printf("\nch_%d send fail!!!\n",ch);
						break;
					}
					if(g_print_comm_raw && (g_print_port & (1<<ch)))
					{
						if((ch+1) != CFG_UART_GPS)
							rt_printf("\r\n");
					}
				} 
				{	
				#ifdef FLOW_CALC_FUNC
					if(ch == tRunPara.flow_port)
					{
						g_sw_pub.ac_in[PUB_AC_IN_FLOW] += (prc->sendbuf[0] + 46)*Q16_BASE; //TCP+IP包头40个字节，数据部分1个字节，PPP头7E 21 ，PPP尾校验和2位＋1个7E，总共是40＋1＋5＝46个字节
					}
				#endif			
					if (uart_test_begin)
					{
						uart_test_flag[ch][0] = 1;
					}
					prc->bSend=false;
					prc->nSendCnt = 0;
					send_len = 0;
					RS_Recv_Enable(ch);
					if(tRunPara.tUartPara[ch].wProtocol==PROTOCOL_HMI)
					{
						Reset_Uart_Link((UART_COMM_STRUCT *)g_tRsComm[ch].ptBuf);
					}
					mainloop_wakeup();
					prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	

				}
				//prc->sendbuf[0] = 0;
			}

		}
//发送 end
#endif	
	}
	
	rt_printf("\nch_%d thread out!!!!",ch);
#ifdef LINUX_KERNEL_APP
	if(ts[ch])
	{
		kthread_stop(ts[ch]);
		ts[ch] = NULL;
	}
#endif

#ifdef CPU_FUXI
	 watchdog_remove_item(wdt_id[ch]);
#endif
	
	return 0;	
}

/*
	创建串口收发线程
	ch: CFG_UART_NUM_MAX的i 序号
*/
#ifdef LINUX_KERNEL_APP
int uart_isr_thread_create(int ch)
{

	//int ret = 0;	
	char thread_name[256];
	l_ch[ch] = ch;


	//创建
	memset(thread_name,0,sizeof(thread_name));
	sprintf(thread_name, "uart_isr_%d", ch);
	//printk("tobe create %s\r\n",thread_name);
	ts[ch] = kthread_run(uart_isr_thread, (void *)(&l_ch[ch]), thread_name);
	if(ts[ch] == NULL)
	{
		rt_printf("tobe create %s faild!!!!!!!!!\r\n",thread_name);
		rt_printf("%s:ts=%p\r\n", __func__, ts[ch]);
		return -1;
	}
		
	// 设置调度策略和优先级
	sp[ch].sched_priority = 12;
	sched_setscheduler(ts[ch], SCHED_FIFO, &sp[ch]);

	return 0;	
}
#else
int uart_isr_thread_create(int ch)
{
    int ret;
	l_ch[ch] = ch;

    ret = pthread_create(&l_id[ch], NULL, (void *)uart_isr_thread, (void *)&l_ch[ch]);
    if(ret != 0) {
        printf("can not create thread uart_isr_thread: %d\r\n",errno);
        return -1;
    }

	
    return 0;
}
#endif

#else
/**************************************************************************
函数名称：uart1_isr
函数版本：1.00 
作者：   
创建日期：2008.9.1     
函数功能说明：485口接收处理程序，在625中断中调用
输入参数：
输出参数：
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/

void uart_isr(void)  /* 串口处理*/
{
	volatile unsigned char status;
	volatile SERIAL_COMM *prc;
	
	int cnt=0;
	int i;
	for(i=0;i<CFG_UART_NUM_MAX;i++)
	{
		s8 chnl=UART_CHANNEL[i];

		if( chnl < 0
			|| chnl == g_con_uart_index 
		 	|| tRunPara.tUartPara[i].wProtocol == PROTOCOL_IDLE)
		{
			continue;
		}

		// 如果GPS对时打开，必须关闭串口。
		if(g_clock_mode_gps && chnl == CFG_UART_GPS)
		{
			continue;
		}
		
		//如果是使用内部GPRS，则不用再走下面的代码流程
		if(chnl==CFG_UART_GPRS_IN )
		{
			continue;	
		}
	#ifdef FUN_FUXI_ESAM
		else if(chnl==CFG_UART_CHIP_S1 )
		{
			continue;	
		}
	#endif

		//面板做特殊处理
		if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_HMI)
		{
			//规约处理
			protocol_proc_task(i);	
			continue;	
		}

		//如果是数显仪表
		if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_SXYB)
		{
			//数显仪表处理
			sxyb_proc(chnl);	
			continue;	
		}
		
		
		prc=&g_tRsComm[i];

		// 接收超时检查
		status=MCF_UART_USR(chnl);
		if((status& MCF_UART_USR_RXRDY) == 0)
		{
			if( ustimer_get_duration(prc->us0_recv) > prc->us_recv_timeout) 
			{
				prc->b_recv_reset = 1;
			}
		}

		// 接收
		while (status& MCF_UART_USR_RXRDY)  // 接收数据
		{
		 	if((!(status&MCF_UART_USR_PE))&&(!(status&MCF_UART_USR_FE)))
		 	{
		 		u8 c;
		 		c = MCF_UART_URB(chnl);
				IEC_Recv(c,i);	  
				if(g_print_comm_raw && (g_print_port & (1<<i)))
				{
					rt_printf("%02x ",c);
				}
				s_stat_rx(i, 1);//接收字节数计数
				prc->us0_recv = ustimer_get_origin();//记录接收数据的时间戳	
				g_run_stu.led[i*2+1]=1;  //接收灯
		 	}
			else
			{
				status=MCF_UART_URB(chnl);
				MCF_UART_UCR(chnl) = MCF_UART_UCR_RESET_ERROR;  // 接收出错，清标志
				s_stat_rx_err(i, 1);//接收错误计数
			}
			status=MCF_UART_USR(chnl);
			if(++cnt>2)break;
		}


		// 发送
		if(prc->bextsend
		#ifdef FUNC_ENCRY_IN_ONE_SERIAL
			|| prc->bextsend_1
			|| prc->bextsend_2
			|| prc->bextsend_3
		#endif
		)
		{
			// 规约要求帧与帧之间间隔必须大于33位。
			if((prc->extsendcnt== 0 // 帧头
			#ifdef FUNC_ENCRY_IN_ONE_SERIAL
				|| prc->extsendcnt_1 == 0
				|| prc->extsendcnt_2 == 0
				|| prc->extsendcnt_3 == 0
			#endif
				)
				&& ((ustimer_get_duration(prc->us0_recv) < 5*USTIMER_MS) // 与接收帧之间的间隔
				|| (ustimer_get_duration(prc->us0_send) < 5*USTIMER_MS))) // 与发送帧之间的间隔
			{				 
				continue;
			}
		 
			if(prc->extsendcnt<prc->extsendlen
			#ifdef FUNC_ENCRY_IN_ONE_SERIAL
				|| (((prc->bextsend_1 && (prc->extsendcnt_1<prc->extsendlen_1))
				|| (prc->bextsend_2 && (prc->extsendcnt_2<prc->extsendlen_2))
				|| (prc->bextsend_3 && (prc->extsendcnt_3<prc->extsendlen_3))) && gb_bready)
			#endif
			) 					// 发送没完成,继续发送
			{	
				if (status& MCF_UART_USR_TXRDY)  // 可发送数据
				{
				#ifdef FUNC_ENCRY_IN_ONE_SERIAL
					if(prc->bextsend_1)
					{

						MCF_UART_UTB(chnl) = prc->extsendbuf_1[prc->extsendcnt_1];
						prc->extsendcnt_1++;
						if((prc->extsendcnt_1+1) > prc->extsendlen_1)
						{
							gb_bready = false;
						}
					}
					else if(prc->bextsend_2)
					{

						if(!prc->bextsend_1)
						{
							MCF_UART_UTB(chnl) = prc->extsendbuf_2[prc->extsendcnt_2];
							prc->extsendcnt_2++;
						}
						if((prc->extsendcnt_2+1) > prc->extsendlen_2)
						{
							gb_bready = false;
						}
					}
					else if(prc->bextsend_3)
					{

						if(!prc->bextsend_1 && !prc->bextsend_2)
						{
							MCF_UART_UTB(chnl) = prc->extsendbuf_3[prc->extsendcnt_3];
							prc->extsendcnt_3++;
						}
						if((prc->extsendcnt_3+1) > prc->extsendlen_3)
						{
							gb_bready = false;
						}
					}
					else
				#endif
					{
						MCF_UART_UTB(chnl) = prc->extsendbuf[prc->extsendcnt];
						if(g_print_comm_raw && (g_print_port & (1<<i)))
						{
							if(prc->extsendcnt == 0)
							{
								rt_printf("\r\nTX[%d]:",i);
							}
							rt_printf("%02x ",prc->extsendbuf[prc->extsendcnt]);
							if(prc->extsendcnt == prc->extsendlen-1)
							{
								rt_printf("\r\n");
							}
						}
						prc->extsendcnt++;
					}
					
					s_stat_tx(i, 1);//发送字节数计数
					g_run_stu.led[i*2+0]=1;  //发送灯
				}
			} 
			else if(status & MCF_UART_USR_TXEMP)
			{	
			#ifdef FUNC_ENCRY_IN_ONE_SERIAL
				if(prc->bextsend_1)
					prc->bextsend_1=false;
				else if(prc->bextsend_2)
					prc->bextsend_2=false;
				else if(prc->bextsend_3)
					prc->bextsend_3=false;

				gb_bready = true;
				
				if(prc->extsendcnt_1 != 0)
					prc->extsendcnt_1 = 0;
				else if(prc->extsendcnt_2 != 0)
					prc->extsendcnt_2 = 0;
				else if(prc->extsendcnt_3 != 0)
				prc->extsendcnt_3 = 0;
				
			#endif
				prc->bextsend=false;
				prc->extsendcnt = 0;
				mainloop_wakeup();
				prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
			}	
			
		}
		else if(prc->bSend) 		// 发送
		{
			// 规约要求帧与帧之间间隔必须大于33位。
			if(prc->nSendCnt <= 1 // 帧头
				&& ((ustimer_get_duration(prc->us0_recv) < 5*USTIMER_MS) // 与接收帧之间的间隔
				|| (ustimer_get_duration(prc->us0_send) < 5*USTIMER_MS))) // 与发送帧之间的间隔
			{				 
				continue;
			}
		 
			if(prc->nSendCnt<=prc->sendbuf[0]) 					// 发送没完成,继续发送
			{	
				if (status& MCF_UART_USR_TXRDY)  // 可发送数据
				{
					MCF_UART_UTB(chnl) = prc->sendbuf[prc->nSendCnt];
					if(g_print_comm_raw && (g_print_port & (1<<i)))
					{
						if(prc->nSendCnt <= 1)
						{

							rt_printf("\r\nTX[%d]:",i);
						}
						rt_printf("%02x ",prc->sendbuf[prc->nSendCnt]);
						if(prc->nSendCnt == prc->sendbuf[0])
						{

							rt_printf("\r\n");
						}
					}

					prc->nSendCnt++;
					s_stat_tx(i, 1);//发送字节数计数
					g_run_stu.led[i*2+0]=1;  //发送灯有效
				}
			} 
			else if(status & MCF_UART_USR_TXEMP)
			{	
				if (uart_test_begin)
				{
					uart_test_flag[i][0] = 1;
				}
				prc->bSend=false;
				prc->nSendCnt = 0;
				RS_Recv_Enable(i);
				if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_HMI)
				{
					Reset_Uart_Link((UART_COMM_STRUCT *)g_tRsComm[i].ptBuf);
				}
				mainloop_wakeup();
				prc->us0_send = ustimer_get_origin();//记录发送数据的时间戳	
			}		
		}
	}
}
#endif

void uart_232_485_test(u8 *buf)
{
	int i;
	u8 dat[6] = {0x10, 0x40, 0x01, 0x00, 0x41,0x16};

	memset (uart_test_flag, 0, sizeof(uart_test_flag));
	// RS232测试
	if (buf[0])
	{
		for (i=0; i<2; i++)
		{
			g_tRsComm[i].sendbuf[0] = 6;
			memcpy(&g_tRsComm[i].sendbuf[1],dat,6);
			RS_Send_Enable(i);	
			g_tRsComm[i].nSendCnt=1;   
			g_tRsComm[i].bSend=true;
			rt_printf("TX_101_%d:",i);
			print_msg("",&g_tRsComm[i].sendbuf[1],g_tRsComm[i].sendbuf[0]);
		}
	}

	// RS485测试
	if (buf[1])
	{
		for (i=3; i<6; i++)
		{
			g_tRsComm[i].sendbuf[0] = 6;
			memcpy(&g_tRsComm[i].sendbuf[1],dat,6);
			RS_Send_Enable(i);	
			g_tRsComm[i].nSendCnt=1;   
			g_tRsComm[i].bSend=true;
			rt_printf("TX_101_%d:",i);
			print_msg("",&g_tRsComm[i].sendbuf[1],g_tRsComm[i].sendbuf[0]);
		}		
	}

	// 延时2ms，以保证通讯完毕
	ustimer_delay(200*USTIMER_MS);
	msleep(200);//nodify by sunxi for 335x 

	IECCommTask();
	
	{
		u8 i;
		for(i=0; i<CFG_UART_NUM_MAX-1; i++)
		{
			rt_printf("chnl = %d, send=%d, recv=%d\r\n", 
					i, uart_test_flag[i][0], uart_test_flag[i][1]);
		}
	}
}


void iec_GetMsgInfo(u8 *buf,int len,u8 *ti,u8 *cot,u8 *se,bool b101)
{
	int i;

	u8 AddByte=0;
	u8 CotByte=0;	//传送原因双字节
	u8 AppByte=0;	//应用单元地址双字节
	u8 sel;
	// 所有定长帧的长度都不大于6个字节,不定长帧都大于等于15字节
	if(len < 8)
	{
		*ti  = 0;
		*cot = 0;
		*se  = 0;
		return;
	}

	if(b101)
	{
		if(tRunPara.b101Addr2Byte) AddByte=1;		
		if(tRunPara.b101Cot2Byte)  CotByte=1;		
		if(tRunPara.b101App2Byte)  AppByte=1;
		sel=buf[12+AddByte+CotByte+AppByte];
	}	
	else
	{
		sel=buf[15];
	}
	// 基本信息
	*ti  = buf[6+AddByte];
	*cot = buf[8+AddByte];
	*se  = 0;
	if(*ti==0xcb)  // 参数修改，选择位不同
	{
		if(!b101)
		{
			sel=buf[14]; 
		}
	}
	// 更新se
	for(i=0;i<TI_SELECT_NUM; i++)
	{
		if(*ti == g_ti_select[i])
		{
			*se  = (sel&0x80)? 1 : 0;
			break;
		}
	}
	if(*ti==210)  // 文件操作
	{
		BYTE cmd;
		if(b101)
		{
			cmd=buf[13+AddByte+CotByte+AppByte]; // 文件操作命令码
		}
		else
		{
			cmd=buf[16];  
		}

		if(cmd==7&&*cot==6)  // 写文件激活与其他文件类操作不同
		{
			*se=1;
		}
		else
		{
			*se=0;
		}
		
	}
	return ;
}



/*************远方修改定值，固定参数初始化************************/
#define MAX_UTF8_NUM 64
typedef struct FIXSET_UTF8
{
	int num;
	u16 intcode[MAX_UTF8_NUM];
	u16 unicode[MAX_UTF8_NUM];
}FIXSET_UTF8_DEF;

FIXSET_UTF8_DEF tUtf8;

int  iec_findchardot(u8 *buf,u8 *str)
{
	u8 *ps;	
	int i,lenth=0;
	ps=strchr(buf,',');
	if(ps)  // 存在','
	{
		lenth=ps-buf;
		for(i=0;i<lenth;i++)
		{
			str[i]=*buf++;
		}
		str[i]='\0';	
	}
	return lenth;
}
static void iec_getfixsetinf(RMT_FIXED_TABLE *pfixedset,u8 *buf)
{
	u8 str[128],type=0;
	int len,i;
	len=iec_findchardot(buf,str);
	if(len==0)return;
	if(strcmp(str,"FIXSET")==0) //固定参数
	{
		buf+=len+1;
		len=iec_findchardot(buf,str);
		if(len==0)return;
		type=strtoul(str,NULL,10);
		for(i=0;i<pfixedset->num;i++)
		{
			if(type==pfixedset->set[i].type)
			{
				buf+=len+1;
				len=iec_findchardot(buf,str); // 取输入点号
				if(len==0)return;
				if(type==FIXED_SET_CRC)
				{
					WORD crc;
					crc=strtoul(str,NULL,16);
					pfixedset->set[i].str[0]=(BYTE)(crc);
					pfixedset->set[i].str[1]=(BYTE)(crc>>8);
					pfixedset->set[i].len=2;
				}
				else
				{
					strcpy(pfixedset->set[i].str,str);
					pfixedset->set[i].len=strlen(pfixedset->set[i].str);		
				}
				break;
			}
		}
	}
	else if(strcmp(str,"UNICODE")==0) //固定参数
	{
		if(tUtf8.num>=MAX_UTF8_NUM)return;
		buf+=len+1;
		len=iec_findchardot(buf,str);
		if(len==0)return;		
		tUtf8.intcode[tUtf8.num]=str[1]|(str[0]<<8);  //汉字内码
		buf+=len+1;
		len=iec_findchardot(buf,str); // 
		tUtf8.unicode[tUtf8.num]=strtoul(str,NULL,16); // unicode
		tUtf8.num++;
	}
}

int  iec_get_fixedset_csv(RMT_FIXED_TABLE *pfixedset)
{
	u32 i,file_length;
	struct file * pfile;
	u8 *filebuf;
	u8  filestr[64],*pstr,strlenth;
	loff_t pos;
	// 打开文件
	pfile = rt_file_open("/app/data/fixset.csv",O_RDONLY ,0);
	if(IS_ERR(pfile))
	{
//		rt_printf("error! 无法打开 iec_cfg.csv\r\n");
		return -1;
	}

	// 得到文件长度
	file_length = rt_file_getfile_size(pfile);
	if(file_length == 0)
	{
		rt_file_close(pfile,0);
		return -2; 	
	}

	// 分配内存
	filebuf = rt_malloc(file_length);
	if((filebuf) == NULL)
	{
		rt_file_close(pfile,0);
		return -3; 	
	}

	pos = 0;
	if(rt_file_read(pfile,filebuf,file_length,&pos) != file_length)
	{
		rt_file_close(pfile,0);
		rt_free(filebuf);
		return -4;
	}
	pstr = filestr;
	strlenth=0;   // 纠错处理
	//找到\r\n位置，得到一行长度
	tUtf8.num=0;
	for(i = 0; i < file_length; i++)
	{
		*pstr++=filebuf[i];
		strlenth++;
		if(filebuf[i] == 0x0a||strlenth>=64)
		{
			pstr-=2;  //  去掉回车换行
			*pstr='\0';
			iec_getfixsetinf(pfixedset,filestr);
			pstr=filestr;
			strlenth=0;
		}
	}
	rt_file_close(pfile,0);	// 关闭文件
	rt_free(filebuf);			// 释放内存
	return 0;
}

void  iec_init_fixedset(void *pt,RMT_FIXED_TABLE *pfixedset,bool b104)
{
	int i;
	WORD num,no;
	num=0;	
	for(i=0;i<FIXEDSET_TABLE_NUMBER;i++)
	{
		pfixedset->set[num].type=tfixedsettable[i].index;
		switch(tfixedsettable[i].index)
		{
			case FIXED_SET_CRC:
				pfixedset->set[num].str[0]=(BYTE)(m_CodeCrc);
				pfixedset->set[num].str[1]=(BYTE)(m_CodeCrc>>8);
				pfixedset->set[num].len=2;
				break;
			case FIXED_SET_MAC1:
			case FIXED_SET_MAC2:
				no=tfixedsettable[i].index-FIXED_SET_MAC1;
				rt_if_mac_get(no,pfixedset->set[num].str);
				pfixedset->set[num].len=6;
				break;
			case FIXED_SET_SVR: // 软件版本
				sprintf(pfixedset->set[num].str,"SV%02d.%03d",VER_NUM/1000,VER_NUM%1000);
				pfixedset->set[num].len=strlen(pfixedset->set[num].str);
				break;

			case FIXED_SET_ID: 
				if(env_get_info(ENV_PID))
				{
					strcpy(pfixedset->set[num].str,env_get_info(ENV_PID));
					
				}
				else
				{
					strcpy(pfixedset->set[num].str,"");
				}
				pfixedset->set[num].len=strlen(pfixedset->set[num].str);
				break;				
			case FIXED_SET_COM:
				if(b104)
				{
					strcpy(pfixedset->set[num].str,"2016版扩展104");
				}
				else
				{
					IEC101_DEF *pt101=(IEC101_DEF *)pt;
					if(tRunPara.tUartPara[pt101->chnl].wProtocol==PROTOCOL_101_PH)
					{
						strcpy(pfixedset->set[num].str,"2016版扩展平衡式101");
					}
					else
					{
						strcpy(pfixedset->set[num].str,"2016版扩展非平衡式101");
					}
				}
				pfixedset->set[num].len=strlen(pfixedset->set[num].str);
				break;
			case FIXED_SET_CPT:
				strcpy(pfixedset->set[num].str,VER_TIME);
				pfixedset->set[num].len=strlen(pfixedset->set[num].str);
				break;
			default:	
				strcpy(pfixedset->set[num].str,tfixedsettable[i].vstr);
				pfixedset->set[num].len=strlen(tfixedsettable[i].vstr);
		}
		pfixedset->set[num].di=tfixedsettable[i].di;
		pfixedset->set[num].unit=tfixedsettable[i].unit;
		num++;
	}
	pfixedset->num=num;
	iec_get_fixedset_csv(pfixedset);  // 从csv文件中更新相关固定参数信息
	
}

int enc_unicode_to_utf8_one(unsigned short unic, unsigned char *pOutput)
{
    if ( unic <= 0x007F )
    {
        // * U-00000000 - U-0000007F:  0xxxxxxx
        *pOutput     = (unic & 0x7F);
        return 1;
    }
    else if ( unic >= 0x0080 && unic <= 0x07FF )
    {
        // * U-00000080 - U-000007FF:  110xxxxx 10xxxxxx
        *(pOutput+1) = (unic & 0x3F) | 0x80;
        *pOutput     = ((unic >> 6) & 0x1F) | 0xC0;
        return 2;
    }
    else if ( unic >= 0x0800 && unic <= 0xFFFF )
    {
        // * U-00000800 - U-0000FFFF:  1110xxxx 10xxxxxx 10xxxxxx
        *(pOutput+2) = (unic & 0x3F) | 0x80;
        *(pOutput+1) = ((unic >>  6) & 0x3F) | 0x80;
        *pOutput     = ((unic >> 12) & 0x0F) | 0xE0;
        return 3;
    }  
    return 0;
}

BYTE  iec_GBK2Utf8(BYTE *dst,BYTE *src,BYTE srclen)
{
	int i;
	int len=0;

	for(i=0;i<srclen;)
	{
		if(src[i]>0x80)  //是汉字
		{
			u16 intcode,unicode;
			int ulflen;
			int j;
			intcode=src[i+1]|(src[i]<<8);
			unicode=0;
			for(j=0;j<tUtf8.num;j++)
			{
				if(tUtf8.intcode[j]==intcode) // 内码相同，取内码对应的unicode
				{
					unicode=tUtf8.unicode[j];
					break;
				}
			}
			if(unicode>0)
			{			
				ulflen=enc_unicode_to_utf8_one(unicode,&dst[len]);
				len+=ulflen;
			}
			i+=2;
		}
		else
		{
			dst[len]=src[i];
			len++;
			i++;
		}
	}
	return len;
}

BYTE  iec_GBK2Unicode(BYTE *dst,BYTE *src,BYTE srclen)
{
	int i;
	int len=0;

	for(i=0;i<srclen;)
	{
		if(src[i]>0x80)  //是汉字
		{
			u16 intcode,unicode;
			int j;
			intcode=src[i+1]|(src[i]<<8);
			unicode=0;
			for(j=0;j<tUtf8.num;j++)
			{
				if(tUtf8.intcode[j]==intcode) // 内码相同，取内码对应的unicode
				{
					unicode=tUtf8.unicode[j];
					break;
				}
			}
			if(unicode>0)
			{			
				dst[len]=(u8)unicode;
				dst[len+1]=(u8)(unicode>>8);
				len+=2;
			}
			i+=2;
		}
		else
		{
			dst[len]=src[i];
			len++;
			i++;
		}
	}
	return len;
}

int  iec_add2frame(BYTE *pbuf,RMT_SET_VAL *pset,bool b104)
{
	int onebyte=0;
#ifdef FIX_PARAM_FORMAT
	bool bfixset=false;
#endif
	*pbuf++=(BYTE)pset->di;
	*pbuf++=(BYTE)(pset->di>>8);
	if(b104)
	{
		*pbuf++=0; // 104规约信息体地址为三个字节
		onebyte=1;
	}
#ifdef FIX_PARAM_FORMAT
	if((pset->di>0x8000)&&(pset->di<0x8020)&&(pset->unit == STR_R))
	{
		bfixset=true;
	}
	if(pRunSet->bTT_Utf8&&bfixset)
	{
		BYTE len;
		BYTE tmpbuf[128];
		
		len=iec_GBK2Utf8(tmpbuf,pset->str,pset->len);
		*pbuf++=pset->unit;
		*pbuf++=len;
		memcpy(pbuf,tmpbuf,len);
		return (len+onebyte+4);
	}
	else if(pRunSet->bTT_Unicode&&bfixset)
	{
		BYTE len;
		BYTE tmpbuf[128];
		len=iec_GBK2Unicode(tmpbuf,pset->str,pset->len);
		*pbuf++=pset->unit;
		*pbuf++=len;
		memcpy(pbuf,tmpbuf,len);
		return (len+onebyte+4);
	}
	else
#endif	
	{
		*pbuf++=pset->unit;
		*pbuf++=pset->len;
		memcpy(pbuf,pset->str,pset->len);
		return (pset->len+onebyte+4);
	}
	return 0;
}

int  iec_add2frame_dz(BYTE *pbuf,RMT_SET_VAL *pset,bool b104)
{
	int onebyte=0;
	*pbuf++=(BYTE)pset->di;
	*pbuf++=(BYTE)(pset->di>>8);
	if(b104)
	{
		*pbuf++=0; // 104规约信息体地址为三个字节
		onebyte=1;
	}

	memcpy(pbuf,pset->str,pset->len);
	return (pset->len+onebyte+2);
}

void  iec_set2rmtset( RMT_SET_VAL *rmtset,WORD Tag,WORD group,WORD setno,float fv )
{
	u32 ll;	
	switch(Tag)
	{
		case BOOL_R:
		case TINY_R:
		case UTINY_R:
			rmtset->len=1;
			rmtset->str[0]=(BYTE)fv;
			break;		
		case UINT_R:
		case INT_R:
		case LONG_R:
		case ULONG_R:
			rmtset->len=4;
			ll=(u32)fv;
			rmtset->str[0]=(BYTE)(ll>>0);
			rmtset->str[1]=(BYTE)(ll>>8);
			rmtset->str[2]=(BYTE)(ll>>16);
			rmtset->str[3]=(BYTE)(ll>>24);
			break;		

		case SHORT_R:
		case USHORT_R:
			rmtset->len=2;
			ll=(u32)fv;
			rmtset->str[0]=(BYTE)(ll>>0);
			rmtset->str[1]=(BYTE)(ll>>8);
			break;		
		case FLOAT_R:
			{
				union{
				float ff;
				u8 tt[4];
				}ff;	
				rmtset->len=4;
				ff.ff=fv;
				CopySwap(rmtset->str,ff.tt,sizeof(ff.tt),true);
			}
			break;	
		case STR_R:
			{
				union{
				float ff;
				u8 tt[4];
				}ff;
				WORD wType=0;

				ff.ff=fv;

				if(group==SETGROUP_TYPE_PUB)
				{
					wType = tPubSetTable[setno].wType;
				}
				else if(group==SETGROUP_TYPE_BH)
				{
					wType = tSwSetTable[setno].wType;
				}
				else if(group==SETGROUP_TYPE_PARA)
				{
					wType = tEquipParaTable[setno].wType;
				}
				else if(group==SETGROUP_TYPE_CSTSET)
				{
					wType = tCstSetTable[setno].wType;
				}
				else
				{			
					rmtset->len=0;	
					break;
				}

				if(wType == SETTYPE_IP)
				{
					sprintf(rmtset->str,"%d.%d.%d.%d",ff.tt[3],ff.tt[2],ff.tt[1],ff.tt[0]);
					rmtset->len=strlen(rmtset->str);
				}
				else
				{
					rmtset->len=0;	
			      	break;			
				}				
			}
			break;	
		default:
			rmtset->len=0;	
		      break;			
		
	}

	rmtset->unit=Tag;

}
//佛山局参数低位在前，高位在后 
//浮点->缓冲区
static void float2IECbuf(BYTE *buf,float f)
{
	union
	{
		float ff;
		u8 tt[4];
	}ff;
	ff.ff = f;
	CopySwap(buf,ff.tt,sizeof(ff.tt),true);
}
//缓冲区->浮点数
static float IECbuf2Foat(BYTE *buf)
{
	union
	{
		float ff;
		u8 tt[4];
	}ff;

	CopySwap(ff.tt,buf,4,false);

	return ff.ff;
}
//获取参数信息定义的偏移量
static int getSetTableOffset(const TSETTABLE *pTable,WORD maxTable, WORD parId,WORD set_group, bool b_write)
{
	int i;
	
	#if 0
	for(i=0;i<maxTable;i++)
	{
		int j;
		for(j=0;j<ParaIDNum;j++)
		{
			if(tParaID[j].parId==parId&&tParaID[j].group_type==set_group)
			{
				rt_printf("%s Type=%d %d i=%d\r\n",pTable[i].szName,parId,set_group,i);
				return i;

			}
		}
	}		
	#endif
#ifdef FUNC_YT_HARD_YB
	if(set_group != SETGROUP_TYPE_BY)
#endif
	{
		for(i=0; i<ParaIDNum; i++)
		{
			if(tParaID[i].parId==parId && tParaID[i].group_type==set_group && parId)
			{				
		
		#ifdef FUNC_GET_RD_ONLY
				if(b_write)
				{
					if(!tParaID[i].b_rd_only)
					{						
						return tParaID[i].setno;
						//return i;
					}
					else
					{
						rt_printf("%x为只读定值,禁止写！\r\n",parId);
						return -1;
					}
				}
				else
		#endif
				{
					//rt_printf("%s Type=%d %d i=%d\r\n",pTable[i].szName,parId,set_group,i);				
					return tParaID[i].setno;
					//return i;
				}
			}	
		}
	}
#ifdef FUNC_YT_HARD_YB
	else
	{
	#ifdef FUNC_YT_MIX
		for(i=0; i<(YT_SW_HARD_YB_NUM+YT_PUB_HARD_YB_NUM+MIX_YT_NUM); i++)
	#else
		for(i=0; i<(YT_SW_HARD_YB_NUM+YT_PUB_HARD_YB_NUM); i++)
	#endif
		{
			if((tHardYBID[i]==parId) && (parId != 0))
			{
				if(b_write)
				{
					return -1;
				}
				else
				{
					return i;
				}
			}
		}
	}
#endif

	return -1;
}
//参数预置
bool selectRunParId(WORD sw, WORD parId, BYTE *pbuf)
{
	int parTable=0;
	float value = 0;
	if(sw > SWITCH_NUM_MAX)
		return false;
	
#ifndef FUNC_MORE_PRESET	
	//放在所有参数处理的前面，包括只读定值在内的都需进行比较和统计
	if(bfirst_sel)	//wirteRunParId中对selectRunParId有调用，为避免数组记录内容出错，限定为预置参数时(bfirst_sel=true)才允许写比较数组
	{
		buf_forCompare[i_forCompare++] = (BYTE)(parId >> 8);
		buf_forCompare[i_forCompare++] = (BYTE)parId;
		memcpy(&buf_forCompare[i_forCompare],pbuf,4);
		i_forCompare += 4;
	}
#endif	

#if defined  GD_AREA_FOS || defined GD_AREA_FOS_2021 || defined FOS_2021
	if(parId==0x5001 || parId==0x5002)//佛山局要求5001:常规继电保护模式 0x5002 常规继电保护定值区号 只读，不可更改
		return false;

	#ifdef FOS_2021
		if(parId==0x5024)		//远方整定投入软压板
		{
			rt_printf("远方整定投入软压板不允许远方修改\r\n");
			return false;
		}
	#endif
#elif defined GD_AREA_SHANWEI
	if(parId==0x500b || parId==0x5045)//汕尾局要求500b:常规继电保护模式 5045:常规FA自动化模式 只读，不可更改
		return false;
#elif defined GD_AREA_ECZD_MAOMING
	//茂名局要求5001:定值区号 5013:常规继电保护模式/5051:电压电流型继电保护模式/508d:智能分布式保护模式/50ab:转换把手位置/504c、507e:远方整定投入软压板 只读，不可更改
	if(parId==0x5001 || parId==0x5013 || parId==0x5051 || parId==0x508d || parId==0x50ab || parId==0x504c || parId==0x507e)
		return false;
#elif defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC || defined GD_AREA_ZHONGSHAN
/*19年中山要求5001:保护总投退 5002:电流型保护模式投退 5003:电压电流型保护模式投退 5004:智能分布式保护模式投退 5011:远方修改功能只读，不可更改
19年中山要求5001:保护总投退 5002:电流型保护模式投退 5003:电压电流型保护模式投退 5004:智能分布式保护模式投退 5005:远方修改功能只读，不可更改*/
	if(parId==0x5001 || parId==0x5002 || parId==0x5003 || parId==0x5004)
		return false;

	#ifdef GD_AREA_ZHONGSHAN
		if(parId==0x5011)
	#elif defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC
		if(parId==0x5005)
	#endif
			return false;
#elif defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	if(parId==0x5001 || parId==0x5024 || parId==0x505f || parId==0x5060
		|| parId==0x5032 || parId==0x5033 || parId==0x5034 || parId==0x5035 || parId==0x5036
		|| parId==0x5037 || parId==0x5038 || parId==0x5039 || parId==0x503a || parId==0x503b
		|| parId==0x5501 || parId==0x5502 || parId==0x5503 || parId==0x5504 || parId==0x5505
		|| parId==0x5506 || parId==0x5507 || parId==0x5508 || parId==0x5509 || parId==0x550a)
		return false;
/*#elif defined GD_AREA_ECZD_SHAOGUAN_2021
	if(parId==0x5001 || parId==0x5002 || parId==0x5003 || parId==0x5004 || parId==0x5005 || parId==0x5006)
	{//5001：保护/FA，5002：同期合闸，5003：自动解列，5004：停用，5005：远方投入，5006：定值区号
		return false;
	}*/
#elif defined GD_AREA_DONGGUAN_2021
		if(parId==0x500C || parId==0x5065)
		{
			return false;
		}
#elif 0
	if(parId==0x5001)//云浮郁南要求5001:定值区号 只读，不可更改
	{
		return false;		
	}
#endif
	value = IECbuf2Foat(pbuf);

	rt_printf("预置参数 parId %02x=%f \r\n",parId,value);
	
	parTable=getSetTableOffset(&tPubSetTable[0],PUB_SET_NUMBER,parId,SETGROUP_TYPE_PUB, true);
	if(parTable != -1)
	{
		rt_printf("%s PubType=%d %d i=%d\r\n",tPubSetTable[parTable].szName,parId,SETGROUP_TYPE_PUB,parTable);
		if(value<=tPubSetTable[parTable].fMax && value>=tPubSetTable[parTable].fMin)
			return true;
		else
		{
			rt_printf("预置参数超范围，失败 par=%f parTable=%d            max=%f min%f\r\n",value,parTable,tPubSetTable[parTable].fMax,tPubSetTable[parTable].fMin);	
			return false;
		}
	}
	parTable=getSetTableOffset(&tSwSetTable[0],SW_SET_NUMBER,parId,SETGROUP_TYPE_BH, true);
	if(parTable != -1)
	{
		//parTable -= PUB_SET_NUMBER;
		//if(parTable > 0 && parTable < SW_SET_NUMBER)
		{	
			rt_printf("%s BhType=%d %d i=%d\r\n",tSwSetTable[parTable].szName,parId,SETGROUP_TYPE_BH,parTable);
		#ifdef BH_FA_INONE_SW
			if(0 == strcmp(tSwSetTable[parTable].szName,"保护/FA"))
			{//判断“保护/FA”时需对主站送过来的值作减1运算以满足实际列表BHorFA_List里的值
				if(((value-1)<=tSwSetTable[parTable].fMax) && ((value-1)>=tSwSetTable[parTable].fMin))
					return true;
				else
				{
					rt_printf("预置参数超范围，失败 par=%f parTable=%d			max=%f min%f\r\n",value,parTable,tSwSetTable[parTable].fMax,tSwSetTable[parTable].fMin);	
					return false;
				}
			}
			else
		#endif
			{
				if(value<=tSwSetTable[parTable].fMax && value>=tSwSetTable[parTable].fMin)
					return true;
				else
				{
					rt_printf("预置参数超范围，失败 par=%f parTable=%d            max=%f min%f\r\n",value,parTable,tSwSetTable[parTable].fMax,tSwSetTable[parTable].fMin);	
					return false;
				}
			}
		}	
	}
	if(parTable == -1)
		rt_printf("预置参数地址不存在parID=%x\r\n",parId);
	else
		rt_printf("预置参数非法par=%f\r\n",value);

	return false;

}//写读取,生效
bool wirteRunParId(WORD sw, WORD parId, BYTE *pbuf,u8 ti)
{
	int parTable=0, j=0;
#ifndef FUNC_MORE_PRESET
	BYTE buf[6];
	int i=0;
#endif
	SET_VALUE *parBuf;
	rt_printf("写参数 %02x=%f \r\n",parId,IECbuf2Foat(pbuf));		
	if(sw>SWITCH_NUM_MAX)
		return false;
	
#ifdef FUNC_MORE_PRESET
	if(gb_101_yt)
	{
		for(j=0;j<sizeof(PresetData101[g_CountSet101-1]);j++)
		{
			if(0 == (j+1)%7)
			{//跳过设定命令限定词qos(每7位最后一位)
				continue;
			}
			
			if(SetData101[g_CountSet101-1].yc_data[j] != PresetData101[g_CountSet101-1].yc_data[j])
			{
				rt_printf("固化定值与预置定值不一样,请检查第%d帧执行报文,parId=%x\r\n",g_CountSet101,parId);
				return false;
			}
		}
	}
	else
	{				
		for(j=0;j<sizeof(PresetData104[g_CountSet104-1]);j++)
		{
			if(ti==FOS_PAR_SET_ONE || ti==FOS_PAR_SET_MUL)
			{				
				if(0 == (j+1)%8) continue;
			}
			else
			{
				if(0 == (j+1)%7) continue;
			}
			
			if(SetData104[g_CountSet104-1].yc_data[j] != PresetData104[g_CountSet104-1].yc_data[j])
			{
				rt_printf("固化定值与预置定值不一样,请检查第%d帧执行报文,parId=%x\r\n",g_CountSet104,parId);
				return false;
			}
		}
	}
#else	
	//放在所有参数处理的前面，包括只读定值在内的都需进行比较和统计
	buf[i++] = (BYTE)(parId >> 8);
	buf[i++] = (BYTE)parId;
	memcpy(&buf[i],pbuf,4);
	for(j=0;j<6;j++)
	{
		if(buf[j] == buf_forCompare[j+j_forCompare])
			continue;
		else
		{
			rt_printf("固化定值与预置定值不一样，请检查parId=%x\r\n",parId);
			j_forCompare += 6;
			return false;
		}
	}
	j_forCompare += 6;
#endif

#if defined  GD_AREA_FOS || defined GD_AREA_FOS_2021 || defined FOS_2021
	if(parId==0x5001 || parId==0x5002)//佛山局要求5001:常规继电保护模式 0x5002 常规继电保护定值区号 只读，不可更改
		return false;

	#ifdef FOS_2021
		if(parId==0x5024)		//远方整定投入软压板
		{
			rt_printf("远方整定投入软压板不允许远方修改\r\n");
			return false;
		}
	#endif
#elif defined GD_AREA_SHANWEI
	if(parId==0x500b || parId==0x5045)//汕尾局要求500b:常规继电保护模式 5045:常规FA自动化模式 只读，不可更改
		return false;
#elif defined GD_AREA_ECZD_MAOMING
	//茂名局要求5001:定值区号 5013:常规继电保护模式/5051:电压电流型继电保护模式/508d:智能分布式保护模式/50ab:转换把手位置/504c、507e:远方整定投入软压板 只读，不可更改
	if(parId==0x5001 || parId==0x5013 || parId==0x5051 || parId==0x508d || parId==0x50ab || parId==0x504c || parId==0x507e)
		return false;
#elif defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC || defined GD_AREA_ZHONGSHAN
/*19年中山要求5001:保护总投退 5002:电流型保护模式投退 5003:电压电流型保护模式投退 5004:智能分布式保护模式投退 5011:远方修改功能只读，不可更改
19年中山要求5001:保护总投退 5002:电流型保护模式投退 5003:电压电流型保护模式投退 5004:智能分布式保护模式投退 5005:远方修改功能只读，不可更改*/
	if(parId==0x5001 || parId==0x5002 || parId==0x5003 || parId==0x5004)
		return false;
	
	#ifdef GD_AREA_ZHONGSHAN
		if(parId==0x5011)
	#elif defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC
		if(parId==0x5005)
	#endif
			return false;
#elif defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	if(parId==0x5001 || parId==0x5024 || parId==0x505f || parId==0x5060
		|| parId==0x5032 || parId==0x5033 || parId==0x5034 || parId==0x5035 || parId==0x5036
		|| parId==0x5037 || parId==0x5038 || parId==0x5039 || parId==0x503a || parId==0x503b
		|| parId==0x5501 || parId==0x5502 || parId==0x5503 || parId==0x5504 || parId==0x5505
		|| parId==0x5506 || parId==0x5507 || parId==0x5508 || parId==0x5509 || parId==0x550a)
		return false;
/*#elif defined GD_AREA_ECZD_SHAOGUAN_2021
	if(parId==0x5001 || parId==0x5002 || parId==0x5003 || parId==0x5004 || parId==0x5005 || parId==0x5006)
	{//5001：保护/FA，5002：同期合闸，5003：自动解列，5004：停用，5005：远方投入，5006：定值区号
		return false;
	}*/
#elif defined GD_AREA_DONGGUAN_2021
	if(parId==0x500C || parId==0x5065)
	{
		return false;
	}
#endif

	if(selectRunParId(sw, parId, pbuf) ==false)	return false;
	
	parBuf = rt_malloc(SET_NUMBER*4);	
	if(!parBuf)
	{
		rt_printf("\r\n远方写定值，分配定值缓冲区错误!\r\n");
		return false;
	}
	if(!ReadSet(m_runsection,(void *)parBuf))  // 读定值
	{
		GetDefSet((float*)parBuf);
	}

	parTable=getSetTableOffset(&tPubSetTable[0],PUB_SET_NUMBER,parId,SETGROUP_TYPE_PUB, true);
	if(parTable != -1)
	{
	#ifdef GD_ECZD_FOS_FTU_2021
		if(parId == 0x5026)
		{//0x5026与停用压板关联，但取值相反。主站下0时压板为1，主站下1时压板为0
			parBuf[SET_BH_YB].ff = IECbuf2Foat(pbuf);
			if(parBuf[SET_BH_YB].ff)
			{
				parBuf[SET_BH_YB].ff = 0;
			}
			else
			{
				parBuf[SET_BH_YB].ff = (float)1;
			}
			rt_printf("写SET_BH_YB=%f\r\n",parBuf[SET_BH_YB].ff);
		}
		else
	#endif
		{
			//rt_printf("%s ID=%d  i=%d\r\n",tPubSetTable[parTable].szName,parId,parTable);
			parBuf[parTable].ff = IECbuf2Foat(pbuf);
			rt_printf("写parBuf=%f\r\n",parBuf[parTable].ff);
		}
	}
	else
	{
		parTable=getSetTableOffset(&tSwSetTable[0],SW_SET_NUMBER,parId,SETGROUP_TYPE_BH, true);
		if(parTable != -1)
		{
			//parTable -= PUB_SET_NUMBER;
			//if(parTable > 0 && parTable < SW_SET_NUMBER)
			{
				//rt_printf("%s ID=%x  i=%d\r\n",tSwSetTable[parTable].szName,parId,parTable);
			#ifdef BH_FA_INONE_SW
				if(0 == strcmp(tSwSetTable[parTable].szName,"保护/FA"))
				{//判断“保护/FA”时需对主站送过来的值作减1运算以满足实际列表BHorFA_List里的值
					parBuf[sw*parTable+PUB_SET_NUMBER].ff = (IECbuf2Foat(pbuf)-1);
					rt_printf("wirteRunParId=%02x i=%d %f\r\n",parId,parTable,parBuf[sw*parTable+PUB_SET_NUMBER].ff);
				}
				else
			#endif
				{
					parBuf[sw*parTable+PUB_SET_NUMBER].ff = IECbuf2Foat(pbuf);
					rt_printf("wirteRunParId=%02x i=%d %f\r\n",parId,parTable,parBuf[sw*parTable+PUB_SET_NUMBER].ff);
				}
			}
		}
	}

	if((parTable>=0)&&pRunSet->bTT_EDIT_YB&&SaveSet(m_runsection,(void *)parBuf)) //必须远方投入软压板为1
	{
		soe_record_opt(EV_SET_OK,0);
		MakeRunSet(false); 
		rt_err_clr(ERR_CODE_SET,0);
		rt_free(parBuf);
		return true;
	}
	else
	{
		soe_record_opt(EV_SET_FAIL,0);
		rt_printf("写参数失败\r\n");
		rt_free(parBuf);
		return false;	
	}

	
}

//读参数
bool readRunParId(WORD sw, WORD parId, BYTE *pbuf)
{
	int parTable=0;
	SET_VALUE *parBuf;
#if defined GD_AREA_ECZD_MAOMING || defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC || defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	SET_VALUE *pparaBuf;
#endif
#ifdef FUNC_YT_HARD_YB
	struct equ_config_di *ecd;
	u8 temp_yx;
#endif
			
	if(sw>SWITCH_NUM_MAX)
		return false;

	parBuf = rt_malloc(SET_NUMBER*4);	
	if(!parBuf)
	{
		rt_free(parBuf);
		rt_printf("\r\n远方读定值，分配定值缓冲区错误!\r\n");
		return false;
	}
	
#if defined GD_AREA_ECZD_MAOMING || defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC || defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	pparaBuf = rt_malloc(EQUIP_PARA_NUMBER*4);	
	if(!pparaBuf)
	{
		rt_free(pparaBuf);
		rt_printf("\r\n远方读定值，分配装置参数缓冲区错误!\r\n");
		return false;
	}
#endif

#if defined  GD_AREA_FOS || defined GD_AREA_FOS_2021  || defined FOS_2021
	#ifdef GD_ECZD_FOS_FTU_2021
		if(parId == 0x5026)
		{
			float2IECbuf(pbuf,(float)pRunSet->bTT_BH_YB);
			rt_free(parBuf);
			return true;
		}
	#else
		if(parId==0x5001)//佛山局要求5001:常规继电保护模式 为保护总硬件遥信,不需要配置
		{
			float2IECbuf(pbuf,(float)BH_ALL_EN(0));
			rt_free(parBuf);
			return true;
		}
	#endif
	
#elif defined GD_AREA_SHANWEI
	if(parId==0x500b)
	{
		float2IECbuf(pbuf,(float)BH_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}
	else if(parId==0x5045)
	{
		float2IECbuf(pbuf,(float)FA_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}
//茂名局要求5001:定值区号 5013:常规继电保护模式/5051:电压电流型继电保护模式/508d:智能分布式保护模式/50ab:转换把手位置 只读，不可更改
#elif defined GD_AREA_ECZD_MAOMING
	if(parId==0x5013)
	{
		float2IECbuf(pbuf,(float)BH_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}
	else if(parId==0x5051)
	{
		float2IECbuf(pbuf,(float)FA_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}
	else if(parId==0x508d)
	{
		float2IECbuf(pbuf,(float)BH_GOOSE_EN(0));
		rt_free(parBuf);
		return true;
	}
	else if(parId==0x50ab)
	{//转换把手位置	1：投入继电保护功能；2：投入FA功能；3：投入智能分布式FA功能；4：禁用功能
		if(BH_ALL_EN(0))
		{
			float2IECbuf(pbuf,(float)1);
			rt_free(parBuf);
			return true;
		}
		else if(FA_ALL_EN(0))
		{
			float2IECbuf(pbuf,(float)2);
			rt_free(parBuf);
			return true;
		}
		else if(BH_GOOSE_EN(0))
		{
			float2IECbuf(pbuf,(float)3);
			rt_free(parBuf);
			return true;
		}
		else
		{
			float2IECbuf(pbuf,(float)4);
			rt_free(parBuf);
			return true;
		}
	}
#elif defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC
	if(parId==0x5001)
	{
		int i;
		for(i=0;i<g_sw_num;i++)
		{
			if(((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) && (g_tRelay[i].run_stu.bh_yx==1))
			{
				rt_printf("SW==%d,常规保护压板合\r\n",i);
				float2IECbuf(pbuf,(float)1);
				rt_free(parBuf);
				return true;
			}
			else if(((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID) && (g_tRelay[i].run_stu.fa_yx)==1)
			{
				rt_printf("SW==%d,常规FA压板合\r\n",i);
				float2IECbuf(pbuf,(float)2);
				rt_free(parBuf);
				return true;
			}
			else if(((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID) && (g_tRelay[i].run_stu.fa_g_yx)==1)
			{
				rt_printf("SW==%d,智能FA压板合\r\n",i);
				float2IECbuf(pbuf,(float)3);
				rt_free(parBuf);
				return true;
			}
			//为调试、测试便于查找问题，预留打印信息
			else if(((short)g_sw[i].di_cfg_index[SW_DI_BHTT] == INDEX_INVALLID)
					|| ((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] == INDEX_INVALLID)
					|| ((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] == INDEX_INVALLID))
			{
				rt_printf("常规保护压板/常规FA压板/智能FA压板DI通道未配置!!!\r\n");
			}
		}
	}
	else if(parId==0x5004)
	{
		int i;
		for(i=0;i<g_sw_num;i++)
		{
			if((short)g_sw[i].di_cfg_index[SW_DI_BHZTT] != INDEX_INVALLID)
			{
				float2IECbuf(pbuf,(float)!g_tRelay[i].run_stu.bhztt);
				rt_free(parBuf);
				return true;
			}
			//为调试、测试便于查找问题，预留打印信息
			else
			{
				rt_printf("停用FA及保护DI通道未配置!!!\r\n");
			}
		}
	}
#elif defined GD_AREA_ZHONGSHAN
	if(parId==0x5001)
	{
		float2IECbuf(pbuf,(float)FUN_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}
	else if(parId==0x5002)
	{
		int i;
		for(i=0;i<g_sw_num;i++)
		{
			if((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID)
			{
				float2IECbuf(pbuf,(float)g_tRelay[i].run_stu.bh_yx);
				rt_free(parBuf);
				return true;
			}
		}
	}
	else if(parId==0x5003)
	{
		int i;
		for(i=0;i<g_sw_num;i++)
		{
			if((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID)
			{
				float2IECbuf(pbuf,(float)g_tRelay[i].run_stu.fa_yx);
				rt_free(parBuf);
				return true;
			}
		}
	}
	else if(parId==0x5004)
	{
		int i;
		for(i=0;i<g_sw_num;i++)
		{
			if((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID)
			{
				float2IECbuf(pbuf,(float)g_tRelay[i].run_stu.fa_g_yx);
				rt_free(parBuf);
				return true;
			}
		}
	}

#elif defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	if(parId==0x5001)
	{
		float2IECbuf(pbuf,(float)BH_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}
	else if(parId==0x5032)
	{
		float2IECbuf(pbuf,(float)FA_ALL_EN(0));
		rt_free(parBuf);
		return true;
	}

#endif

#ifdef FUNC_YT_HARD_YB	
	parTable=getSetTableOffset(0,0,parId,SETGROUP_TYPE_BY, false);
	if(parTable != -1)
	{
		int i;
		for(i=0;i<g_sw_num;i++)
		{
			if((parTable>=0) && (parTable<YT_SW_HARD_YB_NUM))
			{
				if((short)g_sw[i].di_cfg_index[sw_yt_hard_yb_index[parTable]] != INDEX_INVALLID)
				{
					ecd = &g_equ_config_di[g_sw[i].di_cfg_index[sw_yt_hard_yb_index[parTable]]];
					temp_yx = dido_di_is_on(ecd->slot,ecd->index);
					rt_printf("读硬压板:%s=%d\r\n",g_sw_di_name[sw_yt_hard_yb_index[parTable]],temp_yx);
					float2IECbuf(pbuf,(float)temp_yx);
					rt_free(parBuf);
					return true;
				}
				else
				{
					rt_free(parBuf);
					rt_printf("硬压板[%s]未配置,读取失败\r\n",g_sw_di_name[sw_yt_hard_yb_index[parTable]]);
					return false;
				}
			}
		}
		if((parTable>=YT_SW_HARD_YB_NUM) && (parTable<(YT_SW_HARD_YB_NUM+YT_PUB_HARD_YB_NUM)))
		{
			if((short)g_sw_pub.di_cfg_index[pub_yt_hard_yb_index[parTable-YT_SW_HARD_YB_NUM]] != INDEX_INVALLID)
			{
				ecd = &g_equ_config_di[g_sw_pub.di_cfg_index[pub_yt_hard_yb_index[parTable-YT_SW_HARD_YB_NUM]]];
				temp_yx = dido_di_is_on(ecd->slot,ecd->index);
				rt_printf("读硬压板:%s=%d\r\n",g_pub_di_name[pub_yt_hard_yb_index[parTable-YT_SW_HARD_YB_NUM]],temp_yx);
				float2IECbuf(pbuf,(float)temp_yx);
				rt_free(parBuf);
				return true;
			}
			else
			{
				rt_free(parBuf);
				rt_printf("硬压板[%s]未配置,读取失败\r\n",g_pub_di_name[pub_yt_hard_yb_index[parTable-YT_SW_HARD_YB_NUM]]);
				return false;
			}
		}
	#ifdef FUNC_YT_MIX
		else if(parTable>=YT_SW_HARD_YB_NUM+YT_PUB_HARD_YB_NUM)
		{
			int i=0;
    
			//模式硬遥信上送：1：常规保护；2：常规FA；3：智能FA
			if(MIX_MODE_SEL == (parTable-YT_SW_HARD_YB_NUM-YT_PUB_HARD_YB_NUM))
			{
				int ecd_yx_bh=0,ecd_yx_fa=0,ecd_yx_goose=0;
				
				for(i=0;i<g_sw_num;i++)
				{
					if(((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID)
						|| ((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID)
						|| ((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID))
					{//三大模式压板有配置
						if((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID)
						{
							ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_BHTT]];
							ecd_yx_bh = dido_di_is_on(ecd->slot,ecd->index);
						}

						if((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID)
						{
							ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_FA_TT]];
							ecd_yx_fa = dido_di_is_on(ecd->slot,ecd->index);
						}
						
						if((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID)
						{
							ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_FA_GOOSE]];
							ecd_yx_goose = dido_di_is_on(ecd->slot,ecd->index);
						}

						if(ecd_yx_bh)
							temp_yx = 1;	//常规保护压板上送1
						else if(ecd_yx_fa)
							temp_yx = 2;	//常规FA压板上送2
						else if(ecd_yx_goose)
							temp_yx = 3;	//智能FA压板上送3
						else
							temp_yx = 0;	//三大模式压板遥信点都为0时上送0
						
						rt_printf("读硬压板:%s=%d\r\n",mix_yt_index[MIX_MODE_SEL],temp_yx);
						float2IECbuf(pbuf,(float)temp_yx);
						rt_free(parBuf);
						return true;
					}
					else
					{//三大模式压板未配置，上送4
						float2IECbuf(pbuf,(float)4);
						rt_free(parBuf);
						rt_printf("三大模式压板未配置,读取失败\r\n");
						return false;
					}
				}
			}
		}
	#endif
	}
#endif

	if(!ReadSet(m_runsection,(void *)parBuf))  // 读定值
	{
		GetDefSet((float*)parBuf);
	}
	
#if defined GD_AREA_ECZD_MAOMING || defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC || defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	if(!ReadPara((void*)pparaBuf,EEP_EQUIP_PARA_ADDR,EQUIP_PARA_NUMBER,&tEquipParaTable[0]))// 读参数
	{
		GetDefPara((void*)pparaBuf,EQUIP_PARA_NUMBER,&tEquipParaTable[0]);		
	}
#endif

	parTable=getSetTableOffset(&tPubSetTable[0],PUB_SET_NUMBER,parId,SETGROUP_TYPE_PUB, false);
	if(parTable != -1)
	{
		rt_printf("%s Type=%d %d i=%d\r\n",tPubSetTable[parTable].szName,parId,SETGROUP_TYPE_PUB,parTable);
		rt_printf("readRunParId=%02x parTable=%d ",parId,parTable);
		
		rt_printf("parBuf=%f\r\n",parBuf[parTable].ff);
		float2IECbuf(pbuf,parBuf[parTable].ff);
		rt_free(parBuf);
		return true;	
	}
	parTable=getSetTableOffset(&tSwSetTable[0],SW_SET_NUMBER,parId,SETGROUP_TYPE_BH, false);
	if(parTable != -1)
	{
		//parTable -= PUB_SET_NUMBER;
		//if(parTable > 0 && parTable < SW_SET_NUMBER)
		{
			rt_printf("%s Type=%d %d i=%d\r\n",tSwSetTable[parTable].szName,parId,SETGROUP_TYPE_BH,parTable);
			rt_printf("ReadRunParId=%02x swOffset=%d ,offset=%d par=%f\r\n",parId,parTable,parTable*sw+PUB_SET_NUMBER+PUB_SET_NUMBER,parBuf[parTable*sw+PUB_SET_NUMBER].ff);

		#ifdef BH_FA_INONE_SW
			if(0 == strcmp(tSwSetTable[parTable].szName,"保护/FA"))
			{//5001 保护/FA定值上送时需主动加1，因为列表值是0/1/2，需送值为1/2/3
				float2IECbuf(pbuf,(parBuf[sw*parTable+PUB_SET_NUMBER].ff) + (float)1);
			}
			else
		#endif
			{
				float2IECbuf(pbuf,parBuf[sw*parTable+PUB_SET_NUMBER].ff);
			}
		}
		rt_free(parBuf);
		return true;
	}

#if defined GD_AREA_ECZD_MAOMING || defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 || defined GD_AREA_ZHONGSHAN_2020_ZC || defined GD_AREA_MEIZHOU_FTU || defined GD_AREA_MEIZHOU_2021
	parTable=getSetTableOffset(&tEquipParaTable[0],EQUIP_PARA_NUMBER,parId,SETGROUP_TYPE_PARA, false);
	if(parTable != -1)
	{
		//parTable -= PUB_SET_NUMBER+SW_SET_NUMBER;
		//if(parTable > 0 && parTable < EQUIP_PARA_NUMBER)
		{
			rt_printf("%s Type=%d %d i=%d\r\n",tEquipParaTable[parTable].szName,parId,SETGROUP_TYPE_PARA,parTable);
			rt_printf("ReadRunParId=%02x offset=%d par=%f\r\n",parId,parTable,pparaBuf[parTable].ff);
			float2IECbuf(pbuf,pparaBuf[parTable].ff);
		}
		rt_free(pparaBuf);
		return true;
	}
	rt_free(pparaBuf);
#endif

#ifdef FUNC_YT_NO_ID
#ifdef YC_QUANTITY
	if((parId>=0x5001) && (parId<(0x5001+pRunSet->dYC_num)))
#else
	if((parId>=0x5001) && (parId<(0x5001+FOS_PAR_SW_NUM)))
#endif
	{
		rt_printf("遥调未配置的地址时以备用点(默认0值)上送\r\n");
		float2IECbuf(pbuf,(float)0);
		rt_free(parBuf);
		return true;
	}
#endif

	rt_free(parBuf);
#ifdef FUNC_YT_NO_ID
	rt_printf("0x%x>(0x5001+每间隔遥参数量)!!!\r\n",parId);
#endif
	rt_printf("读参数失败\r\n");
	return false;	
}
RMT_SET_VAL RmtSetValDef={0,0,UINT_R,4,{0,},};

int  iec_setread(void *pt,BYTE *pdat,BYTE vsq,bool b104) // dat从定值区号开始
{
	int len,i;
	u16 section;  // 定值区号	
	BYTE setnum=0;
	BYTE framelen = 0;
	BYTE datbuf[256] = {0};
	BYTE over=0;
	RMT_FIXED_TABLE tfixedset;	
	SET_PARAID *tmp_param;
	RMT_SET_VAL tmp_cst_val;
	SET_VALUE *psetbuf,*pparabuf,*pcstbuf,*ppubbuf;	

	section=pdat[0]+(pdat[1]<<8);	  // 定值区号

	if(section>=SEC_NUMBER)  // 定值区不为零,否定应答返回
	{
		rt_printf("\r\n远方读定值，定值区超出范围，否定应答\r\n");
		return -1;
	}

	ppubbuf = rt_malloc(PUB_SET_NUMBER*4);	
	if(!ppubbuf)
	{
		rt_printf("\r\n远方读定值，分配公共定值缓冲区错误!\r\n");
		return -1;
	}

	psetbuf = rt_malloc(SW_SET_NUMBER*4);	
	if(!psetbuf)
	{
		rt_free(ppubbuf);	
		rt_printf("\r\n远方读定值，分配开关定值缓冲区错误!\r\n");
		return -2;
	}	
	
	pparabuf = rt_malloc(EQUIP_PARA_NUMBER*4);
	if(!pparabuf)
	{
		rt_free(ppubbuf);	
		rt_free(psetbuf);
		rt_printf("\r\n远方读定值，分配参数缓冲区错误!\r\n");
		return -3;
	}		

	pcstbuf = rt_malloc(CSTSET_NUMBER*4);	
	if(!pcstbuf)
	{
		rt_free(ppubbuf);	
		rt_free(psetbuf);	
		rt_free(pparabuf);	
		rt_printf("\r\n远方读定值，分配内部定值缓冲区错误!\r\n");
		return -2;
	}

	if(!ReadPara((void*)ppubbuf,EEP_PUB_ADDR,PUB_SET_NUMBER,&tPubSetTable[0]))
	{
		GetDefPara((void*)ppubbuf,PUB_SET_NUMBER,&tPubSetTable[0]); 
	}

	if(!ReadPara((void*)psetbuf,EEP_SET_ADDR+m_runsection*SETSIZE,SW_SET_NUMBER,&tSwSetTable[0]))
	{
		GetDefPara((void*)psetbuf,SW_SET_NUMBER,&tSwSetTable[0]);
	}

	if(!ReadPara((void*)pparabuf,EEP_EQUIP_PARA_ADDR,EQUIP_PARA_NUMBER,&tEquipParaTable[0]))
	{
		GetDefPara((void*)pparabuf,EQUIP_PARA_NUMBER,&tEquipParaTable[0]);		
	}
	
	if(!ReadPara((void*)pcstbuf,EEP_CSTSET_ADDR,CSTSET_NUMBER,&tCstSetTable[0]))
	{
		GetDefPara((void*)pcstbuf,CSTSET_NUMBER,&tCstSetTable[0]);
	}

	iec_init_fixedset(pt,&tfixedset,b104);  // 获取固定定值

	datbuf[0]=(BYTE)section;	  // 区号
	datbuf[1]=(BYTE)(section>>8);
	datbuf[2]=0x01; // 参数特征标识，有后续
	framelen=3;
	setnum=0;

	if(vsq==0) //  读全部定值
	{
		for(i=0;i<tfixedset.num;i++) // 固定定值
		{
			tmp_cst_val=tfixedset.set[i];
			len=iec_add2frame(datbuf+framelen,&tmp_cst_val,b104);
			framelen+=len;
			setnum++;
			if(framelen>200)
			{
				if(b104)
				{
					IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,setnum,IEC_COT_ACTCON,202); // 		
				}
				else
				{
					IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,setnum,IEC_COT_ACTCON,202,FRAME_I);//
				}
				framelen=3;
				setnum=0;
			}
		}
		
		for(i=0;i<ParaIDNum;i++)
		{
			if(!tParaID[i].parId)
				continue;
		
					
			tmp_param= &tParaID[i];
			switch(tmp_param->group_type)
			{
				case SETGROUP_TYPE_PARA:			
				//	rt_printf("description：%s addr：%x   value：%f\r\n",tEquipParaTable[tmp_param->setno].szName,tmp_param->parId,pparabuf[tmp_param->setno].ff);
					iec_set2rmtset(&tmp_cst_val,tEquipParaTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pparabuf[tmp_param->setno].ff);
					break;
				case SETGROUP_TYPE_PUB:			
				//	rt_printf("description：%s addr：%x   value：%f\r\n",tPubSetTable[tmp_param->setno].szName,tmp_param->parId,ppubbuf[tmp_param->setno].ff);
					iec_set2rmtset(&tmp_cst_val,tPubSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,ppubbuf[tmp_param->setno].ff);
					break;
				case SETGROUP_TYPE_CSTSET:					
				//	rt_printf("description：%s addr：%x   value：%f\r\n",tCstSetTable[tmp_param->setno].szName,tmp_param->parId,pcstbuf[tmp_param->setno].ff);
					iec_set2rmtset(&tmp_cst_val,tCstSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pcstbuf[tmp_param->setno].ff);
					break;
				case SETGROUP_TYPE_BH:				
				//	rt_printf("description：%s addr：%x   value：%f\r\n",tSwSetTable[tmp_param->setno].szName,tmp_param->parId,psetbuf[tmp_param->setno].ff);	
					iec_set2rmtset(&tmp_cst_val,tSwSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,psetbuf[tmp_param->setno].ff);
					break;
				default:
					continue;
			}					
			
			tmp_cst_val.di = tmp_param->parId;
			len=iec_add2frame(datbuf+framelen,&tmp_cst_val,b104);
			framelen+=len;
			setnum++;
			
			if(i == ParaIDNum - 1)
			{
				over = 1;
			}	
		
			if((framelen > 200) || over)
			{
				if(over)  //最后的一帧,tag清零
				{
					datbuf[2]=0;	
				}
			
				if(b104)
				{
					IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,setnum,IEC_COT_ACTCON,202); // 
				}
				else
				{
					IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,setnum,IEC_COT_ACTCON,202,FRAME_I);//
				}
				framelen=3;
				setnum=0;
			}
		}
	}	
	else // 读定义点号的定值
	{
		BYTE *ps=&pdat[2]; //从点号开始
		for(i=0;i<vsq;i++)
		{
			int j;
			u16 di;
			bool bfind=false;	
			
			if(tfixedset.set[i].di==0)
				continue;

			di=ps[0]+(ps[1]<<8);		
			for(j=0;j<tfixedset.num;j++) // 固定定值
			{
				if(tfixedset.set[j].di==di)  // 点号对应
				{
					tmp_cst_val=tfixedset.set[j];
					bfind=true;
					break;
				}
			}

			if(!bfind)  
			{
				for(j=0;j<ParaIDNum;j++) //  修改定值
				{				
					if(di != tParaID[j].parId)
						continue;
													
					tmp_param= &tParaID[j];

					switch(tmp_param->group_type)
					{
						case SETGROUP_TYPE_PARA:
							iec_set2rmtset(&tmp_cst_val,tEquipParaTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pparabuf[tmp_param->setno].ff);
							break;
						case SETGROUP_TYPE_PUB:			
							iec_set2rmtset(&tmp_cst_val,tPubSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,ppubbuf[tmp_param->setno].ff);
							break;
						case SETGROUP_TYPE_CSTSET:				
							iec_set2rmtset(&tmp_cst_val,tCstSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pcstbuf[tmp_param->setno].ff);
							break;
						case SETGROUP_TYPE_BH:					
							iec_set2rmtset(&tmp_cst_val,tSwSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,psetbuf[tmp_param->setno].ff);
							break;
						default:
							continue;
					}	
					bfind=true;
					break;
				}
			}

			ps+=2;
			if(b104)ps++;
			// 组报文
			if(bfind)
			{
				tmp_cst_val.di=di;
				len=iec_add2frame(datbuf+framelen,&tmp_cst_val,b104);
				framelen+=len;
				setnum++;
			}
			if(framelen>200||i==vsq-1)
			{
				if(i==vsq-1)  //最后的一帧,tag清零
				{
					datbuf[2]=0;	
				}
				if(b104)
				{
					IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,setnum,IEC_COT_ACTCON,202); // 
				}
				else
				{
					IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,setnum,IEC_COT_ACTCON,202,FRAME_I);//
				}
				framelen=3;
				setnum=0;
			}
		}	
		
	}	

	rt_free(psetbuf);	
	rt_free(pparabuf);
	rt_free(pcstbuf);
	rt_free(ppubbuf);
	
	return 0;
}


int iec_get_equi_ip(char *ip,BYTE *p_out)
{	

    int i,j=0,k=0; 
	char str_ip[4]={'\0'};  

	for(i =0;i<=strlen(ip);i++)
    {  
        if (ip[i]=='\0'||ip[i]=='.')  
        {             
            p_out[k] =atoi(str_ip);   
            if (p_out[k]<0||p_out[k]>255)  
            {   
                return -1;                 
            }  

			k++;
			j=0;

			memset(str_ip,0,sizeof(str_ip));  
  
            continue;  
        }  
	
        str_ip[j]=ip[i];  
        j++;
		
    }     
	

	return 0;
}

#ifdef YPARA_LINK
/*0不级联,返回级联号*/
int get_ypara_linkch_write(void *pt,BYTE *pdat,BYTE vsq,bool b104)
{	
	BYTE *ps; //从点号开始
	u16 di = 0;
	int index=0;	
	BYTE   pdi;  //参数特征标识符
	u8  cmd=0,dport=0;
	

	if(b104)
	{
		IEC104_DEF *pt104 = pt;
		cmd = pt104->msg_ypara_send.ypara_msg.cmd;
		dport = pt104->msg_ypara_send.dport;
	}
	else
	{		
		IEC101_DEF *pt101 = pt;		
		cmd = pt101->msg_ypara_send.ypara_msg.cmd;		
		dport = pt101->msg_ypara_send.dport;
	}
	
	pdi = pdat[2];
	ps=&pdat[3];
	
		
	if((pdi&0xc0)==0) // 定值固化
	{
		if(cmd == YP_SEL)		/*有下发级联预置*/
		{
			return dport;
		}
		else
		{
			return 0;
		}
	}	
	else if((pdi&0xc0)==0x40)	/*撤销*/
	{
		if(cmd == YP_SEL)		/*有下发级联预置*/
		{
			return dport;
		}
		else
		{
			return 0;
		}
	}
	else // 参数预置
	{				
		di=ps[0]+(ps[1]<<8);		
			
		index = get_stbl_index_s(di);
		if(index < 0)	return 0;		/*点号不对*/	

		return tParaID[index].link_ch;	/*级联号*/
		
	}

}


int iec_setread_mananger(void *pt,BYTE *pdat,BYTE vsq,bool b104) // dat从定值区号开始
{
	int len,i;
	u16 section;  // 定值区号	
	BYTE setnum=0;
	BYTE framelen = 0;
	BYTE datbuf[256] = {0};
	BYTE over=0;
	RMT_FIXED_TABLE tfixedset;	
	SET_PARAID *tmp_param;
	SET_PARA_VAL *tmp_pval;
	RMT_SET_VAL tmp_cst_val;
	SET_VALUE *psetbuf,*pparabuf,*pcstbuf,*ppubbuf;		

	section=pdat[0]+(pdat[1]<<8);	  // 定值区号

	if(section>=SEC_NUMBER)  // 定值区不为零,否定应答返回
	{
		rt_printf("\r\n远方读定值，定值区超出范围，否定应答\r\n");
		return -1;
	}

	ppubbuf = rt_malloc(PUB_SET_NUMBER*4);	
	if(!ppubbuf)
	{
		rt_printf("\r\n远方读定值，分配公共定值缓冲区错误!\r\n");
		return -1;
	}

	psetbuf = rt_malloc(SW_SET_NUMBER*4);	
	if(!psetbuf)
	{
		rt_free(ppubbuf);	
		rt_printf("\r\n远方读定值，分配开关定值缓冲区错误!\r\n");
		return -2;
	}	
	
	pparabuf = rt_malloc(EQUIP_PARA_NUMBER*4);
	if(!pparabuf)
	{
		rt_free(ppubbuf);	
		rt_free(psetbuf);
		rt_printf("\r\n远方读定值，分配参数缓冲区错误!\r\n");
		return -3;
	}		

	pcstbuf = rt_malloc(CSTSET_NUMBER*4);	
	if(!pcstbuf)
	{
		rt_free(ppubbuf);	
		rt_free(psetbuf);	
		rt_free(pparabuf);	
		rt_printf("\r\n远方读定值，分配内部定值缓冲区错误!\r\n");
		return -2;
	}

	if(!ReadPara((void*)ppubbuf,EEP_PUB_ADDR,PUB_SET_NUMBER,&tPubSetTable[0]))
	{
		GetDefPara((void*)ppubbuf,PUB_SET_NUMBER,&tPubSetTable[0]); 
	}

	if(!ReadPara((void*)psetbuf,EEP_SET_ADDR+m_runsection*SETSIZE,SW_SET_NUMBER,&tSwSetTable[0]))
	{
		GetDefPara((void*)psetbuf,SW_SET_NUMBER,&tSwSetTable[0]);
	}

	if(!ReadPara((void*)pparabuf,EEP_EQUIP_PARA_ADDR,EQUIP_PARA_NUMBER,&tEquipParaTable[0]))
	{
		GetDefPara((void*)pparabuf,EQUIP_PARA_NUMBER,&tEquipParaTable[0]);		
	}
	
	if(!ReadPara((void*)pcstbuf,EEP_CSTSET_ADDR,CSTSET_NUMBER,&tCstSetTable[0]))
	{
		GetDefPara((void*)pcstbuf,CSTSET_NUMBER,&tCstSetTable[0]);
	}

	iec_init_fixedset(pt,&tfixedset,b104);  // 获取固定定值

	datbuf[0]=(BYTE)section;	  // 区号
	datbuf[1]=(BYTE)(section>>8);
	datbuf[2]=0x01; // 参数特征标识，有后续
	framelen=3;
	setnum=0;

	if(vsq==0) //  读全部定值
	{
		for(i=0;i<tfixedset.num;i++) // 固定定值
		{
			if(tfixedset.set[i].di==0)
				continue;
			tmp_cst_val=tfixedset.set[i];
			len=iec_add2frame(datbuf+framelen,&tmp_cst_val,b104);
			framelen+=len;
			setnum++;
			if(framelen>200)
			{
				if(b104)
				{
					IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,setnum,IEC_COT_ACTCON,202); // 		
				}
				else
				{
					IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,setnum,IEC_COT_ACTCON,202,FRAME_I);//
				}
				
				framelen=3;
				setnum=0;
			}
		}
		
		for(i=0;i<ParaIDNum;i++)
		{
			if(!tParaID[i].parId)
				continue;

			
			if(tParaID[i].link_ch == 0)		/*本地定值*/
			{				
				tmp_param= &tParaID[i];			
				switch(tmp_param->group_type)
				{
					case SETGROUP_TYPE_PARA:						
						iec_set2rmtset(&tmp_cst_val,tEquipParaTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pparabuf[tmp_param->setno].ff);
						break;
					case SETGROUP_TYPE_PUB:			
						iec_set2rmtset(&tmp_cst_val,tPubSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,ppubbuf[tmp_param->setno].ff);
						break;
					case SETGROUP_TYPE_CSTSET:					
						iec_set2rmtset(&tmp_cst_val,tCstSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pcstbuf[tmp_param->setno].ff);
						break;
					case SETGROUP_TYPE_BH:				
						iec_set2rmtset(&tmp_cst_val,tSwSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,psetbuf[tmp_param->setno].ff);
						break;
					default:
						continue;				
				}	
							
			}
			else
			{				
				/*级联定值的值*/					
				tmp_param= &tParaID[i];
				tmp_pval = &tPara_val[i];	

				tmp_cst_val.unit = tmp_pval->datatype;	
				tmp_cst_val.len =  tmp_pval->len;								
				memcpy(tmp_cst_val.str,tmp_pval->str,tmp_pval->len);				
			}	

			/*组包*/		
			tmp_cst_val.di = tmp_param->parId;
			len=iec_add2frame(datbuf+framelen,&tmp_cst_val,b104);
			framelen+=len;
			setnum++;
					
			if(i == ParaIDNum - 1)
			{
				over = 1;
			}			
		
			if((framelen > 200) || over)
			{
				if(over)  //最后的一帧,tag清零
				{
					datbuf[2]=0;	
				}
			
				if(b104)
				{
					IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,setnum,IEC_COT_ACTCON,202); // 
				}
				else
				{
					IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,setnum,IEC_COT_ACTCON,202,FRAME_I);//
				}
				framelen=3;
				setnum=0;
			}
		}
	}	
	else // 读定义点号的定值
	{
		BYTE *ps=&pdat[2]; //从点号开始
		for(i=0;i<vsq;i++)
		{
			int j;
			u16 di;
			bool bfind=false;
			
			di=ps[0]+(ps[1]<<8);		
			for(j=0;j<tfixedset.num;j++) // 固定定值
			{
				if(tfixedset.set[j].di==di)  // 点号对应
				{
					tmp_cst_val=tfixedset.set[j];
					bfind=true;
					break;
				}
			}

			if(!bfind)  
			{
				for(j=0;j<ParaIDNum;j++) //  修改定值
				{				
					if(di != tParaID[j].parId)
						continue;

					if(tParaID[j].link_ch == 0)		/*本地定值*/
					{				
						tmp_param= &tParaID[j];
						switch(tmp_param->group_type)
						{
							case SETGROUP_TYPE_PARA:			
								iec_set2rmtset(&tmp_cst_val,tEquipParaTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pparabuf[tmp_param->setno].ff);
								break;
							case SETGROUP_TYPE_PUB:			
								iec_set2rmtset(&tmp_cst_val,tPubSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,ppubbuf[tmp_param->setno].ff);
								break;
							case SETGROUP_TYPE_CSTSET:					
								iec_set2rmtset(&tmp_cst_val,tCstSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,pcstbuf[tmp_param->setno].ff);
								break;
							case SETGROUP_TYPE_BH:				
								iec_set2rmtset(&tmp_cst_val,tSwSetTable[tmp_param->setno].data_type,tmp_param->group_type,tmp_param->setno,psetbuf[tmp_param->setno].ff);
								break;
							default:
								continue;		
						}	
									
					}
					else
					{				
						/*级联定值的值*/					
						tmp_param= &tParaID[j];
						tmp_pval = &tPara_val[j];				
						tmp_cst_val.unit = tmp_pval->datatype;	
						tmp_cst_val.len =  tmp_pval->len;								
						memcpy(tmp_cst_val.str,tmp_pval->str,tmp_pval->len);																	
					}	
					
					bfind=true;
					break;
				}
			}

			ps+=2;
			if(b104)ps++;

			
			// 组报文
			if(bfind)
			{
				tmp_cst_val.di=di;
				len=iec_add2frame(datbuf+framelen,&tmp_cst_val,b104);
				framelen+=len;
				setnum++;
			}
			
			if(framelen>200||i==vsq-1)
			{
				if(i==vsq-1)  //最后的一帧,tag清零
				{
					datbuf[2]=0;	
				}
				if(b104)
				{
					IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,setnum,IEC_COT_ACTCON,202); // 
				}
				else
				{
					IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,setnum,IEC_COT_ACTCON,202,FRAME_I);//
				}
				framelen=3;
				setnum=0;
			}
		}	
		
	}	

	rt_free(psetbuf);	
	rt_free(pparabuf);
	rt_free(pcstbuf);
	rt_free(ppubbuf);
	
	return 0;
}

#endif

#ifdef YPARA_LINK_S
void set_para_flag(void)
{
	int net;
	IEC104_DEF *pt;

	for(net=0; net<CFG_ETH_MAX_LOGIC; net++)
	{
		pt=&g_t104[net];
		pt->para_updata_flag=1;			
	}	
}

#endif

int  iec_rmtset2set( RMT_SET_DATA *rsd,BYTE *pdat ,bool b104)
{
	int i,len,index;
	BYTE Tag,addoff=0;
	WORD di;
	bool  bover=false;
	di=pdat[0]+(pdat[1]<<8);
	index=0;
	for(i=0;i<RMT_SET_NUMBER;i++)
	{
		if(rsd->di[i]==di) // 预置数据中有对应的点号的定值，覆盖
		{
			index=i;
			bover=true;
			break;
		}
	}
	if(!bover)
	{
		for(i=0;i<RMT_SET_NUMBER;i++)
		{
			if(rsd->di[i]==0) //结构中有点号为0的，可以使用
			{
				index=i;
				break;
			}
		}
	}
	
	if(b104)addoff=1;
	Tag=pdat[2+addoff];
	len=pdat[3+addoff];
	pdat+=(4+addoff);
	rsd->di[index]=di;	
	switch(Tag)
	{
		case BOOL_R:
		case TINY_R:
		case UTINY_R:
			rsd->val[index]=pdat[0];
			break;		
		case UINT_R:
		case INT_R:
		case LONG_R:
		case ULONG_R:
			rsd->val[index]=(pdat[0]+(pdat[1]<<8)+(pdat[2]<<16)+(pdat[3]<<24));
			break;
		case SHORT_R:
		case USHORT_R:
			rsd->val[index]=(pdat[0]+(pdat[1]<<8));
			break;		
		case FLOAT_R:
			{
				union{
					float ff;
					u8 tt[4];
					}ff;	
				CopySwap(ff.tt,pdat,4,false);		
				rsd->val[index]=ff.ff;
				break;	
			}
		case STR_R:
			{
				memset(rsd->t_str[rmt_str_cnt].str,0,sizeof(rsd->t_str[rmt_str_cnt].str));
				memcpy(rsd->t_str[rmt_str_cnt].str,pdat,len);
				rsd->t_str[rmt_str_cnt].di = rsd->di[index];
				rt_printf("%s:di=%04x,str=%s\r\n",__func__,rsd->t_str[rmt_str_cnt].di,rsd->t_str[rmt_str_cnt].str);
				rmt_str_cnt++;
			}
			break;
		default:
			rsd->val[index]=0;	
		      break;			
		
	}

	return len;
}
int iec_set_section=0;

int  iec_saveset( RMT_SET_DATA *rsd)
{
	SET_VALUE *psetbuf,*pparabuf,*pcstbuf;	
	int i;
	bool bset=false,bpara=false,bcst=false;
	int ret=-1;
	SET_PARAID *tmp_param;

	if(!pRunSet->bTT_EDIT_YB)	//远方修改未投入
	{
		for(i=0;i<RMT_SET_NUMBER;i++)
		{
			rsd->di[i]=0;
		}
		rsd->bpreset=false;	
		rt_printf("\r\n远方修改定值未投入!\r\n");
		return -1;			
	}
	psetbuf = rt_malloc(SET_NUMBER*4);	
	if(!psetbuf)
	{
		rt_printf("\r\n远方固化定值，分配定值缓冲区错误!\r\n");
		return -2;
	}	
	pparabuf = rt_malloc(EQUIP_PARA_NUMBER*4);
	if(!pparabuf)
	{
		rt_free(psetbuf);
		rt_printf("\r\n远方固化定值，分配参数缓冲区错误!\r\n");
		return -3;
	}		

	pcstbuf = rt_malloc(CSTSET_NUMBER*4);
	if(!pcstbuf)
	{
		//rt_free(pcstbuf);
		rt_free(psetbuf);
		rt_free(pparabuf);
		rt_printf("\r\n远方固化定值，分配内部定值缓冲区错误!\r\n");
		return -4;
	}	

	if(!ReadSet(iec_set_section,(void *)psetbuf))  // 读定值
	{
		GetDefSet((float*)psetbuf);
		
	}
	if(!ReadPara((void*)pparabuf,EEP_EQUIP_PARA_ADDR,EQUIP_PARA_NUMBER,&tEquipParaTable[0]))// 读参数
	{
		GetDefPara((void*)pparabuf,EQUIP_PARA_NUMBER,&tEquipParaTable[0]);		
	}

	 /*读取内部定值*/
	if(!ReadPara((void*)pcstbuf,EEP_CSTSET_ADDR,CSTSET_NUMBER,&tCstSetTable[0]))
	{
		GetDefPara((void*)pcstbuf,CSTSET_NUMBER,&tCstSetTable[0]);
	}
	for(i=0;i<RMT_SET_NUMBER;i++)
	{
		int j;
		WORD di;
		bool bfind=false;
		di=rsd->di[i];
		if(di==0)continue;
		
		for(j=0;j<ParaIDNum;j++)
		{
			int k;
			if(di != tParaID[j].parId)	
				continue;
			
			tmp_param = &tParaID[j];
			switch(tmp_param->group_type)
			{
				case SETGROUP_TYPE_PARA:					
				if(tEquipParaTable[tmp_param->setno].wType == SETTYPE_IP)
				{
					union{
					float ff;
					u8 tt[4];
					}ff;

					for(k=0;k<rmt_str_cnt;k++)
					{
						if(di == rsd->t_str[k].di)
						{
							if(iec_get_equi_ip(rsd->t_str[k].str,ff.tt)==0)
							{
								pparabuf[tmp_param->setno].ff=ff.ff; 
							}
							bpara=true;
							break;
						}
					}
				}
				else
				{
					pparabuf[tmp_param->setno].ff=rsd->val[i];
				}
				bpara=true;
				break;
				case SETGROUP_TYPE_PUB:					
				psetbuf[tmp_param->setno].ff=rsd->val[i];
				bset=true;
				break;

				case SETGROUP_TYPE_CSTSET:					
				pcstbuf[tmp_param->setno].ff=rsd->val[i];
				bcst=true;
				break;
				case SETGROUP_TYPE_BH:			// 第一个开关的定值
				psetbuf[PUB_SET_NUMBER+tmp_param->setno].ff=rsd->val[i];
				bset=true;
				break;
				default:break;
			}		
			bfind=true;
		}

		rsd->di[i] = 0;
		rsd->val[i] = 0;
		
	}

	if(bset)	
	{
		if(SaveSet(iec_set_section,(void *)psetbuf))
		{
			soe_record_opt(EV_SET_OK,0);
			if(iec_set_section != m_runsection)	rt_printf("----iec_set_section=%d,m_runsection=%d\r\n",iec_set_section,m_runsection);
			//if(iec_set_section==m_runsection)
			{				
				MakeRunSet(false); 
				rt_err_clr(ERR_CODE_SET,0);
			}

		}
		else
		{
			soe_record_opt(EV_SET_FAIL,0);
		}
		ret=0;
	}
	if(bpara)
	{
		if(SavePara((void *)pparabuf,EEP_EQUIP_PARA_ADDR,EQUIP_PARA_NUMBER,&tEquipParaTable[0]))
		{
			soe_record_opt(EV_EQUPARA_OK,0);
			MakeRunPara(false, false); 
			rt_err_clr(ERR_CODE_EQU_PARA,0);
		}
		else
		{
			soe_record_opt(EV_EQUPARA_FAIL,0);
		}
		ret=0;
	}
	if(bcst)	
	{
		if(SavePara((void *)pcstbuf,EEP_CSTSET_ADDR,CSTSET_NUMBER,&tCstSetTable[0]))
		{
			soe_record_opt(EV_CSTSET_OK,0);
			MakeRunSet(false); 
			rt_err_clr(ERR_CODE_SET_IN,0);
		}
		else
		{
			soe_record_opt(EV_CSTSET_FAIL,0);
		}
		ret=0;
	}
#ifdef YPARA_LINK_S
	set_para_flag();
#endif
	rt_free(psetbuf); // sunxi 20180719 added
	rt_free(pparabuf); // sunxi 20180719 added
	rt_free(pcstbuf); // sunxi 20180719 added
	return ret;
}
int  iec_setwrite(void *pt,BYTE *pdat,BYTE cot,BYTE vsq,bool b104) // dat从定值区号开始
{
	WORD section;  // 定值区号	
	BYTE   pdi;  //参数特征标识符
	int ret=0;

	RMT_SET_DATA *rsd;

	if(b104)
	{
		IEC104_DEF *pt104=(IEC104_DEF *)pt;
		rsd=&pt104->tr;
	}
	else
	{
		IEC101_DEF *pt101=(IEC101_DEF *)pt;
		rsd=&pt101->tr;
	}


	section=pdat[0]+(pdat[1]<<8);	  // 定值区号
	pdi=pdat[2];

	if(section>=SEC_NUMBER)
	{
		rt_printf("\r\n远方修改定值，定值区越限=%d，否定应答\r\n",section);
		return -1;
	}

	iec_set_section=section;
	if(((pdi&0xc0)==0)&&cot==0x06) // 定值固化
	{
		ret=iec_saveset(rsd);
		rsd->bpreset=false;
	}
	else if(vsq>0&&((pdi&0xc0)==0x80)&&cot==0x06) // 参数预置
	{
		int i;
		rmt_str_cnt=0;
		pdat+=3;
		for(i=0;i<vsq;i++)
		{	
			int len;
			len=iec_rmtset2set(rsd,&pdat[0],b104);
			pdat+=(4+len);
			if(b104)pdat+=1;
		}
		rsd->bpreset=true;
		rsd->us0_preset=ustimer_get_origin();
		
	}
	else if(((pdi&0xc0)==0x40)&&cot==0x09) // 取消预置
	{
		int i;
		rmt_str_cnt=0;
		for(i=0;i<RMT_SET_NUMBER;i++)
		{
			rsd->di[i]=0;
		}
		rsd->bpreset=false;
	}
	else
	{
		rt_printf("\r\n远方修改定值否定应答，vsq:%d 传送原因:0x%02x 特征表示符:0x%02x \r\n",vsq,cot,pdi);
		ret= -2;
	}	
	return ret;

}

void iec_printfixedset(void)
{

	int i;
	WORD index;
	RMT_FIXED_TABLE tfixedset;	
	iec_init_fixedset(&g_t104[0],&tfixedset,true);  // 获取固定定值
	rt_printf("\r\n点号      名称                 信息");
	for(i=0;i<tfixedset.num;i++)
	{
		index=tfixedsettable[i].index;		
		if(index==FIXED_SET_CRC) //  软件版本号
		{
			rt_printf("\r\n%04x  %-24s%04x",tfixedsettable[i].di,tfixedsettable[i].name,(tfixedset.set[i].str[0]+(tfixedset.set[i].str[1]<<8)));
		}
		else if(index==FIXED_SET_MAC1||index==FIXED_SET_MAC2) //  软件版本号
		{
			rt_printf("\r\n%04x  %-24s%02x-%02x-%02x-%02x-%02x-%02x",tfixedsettable[i].di,tfixedsettable[i].name,
					tfixedset.set[i].str[0],tfixedset.set[i].str[1],tfixedset.set[i].str[2],tfixedset.set[i].str[3],tfixedset.set[i].str[4],tfixedset.set[i].str[5]);

		}
		else
		{
			rt_printf("\r\n%04x  %-24s%s",tfixedset.set[i].di,tfixedsettable[i].name,tfixedset.set[i].str);
		}
	} 
}


/**************************************************************************
函数名称：iec_Direct_Echo
函数版本：1.00 
作者：   
创建日期：2007.9.1     
函数功能说明：101规约目录响应
输出参数：pt101缓冲区地址，COT 传送原因
返回值：

更新信息：
更新日志1：
日期：	  
修改者：	  
修改内容：  
修改原因：
***************************************************************************/
 
void iec_dir_echo(void *pt,char *buf,bool b104) // buf 从  操作标识下一字节开始
{
	int i;
	char *pdat;
	char cf;// 操作及召唤标识
	int id; // 目录ID
	BYTE namelen;
	char namestr[64];
	int filenum;
	struct dir_file_struct *pdir,*pdirfree;
	BYTE framelen,filescnt;
	char  datbuf[256];
	char *dir;
	struct rtc_time_t ts,te;
	T_FILE *ptfile;
	if(b104)	ptfile=&((IEC104_DEF *)pt)->tf;
	else		 ptfile=&((IEC101_DEF *)pt)->tf;

	pdat=buf;
	id=pdat[0]+(pdat[1]<<8)+(pdat[2]<<16)+(pdat[3]<<24); // 目录ID
	pdat+=4;
	namelen=*pdat++; // 目录长度
	dir=NULL;	
	strcpy(ptfile->dirpath,"");
	if(namelen>0)
	{
		for(i=0;i<namelen;i++)
		{
			namestr[i]=*pdat++;
		}
#ifdef 	FUN_PATH_TEST	
		if(strstr(namestr,"COMTRADE") != NULL)	/*录波文件*/
		{			
			strcpy(ptfile->dirpath,HF_WAVE_DIR);			
		}
		else
		{
			sprintf(ptfile->dirpath,"/app/%s/",namestr);
		}
#else   
		sprintf(ptfile->dirpath,"/app/%s/",namestr);
#endif
		namestr[namelen]='\0';  // 目录名称字符串结束符
		dir=namestr;
		if(namestr[0]=='/')
		{
			sprintf(ptfile->dirpath,"/app%s/",namestr);//去掉'/'
		}
		else
		{
			sprintf(ptfile->dirpath,"/app/%s/",namestr);
		}
	}	
	cf=*pdat++; // 召唤标识	
	ts.ms=pdat[0]+(pdat[1]<<8);  //查询起始时间
	pdat+=2;
	ts.min=*pdat++;
	ts.hour=*pdat++;
	ts.day=*pdat++;
	ts.month=*pdat++;
	ts.year=*pdat++;
	
	ts.min&=0x3f;            
	ts.hour&=0x1f;
	ts.month&=0x0f;
	ts.day&=0x1f;
	
	te.ms=pdat[0]+(pdat[1]<<8); //查询终止时间
	pdat+=2;
	te.min=*pdat++;
	te.hour=*pdat++;
	te.day=*pdat++;
	te.month=*pdat++;
	te.year=*pdat++;	

	te.min&=0x3f;
	te.hour&=0x1f;
	te.month&=0x0f;
	te.day&=0x1f;
	
	pdir=hf_get_dir_file_n(id,ptfile->dirpath,cf,&ts,&te,&filenum);	 // 根据信息体地址，判断读读哪个目录，获取目录信息
	if(pdir==NULL)	
	{
		filenum=0;
	}	

	pdirfree=pdir;
	// 组织报文
	filescnt=0;
	framelen=0;
	pdat=datbuf;	
	pdat[framelen++]=0; //信息体地址
	pdat[framelen++]=0;
	if(b104)pdat[framelen++]=0;
	pdat[framelen++]=2;// 附加数据包类型
	pdat[framelen++]=2; // 读目录
	pdat[framelen++]=(filenum>0)?0:1;// 结果描述符 :=1 失败

	pdat[framelen++]=(BYTE)(id>>0);  // 标识
	pdat[framelen++]=(BYTE)(id>>8);
	pdat[framelen++]=(BYTE)(id>>16);
	pdat[framelen++]=(BYTE)(id>>24);
	pdat[framelen++]=0; // 后续标识
	pdat[framelen++]=filescnt;  // 文件数量
	if(filenum==0)
	{
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210); // 
	
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210,FRAME_I);//
		}
		return ;
	}
	datbuf[9+b104]=1; // 后续标识	
	pdat=&datbuf[framelen];
	for(i=0;i<filenum;i++)
	{
		struct rtc_time_t rtc;
		u8 week;
		int len;
		len=strlen(pdir->name);
		*pdat++=len;  //文件名长度
		memcpy(pdat,pdir->name,len);
		pdat+=len;
		*pdat++=0;  //文件属性
	        /*文件长度*/
	        *pdat++ = (BYTE)(pdir->file_size);
	        *pdat++ = (BYTE)(pdir->file_size>>8);
	        *pdat++ = (BYTE)(pdir->file_size>>16);
	        *pdat++ = (BYTE)(pdir->file_size>>24);

	        /*日历时钟*/
	        timespec_to_rtc(pdir->file_time,&rtc,1);		        
		 week = WEEK_DAY(pdir->file_time.tv_sec);
	        *pdat++  = (BYTE)(rtc.ms);
	        *pdat++  = (BYTE)(rtc.ms>>8);
	        *pdat++  = (BYTE)(rtc.min);
	        *pdat++  = (BYTE)(rtc.hour);
	        *pdat++  = (BYTE)((week<<5) |rtc.day);
	        *pdat++  = (BYTE)(rtc.month);
	        *pdat++  = (BYTE)(rtc.year);
		framelen+=len+13;
		filescnt++;
		pdir++;
		if(framelen>160||i==(filenum-1))
		{
			if(i==(filenum-1))
			{
				datbuf[9+b104]=0; // 后续标识	
			}
			datbuf[10+b104]=filescnt;  // 文件数量
			if(b104)
			{
				 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210); // 
				ptfile=&((IEC104_DEF *)pt)->tf;

			}
			else
			{
				IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210,FRAME_I);//
				 ptfile=&((IEC101_DEF *)pt)->tf;
			}
			
			framelen=11+b104;
			filescnt=0;
			pdat=&datbuf[framelen];

			
		}
	}
	rt_free(pdirfree);	
}


void iec_readfile_echo(void *pt,char *buf,bool b104) //  buf 从  操作标识下一字节开始 
{
	int i;
	char *pdat,*pfilebuf;
	BYTE namelen,framelen;
	int filelenth;
	//char namestr[64],tmpstr[64];
	char namestr[256],tmpstr[256];//modify by sunxi: 20220629 
	char  datbuf[256];
	uint32_t id;
	T_FILE *ptfile;
	int mulen=0;
	if(b104)	 ptfile=&((IEC104_DEF *)pt)->tf;
	else        ptfile=&((IEC101_DEF *)pt)->tf;

	pdat=buf;
	namelen=*pdat++; // 目录长度
	if(namelen>256)//modify by sunxi: 20220629 这里的长度有可能会超过256！！！
	{
		namelen = 255;
		rt_printf("iec_readfile_echo--------- namelen > 256 !!!!! error!!!\r\n");
	}
	
	strcpy(tmpstr,ptfile->dirpath);
	//if(namelen>0)
	{
		for(i=0;i<namelen;i++)
		{
			namestr[i]=*pdat++;
			if(namestr[i]=='/') // 文件名称带目录，记录目录结束位置
			{
				mulen=i;
			}
		}
	}
	namestr[namelen]='\0';  // 文件名称字符串结束符
	if(mulen>0&&mulen<namelen) // 文件名带目录
	{
		mulen+=1;  //将下发名称的目录信息去掉
	}
	
#ifdef	RCD_STRAN_S
	if(strncmp(namestr,"BAY",3) == 0)	/*录波文件*/
	{
		strcpy(tmpstr,HF_WAVE_DIR); 			
		rt_printf_time("-------传输文件%s激活\r\n",namestr);
		if(ptfile->bTransing||ptfile->bdatTraned)	/*激活文件时有文件传输，释放*/
		{
			iec_freefile(ptfile);			
		}	
	}	
#endif

#ifdef 	FUN_DIR_DEPTH
	if(strncmp(namestr,"soe",strlen("soe")) == 0)	
	{
		if(strstr(ptfile->dirpath,"HISTORY")) strcpy(tmpstr,HF_SOE_101_DIR);	
	}
	else if(strncmp(namestr,"ulog",strlen("ulog")) == 0)	
	{		
		if(strstr(ptfile->dirpath,"HISTORY")) strcpy(tmpstr,HF_LOG_101_DIR);	
	}
	else if(strncmp(namestr,"co",strlen("co")) == 0)	
	{
		if(strstr(ptfile->dirpath,"HISTORY")) strcpy(tmpstr,HF_CO_101_DIR); 				
	}
#endif
	strcat(tmpstr,&namestr[mulen]);

	if(strcmp(p_his_file[HS_FILE_SOE],&namestr[mulen])==0)
	{
		if(!del_history_file(HS_FILE_SOE))
		{
			create_event_rcd_file(HS_FILE_SOE);
		}
		//rt_printf("%s:tmpstr=%s,namestr=%s\r\n",__func__,tmpstr,&namestr[mulen]);
	}
	else if(strcmp(p_his_file[HS_FILE_CO],&namestr[mulen])==0)
	{
		if(!del_history_file(HS_FILE_CO))
		{
			create_event_rcd_file(HS_FILE_CO);
		}
		//rt_printf("%s:tmpstr=%s,namestr=%s\r\n",__func__,tmpstr,&namestr[mulen]);
	}
	

	pfilebuf=hf_get_file_inf_n(tmpstr,&id,&filelenth);
	if(pfilebuf==NULL)
	{
		id=0;
		filelenth=0;
	}

	// 组织报文
	pdat=datbuf;	
	framelen=0;
	pdat[framelen++]=0; //信息体地址
	pdat[framelen++]=0;
	if(b104)pdat[framelen++]=0;
	pdat[framelen++]=2;// 附加数据包类型
	pdat[framelen++]=4; // 读文件激活
	pdat[framelen++]=(filelenth>0)?0:1;// 结果描述符 :=1 失败
	pdat[framelen++]=namelen;  //文件名长度	
	for(i=0;i<namelen;i++)
	{
		pdat[framelen++]=namestr[i];
	}
        /*文件标识*/
	pdat[framelen++] = (BYTE)(id);
       pdat[framelen++] = (BYTE)(id>>8);
       pdat[framelen++] = (BYTE)(id>>16);
	pdat[framelen++] = (BYTE)(id>>24);

        /*文件长度*/
	pdat[framelen++] = (BYTE)(filelenth);
       pdat[framelen++] = (BYTE)(filelenth>>8);
       pdat[framelen++] = (BYTE)(filelenth>>16);
	pdat[framelen++] = (BYTE)(filelenth>>24);
	
	if(b104)
	{
		 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,ptfile->vsq,IEC_COT_ACTCON,210); //
	}
	else
	{
		IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,ptfile->vsq,IEC_COT_ACTCON,210,FRAME_I);//
	}

	//设置文件传输标志，在各规约处理中发送
	if(filelenth>0)
	{
		ptfile->pfilebuf=pfilebuf;
		ptfile->bTransing=true;
		ptfile->offset=0;
		ptfile->id=id;
		ptfile->filelenth=filelenth;
		ptfile->us0_file_trans=ustimer_get_origin();
		
		
	}	
}


void  iec_readfile_send(void *pt,bool b104) //
{
	int i;
	char *pdat;
	BYTE framelen;
	char  datbuf[256];
	T_FILE *ptfile;
	bool beof=false;
	BYTE checksum=0;
	int datalen=FILE_SEND_FRAME_LENTH;

	if(b104)
	{
		 ptfile=&((IEC104_DEF *)pt)->tf;
	}
	else
	{
		 ptfile=&((IEC101_DEF *)pt)->tf;
	}

	if(!ptfile->bTransing||ptfile->offset>=ptfile->filelenth)return ;
	if(ptfile->offset+FILE_SEND_FRAME_LENTH>=ptfile->filelenth)
	{
		datalen=ptfile->filelenth-ptfile->offset;  //最后一帧传输的字节数
		beof=true;
	}

	// 组织报文
	pdat=datbuf;	\
	framelen=0;
	pdat[framelen++]=0; //信息体地址
	pdat[framelen++]=0;
	if(b104)pdat[framelen++]=0;
	pdat[framelen++]=2;// 附加数据包类型
	pdat[framelen++]=5; //读文件数据响应
        /*文件标识*/
	pdat[framelen++] = (BYTE)(ptfile->id);
       pdat[framelen++] = (BYTE)(ptfile->id>>8);
       pdat[framelen++] = (BYTE)(ptfile->id>>16);
	pdat[framelen++] = (BYTE)(ptfile->id>>24);
        /*文件偏移*/
	pdat[framelen++] = (BYTE)(ptfile->offset);
       pdat[framelen++] = (BYTE)(ptfile->offset>>8);
       pdat[framelen++] = (BYTE)(ptfile->offset>>16);
	pdat[framelen++] = (BYTE)(ptfile->offset>>24);
	pdat[framelen++] = beof?0:1; //	后续标志 0：无后续  1：有后续
	
	for(i=0;i<datalen;i++)
	{
		BYTE dd;
		dd=ptfile->pfilebuf[ptfile->offset+i];
		pdat[framelen++] = dd;
		checksum+=dd;
	}
	pdat[framelen++] = checksum; //	校验和
	
	if(b104)
	{
		 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210); //

		 if(!beof)
		 {
			ptfile->offset+=FILE_SEND_FRAME_LENTH;
			ptfile->bTransing=true;    //  104规约 继续传输
		 }
	}
	else
	{
		IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210,FRAME_I);//

		if(pRunSet->bTT_101Transsure)
		{
			ptfile->bTransing=false;    //  101规约  bTransing 在收到文件接收确认帧后置位，启动发送
		}
		else
		{
			 if(!beof)
			 {
				ptfile->offset+=FILE_SEND_FRAME_LENTH;
				ptfile->bTransing=true;    //  继续传输
			 }
		}
	}
	if(beof)  // 文件传输完毕
	{
	#ifdef RCD_STRAN_S
		newrcd_queque *rcd;
		if(!b104)
		{
			rcd=&((IEC101_DEF *)pt)->rcd_qt;
			del_data_queue(&rcd->queue);		
			log_str_time(LOG_OPERATE,"文件传输结束",0,1); 
		}
		else
		{
			rcd=&((IEC104_DEF *)pt)->rcd_qt;
			del_data_queue(&rcd->queue);	
			rt_printf("---------文件传输结束,清缓存\r\n");
			log_str_time(LOG_OPERATE,"文件传输结束",0,1); 
		}
	#endif
		ptfile->bTransing=false;
		ptfile->bdatTraned=false;
		iec_freefile(ptfile);
	}
	else
	{	
		ptfile->bdatTraned=true;
		ptfile->us0_file_trans=ustimer_get_origin();	   	
	}
}
void iec_readfile_sure(void *pt,u8 *buf,bool b104) //buf 从  操作标识下一字节开始 
{
	T_FILE *ptfile;
	BYTE *pdat;
	DWORD id,offset;
	pdat=buf;
	id=pdat[0]|(pdat[1]<<8)|(pdat[2]<<16)|(pdat[3]<<24); // 目录ID
	pdat+=4;
	offset=pdat[0]+(pdat[1]<<8)+(pdat[2]<<16)+(pdat[3]<<24); // 偏移

	if(b104)
	{
		 ptfile=&((IEC104_DEF *)pt)->tf;
	}
	else
	{
		 ptfile=&((IEC101_DEF *)pt)->tf;
	}
	if(ptfile->id!=id||
		(offset+FILE_SEND_FRAME_LENTH>=ptfile->filelenth))
	{
		return; // 文件已传输完毕
	}
	ptfile->offset=offset+FILE_SEND_FRAME_LENTH;  // 将偏移增加，继续传输
	ptfile->bTransing=true;
	ptfile->bdatTraned=false;
}

void iec_freefile(T_FILE *ptfile) // dat  从信息对象开始
{
	if(ptfile->pfilebuf==NULL)return;
	rt_free(ptfile->pfilebuf);
	ptfile->pfilebuf=NULL;
	rt_printf("\r\n文件节传输完毕，释放内存，文件ID:%d 长度:%d\r\n",ptfile->id,ptfile->filelenth);
}


void iec_writefile_echo(void *pt,BYTE *buf,bool b104) //  buf 从  操作标识下一字节开始 
{
	int i;
	BYTE *pdat;
	BYTE namelen,framelen,ret;
	char namestr[64];
	char  datbuf[256];
	T_FILE *ptfile;
	if(b104)	 ptfile=&((IEC104_DEF *)pt)->tf;
	else        ptfile=&((IEC101_DEF *)pt)->tf;

	pdat=buf;
	namelen=*pdat++; // 长度
	if(namelen>=64)namelen=63;  // 文件名不能超过64字节
	if(namelen>0)
	{
		for(i=0;i<namelen;i++)
		{
			namestr[i]=*pdat++;
		}
	}
	namestr[namelen]='\0';  // 文件名称字符串结束符
	strcpy(ptfile->wfilename,"/tmp/");
	strcat(ptfile->wfilename,namestr);
	//if(ptfile->bUpdateStart) // 启动程序更新，备份升级文件名称
	{
		strcpy(ptfile->updatefilename,namestr);
	}
	ptfile->wId=pdat[0]|(pdat[1]<<8)|(pdat[2]<<16)|(pdat[3]<<24);
	pdat+=4;
	ptfile->wfilelenth=pdat[0]|(pdat[1]<<8)|(pdat[2]<<16)|(pdat[3]<<24);

	rt_printf("\r\n%s wlenth=%d",ptfile->wfilename,ptfile->wfilelenth);

	
	if(strstr(KO_FILE_NAME,namestr)==NULL)
	{
		ret=2;
	}
	else if(ptfile->wfilelenth>=2048*1024)  // 文件大于2M
	{
		ret=3;
	}
	else
	{
		ret=0;
	}
	// 组织报文
	pdat=datbuf;	\
	framelen=0;
	pdat[framelen++]=0; //信息体地址
	pdat[framelen++]=0;
	if(b104)pdat[framelen++]=0;	
	pdat[framelen++]=2;// 附加数据包类型
	pdat[framelen++]=8; // 写文件激活
	pdat[framelen++]=ret;// 结果描述符 :=2 未知文件名
	pdat[framelen++]=namelen;  //文件名长度	
	for(i=0;i<namelen;i++)
	{
		pdat[framelen++]=namestr[i];
	}
        /*文件标识*/
	pdat[framelen++] = (BYTE)(ptfile->wId);
       pdat[framelen++] = (BYTE)(ptfile->wId>>8);
       pdat[framelen++] = (BYTE)(ptfile->wId>>16);
	pdat[framelen++] = (BYTE)(ptfile->wId>>24);

        /*文件长度*/
	pdat[framelen++] = (BYTE)(ptfile->wfilelenth);
       pdat[framelen++] = (BYTE)(ptfile->wfilelenth>>8);
       pdat[framelen++] = (BYTE)(ptfile->wfilelenth>>16);
	pdat[framelen++] = (BYTE)(ptfile->wfilelenth>>24);
	
	if(b104)
	{
		 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,ptfile->vsq,IEC_COT_ACTCON,210); //
	}
	else
	{
		IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,ptfile->vsq,IEC_COT_ACTCON,210,FRAME_I);//
	}

	if(ret==0)  // 创建写文件接收缓冲区
	{
		
		ptfile->writebuf= rt_malloc(ptfile->wfilelenth); //

		if(!ptfile->writebuf)
		{
			rt_printf("%s:rt_malloc eror\r\n", __func__);
			return ;
		}
		ptfile->us0_file_write=ustimer_get_origin();	   	
		ptfile->bdatwriting=true;
	}	
}

void iec_writefile_sure(void *pt,BYTE *buf,bool b104,u8 datlen) //  buf 从  操作标识下一字节开始  datlen为含操作标识的报文长度，即文档中关于文件相关报文的长度
{
	int i;
	BYTE *pdat;
	BYTE framelen,ret;
	u32 id,offset;
	char  datbuf[256];
	T_FILE *ptfile;
	bool beof=false;
	if(b104)	 ptfile=&((IEC104_DEF *)pt)->tf;
	else        ptfile=&((IEC101_DEF *)pt)->tf;

	pdat=buf;
	id=pdat[0]|(pdat[1]<<8)|(pdat[2]<<16)|(pdat[3]<<24);
	pdat+=4;
	offset=pdat[0]|(pdat[1]<<8)|(pdat[2]<<16)|(pdat[3]<<24);
	pdat+=4;
	pdat+=1;  //后续标识
	datlen-=11;
	ret=0;	

	for(i=0;i<datlen;i++)
	{
		if((offset+i)<ptfile->wfilelenth)
		{
			if(ptfile->writebuf) ptfile->writebuf[offset+i]=*pdat++;
		}
	}	
	if((offset+datlen)>=ptfile->wfilelenth)
	{
		beof=true;
	}	
	ptfile->us0_file_write=ustimer_get_origin();	   	

	if(id!=ptfile->wId) // id不一致
	{
		ret=4;
		beof=true;
		rt_printf("写文件: %s ID不一致! id=%d,wId=%d\r\n",ptfile->wfilename,id,ptfile->wId);		
	}
	if(ptfile->bUpdateCancel)
	{
		ptfile->bUpdateCancel=false;
		beof=true;
		ret=1;
	}
	if(beof)  //文件结束，写缓冲到文件中
	{

		loff_t pos;
		int retlen;
		//创建文件
		struct file * 	handle;
		if(ret==0)
		{	
			handle = rt_file_open(ptfile->wfilename,O_CREAT|O_RDWR|O_TRUNC,0);
			if(IS_ERR(handle))
			{ 
				rt_printf("\r\n写文件: %s 创建失败!\r\n",ptfile->wfilename);
				ret=1;				
			} 
			else
			{
				pos=0;
				retlen=rt_file_write(handle,ptfile->writebuf,ptfile->wfilelenth,&pos);
				rt_printf("\r\n写文件: %s 返回%d  filelenth=%d\r\n",ptfile->wfilename,retlen,ptfile->wfilelenth);
				if(retlen!=ptfile->wfilelenth)// 写入文件长度不对应
				{
					ret=3;
				}
				rt_file_close(handle,0);
			}
		}
		ptfile->bdatwriting=false;
		rt_free(ptfile->writebuf);	
		ptfile->writebuf=NULL;

	}
	
	if(beof||(!b104&&pRunSet->bTT_101Transsure ))  // 101规约需发确认帧，或规约文件最后一帧
	{
		// 组织报文
		pdat=datbuf;	
		framelen=0;
		pdat[framelen++]=0; //信息体地址
		pdat[framelen++]=0;
		if(b104)pdat[framelen++]=0;
		pdat[framelen++]=2;// 附加数据包类型
		pdat[framelen++]=10; // 写文件激活
	        /*文件标识*/
		pdat[framelen++] = (BYTE)(ptfile->wId);
	       pdat[framelen++] = (BYTE)(ptfile->wId>>8);
	       pdat[framelen++] = (BYTE)(ptfile->wId>>16);
		pdat[framelen++] = (BYTE)(ptfile->wId>>24);

	        /*文件长度*/
		pdat[framelen++] = (BYTE)(offset);
	       pdat[framelen++] = (BYTE)(offset>>8);
	       pdat[framelen++] = (BYTE)(offset>>16);
		pdat[framelen++] = (BYTE)(offset>>24);
		pdat[framelen++]=ret;// 结果描述符 :=2 未知文件名

		
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210); //
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,ptfile->vsq,IEC_COT_REQ,210,FRAME_I);//
		}
	}
	
#ifdef SEC_BOX_CODE
	if(b104&&!beof)
	{
		ptfile->recvwrnum+=2;
		if(ptfile->recvwrnum>=tRunPara.w104K)
		{
			IEC104_Echo_US((IEC104_DEF *)pt,FRAME_S);
			ptfile->recvwrnum=0;
		}
	}
#endif
}

int  iec_file_app(void *pt,BYTE *buf,BYTE cot,BYTE framelen,bool b104) // dat  从信息体地址后开始 framelen 从信息体地址后 附件数据类型包计算
{
	int ret=0;
	if(buf[0]!=2)//   附加数据类型包 ==2 文件传输
	{
		return -1;
	}

	// 判断传送原因和操作标识是否一致，不一致返回错误
	if(!(((buf[1]==3||buf[1]==7)&&(cot==IEC_COT_ACT)) 
		||((buf[1]==1||buf[1]==6||buf[1==9])&&(cot==IEC_COT_REQ))))
	{
		//return -2;  // 为方便调试，先屏蔽此处理
	}	
	switch(buf[1])
	{
		case 1: // 读目录
		{
			if(!del_history_file(HS_FILE_SOE))
			{
				create_event_rcd_file(HS_FILE_SOE);
			}

			if(!del_history_file(HS_FILE_CO))
			{
				create_event_rcd_file(HS_FILE_CO);
			}
			iec_dir_echo(pt,&buf[2],b104); // 报文从  操作标识下一字节开始
			break;
		}
		case 3: //读文件激活
		{
			iec_readfile_echo(pt,&buf[2],b104);
			break;
		}
		case 6: //读文件数据响应确认
		{
			iec_readfile_sure(pt,&buf[2],b104);
			break;
		}
		case 7: //写文件激活
		{
			iec_writefile_echo(pt,&buf[2],b104);
			break;
		}
		case 9: //写文件传输确认
		{
			iec_writefile_sure(pt,&buf[2],b104,framelen);
			break;
		}

		
		default:ret=-1;
	}
	
	return ret;
}




/*************软件升级报文*****************************/

int  iec_pro_update(void *pt,BYTE cot,BYTE ctype,bool b104) 
{
	BYTE framelen,rcot;
	char *pdat, datbuf[32];
	T_FILE *ptfile;
	bool s_e;
#ifdef SEC_BOX_CODE
	char md5inf[32];
	int   md5lenth=0;
#endif
	if(b104)	 ptfile=&((IEC104_DEF *)pt)->tf;
	else        ptfile=&((IEC101_DEF *)pt)->tf;

	s_e=(ctype&0x80)?1:0;
	if(cot==IEC_COT_ACT&&s_e) // 升级启动命令
	{
		rcot=IEC_COT_ACTCON;
		ptfile->bUpdateStart=true;
		strcpy(ptfile->updatefilename,"");
		rt_printf("\r\n升级启动");
		g_sec_md5_ret=-1;
		// 组织报文
		pdat=datbuf;	
		framelen=0;
		pdat[framelen++]=0; //信息体地址
		pdat[framelen++]=0;
		if(b104)pdat[framelen++]=0;	
		pdat[framelen++]=ctype;		
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,0,rcot,211); //
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,0,rcot,211,FRAME_I);//
		}		
	}
	else if(cot==6&&!s_e) // 升级结束命令
	{
		char file_name[64];
		char log_buf[128]={0};
		rcot=IEC_COT_ACTCON;
		ptfile->bUpdateStart=false;
		// 判断文件真实性，并启动升级处理
		// 组织报文
		pdat=datbuf;	
		framelen=0;
		pdat[framelen++]=0; //信息体地址
		pdat[framelen++]=0;
		if(b104)pdat[framelen++]=0;	
		pdat[framelen++]=ctype;		
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,0,rcot,211); //
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,0,rcot,211,FRAME_I);//
		}

#ifdef SEC_BOX_CODE
		md5lenth=sec_md5_get_inf(md5inf);

#endif
		sprintf(file_name,"%s%s","/app/",ptfile->updatefilename);
		rt_printf_time("\r\n程序升级:->%s\r\n",file_name);
		if(strcmp(file_name,KO_FILE_NAME)==0)  // 文件名相同
		{	int index;
			char from_file_name[64];
			char to_file_name[64];
			char old_file_name[64];
			index=file_check(ptfile->updatefilename,ATTR_DOWN);
			if(index>=0)
			{	
				int ret=file_check_info(index) ;
				sprintf(from_file_name,"%s%s","/tmp/",g_file_item[index].file_name);
				if (ret == 0&&(((g_sec_md5_ret==0)&&pRunSet->bTT_ESAM)||!pRunSet->bTT_ESAM))
				{
					watchdog_feed_mainloop_50s();
					sprintf(to_file_name,"%s%s",g_file_item[index].file_dir,g_file_item[index].file_name);
					//sprintf(from_file_name,"%s%s","/tmp/",g_file_item[index].file_name);
					sprintf(old_file_name,"%s%s",to_file_name,"_1");
					
					rt_file_mv(to_file_name,old_file_name);
					rt_file_mv(from_file_name,to_file_name);
					sprintf(file_name,"%s%s%s","文件更新",g_file_item[index].file_dir,g_file_item[index].file_name);
					log_str_time(LOG_OPERATE,file_name,0,1);
					
					sprintf(log_buf,"%s updated",g_file_item[index].file_name);
					load_hs_log_rcd(TYPE_SW_UPDATE,true,NULL,log_buf,1);

					rt_printf_time("\r\n%s 程序升级完毕，等待复位\r\n",file_name);
					ptfile->bUpdateReset=true;
					ptfile->us0_updatereset=ustimer_get_origin();
				}
				else
				{
					rt_printf("\r\n%s 升级失败! ret=%d g_sec_md5_ret=%d\r\n",from_file_name,ret,g_sec_md5_ret);
					rt_file_del(from_file_name);
				}	
			}

		}

		if(pRunSet->bTT_ESAM&&(g_sec_md5_ret>0))  // md5 检查错误应答 安全信息1f报文
		{
			if(b104)
			{
				 ((IEC104_DEF *)pt)->bEchosecmd5=true;
			}
			else
			{
				 ((IEC101_DEF *)pt)->bEchosecmd5=true;
			}
		}
	}
	else if(cot==IEC_COT_DEACT&&!s_e) // 升级撤销
	{
		rcot=IEC_COT_DEACTCON;
		ptfile->bUpdateCancel=true;
		ptfile->bUpdateStart=false;
		strcpy(ptfile->updatefilename,"");
		// 组织报文
		pdat=datbuf;	
		framelen=0;
		pdat[framelen++]=0; //信息体地址
		pdat[framelen++]=0;
		if(b104)pdat[framelen++]=0;	
		pdat[framelen++]=ctype;		
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,0,rcot,211); //
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,0,rcot,211,FRAME_I);//
		}
	}
	else
	{
		rcot=IEC_COT_UN_COT;		
		// 组织报文
		pdat=datbuf;	
		framelen=0;
		pdat[framelen++]=0; //信息体地址
		pdat[framelen++]=0;
		if(b104)pdat[framelen++]=0;	
		pdat[framelen++]=ctype;		
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,0,rcot,211); //
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,0,rcot,211,FRAME_I);//
		}
	}
#if 0
	// 组织报文
	pdat=datbuf;	
	framelen=0;
	pdat[framelen++]=0; //信息体地址
	pdat[framelen++]=0;
	if(b104)pdat[framelen++]=0;	
	pdat[framelen++]=ctype;		
	if(b104)
	{
		 IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,0,rcot,211); //
	}
	else
	{
		IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,0,rcot,211,FRAME_I);//
	}
#endif

#ifdef SEC_BOX_CODE

	//扩展报文，回复md5信息

	if(cot==6&&!s_e&&!pRunSet->bTT_ESAM) // 升级结束命令
	{
		rcot=63;
		if(b104)
		{
			 IEC104_AddFrame((IEC104_DEF *)pt, md5inf,md5lenth,0,rcot,211); //
		}
		else
		{
			IEC101_Asdu_Add((IEC101_DEF *)pt,md5inf,md5lenth,0,rcot,211,FRAME_I);//
		}
	}	
#endif
	return 0;
	
}


/*******************下面是故障指示板通信处理过程********************/

static void FaultComm_Recv_Rst(IEC101_DEF *pt)
{
	pt->nTypeCounter=0;
	pt->nRecvLenth=0;
	pt->nRecvCounter=0;
}

static void FaultComm_Send(IEC101_DEF *pt)
{
	RS_Send_Enable(pt->chnl);	
	g_tRsComm[pt->chnl].nSendCnt=1;   // 发送缓冲区的第一个字节为发送长度
	g_tRsComm[pt->chnl].bSend=true;
}

void FaultComm_Init(IEC101_DEF *pt,BYTE chnl)
{
	// 接收帧间隔为重发间隔时间的一半
	g_tRsComm[chnl].us_recv_timeout = pRunSet->dT101Resend*USTIMER_SEC/2;
	
	memset(pt,0,sizeof(IEC101_DEF));
	pt->type=IEC_FAULT_CHN;
	pt->chnl=chnl;

	pt->us0_msend=ustimer_get_origin();	
}
void FaultComm_Applay(IEC101_DEF *pt)
{
	BYTE *pd;
	u32 slot;

	// 检查状态板是否配置
	slot = equ_get_slot_by_type(BOARD_TYPE_RS_STATUS);
	if(slot == 0)
	{
		return;
	}

	// 接收数据处理
	if(pt->bData)			 
	{
		pt->bData=false;
 		pd=&pt->recvbuf[4];//  68 L L 68 zone addr data0 data1 sum 16
 		if(pd[1]==0x55)  //是状态板地址 
 		{
			if(pd[2])  //有复归按键产生
			{
				ResetHzLed(0);
				SignalReset(0,true);  //复归按键处理
				rt_printf("状态指示板复归信号产生。\r\n");
			}
			
			pt->msend_retries=0;
			pt->bMSend=false;
			
			if(rt_err_clr(ERR_CODE_SB_COMM,slot) == 2)
			{
				rt_printf("状态板通讯恢复\r\n");
				soe_record_ev(EV_BOARDCOMM, 0, 0,0,0 );        
			}
 		}		
	}


	// 1秒主动更新一次
	if(ustimer_get_duration(pt->us0_msend) > USTIMER_SEC)
	{
		DWORD led=0,ledsw=0,pos,i;
		
		// 通讯状态监测
		if(pt->bMSend) 
		{
			if(++pt->msend_retries>2)  //重发三次
			{
				if(rt_err_set(ERR_CODE_SB_COMM,slot) == 2)
				{
					rt_printf("状态板通讯异常\r\n");
					soe_record_ev(EV_BOARDCOMM, 1, 0,0,0 );        
				}
			}
		}	
		
		for(i=0;i<g_sw_num;i++)
		{	
			// 合位灯
			pos = i*4+0;
			if(g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no])
			{
				ledsw |= 1<<(i*2+0);
			}
			// 跳位灯
			pos = i*4+1;
			if(g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no])
			{
				ledsw |= 1<<(i*2+1);
			}
			// 过流灯
			pos = i*4+2;
			if(g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no])
			{
				led |= 1<<(i*2+0);
			}
			// 接地灯
			pos = i*4+3;
			if(g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no])
			{
				led |= 1<<(i*2+1);
			}
		}

		//rt_printf("ledsw=%08x,led=%08x.\r\n",ledsw,led);
		
		pd=g_tRsComm[pt->chnl].sendbuf;		
		pd[0]=16; //报文长度			
		pd[1]=0x68;  	//报文头
		pd[2]=10;
		pd[3]=10;
		pd[4]=0x68;		
		pd[5]=0;        //控制域
		pd[6]=0x55;	//链路地址
		pd[7]=(ledsw>>0)&0xff;
		pd[8]=(ledsw>>8)&0xff;
		pd[9]=(ledsw>>16)&0xff;
		pd[10]=(ledsw>>24)&0xff;
		pd[11]=(led>>0)&0xff;
		pd[12]=(led>>8)&0xff;
		pd[13]=(led>>16)&0xff;
		pd[14]=(led>>24)&0xff;
		pd[15]=pd[5]+pd[6]+pd[7]+pd[8]+pd[9]+pd[10]+pd[11]+pd[12]+pd[13]+pd[14];
		pd[16]=0x16;	
		
		FaultComm_Send(pt);	
		pt->bMSend=true;
		pt->us0_msend=ustimer_get_origin();		
	}
}

void  FaultComm_Recv(IEC101_DEF *pt,BYTE byRevData) 
{
	pt->recvbuf[pt->nRecvCounter++]=byRevData;
	switch(pt->nTypeCounter)
	{
		case 0:
		if(byRevData==0x68)
		{
			pt->nTypeCounter=1;
		}
		else
		{
			FaultComm_Recv_Rst(pt);
		}
		break;
		case 1:
			pt->nTypeCounter=2;
			pt->nRecvLenth=byRevData;			//长帧长度
			if(pt->nRecvLenth>IEC101_RECVBUF_MAX)
			{
				FaultComm_Recv_Rst(pt);
			}
			break;
		case 2:
			if(pt->nRecvLenth==byRevData)
			{
				pt->nTypeCounter=3;
			}
			else
			{
				FaultComm_Recv_Rst(pt);
			}
			break;
		case 3:
			if(byRevData==0x68)
			{
				pt->nTypeCounter=4;
			}
			else
			{
				FaultComm_Recv_Rst(pt);
			}
			break;
		case 4:  //控制域
			pt->sum=byRevData;
			pt->nTypeCounter=5;
			break;
		case 5: //目标地址
				pt->sum+=byRevData;
				pt->nRecvCnt=0;
				pt->nTypeCounter=6;
			break;
		case 6:	 //有效数据			//有效数据
			if(++pt->nRecvCnt>=pt->nRecvLenth-2)
			{
				pt->nTypeCounter=7;
			}
			pt->sum+=byRevData;
			break;
		case 7:		 //校验和	
			if(pt->sum==byRevData)
			{
				pt->nTypeCounter=8;
			}
			else
			{
				FaultComm_Recv_Rst(pt);
			}
			break;
		case 8:  //结束符
			FaultComm_Recv_Rst(pt);
			if(byRevData==0x16)	//校验结束字符,报文接收完毕，
			{
				pt->bData=true;
				return ;
			}
			break;
		default:   
			FaultComm_Recv_Rst(pt);
			break;
		}	//类型校验结束				
}





