#include "head.h"

#ifdef FUNC_SEL_BAT_MODULE
#define FRAME_WAIT	1	/*等待应答*/
#define FRAME_NULL  0	/*空闲状态*/


/******************************************************************************
函数名称：chck_sum
创建日期：2020-12-07
作    者： 马紫强
功能说明：累加和校验码计算
输入参数：p_buf数据，len长度
输出参数：无
返 回 值：无
*/
int chck_sum(u8* p_buf,int len)    
{
	int i;
	int i_sum=0;

	for (i=0;i<len;i++)
	{
		i_sum+=p_buf[i];
	}
	i_sum=i_sum&0xffff;
	return i_sum;
}

/******************************************************************************
函数名称：pwrm_print_msg
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约打印信息
输入参数：无
输出参数：无
返 回 值：无
*/
void pwrm_print_msg(char *msg,u8 *buf,unsigned int len,u8 chnl)
{
	struct rtc_time_t tm;
	char str[128];	
	
	sys_time_get(&tm);
	sprintf(str,"<%d-%d:%d>%s",tm.hour,tm.min,tm.ms,msg);
	
	if(g_print_lnk && (g_print_port & (1<<chnl)))		/*打印接收的报文*/
	{
		print_msg(str,buf,len);
	}	
}


/******************************************************************************
函数名称：get_pwrminf
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约初始化规约参数
输入参数：pt规约参数，参数内容
输出参数：无
返 回 值：无
*/
static void get_pwrminf(pwdmodlue_def *pt,u8 *filestr)
{
	if(filestr[0]=='[') /*规约类型*/
	{
		pt->bcfg=false;
		if(strcmp(filestr,"[COMALL_PTL_PWDMODULE]")==0)
		{
			pt->bcfg=true;
		}
		return;
	}
	if(!pt->bcfg)return;
	
	if(strstr(filestr,"retrytime")) 
	{
		pt->retrytime=getstrval(filestr)*SAM_FREQUENCY;  /*单位秒，转为dTcounter 值*/
	}
	else if(strstr(filestr,"sendinteraltime")) 
	{
		pt->sendinteraltime=getstrval(filestr)*SAMFREQ/20; /*单位毫秒，转为dTcounter值*/
	}
	else if(strstr(filestr,"ykhh_interaltime")) 
	{
		pt->ykhh_interaltime=getstrval(filestr)*SAM_FREQUENCY;  /*单位秒，转为dTcounter 值*/
	}
	
}


/******************************************************************************
函数名称：pwrm_init_inf
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约初始化规约参数
输入参数：pt规约参数
输出参数：无
返 回 值：0成功，<0失败
*/
static int  pwrm_init_inf(pwdmodlue_def *pt)
{
	
	u32 i,file_length;
	struct file * pfile;	
	u8 *filebuf;	
	loff_t pos;	
	u8  filestr[128],*pstr;
	u8	strlenth=0;
	
	pfile = rt_file_open("/app/data/pcolcfg.ini",O_RDONLY ,0);	/*打开文件*/
	if(IS_ERR(pfile))
	{
		dp_err_n_c_rt("error! 无法打开 pcolcfg.ini\r\n");
		return -1;
	}

	rt_file_llseek(pfile,0,SEEK_END);	
	file_length = pfile->f_pos;
	rt_file_llseek(pfile,0,SEEK_SET);
	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;
	for(i = 0; i < file_length; i++)
	{
		*pstr++=filebuf[i];
		strlenth++;
		if(filebuf[i] == 0x0a||strlenth>=128)	/*接收完一行*/
		{
			int j;
			pstr = filestr;
			for(j=0;j<strlenth;j++)
			{
				if(*pstr==' '||*pstr=='\t')  /*取空格或tab 前的字符*/
				{
					*pstr='\0';
					break;
				}
				pstr++;
			}
			*pstr='\0';
			get_pwrminf(pt,filestr);
			pstr=filestr;
			strlenth=0;
		}
	}
	rt_file_close(pfile,0);	/*关闭文件*/
	rt_free(filebuf);			/*释放内存*/
	return 0;
}

