/******************************************************************** 版权所有: 文件版本: 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; // 通信灯状态 bool g_bCommStatus; u32 g_comm_link_status; // 通信连接状态,每个通道用一个bit表示 bool byc_filter; // 遥测滤波,防止遥测没有稳定下来突发上送 BYTE g_arrIECBuf[IEC_TBUF_LEN]; // 通信规约处理时使用的数据缓冲区 SERIAL_COMM g_tRsComm[CFG_UART_NUM_MAX]; // 4个串行通信口的通信结构定义 union u_RsIEC g_tRsIEC[CFG_UART_NUM_MAX]; // 串口规约共用结构buf区,目前有101 104规约 s8 UART_CHANNEL[CFG_UART_NUM_MAX] = {CFG_UART_485_0, CFG_UART_485_1, CFG_UART_232_0, CFG_UART_232_1, CFG_UART_GPS, CFG_UART_BK_0, CFG_UART_BK_1, CFG_UART_CHIP_S1}; u8 uart_test_begin = 0; u8 uart_test_flag[CFG_UART_NUM_MAX][2]; // 定义预置/固化参数时用于比较的数组及变量 BYTE buf_forCompare[256] = {0}; // 预置报文和固化报文的比较存储数组 int i_forCompare = 0, j_forCompare = 0; // 比较数组存储时计数用 bool bfirst_sel = false; // 预置标志 #ifdef FUNC_ENCRY_IN_ONE_SERIAL bool gb_bready = true; #endif #ifdef CPU_FUXI int g_uart_isr_thread_create_flag[CFG_UART_NUM_MAX] = {0}; static struct task_struct *ts[CFG_UART_NUM_MAX]; static struct sched_param sp[CFG_UART_NUM_MAX]; static int l_ch[CFG_UART_NUM_MAX]; #endif int g_link_uart_chnl = -1; // 级联串口号 static void IEC_Recv(BYTE cDat, BYTE chnl); #ifdef FUN_GPRS // modfiy for xxxxxx 20220706 GPRS没有使用。 extern void (*g_IEC_Recv)(unsigned char cDat, unsigned char chnl); extern int gprs_net_init(void); extern int g_gh_vs_is_idle; extern int g_update_dz; #else // 接收数据处理回调函数 void (*g_IEC_Recv)(unsigned char cDat, unsigned char chnl); #endif #ifdef LINUX_USER_APP static int l_ch[CFG_UART_NUM_MAX]; static pthread_t l_id[CFG_UART_NUM_MAX]; extern int main_mod_is_exit(void); extern void mainloop_wakeup(void); #endif #ifdef CPU_FUXI int uart_isr_thread_create(int ch); extern int main_mod_is_exit(void); #endif extern void FaultComm_Init(IEC101_DEF *pt, BYTE chnl); extern void FaultComm_Applay(IEC101_DEF *pt); extern void FaultComm_Recv(IEC101_DEF *pt, BYTE byRevData); #define CFG_LINK_EQU_SOE_NUM 10 // 级联装置保存SOE数量 u8 g_ti_select[] = { 0x2d, // 单点命令(45) 0x2e, // 双点命令(46) 0xcb, // 写参数和定值(203) 报文格式不同,若需要,应特殊处理 0xd3, // 软件升级(211) }; u8 TI_SELECT_NUM = (sizeof(g_ti_select)); // 文件,信息体对应表 typedef struct DI_DIR { DWORD di; // 485 波特 char *dir; // 串口校验方式无奇偶校验等 } DI_DIR; DI_DIR di_dir[] = { {0x0000, " "}, {0x6804, HF_SOE_101_DIR}, // 6804 {0x6805, HF_CO_101_DIR}, {0x0cea, HF_EXV_101_DIR}, // 6802 {0x6805, HF_FIXPT_101_DIR}, {0x680A, HF_WAVE_DIR}, }; const int DI_DIR_NUMBER = sizeof(di_dir) / sizeof(di_dir[0]); // 个数 #ifdef GEN_QUEUE s32 queue_init(QTYPE *queque, s32 maxsize, void *data, s32 s_size) { queque->count = 0; queque->front = 0; queque->rear = 0; queque->maxsize = maxsize; queque->s_size = s_size; queque->data = data; /*元素实体*/ return 0; } s32 get_queue_count(QTYPE *queue) { return queue->count; } /*函数功能说明:队列操作的通用写接口*/ s32 add_data_queque(QTYPE *queue, u8 *data, u8 op_type) { s32 rear = 0; u32 pos = 0; if ((queue->count >= queue->maxsize) && (op_type == KEEP_QUEUE)) /*队列满,保持原数据*/ { return -1; } rear = queue->rear; pos = rear * queue->s_size; memcpy(&queue->data[pos], data, queue->s_size); queue->rear = (queue->rear + 1) % queue->maxsize; queue->count++; ; /*************/ if ((queue->count > queue->maxsize) && (op_type == OVER_QUEUE)) { queue->count = queue->maxsize; queue->front = (queue->front + 1) % queue->maxsize; } /*************/ return 0; } /*队列操作的通用读接口*/ s32 get_data_queque(QTYPE *queue, u8 *data) { u32 pos = 0; if (queue->count == 0) return -1; /*无数据*/ pos = queue->front * queue->s_size; memcpy(data, &queue->data[pos], queue->s_size); queue->front = (queue->front + 1) % queue->maxsize; queue->count--; return 0; } /*队列操作的通用检查接口*/ s32 check_data_queque(QTYPE *queue, u8 *data) { u32 pos = 0; if (queue->count == 0) return -1; /*无数据*/ pos = queue->front * queue->s_size; memcpy(data, &queue->data[pos], queue->s_size); return 0; } /*队列操作的通用减接口*/ void del_data_queue(QTYPE *queue) { if (queue->count > 0) { queue->front = (queue->front + 1) % queue->maxsize; queue->count--; } } s32 print_queque(QTYPE *queue, u8 type) { s32 i = 0; s32 pos = 0; s32 ret = 0; s32 front = 0; rt_printf("queue------count=%d,s_size=%d,maxsize=%d,front=%d,rear=%d\r\n", (int)queue->count, (int)queue->s_size, (int)queue->maxsize, (int)queue->front, (int)queue->rear); for (i = 0; i < queue->count; i++) { front = (queue->front + i) % queue->maxsize; pos = front * queue->s_size; if (type == RCD_PRINT) { newrcd_m_struct *data; data = (newrcd_m_struct *)&queue->data[pos]; rt_printf("---data[%x][%x]:%s,addr=%d\r\n", (int)front, (int)pos, data->filename, data->addr); } else if (type == PARA_PRINT) { para_chg_single *data; data = (para_chg_single *)&queue->data[pos]; rt_printf("---data[%x][%x]:%f,parId=%x\r\n", (int)front, (int)pos, data->val, data->parId); } } return ret; } #endif #ifdef RCD_STRAN_S void iec_commadd_rcd(char *filename) { int i = 0; char data[128] = {0}; IEC101_DEF *pt101; IEC104_DEF *pt104; for (i = 0; i < CFG_UART_NUM_MAX; i++) { if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_101) // 串口级联规约 { pt101 = (IEC101_DEF *)g_tRsComm[i].ptBuf; strncpy(data, filename, sizeof(data)); add_data_queque(&pt101->rcd_qt.queue, data, OVER_QUEUE); } } for (i = 0; i < CFG_ETH_MAX_LOGIC; i++) { pt104 = &g_t104[i]; strncpy(data, filename, sizeof(data)); add_data_queque(&pt104->rcd_qt.queue, data, OVER_QUEUE); } } #endif char *IEC_Getdir(DWORD di) { int i; for (i = 0; i < DI_DIR_NUMBER; i++) { if (di == di_dir[i].di) return di_dir[i].dir; } return di_dir[0].dir; } bool getCommStatus(void) { int i; for (i = 0; i < CFG_UART_NUM_MAX + CFG_ETH_NUM_MAX; i++) { if (soe_check(EV_COMM1_ERR + i)) return true; } return false; } // 获取101级联通信状态 bool getIecLink101Status(void) { int i; for (i = EV_LINK_EQU1; i < EV_LINK_EQU10; i++) { if (soe_check(i)) return true; } return false; } /************************************************************************** 函数名称:IEC_CommInit 函数版本:1.00 作者: 创建日期:2008.9.1 函数功能说明:外部通信初始化 输入参数: 输出参数: 返回值: 更新信息: 更新日志1: 日期: 修改者: 修改内容: 修改原因: ***************************************************************************/ void IEC_CommInit(void) // 外部通信初始化 { int i, ret; s_stat_reset(1); // 初始串口统计信息 // 相关通道规约应用初始化 g_link_uart_chnl = -1; for (i = 0; i < CFG_UART_NUM_MAX; i++) { // 不管硬件通道是否存在,都将参数设置放入串口统计信息中 s_stat_protocol(i, (int)tRunPara.tUartPara[i].wProtocol); // 统计规约 // 如果硬件通道不存在,跳过 if (UART_CHANNEL[i] < 0) continue; // 如果没有初始化标志,意味着设置没有更新,不重新初始化 if (!tRunPara.tUartPara[i].bInit) continue; tRunPara.tUartPara[i].bInit = false; // 清初始化标志 memset(&g_tRsComm[i], 0, sizeof(g_tRsComm[i])); g_tRsComm[i].ptBuf = (BYTE *)&g_tRsIEC[i]; if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_101 || tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_PH || tRunPara.tUartPara[i].wProtocol == PROTOCOL_MAINTAIN #ifdef FUNC_ENCRY_IN_ONE_SERIAL || tRunPara.tUartPara[i].wProtocol == PROTOCOL_WED_ENC #endif ) // 103 { IEC101_Init((IEC101_DEF *)g_tRsComm[i].ptBuf, i); } else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_M || tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_PH_M) // 101级联 { lnk_101_init((IECLINK_DEF *)g_tRsComm[i].ptBuf, i, (tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_PH_M)); } else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_104) // 104规约 { IEC104_Init_RS((IEC104_DEF *)g_tRsComm[i].ptBuf, i); } #if !defined CPU_FUXI else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_HMI) // 面板规约 { uart_comm_init((UART_COMM_STRUCT *)g_tRsComm[i].ptBuf, i); } else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_FAULT) // 状态板通信 { FaultComm_Init((IEC101_DEF *)g_tRsComm[i].ptBuf, i); } #endif else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_MODBUS) // modbus主站规约 { modbus_Init((MODBUS_DEF *)g_tRsComm[i].ptBuf, i); } #if defined(ADD_ATGM366_GPS_FUN) || defined(DEV_GPS_ATGM366) || defined(DEV_GPS_ATGM332D) else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_GPS) // GPS模块 { GPSCommInit((GPS_COMM *)g_tRsComm[i].ptBuf, i); } #endif else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_AUTHOR_BL) // 蓝牙模块) { bluetooth_init((BLUETOOTH_DEF *)g_tRsComm[i].ptBuf, i); } #ifdef BATTERY_WITH_COMM else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_POWER_MOD) { PowerModuleCommInit((COMM_POW_MOD *)g_tRsComm[i].ptBuf, i); } #ifdef FUNC_SEL_BAT_MODULE else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_PWRM) { pwrm_Init((pwdmodlue_def *)g_tRsComm[i].ptBuf, i); } #endif #endif #ifdef FUN_GPRS // modfiy for xxxxxx 20220706 GPRS没有使用。 if (UART_CHANNEL[i] == CFG_UART_GPRS_IN) { g_gh_vs_is_idle = 1; // 置为空闲.如果不空闲,后续代码会改变此变量的值. } #endif // 如果此串口不是系统控制台串口,协议也不是空闲,初始化串口 if (UART_CHANNEL[i] != g_con_uart_index && tRunPara.tUartPara[i].wProtocol != PROTOCOL_IDLE) { #ifdef FUN_GPRS // modfiy for xxxxxx 20220706 GPRS没有使用。 if (UART_CHANNEL[i] == CFG_UART_GPRS_IN) { g_gh_vs_is_idle = 0; // 置为不空闲 continue; } #endif #ifdef FUN_FUXI_ESAM else if (UART_CHANNEL[i] == CFG_UART_CHIP_S1) { continue; } #endif // 如果GPS对时打开,必须关闭串口。 if (g_clock_mode_gps && UART_CHANNEL[i] == CFG_UART_GPS) { continue; } #ifdef IECCOM_DEBUG rt_printf("UART_CHANNEL[%d]=%d,tRunPara.tUartPara[%d].wProtocol=%d,tRunPara.tUartPara[%d].wBaud=%d tUartPara[%d].wParity=%d\r\n", i, UART_CHANNEL[i], i, tRunPara.tUartPara[i].wProtocol, i, tRunPara.tUartPara[i].dBaud, i, tRunPara.tUartPara[i].wParity); #endif ret = uart_open(UART_CHANNEL[i], tRunPara.tUartPara[i].dBaud, tRunPara.tUartPara[i].wParity); if (ret < 0) { printf("%s: outside uart %d open failed!\n", __FUNCTION__, UART_CHANNEL[i]); } RS_Ena_Init(i); RS_Recv_Enable(i); #if defined CPU_FUXI uart_isr_thread_create(i); #endif } #if !defined CPU_FUXI // 串口打开后,再初始化 if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_HMI) // 面板规约 { g_h_boj[0].fd = UART_CHANNEL[i]; user_conf_init(); // 用户配置初始化(面板) } #endif } // 回调函数 g_IEC_Recv = IEC_Recv; #ifdef FUN_GPRS // modfiy for xxxxxx 20220706 GPRS没有使用。 g_update_dz = 1; // 置标志,要求任务重新初始化虚拟串口 #endif // 内部GPRS初始化 // gprs_net_init(); } /************************************************************************** 函数名称:IEC_Recv 函数版本:1.00 作者: 创建日期:2008.9.1 函数功能说明:通信口接收处理,根据不同的规约类型,调用不同的接收函数 输入参数: 输出参数: 返回值: 更新信息: 更新日志1: 日期: 修改者: 修改内容: 修改原因: ***************************************************************************/ static void IEC_Recv(BYTE cDat, BYTE chnl) { if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_101 || tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_101_PH || tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_MAINTAIN #ifdef FUNC_ENCRY_IN_ONE_SERIAL || tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_WED_ENC #endif ) // 101规约 { IEC101_Recv_Int((IEC101_DEF *)g_tRsComm[chnl].ptBuf, cDat); } else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_101_M || tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_101_PH_M) // 级联 { lnk_101_recv((IECLINK_DEF *)g_tRsComm[chnl].ptBuf, cDat); } else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_104) // 104规约 { IEC104_Recv((IEC104_DEF *)g_tRsComm[chnl].ptBuf, cDat); } #if !defined CPU_FUXI else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_FAULT) // 状态板 { FaultComm_Recv((IEC101_DEF *)g_tRsComm[chnl].ptBuf, cDat); } #endif else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_MODBUS) // modbus主站规约 { modbus_Recv((MODBUS_DEF *)g_tRsComm[chnl].ptBuf, cDat); } #if defined(ADD_ATGM366_GPS_FUN) || defined(DEV_GPS_ATGM366) || defined(DEV_GPS_ATGM332D) else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_GPS) // GPS模块 { GPS_Recv((GPS_COMM *)g_tRsComm[chnl].ptBuf, cDat); } #endif else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_AUTHOR_BL) // 加密蓝牙模块 { bluetooth_recv((BLUETOOTH_DEF *)g_tRsComm[chnl].ptBuf, cDat); } #ifdef BATTERY_WITH_COMM else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_POWER_MOD) { PowerModuleCommRecv((COMM_POW_MOD *)g_tRsComm[chnl].ptBuf, cDat); } #ifdef FUNC_SEL_BAT_MODULE else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_PWRM) // 电源模块规约 { pwrm_Recv((pwdmodlue_def *)g_tRsComm[chnl].ptBuf, cDat); } #endif #endif } #ifdef FUN_FUXI_ESAM void commtask_recv(u8 chnl) { int ret = 0, i = 0; BYTE buf[256]; s1_process(); ret = read_chip_s1(buf, 256); if (ret > 0) /*收到报文收据*/ { // rt_printf("s1_tclrecv:::"); for (i = 0; i < ret; i++) { if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_104) // 104规约 { // rt_printf("[%02x] ",buf[i]); IEC104_Recv_Int((IEC104_DEF *)g_tRsComm[chnl].ptBuf, buf[i]); } else if (tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_101 || tRunPara.tUartPara[chnl].wProtocol == PROTOCOL_101_PH) { IEC101_Recv_Int((IEC101_DEF *)g_tRsComm[chnl].ptBuf, buf[i]); } } // rt_printf("\r\n"); } } #endif /************************************************************************** 函数名称:IEC_485_Task 函数版本:1.00 作者: 创建日期:2008.9.1 函数功能说明:RS485接受处理任务 输入参数: 输出参数: 返回值: 更新信息: 更新日志1: 日期: 修改者: 修改内容: 修改原因: ***************************************************************************/ void IECCommTask(void) { int i, equNum; int commErrTab[CFG_UART_NUM_MAX]; // int equErrTab[]={true}; // 串口规约处理 g_bCommStatus = FALSE; for (i = 0; i < CFG_UART_NUM_MAX; i++) { // 如果串口不存在,跳过 if (UART_CHANNEL[i] < 0) { continue; } #ifdef FUN_FUXI_ESAM else if (UART_CHANNEL[i] == CFG_UART_CHIP_S1) { commtask_recv(i); } #endif commErrTab[i] = true; // 初始化通信端口状态为异常 // 外部通信报文处理 if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_101 || tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_PH || tRunPara.tUartPara[i].wProtocol == PROTOCOL_MAINTAIN #ifdef FUNC_ENCRY_IN_ONE_SERIAL || tRunPara.tUartPara[i].wProtocol == PROTOCOL_WED_ENC #endif ) // 101规约 { IEC101_DEF *pt; IEC101_Applay((IEC101_DEF *)g_tRsComm[i].ptBuf); IEC101_AutoTimer((IEC101_DEF *)g_tRsComm[i].ptBuf); // 101 规约定时处理 pt = (IEC101_DEF *)g_tRsComm[i].ptBuf; if (pt->st101 == IEC101_ST_DATA) { commErrTab[i] = false; g_bCommStatus = true; } } else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_M || tRunPara.tUartPara[i].wProtocol == PROTOCOL_101_PH_M) // 串口级联规约 { IECLINK_DEF *pt; pt = (IECLINK_DEF *)g_tRsComm[i].ptBuf; lnk_101_app((IECLINK_DEF *)g_tRsComm[i].ptBuf); // equNum = pt->slave_current;//按级联地址不同开始计数开始算级联个数 MAX=CFG_LINK_101_NUM equNum = pt->slave_addr; // 按级联地址开始算级联个数 MAX=32 commErrTab[i] = false; // 不监视装置状态的时候,通道默认为正常 if (equNum && equNum <= pt->slave_num) { if (tRunPara.dLinkStateCh == i) // 监测该通道级联装置信息 { if (equNum <= CFG_LINK_EQU_SOE_NUM && soe_check(EV_LINK_EQU1 + equNum - 1) != (!pt->tlnk.bLinkOK)) soe_record_ev(EV_LINK_EQU1 + equNum - 1, (!pt->tlnk.bLinkOK), 0, 0, 0); // 级联装置状态 // rt_printf("slave_current = %d slave_addr=%d slave_num=%d\r\n",pt->slave_current,pt->slave_addr,pt->slave_num); for (equNum = 0; (equNum < pt->slave_num && equNum <= CFG_LINK_EQU_SOE_NUM); equNum++) { if (soe_check(EV_LINK_EQU1 + equNum)) // 当前有一装置异常 { commErrTab[i] = true; // 该通信端口异常 break; } } } // else //if(soe_check(EV_LINK_EQU1+equNum))//当前有一装置异常 { // commErrTab[i] = true;//该通信端口异常 // break; } } } else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_104) // 104规约 { IEC104_DEF *pt104; IEC104_App((IEC104_DEF *)g_tRsComm[i].ptBuf); pt104 = (IEC104_DEF *)g_tRsComm[i].ptBuf; if (pt104->state == IEC104_ST_STARTED) { commErrTab[i] = false; } } #if !defined CPU_FUXI 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); } #endif else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_MODBUS) // modbus主站规约 { modbus_Applay((MODBUS_DEF *)g_tRsComm[i].ptBuf); modbus_AutoTimer((MODBUS_DEF *)g_tRsComm[i].ptBuf); } #if defined(ADD_ATGM366_GPS_FUN) || defined(DEV_GPS_ATGM366) || defined(DEV_GPS_ATGM332D) else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_GPS) // GPS模块 { GPS_Comm_App((GPS_COMM *)g_tRsComm[i].ptBuf); } #endif else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_AUTHOR_BL) // 蓝牙模块 { bluetooth_app((BLUETOOTH_DEF *)g_tRsComm[i].ptBuf); bluetooth_timer((BLUETOOTH_DEF *)g_tRsComm[i].ptBuf); } #ifdef BATTERY_WITH_COMM else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_POWER_MOD) { PowerModuleCommRun((COMM_POW_MOD *)g_tRsComm[i].ptBuf); } #ifdef FUNC_SEL_BAT_MODULE else if (tRunPara.tUartPara[i].wProtocol == PROTOCOL_PWRM) // 电源模块规约 { pwrm_recv_proc((pwdmodlue_def *)g_tRsComm[i].ptBuf); pwrm_send_entry((pwdmodlue_def *)g_tRsComm[i].ptBuf); } #endif #endif else // if(tRunPara.tUartPara[i].wProtocol==PROTOCOL_NULL) { commErrTab[i] = false; // continue; } if (soe_check(EV_COMM1_ERR + i) != commErrTab[i]) { soe_record_ev(EV_COMM1_ERR + i, commErrTab[i], 0, 0, 0); // 记录该端口通信状态 } } // 以太网级联从设备 for (i = 0; i < CFG_LINK_104_NUM; i++) { if (tRunPara.ip104Link[i]) { // if(tRunPara.dLinkStateCh==8)//监测该通道级联装置信息 { if (!net_104link_is_connect(i)) { if (soe_check(EV_LINK_EQU1 + i) != 1) { // rt_printf("级联装置状态改变产生异常SOE,断开连接\n\r"); soe_record_ev(EV_LINK_EQU1 + i, 1, 0, 0, 0); // 级联装置状态 } } else if (net_104link_is_connect(i) && g_link_104[i].bData) { if (soe_check(EV_LINK_EQU1 + i) != 0) { // rt_printf("级联装置状态改变产生恢复SOE,建立连接\n\r"); soe_record_ev(EV_LINK_EQU1 + i, 0, 0, 0, 0); // 级联装置状态 } } } lnk_104_app(i); } } } u8 get_is_invert(u16 no) { int i; for (i = 0; i < g_table_head->di_num; i++) { if (g_di_table[i].cp == no) return g_di_table[i].is_inverse; } return 0; } #ifdef IECTABLE_NEWDPI_V106 u8 get_is_dpi(u16 no) { int i; for (i = 0; i < g_table_head->di_num; i++) { if (g_di_table[i].cp == no) return g_di_table[i].dpi; } return 0; } #endif #ifdef SOE_RELINK_DISCOS bool is_resume_soe(u8 ch) { if (g_soe_queue.bSoeRelink[ch]) /*发生续传中*/ { if (g_soe_queue.tail_send[ch].n != g_soe_queue.relink_tail_bak[ch].n) { rt_printf("------通讯续传中tail_send:%d,bak:%d\r\n", g_soe_queue.tail_send[ch].n, g_soe_queue.relink_tail_bak[ch].n); return true; } else { rt_printf("------通讯续传结束\r\n"); g_soe_queue.bSoeRelink[ch] = false; /*续传结束*/ } } return false; } #endif int asdu_get_event(u8 ch, u16 head, u8 *pcos, u8 *psoe, u8 *pcos1, u8 *psoe1, u16 *psoe_sno, u16 *psoe_dno, int baddr3, bool *bf, EVENT_STRUCT *ev, u16 *extarg, u8 *yxtype, u8 *pcosnum, u8 *pcosnum1) { bool b_siq = false; int soe_no = 0, cnt_s = 0, cnt_d = 0, cnt_evp = 0; u8 SIQ, week; u8 soe_type; u16 no, index = 0; EVENT_STRUCT event; struct rtc_time_t rt; u8 isInverse = 0; u8 ditype = 0; *pcosnum = 0; *pcosnum1 = 0; while (g_soe_queue.tail_send[ch].n != head) // 有SOE产生 { #ifdef SOE_RELINK_DISCOS bool bresuming = false; bresuming = is_resume_soe(ch); #endif // 得到一个事件 index = g_soe_queue.tail_send[ch].n; soe_no = soe_get(ch, &event); if (soe_no < 0) { rt_printf_time("soe_get(%d):ret=%d.\r\n", ch, soe_no); break; } // 得到检查通讯点号,如果为0,则此事件不需要发送 // 此处会滤除不需发送的事件的,例如操作事件。 no = soe_lp2cp(event.ev_type, event.ev_code, event.ev_arg[1]); if (no == 0) { continue; } #ifdef IEC_JXYB_DEAL if (g_run_stu.bjx) { u8 yx_slot = (u8)(event.ev_code >> 8); // 板卡号 u8 yx_no = (u8)(event.ev_code); // 遥信号 u8 yx_type = equ_pub_di_type(yx_slot, yx_no); { if (yx_type > 0) { yx_type -= 1; if (yx_type != PUB_DI_JX) { continue; } } else { continue; } } } #endif #ifdef IECTABLE_NEWDPI_V106 { int k; u8 owner = 0; isInverse = get_is_invert(no); ditype = get_is_dpi(no); // 整理好SIQ,单双点需要转换 soe_type = event.ev_type & SOE_TYPE_MASK; SIQ = event.ev_value; for (k = 0; k < g_table_head->di_num; k++) { if (g_di_table[k].cp == no) { owner = g_di_table[k].owner; break; } } if (tRunPara.bSDPI) { if (soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK) { if (ditype == 0) // 单点上送 { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 } } else { if (ditype == 1) // 双点上送 { SIQ += 1; // 转为双点点信息 } } } else { ditype = tRunPara.bDPI ? 1 : 0; if (ditype == 1) // 双点上送 { if (soe_type != SOE_TYPE_DPI && soe_type != SOE_TYPE_LNK) { SIQ += 1; // 转为双点点信息 } } else { if (soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK) { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 } } } if (isInverse) { if (ditype == 1) // 双点取反 { if (SIQ == 2) { SIQ = 1; } else if (SIQ == 1) { SIQ = 2; } } else // 单点取反 { SIQ = (SIQ == 0) ? 1 : 0; } } } #else { u8 owner = 0; int j, k, id1, id2; bool db_special = 0; // 特殊双点 static u8 bh_fa_keep[SWITCH_NUM_EXT] = {0}; for (k = 0; k < g_table_head->di_num; k++) { if (g_di_table[k].cp == no) { owner = g_di_table[k].owner; break; } } for (j = 0; j < g_table_head->di_db_num; j++) { db_special = false; if (no == g_di_db_table[j].cp) { id1 = g_di_db_table[j].no[0] & 0xff; id2 = g_di_db_table[j].no[1] & 0xff; if (((id1 == (SW_DI_BHTT + 1)) && (id2 == (SW_DI_FA_TT + 1))) || ((id2 == (SW_DI_BHTT + 1)) && (id1 == (SW_DI_FA_TT + 1)))) { // rt_printf("%s:cp=0x%04x,id1=0x%04x,id2=0x%04x\r\n",__func__,g_di_db_table[j].cp,g_di_db_table[j].no[0],g_di_db_table[j].no[1]); db_special = true; break; } } } isInverse = get_is_invert(no); // 整理好SIQ,单双点需要转换 soe_type = event.ev_type & SOE_TYPE_MASK; SIQ = event.ev_value; // 级联上送的SOE带品质描述 if (SIQ & 0x80) { #ifdef IEC_QDS_HAVE b_siq = true; SIQ = (SIQ & 0x7f); #endif } if (db_special) { if (g_sw[owner].di[SW_DI_BHTT] == 1 && g_sw[owner].di[SW_DI_FA_TT] == 1) SIQ = bh_fa_keep[owner]; else { if (g_sw[owner].di[SW_DI_FA_TT] == 2) SIQ = 1; else if (g_sw[owner].di[SW_DI_BHTT] == 2) SIQ = 0; bh_fa_keep[owner] = SIQ; } if (SIQ == 0) { SIQ = 1; } else { SIQ = 2; } } // rt_printf("%s(2):soe_type=%d,SIQ=0x%02x,owner=%d,no=0x%04x,indexno=%d,isInverse=%d\r\n",__func__,soe_type,SIQ,owner,no,g_di_table[k].indexno,isInverse); if (tRunPara.bSDPI) { ditype = (soe_type == SOE_TYPE_DPI) ? 1 : 0; if (soe_type == SOE_TYPE_LNK) { if (SWITCH_NUM_EXT == owner) // 将默认开关31当成级联双点 { ditype = 1; } else { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 if (isInverse) { SIQ = (SIQ == 0) ? 1 : 0; } } } else { if (soe_type != SOE_TYPE_DPI) { if (isInverse) { SIQ = (SIQ == 0) ? 1 : 0; } } else { if (isInverse) { if (SIQ == 2) { SIQ = 1; } else if (SIQ == 1) { SIQ = 2; } } } } /* if((soe_type == SOE_TYPE_DPI)&&(isInverse)) { SIQ =((~SIQ)&0x03); } */ } else { if (tRunPara.bDPI) { if (soe_type != SOE_TYPE_DPI && soe_type != SOE_TYPE_LNK) { SIQ += 1; // 转为双点信息 } if (isInverse) { if (SIQ == 2) { SIQ = 1; } else if (SIQ == 1) { SIQ = 2; } } } else { if (soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK) { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 } if (soe_type != SOE_TYPE_PLC) { if (isInverse) { SIQ = (SIQ == 0) ? 1 : 0; } } } ditype = tRunPara.bDPI ? 1 : 0; } } #endif *yxtype = ditype; if (g_run_stu.bToolRmtTest || g_run_stu.bHmiRmtTest) // 测试模式,遥信置为无效 { if (pRunSet->bTT_RmtTest) SIQ |= 0x80; } #if !defined IEC_JXYB_DEAL && !defined FUNC_JX_YC_SIQ00 if (g_run_stu.bjx || b_siq) SIQ |= 0x80; #endif // 单点 if (*yxtype == 0) { // COS #ifdef SOE_RELINK_DISCOS if (!bresuming) #endif { *pcos++ = (u8)no; // 信息体地址L *pcos++ = (u8)(no >> 8); // 信息体地址H if (baddr3) { *pcos++ = 0; // 信息体地址H2 } *pcos++ = SIQ; // 遥信 *pcosnum += 1; } // SOE timespec_to_rtc(event.ts, &rt, 1); week = WEEK_DAY(event.ts.tv_sec); *psoe++ = (u8)no; // 信息体地址L *psoe++ = (u8)(no >> 8); // 信息体地址H if (baddr3) { *psoe++ = 0; // 信息体地址H2 } *psoe++ = SIQ; // 遥信 *psoe++ = (u8)rt.ms; *psoe++ = (u8)(rt.ms >> 8); *psoe++ = (u8)rt.min; *psoe++ = (u8)rt.hour; *psoe++ = ((week << 5) | rt.day); *psoe++ = (u8)rt.month; *psoe++ = (u8)rt.year; cnt_s++; *psoe_sno = soe_no; } else { #ifdef SOE_RELINK_DISCOS if (!bresuming) #endif { *pcos1++ = (u8)no; // 信息体地址L *pcos1++ = (u8)(no >> 8); // 信息体地址H if (baddr3) { *pcos1++ = 0; // 信息体地址H2 } *pcos1++ = SIQ; // 遥信 *pcosnum1 += 1; } // SOE timespec_to_rtc(event.ts, &rt, 1); week = WEEK_DAY(event.ts.tv_sec); *psoe1++ = (u8)no; // 信息体地址L *psoe1++ = (u8)(no >> 8); // 信息体地址H if (baddr3) { *psoe1++ = 0; // 信息体地址H2 } *psoe1++ = SIQ; // 遥信 *psoe1++ = (u8)rt.ms; *psoe1++ = (u8)(rt.ms >> 8); *psoe1++ = (u8)rt.min; *psoe1++ = (u8)rt.hour; *psoe1++ = ((week << 5) | rt.day); *psoe1++ = (u8)rt.month; *psoe1++ = (u8)rt.year; cnt_d++; *psoe_dno = soe_no; } if (event.ev_type & SOE_TYPE_FAULT) // 该事件需上送故障信息 { if (ev != NULL) { *ev++ = event; *extarg++ = index; cnt_evp++; } //*bf=(num_p>0)&&tRunPara.bEvPara; } if (cnt_s >= MAX_SOE_PER_FRAME) { break; } if (cnt_d >= MAX_SOE_PER_FRAME) { break; } // if(tRunPara.bSDPI)break; // 单双点配置,SOE逐条上送 } return (cnt_s + (cnt_d << 8) + (cnt_evp << 16)); } int asdu_get_event_104(u8 ch, u16 head, u8 *pcos, u8 *psoe, u16 *psoe_no, int baddr3, bool *bf, EVENT_STRUCT *ev, u16 *extarg, u8 *yxtype) { bool b_siq = false; int soe_no = 0, cnt = 0; u8 SIQ, week; u8 soe_type; u16 no, index = 0; EVENT_STRUCT event; struct rtc_time_t rt; u8 isInverse = 0; u8 ditype = 0; while (g_soe_queue.tail_send[ch].n != head) // 有SOE产生 { // 得到一个事件 index = g_soe_queue.tail_send[ch].n; soe_no = soe_get(ch, &event); if (soe_no < 0) { rt_printf_time("soe_get(%d):ret=%d.\r\n", ch, soe_no); break; } // 得到检查通讯点号,如果为0,则此事件不需要发送 // 此处会滤除不需发送的事件的,例如操作事件。 no = soe_lp2cp(event.ev_type, event.ev_code, event.ev_arg[1]); if (no == 0) { continue; } #ifdef IEC_JXYB_DEAL if (g_run_stu.bjx) { u8 yx_slot = (u8)(event.ev_code >> 8); // 板卡号 u8 yx_no = (u8)(event.ev_code); // 遥信号 u8 yx_type = equ_pub_di_type(yx_slot, yx_no); { if (yx_type > 0) { yx_type -= 1; if (yx_type != PUB_DI_JX) { continue; } } else { continue; } } } #endif #ifdef IECTABLE_NEWDPI_V106 { int k; u8 owner = 0; isInverse = get_is_invert(no); ditype = get_is_dpi(no); // 整理好SIQ,单双点需要转换 soe_type = event.ev_type & SOE_TYPE_MASK; SIQ = event.ev_value; for (k = 0; k < g_table_head->di_num; k++) { if (g_di_table[k].cp == no) { owner = g_di_table[k].owner; break; } } if (tRunPara.bSDPI) { if (soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK) { if (ditype == 0) // 单点上送 { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 } } else { if (ditype == 1) // 双点上送 { SIQ += 1; // 转为双点点信息 } } } else { ditype = tRunPara.bDPI ? 1 : 0; if (ditype == 1) // 双点上送 { if (soe_type != SOE_TYPE_DPI && soe_type != SOE_TYPE_LNK) { SIQ += 1; // 转为双点点信息 } } else { if (soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK) { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 } } } if (isInverse) { if (ditype == 1) // 双点取反 { if (SIQ == 2) { SIQ = 1; } else if (SIQ == 1) { SIQ = 2; } } else // 单点取反 { SIQ = (SIQ == 0) ? 1 : 0; } } } #else { u8 owner = 0; int j, k, id1, id2; bool db_special = 0; // 特殊双点 static u8 bh_fa_keep[SWITCH_NUM_EXT] = {0}; for (k = 0; k < g_table_head->di_num; k++) { if (g_di_table[k].cp == no) { owner = g_di_table[k].owner; break; } } for (j = 0; j < g_table_head->di_db_num; j++) { db_special = false; if (no == g_di_db_table[j].cp) { id1 = g_di_db_table[j].no[0] & 0xff; id2 = g_di_db_table[j].no[1] & 0xff; if (((id1 == (SW_DI_BHTT + 1)) && (id2 == (SW_DI_FA_TT + 1))) || ((id2 == (SW_DI_BHTT + 1)) && (id1 == (SW_DI_FA_TT + 1)))) { // rt_printf("%s:cp=0x%04x,id1=0x%04x,id2=0x%04x\r\n",__func__,g_di_db_table[j].cp,g_di_db_table[j].no[0],g_di_db_table[j].no[1]); db_special = true; break; } } } isInverse = get_is_invert(no); // 整理好SIQ,单双点需要转换 soe_type = event.ev_type & SOE_TYPE_MASK; SIQ = event.ev_value; // 级联上送的SOE带品质描述 if (SIQ & 0x80) { #ifdef IEC_QDS_HAVE b_siq = true; SIQ = (SIQ & 0x7f); #endif } if (db_special) { if (g_sw[owner].di[SW_DI_BHTT] == 1 && g_sw[owner].di[SW_DI_FA_TT] == 1) SIQ = bh_fa_keep[owner]; else { if (g_sw[owner].di[SW_DI_FA_TT] == 2) SIQ = 1; else if (g_sw[owner].di[SW_DI_BHTT] == 2) SIQ = 0; bh_fa_keep[owner] = SIQ; } if (SIQ == 0) { SIQ = 1; } else { SIQ = 2; } } // rt_printf("%s(2):soe_type=%d,SIQ=0x%02x,owner=%d,no=0x%04x,indexno=%d,isInverse=%d\r\n",__func__,soe_type,SIQ,owner,no,g_di_table[k].indexno,isInverse); if (tRunPara.bSDPI) { ditype = (soe_type == SOE_TYPE_DPI) ? 1 : 0; if (soe_type == SOE_TYPE_LNK) { if (SWITCH_NUM_EXT == owner) // 将默认开关31当成级联双点 { ditype = 1; } else { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 if (isInverse) { SIQ = (SIQ == 0) ? 1 : 0; } } } else { if (soe_type != SOE_TYPE_DPI) { if (isInverse) { SIQ = (SIQ == 0) ? 1 : 0; } } else { if (isInverse) { if (SIQ == 2) { SIQ = 1; } else if (SIQ == 1) { SIQ = 2; } } } } /* if((soe_type == SOE_TYPE_DPI)&&(isInverse)) { SIQ =((~SIQ)&0x03); } */ } else { if (tRunPara.bDPI) { if (soe_type != SOE_TYPE_DPI && soe_type != SOE_TYPE_LNK) { SIQ += 1; // 转为双点信息 } if (isInverse) { if (SIQ == 2) { SIQ = 1; } else if (SIQ == 1) { SIQ = 2; } } } else { if (soe_type == SOE_TYPE_DPI || soe_type == SOE_TYPE_LNK) { SIQ = (SIQ == SW_DI_TYPE_ON); // 转为单点信息 } if (soe_type != SOE_TYPE_PLC) { if (isInverse) { SIQ = (SIQ == 0) ? 1 : 0; } } } ditype = tRunPara.bDPI ? 1 : 0; } } #endif *yxtype = ditype; if (g_run_stu.bToolRmtTest || g_run_stu.bHmiRmtTest) // 测试模式,遥信置为无效 { if (pRunSet->bTT_RmtTest) SIQ |= 0x80; } #if !defined IEC_JXYB_DEAL && !defined FUNC_JX_YC_SIQ00 if (g_run_stu.bjx || b_siq) SIQ |= 0x80; #endif // COS *pcos++ = (u8)no; // 信息体地址L *pcos++ = (u8)(no >> 8); // 信息体地址H if (baddr3) { *pcos++ = 0; // 信息体地址H2 } *pcos++ = SIQ; // 遥信 // SOE timespec_to_rtc(event.ts, &rt, 1); week = WEEK_DAY(event.ts.tv_sec); *psoe++ = (u8)no; // 信息体地址L *psoe++ = (u8)(no >> 8); // 信息体地址H if (baddr3) { *psoe++ = 0; // 信息体地址H2 } *psoe++ = SIQ; // 遥信 *psoe++ = (u8)rt.ms; *psoe++ = (u8)(rt.ms >> 8); *psoe++ = (u8)rt.min; *psoe++ = (u8)rt.hour; *psoe++ = ((week << 5) | rt.day); *psoe++ = (u8)rt.month; *psoe++ = (u8)rt.year; cnt++; if (event.ev_type & SOE_TYPE_FAULT) // 该事件需上送故障信息 { if (ev != NULL) { *ev = event; *bf = true && tRunPara.bEvPara; *extarg = index; break; } } if (cnt >= MAX_SOE_PER_FRAME) { break; } if (tRunPara.bSDPI) break; // 单双点配置,SOE逐条上送 } *psoe_no = soe_no; return cnt; } int asdu_get_event_yc(BYTE *dat, int baddr3, u16 arg_index) { int evsw; int i, j; BYTE indexno; BYTE ycnum = 0; EVENT_EXT_ARG *pArg; pArg = &g_soe_queue.tExtArg[arg_index]; // 附加参数 for (i = 0; i < EXT_ARG_NUMBER; i++) { if (pArg->type[i] == SW_AC_IA || pArg->type[i] == SW_AC_IB || pArg->type[i] == SW_AC_IC || pArg->type[i] == SW_AC_I0) { evsw = pArg->sw + 1; } else { evsw = 0; } indexno = (pArg->type[i] & 0x7f) + 1; for (j = 0; j < g_table_head->ac_num; j++) { u8 no = g_ac_table[j].indexno; if (g_ac_table[j].owner == evsw && no == indexno) // soe参数在转发表中有配置获取点号 { WORD di = g_ac_table[j].cp; union { float ff; u8 tt[4]; } ff; if (pRunSet->bTT_EV_YCRate) { ff.ff = (float)pArg->arg[i] / 65536 * ((float)g_ac_table[j].rate / 65536.0); } else { ff.ff = (float)pArg->arg[i] / 65536; } *dat++ = (BYTE)di; *dat++ = (BYTE)(di >> 8); if (baddr3) *dat++ = 0; dat += CopySwap(dat, ff.tt, sizeof(ff.tt), true); ycnum++; } } } return ycnum; } #ifdef CPU_FUXI static int uart_isr_thread(void *arg) { int ret = 0; int i = 0; int send_fail_cnt = 0; int send_len = 0; static unsigned char buf[256]; #ifdef LINUX_USER_APP char thread_name[25]; #endif int ch = *((int *)arg); volatile SERIAL_COMM *prc; prc = &g_tRsComm[ch]; #ifdef RT_THREAD_DEBUG rt_printf("uart_isr_thread---%d\r\n", ch); #endif #ifdef CPU_FUXI memset(thread_name, 0, sizeof(thread_name)); sprintf(thread_name, "uart_isr_%d", ch); prctl(PR_SET_NAME, thread_name); uint32_t wdt_id[20]; int rc = watchdog_add_item(thread_name, &wdt_id[ch], 120); if (rc != 0) { printf("can not add %s task to wdt\r\n", thread_name); return -1; } #endif while (1) { #ifdef CPU_FUXI msleep(5); watchdog_feed(wdt_id[ch]); #else msleep(1); // noted by sunxi: 20220706 面板切换太慢,5ms->1ms,以提高速度 #endif // 检查是否退出 if (main_mod_is_exit()) { uart_close(UART_CHANNEL[ch]); break; } if (UART_CHANNEL[ch] < 0 || UART_CHANNEL[ch] == g_con_uart_index || tRunPara.tUartPara[ch].wProtocol == PROTOCOL_IDLE) { continue; } #if 0 // 如果GPS对时打开,必须关闭串口。 if(g_clock_mode_gps && chnl == CFG_UART_GPS) { continue; } #endif // 如果是使用内部GPRS,则不用再走下面的代码流程 if (UART_CHANNEL[ch] == CFG_UART_GPRS_IN) { continue; } #ifdef FUN_FUXI_ESAM else if (UART_CHANNEL[ch] == CFG_UART_CHIP_S1) { continue; } #endif #if !defined CPU_FUXI // 面板做特殊处理 if (tRunPara.tUartPara[ch].wProtocol == PROTOCOL_HMI) { // 规约处理 protocol_proc_task(ch); continue; } #endif #if 1 // 接收 start ret = uart_select(UART_CHANNEL[ch]); // 有数据可读 if (ret > 0) { // rt_printf("\nch_%d have select.\n",ch); // 读取数据 memset(buf, 0, sizeof(buf)); ret = uart_read(UART_CHANNEL[ch], buf, sizeof(buf)); if (ret > 0) { // 处理101规约报文 if (g_IEC_Recv) { // rt_printf("ch_%d have rev:\n",ch); for (i = 0; i < ret; i++) { #ifdef FLOW_CALC_FUNC if (ch == tRunPara.flow_port) { g_sw_pub.ac_in[PUB_AC_IN_FLOW] += Q16_BASE; } #endif g_IEC_Recv(buf[i], ch); if (g_print_comm_raw && (g_print_port & (1 << ch))) { if (UART_CHANNEL[ch] == CFG_UART_232_0) { rt_printf("%c", buf[i]); } else { rt_printf("%02x ", buf[i]); } } } // rt_printf("\n"); s_stat_rx(ch, ret); // 接收字节数计数 prc->us0_recv = ustimer_get_origin(); // 记录接收数据的时间戳 } #if 0 //测试代码 rt_printf("\nch_%d RECV num=%d frame:",ch,ret); for(i = 0; i < ret; i++) { rt_printf("%02x ", (unsigned char)buf[i]); } rt_printf("\n"); uart_write(ch, (const char *)buf, ret);//sunxi for test #endif } else if (ret < 0) { // rt_printf("\nch_%d read err!\n",ch); s_stat_rx_err(ch, 1); // 接收错误计数 } } else { msleep(5); if (ret < 0) { // rt_printf("\nch_%d select err!\n",ch); s_stat_rx_err(ch, 1); // 接收错误计数 } if (ustimer_get_duration(prc->us0_recv) > prc->us_recv_timeout) { prc->b_recv_reset = 1; } } // 接收 end #endif #if 1 // 发送 start if (prc->bextsend #ifdef FUNC_ENCRY_IN_ONE_SERIAL || prc->bextsend_1 || prc->bextsend_2 || prc->bextsend_3 #endif ) { // 规约要求帧与帧之间间隔必须大于33位。 if ((prc->extsendcnt == 0 // 帧头 #ifdef FUNC_ENCRY_IN_ONE_SERIAL || prc->extsendcnt_1 == 0 || prc->extsendcnt_2 == 0 || prc->extsendcnt_3 == 0 #endif ) && ((ustimer_get_duration(prc->us0_recv) < 5 * USTIMER_MS) // 与接收帧之间的间隔 || (ustimer_get_duration(prc->us0_send) < 5 * USTIMER_MS))) // 与发送帧之间的间隔 { continue; } if (prc->extsendlen > 0) { send_fail_cnt = 0; send_len = 0; while (send_len < prc->extsendlen) // 发送没完成,继续发送 { if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\nTX[%d]:", ch); } ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf[prc->extsendcnt + send_len], (prc->extsendlen - send_len)); if (ret > 0) { if (g_print_comm_raw && (g_print_port & (1 << ch))) { for (i = 0; i < ret; i++) { rt_printf("%02x ", prc->extsendbuf[prc->extsendcnt + send_len + i]); } } send_len += ret; s_stat_tx(ch, ret); // 发送字节数计数 } else if (send_fail_cnt++ > 5) { send_fail_cnt = 0; // rt_printf("\nch_%d send fail!!!\n",ch); break; } } if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\n"); } { prc->bextsend = false; prc->extsendcnt = 0; mainloop_wakeup(); prc->us0_send = ustimer_get_origin(); // 记录发送数据的时间戳 } } #ifdef FUNC_ENCRY_IN_ONE_SERIAL else if (prc->extsendlen_1 > 0) { send_fail_cnt = 0; send_len = 0; while (send_len < prc->extsendlen_1) // 发送没完成,继续发送 { if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\nTX[%d]:", ch); } ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf_1[prc->extsendcnt_1 + send_len], (prc->extsendlen_1 - send_len)); if (ret > 0) { if (g_print_comm_raw && (g_print_port & (1 << ch))) { for (i = 0; i < ret; i++) { rt_printf("%02x ", prc->extsendbuf_1[prc->extsendcnt_1 + send_len + i]); } } send_len += ret; s_stat_tx(ch, ret); // 发送字节数计数 } else if (send_fail_cnt++ > 5) { send_fail_cnt = 0; // rt_printf("\nch_%d send fail!!!\n",ch); break; } } if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\n"); } { prc->bextsend_1 = false; prc->extsendcnt_1 = 0; mainloop_wakeup(); prc->us0_send = ustimer_get_origin(); // 记录发送数据的时间戳 } } else if (prc->extsendlen_2 > 0) { send_fail_cnt = 0; send_len = 0; while (send_len < prc->extsendlen_2) // 发送没完成,继续发送 { if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\nTX[%d]:", ch); } ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf_2[prc->extsendcnt_2 + send_len], (prc->extsendlen_2 - send_len)); if (ret > 0) { if (g_print_comm_raw && (g_print_port & (1 << ch))) { for (i = 0; i < ret; i++) { rt_printf("%02x ", prc->extsendbuf_2[prc->extsendcnt_2 + send_len + i]); } } send_len += ret; s_stat_tx(ch, ret); // 发送字节数计数 } else if (send_fail_cnt++ > 5) { send_fail_cnt = 0; // rt_printf("\nch_%d send fail!!!\n",ch); break; } } if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\n"); } { prc->bextsend_2 = false; prc->extsendcnt_2 = 0; mainloop_wakeup(); prc->us0_send = ustimer_get_origin(); // 记录发送数据的时间戳 } } else if (prc->extsendlen_3 > 0) { send_fail_cnt = 0; send_len = 0; while (send_len < prc->extsendlen_3) // 发送没完成,继续发送 { if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\nTX[%d]:", ch); } ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->extsendbuf_3[prc->extsendcnt_3 + send_len], (prc->extsendlen_3 - send_len)); if (ret > 0) { if (g_print_comm_raw && (g_print_port & (1 << ch))) { for (i = 0; i < ret; i++) { rt_printf("%02x ", prc->extsendbuf_3[prc->extsendcnt_3 + send_len + i]); } } send_len += ret; s_stat_tx(ch, ret); // 发送字节数计数 } else if (send_fail_cnt++ > 5) { send_fail_cnt = 0; // rt_printf("\nch_%d send fail!!!\n",ch); break; } } if (g_print_comm_raw && (g_print_port & (1 << ch))) { rt_printf("\r\n"); } { prc->bextsend_3 = false; prc->extsendcnt_3 = 0; mainloop_wakeup(); prc->us0_send = ustimer_get_origin(); // 记录发送数据的时间戳 } } #endif } else if (prc->bSend) // 发送 { // 规约要求帧与帧之间间隔必须大于33位。 if (prc->nSendCnt <= 1 // 帧头 && ((ustimer_get_duration(prc->us0_recv) < 5 * USTIMER_MS) // 与接收帧之间的间隔 || (ustimer_get_duration(prc->us0_send) < 5 * USTIMER_MS))) // 与发送帧之间的间隔 { continue; } if (prc->sendbuf[0] > 0) { send_fail_cnt = 0; send_len = 0; while (send_len < prc->sendbuf[0]) // 发送没完成,继续发送 { // TODO. noted by sunxi 这里也需要加select,并且write的select与read的select 的参数不一样。 ret = uart_write(UART_CHANNEL[ch], (const char *)&prc->sendbuf[prc->nSendCnt + send_len], (prc->sendbuf[0] - send_len)); if (ret > 0) { if (g_print_comm_raw && (g_print_port & (1 << ch))) { if (send_len == 0) { rt_printf("\r\nTX[%d]:", ch); } for (i = 0; i < ret; i++) { if ((ch + 1) == CFG_UART_GPS) { rt_printf("%c", prc->sendbuf[prc->nSendCnt + send_len + i]); } else { rt_printf("%02x ", prc->sendbuf[prc->nSendCnt + send_len + i]); } } } send_len += ret; s_stat_tx(ch, ret); // 发送字节数计数 } else if (send_fail_cnt++ > 5) { send_fail_cnt = 0; rt_printf("\nch_%d send fail!!!\n", ch); break; } if (g_print_comm_raw && (g_print_port & (1 << ch))) { if ((ch + 1) != CFG_UART_GPS) rt_printf("\r\n"); } } { #ifdef FLOW_CALC_FUNC if (ch == tRunPara.flow_port) { g_sw_pub.ac_in[PUB_AC_IN_FLOW] += (prc->sendbuf[0] + 46) * Q16_BASE; // TCP+IP包头40个字节,数据部分1个字节,PPP头7E 21 ,PPP尾校验和2位+1个7E,总共是40+1+5=46个字节 } #endif if (uart_test_begin) { uart_test_flag[ch][0] = 1; } prc->bSend = false; prc->nSendCnt = 0; send_len = 0; RS_Recv_Enable(ch); #if !defined CPU_FUXI if (tRunPara.tUartPara[ch].wProtocol == PROTOCOL_HMI) { Reset_Uart_Link((UART_COMM_STRUCT *)g_tRsComm[ch].ptBuf); } #endif 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 #endif void uart_232_485_test(u8 *buf) { int i; u8 dat[6] = {0x10, 0x40, 0x01, 0x00, 0x41, 0x16}; memset(uart_test_flag, 0, sizeof(uart_test_flag)); // RS232测试 if (buf[0]) { for (i = 0; i < 2; i++) { g_tRsComm[i].sendbuf[0] = 6; memcpy(&g_tRsComm[i].sendbuf[1], dat, 6); RS_Send_Enable(i); g_tRsComm[i].nSendCnt = 1; g_tRsComm[i].bSend = true; rt_printf("TX_101_%d:", i); print_msg("", &g_tRsComm[i].sendbuf[1], g_tRsComm[i].sendbuf[0]); } } // RS485测试 if (buf[1]) { for (i = 3; i < 6; i++) { g_tRsComm[i].sendbuf[0] = 6; memcpy(&g_tRsComm[i].sendbuf[1], dat, 6); RS_Send_Enable(i); g_tRsComm[i].nSendCnt = 1; g_tRsComm[i].bSend = true; rt_printf("TX_101_%d:", i); print_msg("", &g_tRsComm[i].sendbuf[1], g_tRsComm[i].sendbuf[0]); } } // 延时2ms,以保证通讯完毕 ustimer_delay(200 * USTIMER_MS); msleep(200); // nodify by sunxi for 335x IECCommTask(); { u8 i; for (i = 0; i < CFG_UART_NUM_MAX - 1; i++) { rt_printf("chnl = %d, send=%d, recv=%d\r\n", i, uart_test_flag[i][0], uart_test_flag[i][1]); } } } void iec_GetMsgInfo(u8 *buf, int len, u8 *ti, u8 *cot, u8 *se, bool b101) { int i; u8 AddByte = 0; u8 CotByte = 0; // 传送原因双字节 u8 AppByte = 0; // 应用单元地址双字节 u8 sel; // 所有定长帧的长度都不大于6个字节,不定长帧都大于等于15字节 if (len < 8) { *ti = 0; *cot = 0; *se = 0; return; } if (b101) { if (tRunPara.b101Addr2Byte) AddByte = 1; if (tRunPara.b101Cot2Byte) CotByte = 1; if (tRunPara.b101App2Byte) AppByte = 1; sel = buf[12 + AddByte + CotByte + AppByte]; } else { sel = buf[15]; } // 基本信息 *ti = buf[6 + AddByte]; *cot = buf[8 + AddByte]; *se = 0; if (*ti == 0xcb) // 参数修改,选择位不同 { if (!b101) { sel = buf[14]; } } // 更新se for (i = 0; i < TI_SELECT_NUM; i++) { if (*ti == g_ti_select[i]) { *se = (sel & 0x80) ? 1 : 0; break; } } if (*ti == 210) // 文件操作 { BYTE cmd; if (b101) { cmd = buf[13 + AddByte + CotByte + AppByte]; // 文件操作命令码 } else { cmd = buf[16]; } if (cmd == 7 && *cot == 6) // 写文件激活与其他文件类操作不同 { *se = 1; } else { *se = 0; } } return; } /*************远方修改定值,固定参数初始化************************/ #define MAX_UTF8_NUM 64 typedef struct FIXSET_UTF8 { int num; u16 intcode[MAX_UTF8_NUM]; u16 unicode[MAX_UTF8_NUM]; } FIXSET_UTF8_DEF; FIXSET_UTF8_DEF tUtf8; int iec_findchardot(u8 *buf, u8 *str) { u8 *ps; int i, lenth = 0; ps = strchr(buf, ','); if (ps) // 存在',' { lenth = ps - buf; for (i = 0; i < lenth; i++) { str[i] = *buf++; } str[i] = '\0'; } return lenth; } static void iec_getfixsetinf(RMT_FIXED_TABLE *pfixedset, u8 *buf) { u8 str[128], type = 0; int len, i; len = iec_findchardot(buf, str); if (len == 0) return; if (strcmp(str, "FIXSET") == 0) // 固定参数 { buf += len + 1; len = iec_findchardot(buf, str); if (len == 0) return; type = strtoul(str, NULL, 10); for (i = 0; i < pfixedset->num; i++) { if (type == pfixedset->set[i].type) { buf += len + 1; len = iec_findchardot(buf, str); // 取输入点号 if (len == 0) return; if (type == FIXED_SET_CRC) { WORD crc; crc = strtoul(str, NULL, 16); pfixedset->set[i].str[0] = (BYTE)(crc); pfixedset->set[i].str[1] = (BYTE)(crc >> 8); pfixedset->set[i].len = 2; } else { strcpy(pfixedset->set[i].str, str); pfixedset->set[i].len = strlen(pfixedset->set[i].str); } break; } } } else if (strcmp(str, "UNICODE") == 0) // 固定参数 { if (tUtf8.num >= MAX_UTF8_NUM) return; buf += len + 1; len = iec_findchardot(buf, str); if (len == 0) return; tUtf8.intcode[tUtf8.num] = str[1] | (str[0] << 8); // 汉字内码 buf += len + 1; len = iec_findchardot(buf, str); // tUtf8.unicode[tUtf8.num] = strtoul(str, NULL, 16); // unicode tUtf8.num++; } } int iec_get_fixedset_csv(RMT_FIXED_TABLE *pfixedset) { u32 i, file_length; struct file *pfile; u8 *filebuf; u8 filestr[64], *pstr, strlenth; loff_t pos; // 打开文件 pfile = rt_file_open("/app/data/fixset.csv", O_RDONLY, 0); if (IS_ERR(pfile)) { // rt_printf("error! 无法打开 iec_cfg.csv\r\n"); return -1; } // 得到文件长度 file_length = rt_file_getfile_size(pfile); if (file_length == 0) { rt_file_close(pfile, 0); return -2; } // 分配内存 filebuf = rt_malloc(file_length); if ((filebuf) == NULL) { rt_file_close(pfile, 0); return -3; } pos = 0; if (rt_file_read(pfile, filebuf, file_length, &pos) != file_length) { rt_file_close(pfile, 0); rt_free(filebuf); return -4; } pstr = filestr; strlenth = 0; // 纠错处理 // 找到\r\n位置,得到一行长度 tUtf8.num = 0; for (i = 0; i < file_length; i++) { *pstr++ = filebuf[i]; strlenth++; if (filebuf[i] == 0x0a || strlenth >= 64) { pstr -= 2; // 去掉回车换行 *pstr = '\0'; iec_getfixsetinf(pfixedset, filestr); pstr = filestr; strlenth = 0; } } rt_file_close(pfile, 0); // 关闭文件 rt_free(filebuf); // 释放内存 return 0; } void iec_init_fixedset(void *pt, RMT_FIXED_TABLE *pfixedset, bool b104) { int i; WORD num, no; u8 str_temp[32]; char ca_buf[16]; num = 0; for (i = 0; i < FIXEDSET_TABLE_NUMBER; i++) { pfixedset->set[num].type = tfixedsettable[i].index; pfixedset->set[num].len = 0; pfixedset->set[num].str[0] = 0; #if !defined CPU_FUXI switch (tfixedsettable[i].index) { case FIXED_SET_CRC: pfixedset->set[num].str[0] = (BYTE)(m_CodeCrc); pfixedset->set[num].str[1] = (BYTE)(m_CodeCrc >> 8); pfixedset->set[num].len = 2; break; case FIXED_SET_MAC1: case FIXED_SET_MAC2: no = tfixedsettable[i].index - FIXED_SET_MAC1; rt_if_mac_get(no, pfixedset->set[num].str); pfixedset->set[num].len = 6; break; case FIXED_SET_SVR: // 软件版本 sprintf(pfixedset->set[num].str, "SV%02d.%03d", VER_NUM / 1000, VER_NUM % 1000); pfixedset->set[num].len = strlen(pfixedset->set[num].str); break; case FIXED_SET_ID: if (env_get_info(ENV_PID)) { strcpy(pfixedset->set[num].str, env_get_info(ENV_PID)); } else { strcpy(pfixedset->set[num].str, ""); } pfixedset->set[num].len = strlen(pfixedset->set[num].str); break; case FIXED_SET_COM: if (b104) { strcpy(pfixedset->set[num].str, "2016版扩展104"); } else { IEC101_DEF *pt101 = (IEC101_DEF *)pt; if (tRunPara.tUartPara[pt101->chnl].wProtocol == PROTOCOL_101_PH) { strcpy(pfixedset->set[num].str, "2016版扩展平衡式101"); } else { strcpy(pfixedset->set[num].str, "2016版扩展非平衡式101"); } } pfixedset->set[num].len = strlen(pfixedset->set[num].str); break; case FIXED_SET_CPT: strcpy(pfixedset->set[num].str, VER_TIME); pfixedset->set[num].len = strlen(pfixedset->set[num].str); break; default: strcpy(pfixedset->set[num].str, tfixedsettable[i].vstr); pfixedset->set[num].len = strlen(tfixedsettable[i].vstr); } #else switch (tfixedsettable[i].index) { case FIXED_SET_SVR: // 软件版本 sprintf(pfixedset->set[num].str, "SV%02d.%03d", (VER_NUM >> 16) & 0XFF, VER_NUM & 0XFFF); pfixedset->set[num].len = strlen(pfixedset->set[num].str); break; 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_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); } #endif pfixedset->set[num].di = tfixedsettable[i].di; pfixedset->set[num].unit = tfixedsettable[i].unit; num++; } pfixedset->num = num; iec_get_fixedset_csv(pfixedset); // 从csv文件中更新相关固定参数信息 } int enc_unicode_to_utf8_one(unsigned short unic, unsigned char *pOutput) { if (unic <= 0x007F) { // * U-00000000 - U-0000007F: 0xxxxxxx *pOutput = (unic & 0x7F); return 1; } else if (unic >= 0x0080 && unic <= 0x07FF) { // * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx *(pOutput + 1) = (unic & 0x3F) | 0x80; *pOutput = ((unic >> 6) & 0x1F) | 0xC0; return 2; } else if (unic >= 0x0800 && unic <= 0xFFFF) { // * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx *(pOutput + 2) = (unic & 0x3F) | 0x80; *(pOutput + 1) = ((unic >> 6) & 0x3F) | 0x80; *pOutput = ((unic >> 12) & 0x0F) | 0xE0; return 3; } return 0; } BYTE iec_GBK2Utf8(BYTE *dst, BYTE *src, BYTE srclen) { int i; int len = 0; for (i = 0; i < srclen;) { if (src[i] > 0x80) // 是汉字 { u16 intcode, unicode; int ulflen; int j; intcode = src[i + 1] | (src[i] << 8); unicode = 0; for (j = 0; j < tUtf8.num; j++) { if (tUtf8.intcode[j] == intcode) // 内码相同,取内码对应的unicode { unicode = tUtf8.unicode[j]; break; } } if (unicode > 0) { ulflen = enc_unicode_to_utf8_one(unicode, &dst[len]); len += ulflen; } i += 2; } else { dst[len] = src[i]; len++; i++; } } return len; } BYTE iec_GBK2Unicode(BYTE *dst, BYTE *src, BYTE srclen) { int i; int len = 0; for (i = 0; i < srclen;) { if (src[i] > 0x80) // 是汉字 { u16 intcode, unicode; int j; intcode = src[i + 1] | (src[i] << 8); unicode = 0; for (j = 0; j < tUtf8.num; j++) { if (tUtf8.intcode[j] == intcode) // 内码相同,取内码对应的unicode { unicode = tUtf8.unicode[j]; break; } } if (unicode > 0) { dst[len] = (u8)unicode; dst[len + 1] = (u8)(unicode >> 8); len += 2; } i += 2; } else { dst[len] = src[i]; len++; i++; } } return len; } int iec_add2frame(BYTE *pbuf, RMT_SET_VAL *pset, bool b104) { int onebyte = 0; #ifdef FIX_PARAM_FORMAT bool bfixset = false; #endif *pbuf++ = (BYTE)pset->di; *pbuf++ = (BYTE)(pset->di >> 8); if (b104) { *pbuf++ = 0; // 104规约信息体地址为三个字节 onebyte = 1; } #ifdef FIX_PARAM_FORMAT if ((pset->di > 0x8000) && (pset->di < 0x8020) && (pset->unit == STR_R)) { bfixset = true; } if (pRunSet->bTT_Utf8 && bfixset) { BYTE len; BYTE tmpbuf[128]; len = iec_GBK2Utf8(tmpbuf, pset->str, pset->len); *pbuf++ = pset->unit; *pbuf++ = len; memcpy(pbuf, tmpbuf, len); return (len + onebyte + 4); } else if (pRunSet->bTT_Unicode && bfixset) { BYTE len; BYTE tmpbuf[128]; len = iec_GBK2Unicode(tmpbuf, pset->str, pset->len); *pbuf++ = pset->unit; *pbuf++ = len; memcpy(pbuf, tmpbuf, len); return (len + onebyte + 4); } else #endif { *pbuf++ = pset->unit; *pbuf++ = pset->len; memcpy(pbuf, pset->str, pset->len); return (pset->len + onebyte + 4); } return 0; } int iec_add2frame_dz(BYTE *pbuf, RMT_SET_VAL *pset, bool b104) { int onebyte = 0; *pbuf++ = (BYTE)pset->di; *pbuf++ = (BYTE)(pset->di >> 8); if (b104) { *pbuf++ = 0; // 104规约信息体地址为三个字节 onebyte = 1; } memcpy(pbuf, pset->str, pset->len); return (pset->len + onebyte + 2); } void iec_set2rmtset(RMT_SET_VAL *rmtset, WORD Tag, WORD group, WORD setno, float fv) { u32 ll; switch (Tag) { case BOOL_R: case TINY_R: case UTINY_R: rmtset->len = 1; rmtset->str[0] = (BYTE)fv; break; case UINT_R: case INT_R: case LONG_R: case ULONG_R: rmtset->len = 4; ll = (u32)fv; rmtset->str[0] = (BYTE)(ll >> 0); rmtset->str[1] = (BYTE)(ll >> 8); rmtset->str[2] = (BYTE)(ll >> 16); rmtset->str[3] = (BYTE)(ll >> 24); break; case SHORT_R: case USHORT_R: rmtset->len = 2; ll = (u32)fv; rmtset->str[0] = (BYTE)(ll >> 0); rmtset->str[1] = (BYTE)(ll >> 8); break; case FLOAT_R: { union { float ff; u8 tt[4]; } ff; rmtset->len = 4; ff.ff = fv; CopySwap(rmtset->str, ff.tt, sizeof(ff.tt), true); } break; case STR_R: { union { float ff; u8 tt[4]; } ff; WORD wType = 0; ff.ff = fv; if (group == SETGROUP_TYPE_PUB) { wType = tPubSetTable[setno].wType; } else if (group == SETGROUP_TYPE_BH) { wType = tSwSetTable[setno].wType; } else if (group == SETGROUP_TYPE_PARA) { wType = tEquipParaTable[setno].wType; } else if (group == SETGROUP_TYPE_CSTSET) { wType = tCstSetTable[setno].wType; } else { rmtset->len = 0; break; } if (wType == SETTYPE_IP) { sprintf(rmtset->str, "%d.%d.%d.%d", ff.tt[3], ff.tt[2], ff.tt[1], ff.tt[0]); rmtset->len = strlen(rmtset->str); } else { rmtset->len = 0; break; } } break; default: rmtset->len = 0; break; } rmtset->unit = Tag; } // 佛山局参数低位在前,高位在后 // 浮点->缓冲区 static void float2IECbuf(BYTE *buf, float f) { union { float ff; u8 tt[4]; } ff; ff.ff = f; CopySwap(buf, ff.tt, sizeof(ff.tt), true); } // 缓冲区->浮点数 static float IECbuf2Foat(BYTE *buf) { union { float ff; u8 tt[4]; } ff; CopySwap(ff.tt, buf, 4, false); return ff.ff; } // 获取参数信息定义的偏移量 static int getSetTableOffset(const TSETTABLE *pTable, WORD maxTable, WORD parId, WORD set_group, bool b_write) { int i; #if 0 for(i=0;i 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_ZHONGSHAN_2020 || 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 if (parId == 0x5005) #endif return false; #elif 0 if (parId == 0x5001) // 云浮郁南要求5001:定值区号 只读,不可更改 { return false; } #endif value = IECbuf2Foat(pbuf); rt_printf("预置参数 parId %02x=%f \r\n", parId, value); parTable = getSetTableOffset(&tPubSetTable[0], PUB_SET_NUMBER, parId, SETGROUP_TYPE_PUB, true); if (parTable != -1) { rt_printf("%s PubType=%d %d i=%d\r\n", tPubSetTable[parTable].szName, parId, SETGROUP_TYPE_PUB, parTable); if (value <= tPubSetTable[parTable].fMax && value >= tPubSetTable[parTable].fMin) return true; else { rt_printf("预置参数超范围,失败 par=%f parTable=%d max=%f min%f\r\n", value, parTable, tPubSetTable[parTable].fMax, tPubSetTable[parTable].fMin); return false; } } parTable = getSetTableOffset(&tSwSetTable[0], SW_SET_NUMBER, parId, SETGROUP_TYPE_BH, true); if (parTable != -1) { // parTable -= PUB_SET_NUMBER; // if(parTable > 0 && parTable < SW_SET_NUMBER) { rt_printf("%s BhType=%d %d i=%d\r\n", tSwSetTable[parTable].szName, parId, SETGROUP_TYPE_BH, parTable); { if (value <= tSwSetTable[parTable].fMax && value >= tSwSetTable[parTable].fMin) return true; else { rt_printf("预置参数超范围,失败 par=%f parTable=%d max=%f min%f\r\n", value, parTable, tSwSetTable[parTable].fMax, tSwSetTable[parTable].fMin); return false; } } } } if (parTable == -1) rt_printf("预置参数地址不存在parID=%x\r\n", parId); else rt_printf("预置参数非法par=%f\r\n", value); return false; } // 写读取,生效 bool wirteRunParId(WORD sw, WORD parId, BYTE *pbuf, u8 ti) { int parTable = 0, j = 0; #ifndef FUNC_MORE_PRESET BYTE buf[6]; int i = 0; #endif SET_VALUE *parBuf; rt_printf("写参数 %02x=%f \r\n", parId, IECbuf2Foat(pbuf)); if (sw > SWITCH_NUM_MAX) return false; #ifdef FUNC_MORE_PRESET if (gb_101_yt) { for (j = 0; j < sizeof(PresetData101[g_CountSet101 - 1]); j++) { if (0 == (j + 1) % 7) { // 跳过设定命令限定词qos(每7位最后一位) continue; } if (SetData101[g_CountSet101 - 1].yc_data[j] != PresetData101[g_CountSet101 - 1].yc_data[j]) { rt_printf("固化定值与预置定值不一样,请检查第%d帧执行报文,parId=%x\r\n", g_CountSet101, parId); return false; } } } else { for (j = 0; j < sizeof(PresetData104[g_CountSet104 - 1]); j++) { if (ti == FOS_PAR_SET_ONE || ti == FOS_PAR_SET_MUL) { if (0 == (j + 1) % 8) continue; } else { if (0 == (j + 1) % 7) continue; } if (SetData104[g_CountSet104 - 1].yc_data[j] != PresetData104[g_CountSet104 - 1].yc_data[j]) { rt_printf("固化定值与预置定值不一样,请检查第%d帧执行报文,parId=%x\r\n", g_CountSet104, parId); return false; } } } #else // 放在所有参数处理的前面,包括只读定值在内的都需进行比较和统计 buf[i++] = (BYTE)(parId >> 8); buf[i++] = (BYTE)parId; memcpy(&buf[i], pbuf, 4); for (j = 0; j < 6; j++) { if (buf[j] == buf_forCompare[j + j_forCompare]) continue; else { rt_printf("固化定值与预置定值不一样,请检查parId=%x\r\n", parId); j_forCompare += 6; return false; } } j_forCompare += 6; #endif #if defined GD_AREA_ZHONGSHAN_2020 || 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 if (parId == 0x5005) #endif 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) { { // 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); { 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_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 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_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 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_ZHONGSHAN_2020 if (parId == 0x5001) { int i; for (i = 0; i < g_sw_num; i++) { if (((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) && (g_tRelay[i].run_stu.bh_yx == 1)) { rt_printf("SW==%d,常规保护压板合\r\n", i); float2IECbuf(pbuf, (float)1); rt_free(parBuf); return true; } else if (((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID) && (g_tRelay[i].run_stu.fa_yx) == 1) { rt_printf("SW==%d,常规FA压板合\r\n", i); float2IECbuf(pbuf, (float)2); rt_free(parBuf); return true; } else if (((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID) && (g_tRelay[i].run_stu.fa_g_yx) == 1) { rt_printf("SW==%d,智能FA压板合\r\n", i); float2IECbuf(pbuf, (float)3); rt_free(parBuf); return true; } // 为调试、测试便于查找问题,预留打印信息 else if (((short)g_sw[i].di_cfg_index[SW_DI_BHTT] == INDEX_INVALLID) || ((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] == INDEX_INVALLID) || ((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] == INDEX_INVALLID)) { rt_printf("常规保护压板/常规FA压板/智能FA压板DI通道未配置!!!\r\n"); } } } else if (parId == 0x5004) { int i; for (i = 0; i < g_sw_num; i++) { if ((short)g_sw[i].di_cfg_index[SW_DI_BHZTT] != INDEX_INVALLID) { float2IECbuf(pbuf, (float)!g_tRelay[i].run_stu.bhztt); rt_free(parBuf); return true; } // 为调试、测试便于查找问题,预留打印信息 else { rt_printf("停用FA及保护DI通道未配置!!!\r\n"); } } } #elif defined GD_AREA_ZHONGSHAN if (parId == 0x5001) { float2IECbuf(pbuf, (float)FUN_ALL_EN(0)); rt_free(parBuf); return true; } else if (parId == 0x5002) { int i; for (i = 0; i < g_sw_num; i++) { if ((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) { float2IECbuf(pbuf, (float)g_tRelay[i].run_stu.bh_yx); rt_free(parBuf); return true; } } } else if (parId == 0x5003) { int i; for (i = 0; i < g_sw_num; i++) { if ((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID) { float2IECbuf(pbuf, (float)g_tRelay[i].run_stu.fa_yx); rt_free(parBuf); return true; } } } else if (parId == 0x5004) { int i; for (i = 0; i < g_sw_num; i++) { if ((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID) { float2IECbuf(pbuf, (float)g_tRelay[i].run_stu.fa_g_yx); rt_free(parBuf); return true; } } } #endif #ifdef FUNC_YT_HARD_YB parTable = getSetTableOffset(0, 0, parId, SETGROUP_TYPE_BY, false); if (parTable != -1) { int i; for (i = 0; i < g_sw_num; i++) { if ((parTable >= 0) && (parTable < YT_SW_HARD_YB_NUM)) { if ((short)g_sw[i].di_cfg_index[sw_yt_hard_yb_index[parTable]] != INDEX_INVALLID) { ecd = &g_equ_config_di[g_sw[i].di_cfg_index[sw_yt_hard_yb_index[parTable]]]; temp_yx = dido_di_is_on(ecd->slot, ecd->index); rt_printf("读硬压板:%s=%d\r\n", g_sw_di_name[sw_yt_hard_yb_index[parTable]], temp_yx); float2IECbuf(pbuf, (float)temp_yx); rt_free(parBuf); return true; } else { rt_free(parBuf); rt_printf("硬压板[%s]未配置,读取失败\r\n", g_sw_di_name[sw_yt_hard_yb_index[parTable]]); return false; } } } if ((parTable >= YT_SW_HARD_YB_NUM) && (parTable < (YT_SW_HARD_YB_NUM + YT_PUB_HARD_YB_NUM))) { if ((short)g_sw_pub.di_cfg_index[pub_yt_hard_yb_index[parTable - YT_SW_HARD_YB_NUM]] != INDEX_INVALLID) { ecd = &g_equ_config_di[g_sw_pub.di_cfg_index[pub_yt_hard_yb_index[parTable - YT_SW_HARD_YB_NUM]]]; temp_yx = dido_di_is_on(ecd->slot, ecd->index); rt_printf("读硬压板:%s=%d\r\n", g_pub_di_name[pub_yt_hard_yb_index[parTable - YT_SW_HARD_YB_NUM]], temp_yx); float2IECbuf(pbuf, (float)temp_yx); rt_free(parBuf); return true; } else { rt_free(parBuf); rt_printf("硬压板[%s]未配置,读取失败\r\n", g_pub_di_name[pub_yt_hard_yb_index[parTable - YT_SW_HARD_YB_NUM]]); return false; } } #ifdef FUNC_YT_MIX else if (parTable >= YT_SW_HARD_YB_NUM + YT_PUB_HARD_YB_NUM) { int i = 0; // 模式硬遥信上送:1:常规保护;2:常规FA;3:智能FA if (MIX_MODE_SEL == (parTable - YT_SW_HARD_YB_NUM - YT_PUB_HARD_YB_NUM)) { int ecd_yx_bh = 0, ecd_yx_fa = 0, ecd_yx_goose = 0; for (i = 0; i < g_sw_num; i++) { if (((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) || ((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID) || ((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID)) { // 三大模式压板有配置 if ((short)g_sw[i].di_cfg_index[SW_DI_BHTT] != INDEX_INVALLID) { ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_BHTT]]; ecd_yx_bh = dido_di_is_on(ecd->slot, ecd->index); } if ((short)g_sw[i].di_cfg_index[SW_DI_FA_TT] != INDEX_INVALLID) { ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_FA_TT]]; ecd_yx_fa = dido_di_is_on(ecd->slot, ecd->index); } if ((short)g_sw[i].di_cfg_index[SW_DI_FA_GOOSE] != INDEX_INVALLID) { ecd = &g_equ_config_di[g_sw[i].di_cfg_index[SW_DI_FA_GOOSE]]; ecd_yx_goose = dido_di_is_on(ecd->slot, ecd->index); } if (ecd_yx_bh) temp_yx = 1; // 常规保护压板上送1 else if (ecd_yx_fa) temp_yx = 2; // 常规FA压板上送2 else if (ecd_yx_goose) temp_yx = 3; // 智能FA压板上送3 else temp_yx = 0; // 三大模式压板遥信点都为0时上送0 rt_printf("读硬压板:%s=%d\r\n", mix_yt_index[MIX_MODE_SEL], temp_yx); float2IECbuf(pbuf, (float)temp_yx); rt_free(parBuf); return true; } else { // 三大模式压板未配置,上送4 float2IECbuf(pbuf, (float)4); rt_free(parBuf); rt_printf("三大模式压板未配置,读取失败\r\n"); return false; } } } } #endif } #endif if (!ReadSet(m_runsection, (void *)parBuf)) // 读定值 { GetDefSet((float *)parBuf); } #if defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 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); { float2IECbuf(pbuf, parBuf[sw * parTable + PUB_SET_NUMBER].ff); } } rt_free(parBuf); return true; } #if defined GD_AREA_ZHONGSHAN || defined GD_AREA_ZHONGSHAN_2020 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 (0) if (vsq == 0) // 读全部定值 { for (i = 0; i < tfixedset.num; i++) // 固定定值 { tmp_cst_val = tfixedset.set[i]; len = iec_add2frame(datbuf + framelen, &tmp_cst_val, b104); framelen += len; setnum++; if (framelen > 200) { if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202, FRAME_I); // } framelen = 3; setnum = 0; } } for (i = 0; i < ParaIDNum; i++) { if (!tParaID[i].parId) continue; tmp_param = &tParaID[i]; switch (tmp_param->group_type) { case SETGROUP_TYPE_PARA: // rt_printf("description:%s addr:%x value:%f\r\n",tEquipParaTable[tmp_param->setno].szName,tmp_param->parId,pparabuf[tmp_param->setno].ff); iec_set2rmtset(&tmp_cst_val, tEquipParaTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pparabuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_PUB: // rt_printf("description:%s addr:%x value:%f\r\n",tPubSetTable[tmp_param->setno].szName,tmp_param->parId,ppubbuf[tmp_param->setno].ff); iec_set2rmtset(&tmp_cst_val, tPubSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, ppubbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_CSTSET: // rt_printf("description:%s addr:%x value:%f\r\n",tCstSetTable[tmp_param->setno].szName,tmp_param->parId,pcstbuf[tmp_param->setno].ff); iec_set2rmtset(&tmp_cst_val, tCstSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pcstbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_BH: // rt_printf("description:%s addr:%x value:%f\r\n",tSwSetTable[tmp_param->setno].szName,tmp_param->parId,psetbuf[tmp_param->setno].ff); iec_set2rmtset(&tmp_cst_val, tSwSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, psetbuf[tmp_param->setno].ff); break; default: continue; } tmp_cst_val.di = tmp_param->parId; len = iec_add2frame(datbuf + framelen, &tmp_cst_val, b104); framelen += len; setnum++; if (i == ParaIDNum - 1) { over = 1; } if ((framelen > 200) || over) { if (over) // 最后的一帧,tag清零 { datbuf[2] = 0; } if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202, FRAME_I); // } framelen = 3; setnum = 0; } } } else // 读定义点号的定值 { BYTE *ps = &pdat[2]; // 从点号开始 for (i = 0; i < vsq; i++) { int j; u16 di; bool bfind = false; if (tfixedset.set[i].di == 0) continue; di = ps[0] + (ps[1] << 8); for (j = 0; j < tfixedset.num; j++) // 固定定值 { if (tfixedset.set[j].di == di) // 点号对应 { tmp_cst_val = tfixedset.set[j]; bfind = true; break; } } if (!bfind) { for (j = 0; j < ParaIDNum; j++) // 修改定值 { if (di != tParaID[j].parId) continue; tmp_param = &tParaID[j]; switch (tmp_param->group_type) { case SETGROUP_TYPE_PARA: iec_set2rmtset(&tmp_cst_val, tEquipParaTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pparabuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_PUB: iec_set2rmtset(&tmp_cst_val, tPubSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, ppubbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_CSTSET: iec_set2rmtset(&tmp_cst_val, tCstSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pcstbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_BH: iec_set2rmtset(&tmp_cst_val, tSwSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, psetbuf[tmp_param->setno].ff); break; default: continue; } bfind = true; break; } } ps += 2; if (b104) ps++; // 组报文 if (bfind) { tmp_cst_val.di = di; len = iec_add2frame(datbuf + framelen, &tmp_cst_val, b104); framelen += len; setnum++; } if (framelen > 200 || i == vsq - 1) { if (i == vsq - 1) // 最后的一帧,tag清零 { datbuf[2] = 0; } if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202, FRAME_I); // } framelen = 3; setnum = 0; } } } #endif rt_free(psetbuf); rt_free(pparabuf); rt_free(pcstbuf); rt_free(ppubbuf); return 0; } int iec_get_equi_ip(char *ip, BYTE *p_out) { int i, j = 0, k = 0; char str_ip[4] = {'\0'}; for (i = 0; i <= strlen(ip); i++) { if (ip[i] == '\0' || ip[i] == '.') { p_out[k] = atoi(str_ip); if (p_out[k] < 0 || p_out[k] > 255) { return -1; } k++; j = 0; memset(str_ip, 0, sizeof(str_ip)); continue; } str_ip[j] = ip[i]; j++; } return 0; } #ifdef YPARA_LINK /*0不级联,返回级联号*/ int get_ypara_linkch_write(void *pt, BYTE *pdat, BYTE vsq, bool b104) { BYTE *ps; // 从点号开始 u16 di = 0; int index = 0; BYTE pdi; // 参数特征标识符 u8 cmd = 0, dport = 0; if (b104) { IEC104_DEF *pt104 = pt; cmd = pt104->msg_ypara_send.ypara_msg.cmd; dport = pt104->msg_ypara_send.dport; } else { IEC101_DEF *pt101 = pt; cmd = pt101->msg_ypara_send.ypara_msg.cmd; dport = pt101->msg_ypara_send.dport; } pdi = pdat[2]; ps = &pdat[3]; if ((pdi & 0xc0) == 0) // 定值固化 { if (cmd == YP_SEL) /*有下发级联预置*/ { return dport; } else { return 0; } } else if ((pdi & 0xc0) == 0x40) /*撤销*/ { if (cmd == YP_SEL) /*有下发级联预置*/ { return dport; } else { return 0; } } else // 参数预置 { di = ps[0] + (ps[1] << 8); index = get_stbl_index_s(di); if (index < 0) return 0; /*点号不对*/ return tParaID[index].link_ch; /*级联号*/ } } int iec_setread_mananger(void *pt, BYTE *pdat, BYTE vsq, bool b104) // dat从定值区号开始 { int len, i; u16 section; // 定值区号 BYTE setnum = 0; BYTE framelen = 0; BYTE datbuf[256] = {0}; BYTE over = 0; RMT_FIXED_TABLE tfixedset; SET_PARAID *tmp_param; SET_PARA_VAL *tmp_pval; RMT_SET_VAL tmp_cst_val; SET_VALUE *psetbuf, *pparabuf, *pcstbuf, *ppubbuf; section = pdat[0] + (pdat[1] << 8); // 定值区号 if (section >= SEC_NUMBER) // 定值区不为零,否定应答返回 { rt_printf("\r\n远方读定值,定值区超出范围,否定应答\r\n"); return -1; } ppubbuf = rt_malloc(PUB_SET_NUMBER * 4); if (!ppubbuf) { rt_printf("\r\n远方读定值,分配公共定值缓冲区错误!\r\n"); return -1; } psetbuf = rt_malloc(SW_SET_NUMBER * 4); if (!psetbuf) { rt_free(ppubbuf); rt_printf("\r\n远方读定值,分配开关定值缓冲区错误!\r\n"); return -2; } pparabuf = rt_malloc(EQUIP_PARA_NUMBER * 4); if (!pparabuf) { rt_free(ppubbuf); rt_free(psetbuf); rt_printf("\r\n远方读定值,分配参数缓冲区错误!\r\n"); return -3; } pcstbuf = rt_malloc(CSTSET_NUMBER * 4); if (!pcstbuf) { rt_free(ppubbuf); rt_free(psetbuf); rt_free(pparabuf); rt_printf("\r\n远方读定值,分配内部定值缓冲区错误!\r\n"); return -2; } if (!ReadPara((void *)ppubbuf, EEP_PUB_ADDR, PUB_SET_NUMBER, &tPubSetTable[0])) { GetDefPara((void *)ppubbuf, PUB_SET_NUMBER, &tPubSetTable[0]); } if (!ReadPara((void *)psetbuf, EEP_SET_ADDR + m_runsection * SETSIZE, SW_SET_NUMBER, &tSwSetTable[0])) { GetDefPara((void *)psetbuf, SW_SET_NUMBER, &tSwSetTable[0]); } if (!ReadPara((void *)pparabuf, EEP_EQUIP_PARA_ADDR, EQUIP_PARA_NUMBER, &tEquipParaTable[0])) { GetDefPara((void *)pparabuf, EQUIP_PARA_NUMBER, &tEquipParaTable[0]); } if (!ReadPara((void *)pcstbuf, EEP_CSTSET_ADDR, CSTSET_NUMBER, &tCstSetTable[0])) { GetDefPara((void *)pcstbuf, CSTSET_NUMBER, &tCstSetTable[0]); } iec_init_fixedset(pt, &tfixedset, b104); // 获取固定定值 datbuf[0] = (BYTE)section; // 区号 datbuf[1] = (BYTE)(section >> 8); datbuf[2] = 0x01; // 参数特征标识,有后续 framelen = 3; setnum = 0; if (vsq == 0) // 读全部定值 { for (i = 0; i < tfixedset.num; i++) // 固定定值 { if (tfixedset.set[i].di == 0) continue; tmp_cst_val = tfixedset.set[i]; len = iec_add2frame(datbuf + framelen, &tmp_cst_val, b104); framelen += len; setnum++; if (framelen > 200) { if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202, FRAME_I); // } framelen = 3; setnum = 0; } } for (i = 0; i < ParaIDNum; i++) { if (!tParaID[i].parId) continue; if (tParaID[i].link_ch == 0) /*本地定值*/ { tmp_param = &tParaID[i]; switch (tmp_param->group_type) { case SETGROUP_TYPE_PARA: iec_set2rmtset(&tmp_cst_val, tEquipParaTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pparabuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_PUB: iec_set2rmtset(&tmp_cst_val, tPubSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, ppubbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_CSTSET: iec_set2rmtset(&tmp_cst_val, tCstSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pcstbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_BH: iec_set2rmtset(&tmp_cst_val, tSwSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, psetbuf[tmp_param->setno].ff); break; default: continue; } } else { /*级联定值的值*/ tmp_param = &tParaID[i]; tmp_pval = &tPara_val[i]; tmp_cst_val.unit = tmp_pval->datatype; tmp_cst_val.len = tmp_pval->len; memcpy(tmp_cst_val.str, tmp_pval->str, tmp_pval->len); } /*组包*/ tmp_cst_val.di = tmp_param->parId; len = iec_add2frame(datbuf + framelen, &tmp_cst_val, b104); framelen += len; setnum++; if (i == ParaIDNum - 1) { over = 1; } if ((framelen > 200) || over) { if (over) // 最后的一帧,tag清零 { datbuf[2] = 0; } if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202, FRAME_I); // } framelen = 3; setnum = 0; } } } else // 读定义点号的定值 { BYTE *ps = &pdat[2]; // 从点号开始 for (i = 0; i < vsq; i++) { int j; u16 di; bool bfind = false; di = ps[0] + (ps[1] << 8); for (j = 0; j < tfixedset.num; j++) // 固定定值 { if (tfixedset.set[j].di == di) // 点号对应 { tmp_cst_val = tfixedset.set[j]; bfind = true; break; } } if (!bfind) { for (j = 0; j < ParaIDNum; j++) // 修改定值 { if (di != tParaID[j].parId) continue; if (tParaID[j].link_ch == 0) /*本地定值*/ { tmp_param = &tParaID[j]; switch (tmp_param->group_type) { case SETGROUP_TYPE_PARA: iec_set2rmtset(&tmp_cst_val, tEquipParaTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pparabuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_PUB: iec_set2rmtset(&tmp_cst_val, tPubSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, ppubbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_CSTSET: iec_set2rmtset(&tmp_cst_val, tCstSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, pcstbuf[tmp_param->setno].ff); break; case SETGROUP_TYPE_BH: iec_set2rmtset(&tmp_cst_val, tSwSetTable[tmp_param->setno].data_type, tmp_param->group_type, tmp_param->setno, psetbuf[tmp_param->setno].ff); break; default: continue; } } else { /*级联定值的值*/ tmp_param = &tParaID[j]; tmp_pval = &tPara_val[j]; tmp_cst_val.unit = tmp_pval->datatype; tmp_cst_val.len = tmp_pval->len; memcpy(tmp_cst_val.str, tmp_pval->str, tmp_pval->len); } bfind = true; break; } } ps += 2; if (b104) ps++; // 组报文 if (bfind) { tmp_cst_val.di = di; len = iec_add2frame(datbuf + framelen, &tmp_cst_val, b104); framelen += len; setnum++; } if (framelen > 200 || i == vsq - 1) { if (i == vsq - 1) // 最后的一帧,tag清零 { datbuf[2] = 0; } if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, setnum, IEC_COT_ACTCON, 202, FRAME_I); // } framelen = 3; setnum = 0; } } } rt_free(psetbuf); rt_free(pparabuf); rt_free(pcstbuf); rt_free(ppubbuf); return 0; } #endif #ifdef YPARA_LINK_S void set_para_flag(void) { int net; IEC104_DEF *pt; for (net = 0; net < CFG_ETH_MAX_LOGIC; net++) { pt = &g_t104[net]; pt->para_updata_flag = 1; } } #endif int iec_rmtset2set(RMT_SET_DATA *rsd, BYTE *pdat, bool b104) { int i, len, index; BYTE Tag, addoff = 0; WORD di; bool bover = false; di = pdat[0] + (pdat[1] << 8); index = 0; for (i = 0; i < RMT_SET_NUMBER; i++) { if (rsd->di[i] == di) // 预置数据中有对应的点号的定值,覆盖 { index = i; bover = true; break; } } if (!bover) { for (i = 0; i < RMT_SET_NUMBER; i++) { if (rsd->di[i] == 0) // 结构中有点号为0的,可以使用 { index = i; break; } } } if (b104) addoff = 1; Tag = pdat[2 + addoff]; len = pdat[3 + addoff]; pdat += (4 + addoff); rsd->di[index] = di; switch (Tag) { case BOOL_R: case TINY_R: case UTINY_R: rsd->val[index] = pdat[0]; break; case UINT_R: case INT_R: case LONG_R: case ULONG_R: rsd->val[index] = (pdat[0] + (pdat[1] << 8) + (pdat[2] << 16) + (pdat[3] << 24)); break; case SHORT_R: case USHORT_R: rsd->val[index] = (pdat[0] + (pdat[1] << 8)); break; case FLOAT_R: { union { float ff; u8 tt[4]; } ff; CopySwap(ff.tt, pdat, 4, false); rsd->val[index] = ff.ff; break; } case STR_R: { memset(rsd->t_str[rmt_str_cnt].str, 0, sizeof(rsd->t_str[rmt_str_cnt].str)); memcpy(rsd->t_str[rmt_str_cnt].str, pdat, len); rsd->t_str[rmt_str_cnt].di = rsd->di[index]; rt_printf("%s:di=%04x,str=%s\r\n", __func__, rsd->t_str[rmt_str_cnt].di, rsd->t_str[rmt_str_cnt].str); rmt_str_cnt++; } break; default: rsd->val[index] = 0; break; } return len; } int iec_set_section = 0; int iec_saveset(RMT_SET_DATA *rsd) { SET_VALUE *psetbuf, *pparabuf, *pcstbuf; int i; bool bset = false, bpara = false, bcst = false; int ret = -1; SET_PARAID *tmp_param; if (!pRunSet->bTT_EDIT_YB) // 远方修改未投入 { for (i = 0; i < RMT_SET_NUMBER; i++) { rsd->di[i] = 0; } rsd->bpreset = false; rt_printf("\r\n远方修改定值未投入!\r\n"); return -1; } psetbuf = rt_malloc(SET_NUMBER * 4); if (!psetbuf) { rt_printf("\r\n远方固化定值,分配定值缓冲区错误!\r\n"); return -2; } pparabuf = rt_malloc(EQUIP_PARA_NUMBER * 4); if (!pparabuf) { rt_free(psetbuf); rt_printf("\r\n远方固化定值,分配参数缓冲区错误!\r\n"); return -3; } pcstbuf = rt_malloc(CSTSET_NUMBER * 4); if (!pcstbuf) { // rt_free(pcstbuf); rt_free(psetbuf); rt_free(pparabuf); rt_printf("\r\n远方固化定值,分配内部定值缓冲区错误!\r\n"); return -4; } if (!ReadSet(iec_set_section, (void *)psetbuf)) // 读定值 { GetDefSet((float *)psetbuf); } if (!ReadPara((void *)pparabuf, EEP_EQUIP_PARA_ADDR, EQUIP_PARA_NUMBER, &tEquipParaTable[0])) // 读参数 { GetDefPara((void *)pparabuf, EQUIP_PARA_NUMBER, &tEquipParaTable[0]); } /*读取内部定值*/ if (!ReadPara((void *)pcstbuf, EEP_CSTSET_ADDR, CSTSET_NUMBER, &tCstSetTable[0])) { GetDefPara((void *)pcstbuf, CSTSET_NUMBER, &tCstSetTable[0]); } for (i = 0; i < RMT_SET_NUMBER; i++) { int j; WORD di; bool bfind = false; di = rsd->di[i]; if (di == 0) continue; for (j = 0; j < ParaIDNum; j++) { int k; if (di != tParaID[j].parId) continue; tmp_param = &tParaID[j]; switch (tmp_param->group_type) { case SETGROUP_TYPE_PARA: if (tEquipParaTable[tmp_param->setno].wType == SETTYPE_IP) { union { float ff; u8 tt[4]; } ff; for (k = 0; k < rmt_str_cnt; k++) { if (di == rsd->t_str[k].di) { if (iec_get_equi_ip(rsd->t_str[k].str, ff.tt) == 0) { pparabuf[tmp_param->setno].ff = ff.ff; } bpara = true; break; } } } else { pparabuf[tmp_param->setno].ff = rsd->val[i]; } bpara = true; break; case SETGROUP_TYPE_PUB: psetbuf[tmp_param->setno].ff = rsd->val[i]; bset = true; break; case SETGROUP_TYPE_CSTSET: pcstbuf[tmp_param->setno].ff = rsd->val[i]; bcst = true; break; case SETGROUP_TYPE_BH: // 第一个开关的定值 psetbuf[PUB_SET_NUMBER + tmp_param->setno].ff = rsd->val[i]; bset = true; break; default: break; } bfind = true; } rsd->di[i] = 0; rsd->val[i] = 0; } if (bset) { if (SaveSet(iec_set_section, (void *)psetbuf)) { soe_record_opt(EV_SET_OK, 0); if (iec_set_section != m_runsection) rt_printf("----iec_set_section=%d,m_runsection=%d\r\n", iec_set_section, m_runsection); // if(iec_set_section==m_runsection) { MakeRunSet(false); rt_err_clr(ERR_CODE_SET, 0); } } else { soe_record_opt(EV_SET_FAIL, 0); } ret = 0; } if (bpara) { if (SavePara((void *)pparabuf, EEP_EQUIP_PARA_ADDR, EQUIP_PARA_NUMBER, &tEquipParaTable[0])) { soe_record_opt(EV_EQUPARA_OK, 0); MakeRunPara(false, false); rt_err_clr(ERR_CODE_EQU_PARA, 0); } else { soe_record_opt(EV_EQUPARA_FAIL, 0); } ret = 0; } if (bcst) { if (SavePara((void *)pcstbuf, EEP_CSTSET_ADDR, CSTSET_NUMBER, &tCstSetTable[0])) { soe_record_opt(EV_CSTSET_OK, 0); MakeRunSet(false); rt_err_clr(ERR_CODE_SET_IN, 0); } else { soe_record_opt(EV_CSTSET_FAIL, 0); } ret = 0; } #ifdef YPARA_LINK_S set_para_flag(); #endif rt_free(psetbuf); // sunxi 20180719 added rt_free(pparabuf); // sunxi 20180719 added rt_free(pcstbuf); // sunxi 20180719 added return ret; } int iec_setwrite(void *pt, BYTE *pdat, BYTE cot, BYTE vsq, bool b104) // dat从定值区号开始 { WORD section; // 定值区号 BYTE pdi; // 参数特征标识符 int ret = 0; RMT_SET_DATA *rsd; if (b104) { IEC104_DEF *pt104 = (IEC104_DEF *)pt; rsd = &pt104->tr; } else { IEC101_DEF *pt101 = (IEC101_DEF *)pt; rsd = &pt101->tr; } section = pdat[0] + (pdat[1] << 8); // 定值区号 pdi = pdat[2]; if (section >= SEC_NUMBER) { rt_printf("\r\n远方修改定值,定值区越限=%d,否定应答\r\n", section); return -1; } iec_set_section = section; if (((pdi & 0xc0) == 0) && cot == 0x06) // 定值固化 { ret = iec_saveset(rsd); rsd->bpreset = false; } else if (vsq > 0 && ((pdi & 0xc0) == 0x80) && cot == 0x06) // 参数预置 { int i; rmt_str_cnt = 0; pdat += 3; for (i = 0; i < vsq; i++) { int len; len = iec_rmtset2set(rsd, &pdat[0], b104); pdat += (4 + len); if (b104) pdat += 1; } rsd->bpreset = true; rsd->us0_preset = ustimer_get_origin(); } else if (((pdi & 0xc0) == 0x40) && cot == 0x09) // 取消预置 { int i; rmt_str_cnt = 0; for (i = 0; i < RMT_SET_NUMBER; i++) { rsd->di[i] = 0; } rsd->bpreset = false; } else { rt_printf("\r\n远方修改定值否定应答,vsq:%d 传送原因:0x%02x 特征表示符:0x%02x \r\n", vsq, cot, pdi); ret = -2; } return ret; } void iec_printfixedset(void) { int i; WORD index; RMT_FIXED_TABLE tfixedset; iec_init_fixedset(&g_t104[0], &tfixedset, true); // 获取固定定值 rt_printf("\r\n点号 名称 信息"); for (i = 0; i < tfixedset.num; i++) { index = tfixedsettable[i].index; if (index == FIXED_SET_CRC) // 软件版本号 { rt_printf("\r\n%04x %-24s%04x", tfixedsettable[i].di, tfixedsettable[i].name, (tfixedset.set[i].str[0] + (tfixedset.set[i].str[1] << 8))); } #if !defined CPU_FUXI else if (index == FIXED_SET_MAC1 || index == FIXED_SET_MAC2) // 软件版本号 { rt_printf("\r\n%04x %-24s%02x-%02x-%02x-%02x-%02x-%02x", tfixedsettable[i].di, tfixedsettable[i].name, tfixedset.set[i].str[0], tfixedset.set[i].str[1], tfixedset.set[i].str[2], tfixedset.set[i].str[3], tfixedset.set[i].str[4], tfixedset.set[i].str[5]); } else #endif { rt_printf("\r\n%04x %-24s%s", tfixedset.set[i].di, tfixedsettable[i].name, tfixedset.set[i].str); } } } /************************************************************************** 函数名称:iec_Direct_Echo 函数版本:1.00 作者: 创建日期:2007.9.1 函数功能说明:101规约目录响应 输出参数:pt101缓冲区地址,COT 传送原因 返回值: 更新信息: 更新日志1: 日期: 修改者: 修改内容: 修改原因: ***************************************************************************/ void iec_dir_echo(void *pt, char *buf, bool b104) // buf 从 操作标识下一字节开始 { int i; char *pdat; char cf; // 操作及召唤标识 int id; // 目录ID BYTE namelen; char namestr[64]; int filenum; struct dir_file_struct *pdir, *pdirfree; BYTE framelen, filescnt; char datbuf[256]; char *dir; struct rtc_time_t ts, te; T_FILE *ptfile; if (b104) ptfile = &((IEC104_DEF *)pt)->tf; else ptfile = &((IEC101_DEF *)pt)->tf; pdat = buf; id = pdat[0] + (pdat[1] << 8) + (pdat[2] << 16) + (pdat[3] << 24); // 目录ID pdat += 4; namelen = *pdat++; // 目录长度 dir = NULL; strcpy(ptfile->dirpath, ""); if (namelen > 0) { for (i = 0; i < namelen; i++) { namestr[i] = *pdat++; } #ifdef FUN_PATH_TEST if (strstr(namestr, "COMTRADE") != NULL) /*录波文件*/ { strcpy(ptfile->dirpath, HF_WAVE_DIR); } else { sprintf(ptfile->dirpath, "/app/%s/", namestr); } #else sprintf(ptfile->dirpath, "/app/%s/", namestr); #endif namestr[namelen] = '\0'; // 目录名称字符串结束符 dir = namestr; if (namestr[0] == '/') { sprintf(ptfile->dirpath, "/app%s/", namestr); // 去掉'/' } else { sprintf(ptfile->dirpath, "/app/%s/", namestr); } } cf = *pdat++; // 召唤标识 ts.ms = pdat[0] + (pdat[1] << 8); // 查询起始时间 pdat += 2; ts.min = *pdat++; ts.hour = *pdat++; ts.day = *pdat++; ts.month = *pdat++; ts.year = *pdat++; ts.min &= 0x3f; ts.hour &= 0x1f; ts.month &= 0x0f; ts.day &= 0x1f; te.ms = pdat[0] + (pdat[1] << 8); // 查询终止时间 pdat += 2; te.min = *pdat++; te.hour = *pdat++; te.day = *pdat++; te.month = *pdat++; te.year = *pdat++; te.min &= 0x3f; te.hour &= 0x1f; te.month &= 0x0f; te.day &= 0x1f; pdir = hf_get_dir_file_n(id, ptfile->dirpath, cf, &ts, &te, &filenum); // 根据信息体地址,判断读读哪个目录,获取目录信息 if (pdir == NULL) { filenum = 0; } pdirfree = pdir; // 组织报文 filescnt = 0; framelen = 0; pdat = datbuf; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = 2; // 附加数据包类型 pdat[framelen++] = 2; // 读目录 pdat[framelen++] = (filenum > 0) ? 0 : 1; // 结果描述符 :=1 失败 pdat[framelen++] = (BYTE)(id >> 0); // 标识 pdat[framelen++] = (BYTE)(id >> 8); pdat[framelen++] = (BYTE)(id >> 16); pdat[framelen++] = (BYTE)(id >> 24); pdat[framelen++] = 0; // 后续标识 pdat[framelen++] = filescnt; // 文件数量 if (filenum == 0) { if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210, FRAME_I); // } return; } datbuf[9 + b104] = 1; // 后续标识 pdat = &datbuf[framelen]; for (i = 0; i < filenum; i++) { struct rtc_time_t rtc; u8 week; int len; len = strlen(pdir->name); *pdat++ = len; // 文件名长度 memcpy(pdat, pdir->name, len); pdat += len; *pdat++ = 0; // 文件属性 /*文件长度*/ *pdat++ = (BYTE)(pdir->file_size); *pdat++ = (BYTE)(pdir->file_size >> 8); *pdat++ = (BYTE)(pdir->file_size >> 16); *pdat++ = (BYTE)(pdir->file_size >> 24); /*日历时钟*/ timespec_to_rtc(pdir->file_time, &rtc, 1); week = WEEK_DAY(pdir->file_time.tv_sec); *pdat++ = (BYTE)(rtc.ms); *pdat++ = (BYTE)(rtc.ms >> 8); *pdat++ = (BYTE)(rtc.min); *pdat++ = (BYTE)(rtc.hour); *pdat++ = (BYTE)((week << 5) | rtc.day); *pdat++ = (BYTE)(rtc.month); *pdat++ = (BYTE)(rtc.year); framelen += len + 13; filescnt++; pdir++; if (framelen > 160 || i == (filenum - 1)) { if (i == (filenum - 1)) { datbuf[9 + b104] = 0; // 后续标识 } datbuf[10 + b104] = filescnt; // 文件数量 if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210); // ptfile = &((IEC104_DEF *)pt)->tf; } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210, FRAME_I); // ptfile = &((IEC101_DEF *)pt)->tf; } framelen = 11 + b104; filescnt = 0; pdat = &datbuf[framelen]; } } rt_free(pdirfree); } void iec_readfile_echo(void *pt, char *buf, bool b104) // buf 从 操作标识下一字节开始 { int i; char *pdat, *pfilebuf; BYTE namelen, framelen; int filelenth; // char namestr[64],tmpstr[64]; char namestr[256], tmpstr[256]; // modify by sunxi: 20220629 char datbuf[256]; uint32_t id; T_FILE *ptfile; int mulen = 0; if (b104) ptfile = &((IEC104_DEF *)pt)->tf; else ptfile = &((IEC101_DEF *)pt)->tf; pdat = buf; namelen = *pdat++; // 目录长度 if (namelen > 256) // modify by sunxi: 20220629 这里的长度有可能会超过256!!! { namelen = 255; rt_printf("iec_readfile_echo--------- namelen > 256 !!!!! error!!!\r\n"); } strcpy(tmpstr, ptfile->dirpath); // if(namelen>0) { for (i = 0; i < namelen; i++) { namestr[i] = *pdat++; if (namestr[i] == '/') // 文件名称带目录,记录目录结束位置 { mulen = i; } } } namestr[namelen] = '\0'; // 文件名称字符串结束符 if (mulen > 0 && mulen < namelen) // 文件名带目录 { mulen += 1; // 将下发名称的目录信息去掉 } #ifdef RCD_STRAN_S if (strncmp(namestr, "BAY", 3) == 0) /*录波文件*/ { strcpy(tmpstr, HF_WAVE_DIR); rt_printf_time("-------传输文件%s激活\r\n", namestr); if (ptfile->bTransing || ptfile->bdatTraned) /*激活文件时有文件传输,释放*/ { iec_freefile(ptfile); } } #endif #ifdef FUN_DIR_DEPTH if (strncmp(namestr, "soe", strlen("soe")) == 0) { if (strstr(ptfile->dirpath, "HISTORY")) strcpy(tmpstr, HF_SOE_101_DIR); } else if (strncmp(namestr, "ulog", strlen("ulog")) == 0) { if (strstr(ptfile->dirpath, "HISTORY")) strcpy(tmpstr, HF_LOG_101_DIR); } else if (strncmp(namestr, "co", strlen("co")) == 0) { if (strstr(ptfile->dirpath, "HISTORY")) strcpy(tmpstr, HF_CO_101_DIR); } #endif strcat(tmpstr, &namestr[mulen]); if (strcmp(p_his_file[HS_FILE_SOE], &namestr[mulen]) == 0) { if (!del_history_file(HS_FILE_SOE)) { create_event_rcd_file(HS_FILE_SOE); } // rt_printf("%s:tmpstr=%s,namestr=%s\r\n",__func__,tmpstr,&namestr[mulen]); } else if (strcmp(p_his_file[HS_FILE_CO], &namestr[mulen]) == 0) { if (!del_history_file(HS_FILE_CO)) { create_event_rcd_file(HS_FILE_CO); } // rt_printf("%s:tmpstr=%s,namestr=%s\r\n",__func__,tmpstr,&namestr[mulen]); } pfilebuf = hf_get_file_inf_n(tmpstr, &id, &filelenth); if (pfilebuf == NULL) { id = 0; filelenth = 0; } // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = 2; // 附加数据包类型 pdat[framelen++] = 4; // 读文件激活 pdat[framelen++] = (filelenth > 0) ? 0 : 1; // 结果描述符 :=1 失败 pdat[framelen++] = namelen; // 文件名长度 for (i = 0; i < namelen; i++) { pdat[framelen++] = namestr[i]; } /*文件标识*/ pdat[framelen++] = (BYTE)(id); pdat[framelen++] = (BYTE)(id >> 8); pdat[framelen++] = (BYTE)(id >> 16); pdat[framelen++] = (BYTE)(id >> 24); /*文件长度*/ pdat[framelen++] = (BYTE)(filelenth); pdat[framelen++] = (BYTE)(filelenth >> 8); pdat[framelen++] = (BYTE)(filelenth >> 16); pdat[framelen++] = (BYTE)(filelenth >> 24); if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_ACTCON, 210); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_ACTCON, 210, FRAME_I); // } // 设置文件传输标志,在各规约处理中发送 if (filelenth > 0) { ptfile->pfilebuf = pfilebuf; ptfile->bTransing = true; ptfile->offset = 0; ptfile->id = id; ptfile->filelenth = filelenth; ptfile->us0_file_trans = ustimer_get_origin(); } } void iec_readfile_send(void *pt, bool b104) // { int i; char *pdat; BYTE framelen; char datbuf[256]; T_FILE *ptfile; bool beof = false; BYTE checksum = 0; int datalen = FILE_SEND_FRAME_LENTH; if (b104) { ptfile = &((IEC104_DEF *)pt)->tf; } else { ptfile = &((IEC101_DEF *)pt)->tf; } if (!ptfile->bTransing || ptfile->offset >= ptfile->filelenth) return; if (ptfile->offset + FILE_SEND_FRAME_LENTH >= ptfile->filelenth) { datalen = ptfile->filelenth - ptfile->offset; // 最后一帧传输的字节数 beof = true; } // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = 2; // 附加数据包类型 pdat[framelen++] = 5; // 读文件数据响应 /*文件标识*/ pdat[framelen++] = (BYTE)(ptfile->id); pdat[framelen++] = (BYTE)(ptfile->id >> 8); pdat[framelen++] = (BYTE)(ptfile->id >> 16); pdat[framelen++] = (BYTE)(ptfile->id >> 24); /*文件偏移*/ pdat[framelen++] = (BYTE)(ptfile->offset); pdat[framelen++] = (BYTE)(ptfile->offset >> 8); pdat[framelen++] = (BYTE)(ptfile->offset >> 16); pdat[framelen++] = (BYTE)(ptfile->offset >> 24); pdat[framelen++] = beof ? 0 : 1; // 后续标志 0:无后续 1:有后续 for (i = 0; i < datalen; i++) { BYTE dd; dd = ptfile->pfilebuf[ptfile->offset + i]; pdat[framelen++] = dd; checksum += dd; } pdat[framelen++] = checksum; // 校验和 if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210); // if (!beof) { ptfile->offset += FILE_SEND_FRAME_LENTH; ptfile->bTransing = true; // 104规约 继续传输 } } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210, FRAME_I); // if (pRunSet->bTT_101Transsure) { ptfile->bTransing = false; // 101规约 bTransing 在收到文件接收确认帧后置位,启动发送 } else { if (!beof) { ptfile->offset += FILE_SEND_FRAME_LENTH; ptfile->bTransing = true; // 继续传输 } } } if (beof) // 文件传输完毕 { #ifdef RCD_STRAN_S newrcd_queque *rcd; if (!b104) { rcd = &((IEC101_DEF *)pt)->rcd_qt; del_data_queue(&rcd->queue); log_str_time(LOG_OPERATE, "文件传输结束", 0, 1); } else { rcd = &((IEC104_DEF *)pt)->rcd_qt; del_data_queue(&rcd->queue); rt_printf("---------文件传输结束,清缓存\r\n"); log_str_time(LOG_OPERATE, "文件传输结束", 0, 1); } #endif ptfile->bTransing = false; ptfile->bdatTraned = false; iec_freefile(ptfile); } else { ptfile->bdatTraned = true; ptfile->us0_file_trans = ustimer_get_origin(); } } void iec_readfile_sure(void *pt, u8 *buf, bool b104) // buf 从 操作标识下一字节开始 { T_FILE *ptfile; BYTE *pdat; DWORD id, offset; pdat = buf; id = pdat[0] | (pdat[1] << 8) | (pdat[2] << 16) | (pdat[3] << 24); // 目录ID pdat += 4; offset = pdat[0] + (pdat[1] << 8) + (pdat[2] << 16) + (pdat[3] << 24); // 偏移 if (b104) { ptfile = &((IEC104_DEF *)pt)->tf; } else { ptfile = &((IEC101_DEF *)pt)->tf; } if (ptfile->id != id || (offset + FILE_SEND_FRAME_LENTH >= ptfile->filelenth)) { return; // 文件已传输完毕 } ptfile->offset = offset + FILE_SEND_FRAME_LENTH; // 将偏移增加,继续传输 ptfile->bTransing = true; ptfile->bdatTraned = false; } void iec_freefile(T_FILE *ptfile) // dat 从信息对象开始 { if (ptfile->pfilebuf == NULL) return; rt_free(ptfile->pfilebuf); ptfile->pfilebuf = NULL; rt_printf("\r\n文件节传输完毕,释放内存,文件ID:%d 长度:%d\r\n", ptfile->id, ptfile->filelenth); } void iec_writefile_echo(void *pt, BYTE *buf, bool b104) // buf 从 操作标识下一字节开始 { int i; BYTE *pdat; BYTE namelen, framelen, ret; char namestr[64]; char datbuf[256]; T_FILE *ptfile; if (b104) ptfile = &((IEC104_DEF *)pt)->tf; else ptfile = &((IEC101_DEF *)pt)->tf; pdat = buf; namelen = *pdat++; // 长度 if (namelen >= 64) namelen = 63; // 文件名不能超过64字节 if (namelen > 0) { for (i = 0; i < namelen; i++) { namestr[i] = *pdat++; } } namestr[namelen] = '\0'; // 文件名称字符串结束符 strcpy(ptfile->wfilename, "/tmp/"); strcat(ptfile->wfilename, namestr); // if(ptfile->bUpdateStart) // 启动程序更新,备份升级文件名称 { strcpy(ptfile->updatefilename, namestr); } ptfile->wId = pdat[0] | (pdat[1] << 8) | (pdat[2] << 16) | (pdat[3] << 24); pdat += 4; ptfile->wfilelenth = pdat[0] | (pdat[1] << 8) | (pdat[2] << 16) | (pdat[3] << 24); rt_printf("\r\n%s wlenth=%d", ptfile->wfilename, ptfile->wfilelenth); if (strstr(KO_FILE_NAME, namestr) == NULL) { ret = 2; } else if (ptfile->wfilelenth >= 2048 * 1024) // 文件大于2M { ret = 3; } else { ret = 0; } // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = 2; // 附加数据包类型 pdat[framelen++] = 8; // 写文件激活 pdat[framelen++] = ret; // 结果描述符 :=2 未知文件名 pdat[framelen++] = namelen; // 文件名长度 for (i = 0; i < namelen; i++) { pdat[framelen++] = namestr[i]; } /*文件标识*/ pdat[framelen++] = (BYTE)(ptfile->wId); pdat[framelen++] = (BYTE)(ptfile->wId >> 8); pdat[framelen++] = (BYTE)(ptfile->wId >> 16); pdat[framelen++] = (BYTE)(ptfile->wId >> 24); /*文件长度*/ pdat[framelen++] = (BYTE)(ptfile->wfilelenth); pdat[framelen++] = (BYTE)(ptfile->wfilelenth >> 8); pdat[framelen++] = (BYTE)(ptfile->wfilelenth >> 16); pdat[framelen++] = (BYTE)(ptfile->wfilelenth >> 24); if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_ACTCON, 210); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_ACTCON, 210, FRAME_I); // } if (ret == 0) // 创建写文件接收缓冲区 { ptfile->writebuf = rt_malloc(ptfile->wfilelenth); // if (!ptfile->writebuf) { rt_printf("%s:rt_malloc eror\r\n", __func__); return; } ptfile->us0_file_write = ustimer_get_origin(); ptfile->bdatwriting = true; } } void iec_writefile_sure(void *pt, BYTE *buf, bool b104, u8 datlen) // buf 从 操作标识下一字节开始 datlen为含操作标识的报文长度,即文档中关于文件相关报文的长度 { int i; BYTE *pdat; BYTE framelen, ret; u32 id, offset; char datbuf[256]; T_FILE *ptfile; bool beof = false; if (b104) ptfile = &((IEC104_DEF *)pt)->tf; else ptfile = &((IEC101_DEF *)pt)->tf; pdat = buf; id = pdat[0] | (pdat[1] << 8) | (pdat[2] << 16) | (pdat[3] << 24); pdat += 4; offset = pdat[0] | (pdat[1] << 8) | (pdat[2] << 16) | (pdat[3] << 24); pdat += 4; pdat += 1; // 后续标识 datlen -= 11; ret = 0; for (i = 0; i < datlen; i++) { if ((offset + i) < ptfile->wfilelenth) { if (ptfile->writebuf) ptfile->writebuf[offset + i] = *pdat++; } } if ((offset + datlen) >= ptfile->wfilelenth) { beof = true; } ptfile->us0_file_write = ustimer_get_origin(); if (id != ptfile->wId) // id不一致 { ret = 4; beof = true; rt_printf("写文件: %s ID不一致! id=%d,wId=%d\r\n", ptfile->wfilename, id, ptfile->wId); } if (ptfile->bUpdateCancel) { ptfile->bUpdateCancel = false; beof = true; ret = 1; } if (beof) // 文件结束,写缓冲到文件中 { loff_t pos; int retlen; // 创建文件 struct file *handle; if (ret == 0) { handle = rt_file_open(ptfile->wfilename, O_CREAT | O_RDWR | O_TRUNC, 0); if (IS_ERR(handle)) { rt_printf("\r\n写文件: %s 创建失败!\r\n", ptfile->wfilename); ret = 1; } else { pos = 0; retlen = rt_file_write(handle, ptfile->writebuf, ptfile->wfilelenth, &pos); rt_printf("\r\n写文件: %s 返回%d filelenth=%d\r\n", ptfile->wfilename, retlen, ptfile->wfilelenth); if (retlen != ptfile->wfilelenth) // 写入文件长度不对应 { ret = 3; } rt_file_close(handle, 0); } } ptfile->bdatwriting = false; rt_free(ptfile->writebuf); ptfile->writebuf = NULL; } if (beof || (!b104 && pRunSet->bTT_101Transsure)) // 101规约需发确认帧,或规约文件最后一帧 { // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = 2; // 附加数据包类型 pdat[framelen++] = 10; // 写文件激活 /*文件标识*/ pdat[framelen++] = (BYTE)(ptfile->wId); pdat[framelen++] = (BYTE)(ptfile->wId >> 8); pdat[framelen++] = (BYTE)(ptfile->wId >> 16); pdat[framelen++] = (BYTE)(ptfile->wId >> 24); /*文件长度*/ pdat[framelen++] = (BYTE)(offset); pdat[framelen++] = (BYTE)(offset >> 8); pdat[framelen++] = (BYTE)(offset >> 16); pdat[framelen++] = (BYTE)(offset >> 24); pdat[framelen++] = ret; // 结果描述符 :=2 未知文件名 if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, ptfile->vsq, IEC_COT_REQ, 210, FRAME_I); // } } #ifdef SEC_BOX_CODE if (b104 && !beof) { ptfile->recvwrnum += 2; if (ptfile->recvwrnum >= tRunPara.w104K) { IEC104_Echo_US((IEC104_DEF *)pt, FRAME_S); ptfile->recvwrnum = 0; } } #endif } int iec_file_app(void *pt, BYTE *buf, BYTE cot, BYTE framelen, bool b104) // dat 从信息体地址后开始 framelen 从信息体地址后 附件数据类型包计算 { int ret = 0; if (buf[0] != 2) // 附加数据类型包 ==2 文件传输 { return -1; } // 判断传送原因和操作标识是否一致,不一致返回错误 if (!(((buf[1] == 3 || buf[1] == 7) && (cot == IEC_COT_ACT)) || ((buf[1] == 1 || buf[1] == 6 || buf[1 == 9]) && (cot == IEC_COT_REQ)))) { // return -2; // 为方便调试,先屏蔽此处理 } switch (buf[1]) { case 1: // 读目录 { if (!del_history_file(HS_FILE_SOE)) { create_event_rcd_file(HS_FILE_SOE); } if (!del_history_file(HS_FILE_CO)) { create_event_rcd_file(HS_FILE_CO); } iec_dir_echo(pt, &buf[2], b104); // 报文从 操作标识下一字节开始 break; } case 3: // 读文件激活 { iec_readfile_echo(pt, &buf[2], b104); break; } case 6: // 读文件数据响应确认 { iec_readfile_sure(pt, &buf[2], b104); break; } case 7: // 写文件激活 { iec_writefile_echo(pt, &buf[2], b104); break; } case 9: // 写文件传输确认 { iec_writefile_sure(pt, &buf[2], b104, framelen); break; } default: ret = -1; } return ret; } /*************软件升级报文*****************************/ int iec_pro_update(void *pt, BYTE cot, BYTE ctype, bool b104) { BYTE framelen, rcot; char *pdat, datbuf[32]; T_FILE *ptfile; bool s_e; #ifdef SEC_BOX_CODE char md5inf[32]; int md5lenth = 0; #endif if (b104) ptfile = &((IEC104_DEF *)pt)->tf; else ptfile = &((IEC101_DEF *)pt)->tf; s_e = (ctype & 0x80) ? 1 : 0; if (cot == IEC_COT_ACT && s_e) // 升级启动命令 { rcot = IEC_COT_ACTCON; ptfile->bUpdateStart = true; strcpy(ptfile->updatefilename, ""); rt_printf("\r\n升级启动"); g_sec_md5_ret = -1; // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = ctype; if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, 0, rcot, 211); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, 0, rcot, 211, FRAME_I); // } } else if (cot == 6 && !s_e) // 升级结束命令 { char file_name[64]; char log_buf[128] = {0}; rcot = IEC_COT_ACTCON; ptfile->bUpdateStart = false; // 判断文件真实性,并启动升级处理 // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = ctype; if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, 0, rcot, 211); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, 0, rcot, 211, FRAME_I); // } #ifdef SEC_BOX_CODE md5lenth = sec_md5_get_inf(md5inf); #endif sprintf(file_name, "%s%s", "/app/", ptfile->updatefilename); rt_printf_time("\r\n程序升级:->%s\r\n", file_name); if (strcmp(file_name, KO_FILE_NAME) == 0) // 文件名相同 { int index; char from_file_name[64]; char to_file_name[64]; char old_file_name[64]; index = file_check(ptfile->updatefilename, ATTR_DOWN); if (index >= 0) { int ret = file_check_info(index); sprintf(from_file_name, "%s%s", "/tmp/", g_file_item[index].file_name); if (ret == 0 && (((g_sec_md5_ret == 0) && pRunSet->bTT_ESAM) || !pRunSet->bTT_ESAM)) { watchdog_feed_mainloop_50s(); sprintf(to_file_name, "%s%s", g_file_item[index].file_dir, g_file_item[index].file_name); // sprintf(from_file_name,"%s%s","/tmp/",g_file_item[index].file_name); sprintf(old_file_name, "%s%s", to_file_name, "_1"); rt_file_mv(to_file_name, old_file_name); rt_file_mv(from_file_name, to_file_name); sprintf(file_name, "%s%s%s", "文件更新", g_file_item[index].file_dir, g_file_item[index].file_name); log_str_time(LOG_OPERATE, file_name, 0, 1); sprintf(log_buf, "%s updated", g_file_item[index].file_name); load_hs_log_rcd(TYPE_SW_UPDATE, true, NULL, log_buf, 1); rt_printf_time("\r\n%s 程序升级完毕,等待复位\r\n", file_name); ptfile->bUpdateReset = true; ptfile->us0_updatereset = ustimer_get_origin(); } else { rt_printf("\r\n%s 升级失败! ret=%d g_sec_md5_ret=%d\r\n", from_file_name, ret, g_sec_md5_ret); rt_file_del(from_file_name); } } } if (pRunSet->bTT_ESAM && (g_sec_md5_ret > 0)) // md5 检查错误应答 安全信息1f报文 { if (b104) { ((IEC104_DEF *)pt)->bEchosecmd5 = true; } else { ((IEC101_DEF *)pt)->bEchosecmd5 = true; } } } else if (cot == IEC_COT_DEACT && !s_e) // 升级撤销 { rcot = IEC_COT_DEACTCON; ptfile->bUpdateCancel = true; ptfile->bUpdateStart = false; strcpy(ptfile->updatefilename, ""); // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = ctype; if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, 0, rcot, 211); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, 0, rcot, 211, FRAME_I); // } } else { rcot = IEC_COT_UN_COT; // 组织报文 pdat = datbuf; framelen = 0; pdat[framelen++] = 0; // 信息体地址 pdat[framelen++] = 0; if (b104) pdat[framelen++] = 0; pdat[framelen++] = ctype; if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf, framelen, 0, rcot, 211); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, datbuf, framelen, 0, rcot, 211, FRAME_I); // } } #if 0 // 组织报文 pdat=datbuf; framelen=0; pdat[framelen++]=0; //信息体地址 pdat[framelen++]=0; if(b104)pdat[framelen++]=0; pdat[framelen++]=ctype; if(b104) { IEC104_AddFrame((IEC104_DEF *)pt, datbuf,framelen,0,rcot,211); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt,datbuf,framelen,0,rcot,211,FRAME_I);// } #endif #ifdef SEC_BOX_CODE // 扩展报文,回复md5信息 if (cot == 6 && !s_e && !pRunSet->bTT_ESAM) // 升级结束命令 { rcot = 63; if (b104) { IEC104_AddFrame((IEC104_DEF *)pt, md5inf, md5lenth, 0, rcot, 211); // } else { IEC101_Asdu_Add((IEC101_DEF *)pt, md5inf, md5lenth, 0, rcot, 211, FRAME_I); // } } #endif return 0; } /*******************下面是故障指示板通信处理过程********************/ static void FaultComm_Recv_Rst(IEC101_DEF *pt) { pt->nTypeCounter = 0; pt->nRecvLenth = 0; pt->nRecvCounter = 0; } static void FaultComm_Send(IEC101_DEF *pt) { RS_Send_Enable(pt->chnl); g_tRsComm[pt->chnl].nSendCnt = 1; // 发送缓冲区的第一个字节为发送长度 g_tRsComm[pt->chnl].bSend = true; } void FaultComm_Init(IEC101_DEF *pt, BYTE chnl) { // 接收帧间隔为重发间隔时间的一半 g_tRsComm[chnl].us_recv_timeout = pRunSet->dT101Resend * USTIMER_SEC / 2; memset(pt, 0, sizeof(IEC101_DEF)); pt->type = IEC_FAULT_CHN; pt->chnl = chnl; pt->us0_msend = ustimer_get_origin(); } void FaultComm_Applay(IEC101_DEF *pt) { BYTE *pd; u32 slot; // 检查状态板是否配置 slot = equ_get_slot_by_type(BOARD_TYPE_RS_STATUS); if (slot == 0) { return; } // 接收数据处理 if (pt->bData) { pt->bData = false; pd = &pt->recvbuf[4]; // 68 L L 68 zone addr data0 data1 sum 16 if (pd[1] == 0x55) // 是状态板地址 { if (pd[2]) // 有复归按键产生 { ResetHzLed(0); SignalReset(0, true); // 复归按键处理 rt_printf("状态指示板复归信号产生。\r\n"); } pt->msend_retries = 0; pt->bMSend = false; if (rt_err_clr(ERR_CODE_SB_COMM, slot) == 2) { rt_printf("状态板通讯恢复\r\n"); soe_record_ev(EV_BOARDCOMM, 0, 0, 0, 0); } } } // 1秒主动更新一次 if (ustimer_get_duration(pt->us0_msend) > USTIMER_SEC) { DWORD led = 0, ledsw = 0, pos, i; // 通讯状态监测 if (pt->bMSend) { if (++pt->msend_retries > 2) // 重发三次 { if (rt_err_set(ERR_CODE_SB_COMM, slot) == 2) { rt_printf("状态板通讯异常\r\n"); soe_record_ev(EV_BOARDCOMM, 1, 0, 0, 0); } } } for (i = 0; i < g_sw_num; i++) { // 合位灯 pos = i * 4 + 0; if (g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no]) { ledsw |= 1 << (i * 2 + 0); } // 跳位灯 pos = i * 4 + 1; if (g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no]) { ledsw |= 1 << (i * 2 + 1); } // 过流灯 pos = i * 4 + 2; if (g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no]) { led |= 1 << (i * 2 + 0); } // 接地灯 pos = i * 4 + 3; if (g_led_stu[g_led_slot[slot].sn[pos].sw][g_led_slot[slot].sn[pos].no]) { led |= 1 << (i * 2 + 1); } } // rt_printf("ledsw=%08x,led=%08x.\r\n",ledsw,led); pd = g_tRsComm[pt->chnl].sendbuf; pd[0] = 16; // 报文长度 pd[1] = 0x68; // 报文头 pd[2] = 10; pd[3] = 10; pd[4] = 0x68; pd[5] = 0; // 控制域 pd[6] = 0x55; // 链路地址 pd[7] = (ledsw >> 0) & 0xff; pd[8] = (ledsw >> 8) & 0xff; pd[9] = (ledsw >> 16) & 0xff; pd[10] = (ledsw >> 24) & 0xff; pd[11] = (led >> 0) & 0xff; pd[12] = (led >> 8) & 0xff; pd[13] = (led >> 16) & 0xff; pd[14] = (led >> 24) & 0xff; pd[15] = pd[5] + pd[6] + pd[7] + pd[8] + pd[9] + pd[10] + pd[11] + pd[12] + pd[13] + pd[14]; pd[16] = 0x16; FaultComm_Send(pt); pt->bMSend = true; pt->us0_msend = ustimer_get_origin(); } } void FaultComm_Recv(IEC101_DEF *pt, BYTE byRevData) { pt->recvbuf[pt->nRecvCounter++] = byRevData; switch (pt->nTypeCounter) { case 0: if (byRevData == 0x68) { pt->nTypeCounter = 1; } else { FaultComm_Recv_Rst(pt); } break; case 1: pt->nTypeCounter = 2; pt->nRecvLenth = byRevData; // 长帧长度 if (pt->nRecvLenth > IEC101_RECVBUF_MAX) { FaultComm_Recv_Rst(pt); } break; case 2: if (pt->nRecvLenth == byRevData) { pt->nTypeCounter = 3; } else { FaultComm_Recv_Rst(pt); } break; case 3: if (byRevData == 0x68) { pt->nTypeCounter = 4; } else { FaultComm_Recv_Rst(pt); } break; case 4: // 控制域 pt->sum = byRevData; pt->nTypeCounter = 5; break; case 5: // 目标地址 pt->sum += byRevData; pt->nRecvCnt = 0; pt->nTypeCounter = 6; break; case 6: // 有效数据 //有效数据 if (++pt->nRecvCnt >= pt->nRecvLenth - 2) { pt->nTypeCounter = 7; } pt->sum += byRevData; break; case 7: // 校验和 if (pt->sum == byRevData) { pt->nTypeCounter = 8; } else { FaultComm_Recv_Rst(pt); } break; case 8: // 结束符 FaultComm_Recv_Rst(pt); if (byRevData == 0x16) // 校验结束字符,报文接收完毕, { pt->bData = true; return; } break; default: FaultComm_Recv_Rst(pt); break; } // 类型校验结束 }