/******************************************************************** 版权所有: 文件版本: V1.00 文件名称: IECComm.c 生成日期: 2007年04月26日 作 者:王建军 使用范围: 功 能: 外部通信处理函数 更新信息: 更新日志1: 修改者: 修改日期: 修改内容: 修改原因: *********************************************************************/ #include "head.h" #ifdef LINUX_KERNEL_APP #include "uart_user.h" #include #else #include #include #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; //通信灯状态 #ifdef COMM_STATUS_LED bool g_bCommStatus; #endif 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规约 #ifdef FUN_FUXI_ESAM s8 UART_CHANNEL[CFG_UART_NUM_MAX]={CFG_UART_232_0,CFG_UART_232_1,CFG_UART_HMI,CFG_UART_485_0,CFG_UART_485_1, CFG_UART_485_2,CFG_UART_CHIP_S1}; #else // s8 UART_CHANNEL[CFG_UART_NUM_MAX]={CFG_UART_232_0,CFG_UART_232_1,CFG_UART_HMI,CFG_UART_485_0,CFG_UART_485_1, CFG_UART_485_2}; s8 UART_CHANNEL[CFG_UART_NUM_MAX]={6,4,13,11,8,3,14,9,5,1,15}; //临时调试设置 #endif 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;icount;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;ircd_qt.queue,data,OVER_QUEUE); } } for(i=0;ircd_qt.queue,data,OVER_QUEUE); } } #endif char * IEC_Getdir(DWORD di) { int i; for(i=0;i 0) /*收到报文收据*/ { //rt_printf("s1_tclrecv:::"); for(i=0;ist101 == IEC101_ST_DATA) { commErrTab[i] = false; #ifdef COMM_STATUS_LED//通信状态灯 g_bCommStatus=true; #endif } } 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;(equNumslave_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); } else if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_GPS) // GPS模块 { GPS_Comm_App((GPS_COMM *)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;idi_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;idi_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;kdi_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;kdi_num;k++) { if(g_di_table[k].cp == no) { owner = g_di_table[k].owner; break; } } for(j=0;jdi_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) { if(pRunSet->bTT_QDS) { b_siq=true; SIQ=(SIQ&0x7f); } #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;kdi_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;kdi_num;k++) { if(g_di_table[k].cp == no) { owner = g_di_table[k].owner; break; } } for(j=0;jdi_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) { if(pRunSet->bTT_QDS) { b_siq=true; SIQ=(SIQ&0x7f); } #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;itype[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;jac_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; #ifdef IEC_EVENT_YC_RATE 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; } #else ff.ff=(float)pArg->arg[i]/65536; #endif *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 0) { //处理101规约报文 if(g_IEC_Recv) { for(i=0; ius0_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<extsendcnt == 0) { rt_printf("\r\nTX[%d] len=%d:",ch,prc->extsendlen); } for(i=0; iextsendbuf[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<nSendCnt ==0) { rt_printf("\r\nTX[ch:%d len=%d]:",ch,prc->sendbuf[0]); } for(i=0; isendbuf[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]; rt_printf("uart_isr_thread---%d\r\n", ch); #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; ius0_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_lenextsendlen) // 发送没完成,继续发送 { if(g_print_comm_raw && (g_print_port & (1<extsendbuf[prc->extsendcnt + send_len], (prc->extsendlen - send_len)); if(ret > 0) { if(g_print_comm_raw && (g_print_port & (1<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<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_lenextsendlen_1) // 发送没完成,继续发送 { if(g_print_comm_raw && (g_print_port & (1<extsendbuf_1[prc->extsendcnt_1 + send_len], (prc->extsendlen_1 - send_len)); if(ret > 0) { if(g_print_comm_raw && (g_print_port & (1<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<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_lenextsendlen_2) // 发送没完成,继续发送 { if(g_print_comm_raw && (g_print_port & (1<extsendbuf_2[prc->extsendcnt_2 + send_len], (prc->extsendlen_2 - send_len)); if(ret > 0) { if(g_print_comm_raw && (g_print_port & (1<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<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_lenextsendlen_3) // 发送没完成,继续发送 { if(g_print_comm_raw && (g_print_port & (1<extsendbuf_3[prc->extsendcnt_3 + send_len], (prc->extsendlen_3 - send_len)); if(ret > 0) { if(g_print_comm_raw && (g_print_port & (1<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<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_lensendbuf[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<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<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;ius0_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<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->extsendcntextsendlen #ifdef FUNC_ENCRY_IN_ONE_SERIAL || (((prc->bextsend_1 && (prc->extsendcnt_1extsendlen_1)) || (prc->bextsend_2 && (prc->extsendcnt_2extsendlen_2)) || (prc->bextsend_3 && (prc->extsendcnt_3extsendlen_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<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<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; inum;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;iset[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) { #ifndef GD_AREA_ECZD_JIEYANG_2022 strcpy(pfixedset->set[num].str,"2016版扩展104"); #else strcpy(pfixedset->set[num].str,"104"); #endif } else { #ifndef GD_AREA_ECZD_JIEYANG_2022 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"); } #else strcpy(pfixedset->set[num].str,"101"); #endif } 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;i0x80) //是汉字 { u16 intcode,unicode; int ulflen; int j; intcode=src[i+1]|(src[i]<<8); unicode=0; for(j=0;j0) { 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;i0x80) //是汉字 { u16 intcode,unicode; int j; intcode=src[i+1]|(src[i]<<8); unicode=0; for(j=0;j0) { 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 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//defined GD_AREA_ECZD_YUNFU_YUNAN_2022 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> 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 || defined GD_AREA_ECZD_CHAOZHOU_2022 if(parId==0x5001) { int i; for(i=0;i=0) && (parTableslot,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; #ifdef GD_AREA_HUIZHOU_2021 //模式硬遥信上送: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;islot,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 #ifdef GD_AREA_ECZD_JIEYANG_2022 for(i=0;ifa_ll_cd; rt_printf("读状态:%s=%d\r\n",mix_yt_index[MIX_LL_CD],temp_yx); float2IECbuf(pbuf,(float)temp_yx); rt_free(parBuf); return true; } else if(MIX_BS_HZ == (parTable-YT_SW_HARD_YB_NUM-YT_PUB_HARD_YB_NUM)) { temp_yx = (u8)soe_check(EV_BS_ALL+i*EV_SW_NUM); rt_printf("读状态:%s=%d\r\n",mix_yt_index[MIX_BS_HZ],temp_yx); float2IECbuf(pbuf,(float)temp_yx); rt_free(parBuf); return true; } else if(MIX_TY == (parTable-YT_SW_HARD_YB_NUM-YT_PUB_HARD_YB_NUM)) { if ((short)g_sw[i].di_cfg_index[SW_DI_BHZTT] != INDEX_INVALLID) { ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_BHZTT]]; temp_yx = dido_di_is_on(ecd->slot,ecd->index); } else { temp_yx = !pRunSet->bTT_BH_YB; } rt_printf("读状态:%s=%d\r\n",mix_yt_index[MIX_TY],temp_yx); float2IECbuf(pbuf,(float)temp_yx); rt_free(parBuf); return true; } } #endif } #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;i200) { 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;igroup_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;igroup_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;i200) { 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;igroup_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;igroup_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; netpara_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;idi[i]==di) // 预置数据中有对应的点号的定值,覆盖 { index=i; bover=true; break; } } if(!bover) { for(i=0;idi[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;idi[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;idi[i]; if(di==0)continue; for(j=0;jgroup_type) { case SETGROUP_TYPE_PARA: if(tEquipParaTable[tmp_param->setno].wType == SETTYPE_IP) { union{ float ff; u8 tt[4]; }ff; for(k=0;kt_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;ibpreset=true; rsd->us0_preset=ustimer_get_origin(); } else if(((pdi&0xc0)==0x40)&&cot==0x09) // 取消预置 { int i; rmt_str_cnt=0; for(i=0;idi[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;itf; 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;idirpath,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;iname); *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;i0&&mulenbTransing||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>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;ipfilebuf[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;iwfilename,"/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;iwId); 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;iwfilelenth) { 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: // 读目录 { #ifdef GD_AREA_ECZD_JIEYANG_2022 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); } #endif 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;ichnl].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; } //类型校验结束 }