/******************************************************************************
函数名称：pwrm_Recv_one_frame
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约接收一帧格式正确的报文
输入参数：pt规约参数,byRevData接收到的字符
输出参数：无
返 回 值：1:成功 其他:失败
*/
static int pwrm_Recv_one_frame(pwdmodlue_def *pt,u8 byRevData)
{	
	u8 crc_c = 0;			/*计算的校验码*/
	u8 crc_r = 0; 		/*接收的校验码*/	

	pt->recv[pt->recv_l] = byRevData;	/*保存字符*/
	pt->recv_l++;

	//rt_printf("revbyte:%x\r\n",byRevData);

    switch(pt->recv_l)
    {
	    case 1:
			if(byRevData != PWRM_HEAD1)	/*同步字1不匹配*/
			{
				pt->recv_l = 0;			
			}
			break;
	    case 2:
			if(byRevData != PWRM_HEAD2)	/*同步字*/
			{
				pt->recv_l = 0;
			}
			break;			
	    case 3:
			pt->recv_len = byRevData + 4;	/*报文长度*/
			if(pt->recv_len > 200)			/*防止接收越界*/
			{
				pt->recv_l = 0;							
			}			
			break;
	    default:
	        if (pt->recv_l >= pt->recv_len)	/*已接收完指定长度*/
	        {
	            pt->recv_l = 0;	
				crc_c = (u8)chck_sum(pt->recv,pt->recv_len-1);	/*计算校验码*/				
				crc_r = pt->recv[pt->recv_len-1];

				if(crc_c == crc_r)
				{	
	            	return 1;				/*接收到正确报文*/
				}
				else
				{
					pwrm_print_msg("校验错误",pt->recv,pt->recv_len,pt->chnl);	/*打印报文错误信息*/
				}
	        }
	        break;
    }

	return -1;	
}

/******************************************************************************
函数名称：pwrm_match
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约进行帧匹配
输入参数：无
输出参数：无
返 回 值：无
*/
int pwrm_match(pwdmodlue_def *pt)
{
	u8 s_mcmd=0,s_scmd=0;
	u8 r_mcmd=0,r_scmd=0;
	u8 *buf = pt->recv;

	s_mcmd=pt->m_cmd_re |0x80;
	s_scmd=pt->s_cmd_re;
	
	r_mcmd=buf[PWRM_M_CMD];	/*主命令字*/
	r_scmd=buf[PWRM_S_CMD];	/*子命令字*/


	if((r_mcmd == s_mcmd) && (r_scmd == s_scmd))
	{
		pt->f_sts = FRAME_NULL;		/*空闲状态*/
		return 1;
	}
	else
	{	
		rt_printf("test::s_mcmd =%d,s_scmd=%d,r_mcmd=%d,r_scmd=%d\r\n",s_mcmd,s_scmd,r_mcmd,r_scmd);
		return 0;
	}
	
}


/******************************************************************************
函数名称：pwrm_print_msg
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约打印各类报文
输入参数：无
输出参数：无
返 回 值：无
*/
void pwrm_print_inf(pwdmodlue_def *pt,char *note)
{
	u8 tmp[100] ={0};
	u8 str[100] = {0};
	u8 m_cmd = 0;		/*主类型*/
	u8 s_cmd = 0;		/*子类型*/
	u8 data_ok=0;			

	m_cmd = pt->recv[3];	/*主类型*/
	s_cmd = pt->recv[4];	/*子类型*/	
	sprintf(tmp,"(PWRM子-未知数据)");

	if(m_cmd == 0x81)
	{
		if(s_cmd == 0x01)
		{
			sprintf(tmp,"(PWRM子-电池电压数据):\r\n");						
		}
		else if(s_cmd == 0x02)
		{
			sprintf(tmp,"(PWRM子-电池状态):\r\n");		
		}
		else if(s_cmd == 0x03)
		{
			sprintf(tmp,"(PWRM子-电池电压参数):\r\n");	
		}
	}
	else if(m_cmd == 0x82)/*遥控*/
	{
		data_ok = pt->recv[5];
		if(data_ok &0x80)
		{			
			sprintf(tmp,"(PWRM子-遥控否定应答):\r\n");
		}
		else
		{
			sprintf(tmp,"(PWRM子-遥控肯定应答):\r\n");
		}
	}
	sprintf(str,"%s%s",note,tmp);
	
	pwrm_print_msg(str,pt->recv,pt->recv_len,pt->chnl);	/*打印报文注释*/	
}

/******************************************************************************
函数名称：pwrm_Recv
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约接收报文解包处理
输入参数：pt规约参数,byRevData接收到的字符
输出参数：无
返 回 值：无
*/
void  pwrm_Recv(pwdmodlue_def *pt,u8 byRevData)
{
	int i_ret = 0;
	//int test=0;
	
	i_ret = pwrm_Recv_one_frame(pt,byRevData);	
    if (i_ret==1)                                                   /* 接收到一帧数据 */
    {

/*
		 rt_printf("接收正确一帧:\r\n");
		 for(test=0;test<pt->recv_len;test++)
		 {
			rt_printf("%x ",pt->recv[test]);
		 }		 
    	 rt_printf("\r\n");
*/		 
    	 pt->rervok = 1;
	}	

	return;	
}




/******************************************************************************
函数名称：pwrm_frame_time
创建日期：2020-12-07
作    者： 马紫强
功能说明：帧间隔空循环
输入参数：pt规约参数,chnl通道号
输出参数：无
返 回 值：1时间到，0时间未到
*/
int pwrm_frame_time(pwdmodlue_def *pt)
{
	static int first = 1;
	DWORD frame_time = 0;
	
	if(first)					/*初始化帧时间*/
	{
		pt->f_time = dTCounter;
		first = 0;
	}

	frame_time = dTCounter - pt->f_time;	/*间隔时间*/
	if(frame_time >= pt->sendinteraltime)
	{
		pt->f_time = dTCounter;
		return 0;
	}	

	return 1;
}



/******************************************************************************
函数名称：pwrm_frame_time
创建日期：2020-12-07
作    者： 马紫强
功能说明：判断是否有报文等待超时
输入参数：pt规约参数,chnl通道号
输出参数：无
返 回 值：1时间到，0时间未到
*/
int pwrm_over_time(pwdmodlue_def *pt)
{
	DWORD overtime=0;
	
	if(pt->f_sts == FRAME_WAIT)
	{		
		overtime =	dTCounter - pt->send_time;	
		if(overtime >= pt->retrytime)	/*超时时间已到*/
		{			
			pt->f_sts = FRAME_NULL;
			pt->ykhh_en = 0;			/*释放定时遥控*/
			return 0;
		}
		else							/*继续超时等待*/
		{
			return 1;
		}
	}
	
	return 0;
}

void pwrm_send_one_frame(pwdmodlue_def *pt,u8 flag,char *msg)
{	
	u8 *buf;

	buf = &pt->send[1];
	pwrm_print_msg(msg,&g_tRsComm[pt->chnl].sendbuf[1],g_tRsComm[pt->chnl].sendbuf[0],pt->chnl);	/*打印报文注释*/	
	if(flag)
	{
		pt->f_sts = FRAME_WAIT;
		pt->send_time = dTCounter;
	}
	
	pt->m_cmd_re = buf[PWRM_M_CMD];		/*主命令字*/
	pt->s_cmd_re = buf[PWRM_S_CMD];		/*子命令字*/

	RS_Send_Enable(pt->chnl);
	g_tRsComm[pt->chnl].nSendCnt=1;   // 发送缓冲区的第一个字节为发送长度
	g_tRsComm[pt->chnl].bSend=true;	
	if(!g_bCommLed)g_bCommLed=true;
}

void pwrm_send_ykexe(pwdmodlue_def *pt,u16 cp,u8 val)
{
 	u8 *pd= pt->send;		/*串口发送报文区*/
	u8 crc_c = 0;			/*校验码*/
	u8 off=1;
	u8 s_cmd=0;
	
	s_cmd = (cp>>8)&0xff;
	pd[off++]  = 0xEB;	/*起始符1*/
	pd[off++]  = 0x90;	/*起始符2*/
	pd[off++]  = 0x02;	/*长度*/
	pd[off++]  = 0x02;	/*主功能码*/
	pd[off++]  = s_cmd;	/*子功能码*/
	crc_c = (u8)chck_sum(&pd[1],off-1);
	pd[off++]  = crc_c;	 	/*校验码*/
	
	pd[0] = off -1;			/*报文总长度*/	
	pwrm_send_one_frame(pt,1,"send---(PWRM主-遥控执行):\r\n");	/*发送报文*/
}



void pwrm_send_batac(pwdmodlue_def *pt)
{
 	u8 *pd= pt->send;		/*串口发送报文区*/
	u8 crc_c = 0;			/*校验码*/
	u8 off=1;
	
	pd[off++]  = 0xEB;	/*起始符1*/
	pd[off++]  = 0x90;	/*起始符2*/
	pd[off++]  = 0x02;	/*长度*/
	pd[off++]  = 0x01;	/*主功能码*/
	pd[off++]  = 0x01;	/*子功能码*/
	crc_c = (u8)chck_sum(&pd[1],off-1);
	pd[off++]  = crc_c;	 	/*校验码*/
	
	pd[0] = off -1;			/*报文总长度*/	
	pwrm_send_one_frame(pt,1,"send---(PWRM主-召唤电压数据):\r\n");	/*发送报文*/
}

void pwrm_send_batsts(pwdmodlue_def *pt)
{
 	u8 *pd= pt->send;		/*串口发送报文区*/
	u8 crc_c = 0;			/*校验码*/
	u8 off=1;
	
	pd[off++]  = 0xEB;	/*起始符1*/
	pd[off++]  = 0x90;	/*起始符2*/
	pd[off++]  = 0x02;	/*长度*/
	pd[off++]  = 0x01;	/*主功能码*/
	pd[off++]  = 0x02;	/*子功能码*/
	crc_c = (u8)chck_sum(&pd[1],off-1);
	pd[off++]  = crc_c;	 	/*校验码*/
	pd[0] = off -1;			/*报文总长度*/
	
	pwrm_send_one_frame(pt,1,"send---(PWRM主-召唤电压状态):\r\n");	/*发送报文*/
}

static void pwrm_slave_yk(u8 ch,u8 ti,u8 cot,u8 v,u16 cp ,u8 yktype)
{
	struct do_table *dt;
	LINKYK_DEF *yk;
//	u8 buf[128];
	
	u32 i=0,index=0;
	u16 lt_cp=0,lt_ch=0;	/*点号,通道号*/
	u16 s_ch=0;	
	u8  flag=0;	
	
	s_ch = 	(ch >>5) & 0x07;	/*通道号*/
	// 查找点表，如果找到，保存。
	for(i=0; i<g_lt_do_num; i++)
	{
		lt_cp = g_lt_do[i].cp_s&0xffff;
		lt_ch = (g_lt_do[i].cp_s>>21)&0x07; 
		if((cp == lt_cp) && (s_ch == lt_ch))	/*通道号和级联点号匹配*/	
		{
			index = g_lt_do[i].tbl_index;	/*总表位置*/	
			flag =1;
			break;
		}		
	}
	//rt_printf("i=%d,index=%d\r\n",i,index);
		
	if(flag)
	{		
		dt = &g_do_table[index];
		yk = &g_lnk_yk[dt->owner];
		if(cp != yk->cp_s)
		{
			rt_printf_time("lnk_slave_yk err:cp=%04x,cp_s=%04x",cp,yk->cp_s);
			return;
		}	

		if((cot&0x3f)==IEC_COT_ACT)
		{
			cot=IEC_COT_ACTCON|(cot&0xc0);
		}
		else if((cot&0x3f)==IEC_COT_DEACT)
		{
			cot=IEC_COT_DEACTCON|(cot&0xc0);
		}	
		
		yk->data[yktype].ti=ti;
		yk->data[yktype].cot=cot;
		yk->data[yktype].v=v;				
		yk->flag[yktype] = true;	
		//rt_printf("dt->owner=%d\r\n",dt->owner);
		//sprintf(buf,"级联遥控上行:(ch=%d,cp_s=%04x,cp_m=%04x,ti=%02x,cot=%02x,v=%02x)",ch,lt_cp,dt->cp,ti,cot,v);
		//log_str_time(LOG_OPERATE,buf,0,0);
		//rt_printf_time("%s\r\n",buf);
	}
	else
	{
		rt_printf_time("lnk_slave_yk:查找级联表失败 ch=%d,cp=%04x.\r\n",ch,cp);
	}				
}

void pwrm_send_batpara(pwdmodlue_def *pt)
{
	u8 *pd= pt->send;		/*串口发送报文区*/
	u8 crc_c = 0;			/*校验码*/
	u8 off=1;
	
	pd[off++]  = 0xEB;	/*起始符1*/
	pd[off++]  = 0x90;	/*起始符2*/
	pd[off++]  = 0x02;	/*长度*/
	pd[off++]  = 0x01;	/*主功能码*/
	pd[off++]  = 0x03;	/*子功能码*/
	crc_c = (u8)chck_sum(&pd[1],off-1);
	pd[off++]  = crc_c;	 	/*校验码*/
	pd[0] = off - 1;			/*报文总长度*/
	
	pwrm_send_one_frame(pt,1,"send---(PWRM主-召唤电压参数):\r\n");	/*发送报文*/
}


/******************************************************************************
函数名称：pwrm_unpack
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约对正确的报文进行解析
输入参数：无
输出参数：无
返 回 值：无
*/
void pwrm_unpack(pwdmodlue_def *pt)
{
	u32 i=0,j=0;
	u8 val=0;		
	u8 sts=0,t_sts=0;
	qs16 s_val=0,num=0;			
	u8 off=0,offset=0;		/*偏移*/
	u8 len=0;		/*长度*/
	u8 m_cmd =0 ;	/*主命令字*/
	u8 s_cmd = 0;	/*子命令字*/
	u16 cp =0;		/*级联点号*/
	u16 lt_cp =0;	/*点表中通道号*/
	u16 ch=0;		/*通道号*/
	u16 lt_ch;		/*点表中的通道号*/
	u32 index =0;	/*点表位置*/
	u8 *buf = pt->recv;

	m_cmd = buf[PWRM_M_CMD];
	s_cmd = buf[PWRM_S_CMD];
	len = buf[PWRM_LEN];	/*长度*/
	
	ch=pt->chnl+2;	/*通道号,不判地址*/
	
	if(m_cmd == 0x82)	/*遥控*/
	{
		if(pt->ykhh_en)	/*定时活化*/
		{
			pt->ykhh_en = 0;	
		}
		else
		{
			LINKYK_DEF *yk;
			yk = &g_lnk_yk[pt->yk_kk_no];
			
			offset = 5;
			if(buf[offset] == 0x81)	/*否定应答*/
			{		
				pwrm_slave_yk(yk->chnl,yk->data[IECLINK_YK_SND].ti,7|IEC_COT_PN,yk->data[IECLINK_YK_SND].v,yk->cp_s,IECLINK_YK_ACK);
			}
			else 
			{
				pwrm_slave_yk(yk->chnl,yk->data[IECLINK_YK_SND].ti,7,yk->data[IECLINK_YK_SND].v,yk->cp_s,IECLINK_YK_ACK);
				pwrm_slave_yk(yk->chnl,yk->data[IECLINK_YK_SND].ti,10,yk->data[IECLINK_YK_SND].v,yk->cp_s,IECLINK_YK_END);
			}
		}					
	}	
	else if((m_cmd == 0x81) && (s_cmd == 0x02))	/*遥信*/
	{		
		offset = 5;
		off = offset;
		val = buf[off];		/*取字节值*/
		for(j=0;j<8;j++)	
		{
			sts = (buf[off]>>j) & 1;		/*状态*/
			sts = sts+1;					/*双点*/
			cp = s_cmd*0x100+j;				/*级联点号*/	
			for(i=0; i<g_lt_di_num; i++)
			{
				lt_cp = g_lt_di[i].cp_s&0xffff;
				lt_ch = (g_lt_di[i].cp_s>>21)&0x0f; 					
				if((cp == lt_cp) && (ch == lt_ch))	/*通道号和级联点号匹配*/									
				{
					index = g_lt_di[i].tbl_index;	/*总表位置*/	
					t_sts = sw_di_get(g_di_table[index].owner,g_di_table[index].indexno);
 					sw_di_set(g_di_table[index].owner,g_di_table[index].indexno,sts);	/*写双点遥信*/
					
					//rt_printf("test::unpack遥信:序号%d,位置%d,%d->%d\r\n",i,index,t_sts,sts);			
 					if((t_sts >=0) && (sts != t_sts))	/*发生变位*/
					{
 						if(pt->yx_first)	/*记录SOE*/
						{
							struct timespec ts;
							clk_time_get(&ts);
							if(g_di_table[index].is_inverse)	/*取反*/
							{
								t_sts = (~t_sts)&0x03;
							}
							soe_record_lnk(g_di_table[index].cp ,sts,&ts,(s32)&g_lt_di[index],g_lt_di[index].is_mix,g_lt_di[index].cp_s);/*记录SOE引起重启*/
						}												
					}
					break;
				}
			}
		}
		pt->yx_first = 1;
	}
	else if((m_cmd == 0x81) && ((s_cmd == 0x03) || (s_cmd == 0x01))) /*遥测*/
	{		
		offset = 5;
		num = (len-2)/2;
		for(i=0;i<num;i++)
		{			
			cp = s_cmd*0x100+i;				/*级联点号*/	
			off = offset+i*2;
			s_val = buf[off]*0x100 + buf[off+1];
			s_val *= Q16_BASE;
			
			for(j=0; j<g_lt_ac_num; j++)
			{
				lt_cp = g_lt_ac[j].cp_s&0xffff;
				lt_ch = (g_lt_ac[j].cp_s>>21)&0x0f; 
				if((cp == lt_cp) && (ch == lt_ch))	/*通道号和级联点号匹配*/	
				{
					index = g_lt_ac[j].tbl_index;						
					//rt_printf("test::unpack遥测:序号%d,位置%d,val=%x\r\n",j,index,s_val); 									
					if(g_ac_table[index].owner == 0)
					{
						g_sw_pub.ac_in[g_ac_table[index].indexno-1] = s_val;
					}
					else
					{
						g_sw[g_ac_table[index].owner-1].ac_in[g_ac_table[index].indexno-1] = s_val;
						//rt_printf("test::g_sw[%d].ac_in[%d]=%x\r\n",g_ac_table[index].owner-1,g_ac_table[index].indexno-1,s_val); 
					}	
					break;
				}				
			}			
		}			
	}
}


void pwrm_recv_proc(pwdmodlue_def *pt)
{
	if(pt->rervok)
	{
		if(pwrm_match(pt))	  /*帧是否匹配*/
		 {				
		 	pwrm_print_inf(pt,"echo--");		/*帧匹配*/
			pwrm_unpack(pt);     /*解包处理*/ 
		 }
		else
		 {			
		 	pwrm_print_inf(pt,"rmsg--");	 /*帧不匹配*/
		 }
		pt->rervok = 0;
	}
}

static void pwrm_yk_send(pwdmodlue_def *pt)
{
	int i;		
	for(i=0;i<SWITCH_NUM_EXT_PUB;i++)
	{
		if(pt->yk_sendflag & (1<<i))
		{
			u8 v,cot,ti;
			LINKYK_DEF *yk = &g_lnk_yk[i];
			v=yk->data[IECLINK_YK_SND].v;
			cot=yk->data[IECLINK_YK_SND].cot;
			ti=yk->data[IECLINK_YK_SND].ti;

			if(v&0x80) // 遥控选择，遥控撤销，直接回复应答，不转发
			{
				if(pt->tyk.yk_st!= YK_STATUS_NONE && pt->tyk.yk_st!= YK_STATUS_TIMEOUT)
				{
					//已经有遥控命令选择或在执行
					cot|=IEC_COT_PN;
					memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));					
					rt_printf_time("pwrm有遥控点在执行.\r\n");
				}
				else
				{
					// 记录选择动作
					pt->tyk.yk_st=YK_STATUS_SEL;	/*遥控选择*/
					pt->tyk.no=ti;					/*类型标识*/
					pt->tyk.val=(v&0x3f);			/*分合状态*/
					pt->tyk.wMaster=yk->cp_s;		/*级联通讯点号*/	
					pt->tyk.dTStart=dTCounter;		/*遥控超时开始计时*/				
				}
				pwrm_slave_yk(yk->chnl,ti,cot,v,yk->cp_s,IECLINK_YK_ACK);				
			}
			else if(cot==IEC_COT_DEACT) // 遥控选择，遥控撤销，直接回复应答
			{
				if(pt->tyk.yk_st!= YK_STATUS_SEL)
				{
					cot|=IEC_COT_PN;
				}					
				pwrm_slave_yk(yk->chnl,ti,cot,v,yk->cp_s,IECLINK_YK_ACK);
				memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));
			}
			else // 遥控执行
			{
				if(((pt->tyk.yk_st!= YK_STATUS_SEL)  // 和遥控选择的数据不对应
					||(v !=pt->tyk.val)
					||(yk->cp_s !=pt->tyk.wMaster)
					||(ti != pt->tyk.no)))
				{
					cot|=IEC_COT_PN;
					pwrm_slave_yk(yk->chnl,ti,cot,v,yk->cp_s,IECLINK_YK_ACK);					
					rt_printf_time("pwrm该遥控未选择.\r\n");
				}
				else
				{
					pt->tyk.yk_st=YK_STATUS_EXE;	
					pt->tyk.dTStart=dTCounter;	
					
					if(ti==45)
					{
						v+=1; // 单点转为双点 2=合 1=分
					}
					
					if(v==2) //遥控合
					{
						pwrm_send_ykexe(pt,yk->cp_s,1);	/*合操作*/
					}
					else
					{
						pwrm_send_ykexe(pt,yk->cp_s,0);	/*分操作*/
					}						
					pt->yk_kk_no = i;  //保存发送 g_lnk_yk 索引
				}
				
				memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));	/*释放遥控,可接收新遥控*/
			}				
			// 清除标志 
			g_lnk_yk[i].flag[IECLINK_YK_SND]=false;				
			pt->yk_sendflag &= ~(1<<i);
		}
	}		
}

void pwrm_yk_overtime(pwdmodlue_def *pt)
{
	if(pt->tyk.yk_st==YK_STATUS_SEL)
	{
		if(dTCounter- pt->tyk.dTStart>=tRunPara.dYKTime)	//遥控选择超时
		{
			memset(&pt->tyk,0,sizeof(REMOTEYKSTATUS));		/*释放遥控,可接收新遥控*/		
			rt_printf_time("pwrm遥控选择超时.\r\n");
			pt->tyk.yk_st = YK_STATUS_TIMEOUT; 
		}
	}
}

#if 0
bool pwrm_ykhh_enable(pwdmodlue_def *pt)
{
	if(pt->ykhh_interaltime <= 0)	return false;
	
	if(dTCounter - pt->ykhh_time >= pt->ykhh_interaltime)
	{
		pt->ykhh_time = dTCounter;
		if(pt->ykhh_en == 0)
		{
			pt->ykhh_en=0x81;
			return true;
		}
	}	

	return false;
}
#endif



/******************************************************************************
函数名称：pwrm_send_entry
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约发送入口
输入参数：pt规约参数
输出参数：无
返 回 值：无
*/
void pwrm_send_entry(pwdmodlue_def *pt)
{
	if(pwrm_over_time(pt))		/*有报文等待超时*/
	{
		return;				
	}

	if(pwrm_frame_time(pt)) 	/*帧间隔时间未到返回*/
	{
		return;
	}	

	pwrm_yk_overtime(pt);		/*遥控超时处理*/

	if(pt->yk_sendflag)	/*遥控优先处理*/
	{		
		pwrm_yk_send(pt);
		return;
	}	

	if(pt->ykhh_en&0x80)		/*定时活化*/
	{
		if(pt->ykhh_en == 0x81)
		{
			pwrm_send_ykexe(pt,0x0100,1); /*合操作*/ 				
		}
		else if(pt->ykhh_en == 0x82)
		{
			pwrm_send_ykexe(pt,0x0200,1); /*合操作*/ 				
		}
		pt->ykhh_en &= 0x7F; 
		return;		
	}

	if(pt->send_dp >= REQUEST_NUM)
	{
		pt->send_dp = REQUEST_BATAC;
	}

	switch(pt->send_dp)		/*当前发送序号*/
	{
		case REQUEST_BATAC:
			pwrm_send_batac(pt);	/*请求电池电压*/
			break;
		case REQUEST_BATSTS:
			pwrm_send_batsts(pt);	/*请求电池状态*/
			break;
		case REQUEST_BATPARA:
			pwrm_send_batpara(pt);	/*请求电池参数*/
			break;

		default:
			break;
	}	

	pt->send_dp++;				/*发送下一项*/
}

/******************************************************************************
函数名称：pwrm_Init
创建日期：2020-12-07
作    者： 马紫强
功能说明：电源模块规约初始化
输入参数：pt规约参数,chnl通道号
输出参数：无
返 回 值：无
*/
void pwrm_Init(pwdmodlue_def *pt,u8 chnl)
{
	memset(pt,0,sizeof(pwdmodlue_def));
	pt->chnl = chnl;	
	pt->send = g_tRsComm[chnl].sendbuf;		
	pt->retrytime=5*SAM_FREQUENCY;  		/*单位秒，转为dTcounter 值*//*默认5秒*/	
	pt->sendinteraltime=100*SAMFREQ/20;		 /*单位毫秒，转为dTcounter值*//*默认100毫秒*/
	
	rt_printf("tRunPara.dYKTime=%d\r\n",tRunPara.dYKTime);	
	pwrm_init_inf(pt);	
	rt_printf("\r\npwrm_init(channel=%d):retrytime=%d,sendinteraltime=%d,ykhh_interaltime=%d\r\n",chnl,pt->retrytime,pt->sendinteraltime,pt->ykhh_interaltime);	
}


void set_ykhh_all_flag(void)
{
	int i=0;
	pwdmodlue_def *pt;
	
	for(i=0;i<CFG_UART_NUM_MAX;i++)
	{		
		 if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_PWRM)  // 串口级联规约
		 {
		 	pt = (pwdmodlue_def *)g_tRsComm[i].ptBuf;
			if(pt->ykhh_en == 0) pt->ykhh_en = 0x81;				
		 }
	}
}

void set_ykstop_all_flag(void)
{
	int i=0;
	pwdmodlue_def *pt;
	
	for(i=0;i<CFG_UART_NUM_MAX;i++)
	{		
		 if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_PWRM)  // 串口级联规约
		 {
		 	pt = (pwdmodlue_def *)g_tRsComm[i].ptBuf;
			if(pt->ykhh_en == 0) pt->ykhh_en = 0x82;				
		 }
	}	
}

#endif

