/** * @file bs_connect_impl.c * @brief 平台链路层实现:TCP/4G 连接、收发、4G 双 socket 分发 * * - 联网参数从 t_sys_fix_cfg.s_net_cfg 读取 * - 4G 模式经 WH-GM5 模组,支持 socketA/B 分发 * - 以太网分支(u8_netType!=0)预留待补全 */ #if EC200A_4G_EN #include "plat_comm/4g_module/ec200a_4g.h" #include "plat_comm/4g_module/ec200a_4g_cfg.h" #endif #if WH_GM5_EN #include "plat_comm/4g_module/bs_wh_gm5.h" #endif #include "publicdata/publicdata.h" #include "plat_comm/plat_comm_task.h" #include "plat_comm/lwip_module/lwip_module.h" #define BS_PRINTF_EN 1 //平台收发数据打印 ws_url_t url_info; /** * @brief 网口 TCP:关闭指定平台通道 socket */ void v_bs_eth_close_socket(U8_T u8_id) { if (s_bs_task_ctrl.s_bs_ctrl[u8_id].fd >= 0) { lwip_tcp_close((int)s_bs_task_ctrl.s_bs_ctrl[u8_id].fd); s_bs_task_ctrl.s_bs_ctrl[u8_id].fd = (S32_T)-1; s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_TCP_connect_flag = 0; } } #if 1 //联网参数配置 /** * ************************************************************************ * @brief - 4G模块联网参数获取 * * @param[in] s_4g_para - 4G联网参数结构体 * * * @author jiankalka * @date 2025-09-01 * ************************************************************************ */ #if WH_GM5_EN void v_get_4G_config_para(S_4G_CONFIG_PARA *s_4g_para) { SYS_FIX_CFG_T *t_sys_fix_cfg = &g_t_share_data.t_sys_fix_cfg; memset(s_4g_para , 0 ,sizeof(S_4G_CONFIG_PARA)); //s_4g_para->socketA_IP = testIP; s_4g_para->socketA_IP = t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name; // s_4g_para->socketB_IP = t_sys_fix_cfg->s_net_cfg.u8_serverB_domain_name; s_4g_para->u8_Sim_Type = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_sim_anp_type; s_4g_para->u8_socketB_en = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platB_en; } #endif /* WH_GM5_EN */ /** * ************************************************************************ * @brief - 4G模块参数初始化 * * * * @author jiankalka * @date 2025-09-19 * ************************************************************************ */ void v_bs_4G_data_init(void) { #if EC200A_4G_EN { S_4G_CONFIG_PARA s_4g_para; SYS_FIX_CFG_T *t_sys_fix_cfg = &g_t_share_data.t_sys_fix_cfg; memset(&s_4g_para, 0, sizeof(S_4G_CONFIG_PARA)); s_4g_para.socketA_IP = t_sys_fix_cfg->s_net_cfg.u8_serverA_domain_name; s_4g_para.socketB_IP = t_sys_fix_cfg->s_net_cfg.u8_serverB_domain_name; s_4g_para.u8_Sim_Type = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_sim_anp_type; s_4g_para.u8_socketB_en = t_sys_fix_cfg->s_net_cfg.u_net_comm_para.bits.bit_platB_en; v_4g_data_init(&s_4g_para); } #endif /* EC200A_4G_EN */ #if WH_GM5_EN { S_4G_CONFIG_PARA s_4g_para; v_get_4G_config_para(&s_4g_para); v_wh_gm5_data_init(&s_4g_para); } #endif } /** * ************************************************************************ * @brief - TCP 联网测试函数 * * * @return U8_T - 0未连接TCP 1已连接 * * @author jiankalka * @date 2025-08-29 * ************************************************************************ */ U8_T u8_tcp_connect(U8_T u8_id) { U8_T u8_ret = 0; if(s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_netType == 0) //4G联网 { #if WH_GM5_EN // 无线模块WH_GM5初始化 if(s8_WH_GM5_init() == 0) //如果4g配置成功 { if(s8_check_socket_LinkState(u8_id) >= 0) //查询网路连接状态 { mSleep(100); v_4g_uart_cache_clear(); //4G模块配置完毕 清除串口缓存区中的数据 return 1; } } if(u8_ret == 0 && u32_safe_seconds_since(s_bs_task_ctrl.s_bs_ctrl[u8_id].ulong_restart_timer) > NUM_120) //120分钟 没连上 则重新连接 { v_bs_4G_data_init(); //4G模块控制数据 初始化 s_bs_task_ctrl.s_bs_ctrl[u8_id].ulong_restart_timer = get_current_seconds(); } #endif #if EC200A_4G_EN if(s8_ec200a_4g_init() == 0) { u8_ret = 1; } #endif } else //网线连接 { } return u8_ret; } #endif #if WH_GM5_EN // WH-GM5 4G收发接口 /** * ************************************************************************ * @brief - 4G模块多端口数据接收、用于多socket分端口接收、需要传入两平台接收处理函数接口 * * @param[in] socketA_unPack - socketA 接收处理函数,不存在时赋值为NULL * @param[in] socketB_unPack - socketB 接收处理函数,不存在时赋值为NULL * * * @author jiankalka * @date 2025-09-02 * ************************************************************************ */ void v_4g_wh5_data_divide_recv(RecvUnpackHandler socketA_unPack, RecvUnpackHandler socketB_unPack) { // 静态缓冲区用于保存残包 static U8_T u8_recv_saveBuf[BS_RECV_BUF_LEN]; static U16_T u16_recv_saveLen = 0; // 1. 数据合并:将新数据与静态缓冲区的残包合并 U16_T u16_totalLen = 0; // 总数据长度(静态缓冲区+新数据) U16_T u16_rcvByteNum = 0; // 当前解析位置 U16_T u16_oneFrmLen = 0; // 完整帧长度 U16_T u16_dataLen = 0; // 数据域长度 U8_T frameType = 0; // 帧类型 U8_T flags = 0; // 标志位 U8_T* payloadStart = NULL; // 有效载荷起始位置 U16_T payloadLen = 0; // 有效载荷长度 U8_T u8_recvBuf[BS_RECV_BUF_LEN] = {0}; //接收数据缓存区 // 0. 获取串口数据 U16_T u16_recvLen = u16_usart_recv(COM_PORT_BS, u8_recvBuf, BS_RECV_BUF_LEN); // 如果没有接收到数据,直接返回 if(u16_recvLen == 0) { return; } // 计算新数据需要复制的长度(避免缓冲区溢出) U16_T actualCopyLen = u16_recvLen; if (u16_recv_saveLen + u16_recvLen > BS_RECV_BUF_LEN) { // 缓冲区溢出处理:保留新数据,丢弃最旧的数据 U16_T overflowBytes = (u16_recv_saveLen + u16_recvLen) - BS_RECV_BUF_LEN; // 移动现有数据,为新数据腾出空间 memmove(u8_recv_saveBuf, &u8_recv_saveBuf[overflowBytes], u16_recv_saveLen - overflowBytes); u16_recv_saveLen -= overflowBytes; // 更新实际可复制长度 actualCopyLen = BS_RECV_BUF_LEN - u16_recv_saveLen; } // 追加新数据到静态缓冲区末尾 memcpy(u8_recv_saveBuf + u16_recv_saveLen, u8_recvBuf, actualCopyLen); u16_recv_saveLen += actualCopyLen; // 设置总数据长度 u16_totalLen = u16_recv_saveLen; // 2. 主解析循环 - 处理完整帧 while (u16_totalLen >= 8) { // 帧头检查 if (u8_recv_saveBuf[u16_rcvByteNum] != 0xAA || u8_recv_saveBuf[u16_rcvByteNum+1] != 0xFD || u8_recv_saveBuf[u16_rcvByteNum+2] != 0x55) { // 帧头不匹配,移动搜索位置 u16_rcvByteNum++; u16_totalLen--; continue; } // 获取数据长度(大端格式) u16_dataLen = (U16_T)((u8_recv_saveBuf[u16_rcvByteNum+3] << 8) | u8_recv_saveBuf[u16_rcvByteNum+4]); // 计算完整帧长度 = 头部(3) + 长度字段(2) + 元数据(3) + 数据长度 u16_oneFrmLen = 6 + u16_dataLen; // 检查帧完整性 if (u16_oneFrmLen > u16_totalLen) { // 残包处理:帧不完整,等待更多数据 break; } // 提取关键字段 frameType = u8_recv_saveBuf[u16_rcvByteNum + 5]; // 类型字段(0x61/0x62) flags = u8_recv_saveBuf[u16_rcvByteNum + 6]; // 标志位 // 安全获取有效载荷(跳过帧头、长度字段和类型字段) payloadStart = &u8_recv_saveBuf[u16_rcvByteNum + 7]; payloadLen = u16_dataLen - 2; // 减去类型和标志位 // 确保有效载`` 荷在缓冲区范围内 if ((payloadStart + payloadLen) > (u8_recv_saveBuf + BS_RECV_BUF_LEN)) { // 缓冲区越界错误处理:重置缓冲区 u16_recv_saveLen = 0; return; } // 处理网络返回数据 if ((flags & 0x80) == 0) { if (frameType == 0x61 && socketA_unPack != NULL) { // SOCKETA数据 socketA_unPack(0, payloadStart, payloadLen); } else if (frameType == 0x62 && socketB_unPack != NULL) { // SOCKETB数据 socketB_unPack(1, payloadStart, payloadLen); } //测试打印 #if BS_PRINTF_EN printf("--------------plat[%d] recv\r\n",frameType - 0x60); for (int i = 0; i < u16_recvLen; i++) { printf("%02x ",u8_recvBuf[i]); } printf("\n---------------\r\n"); #endif } // 移动位置指针(处理完整帧) u16_rcvByteNum += u16_oneFrmLen; u16_totalLen -= u16_oneFrmLen; } // 3. 残包处理:保存剩余数据到静态缓冲区 if (u16_totalLen > 0) { // 移动剩余数据到静态缓冲区开头 if (u16_rcvByteNum > 0) { memmove(u8_recv_saveBuf, &u8_recv_saveBuf[u16_rcvByteNum], u16_totalLen); } u16_recv_saveLen = u16_totalLen; } else { // 没有剩余数据,重置静态缓冲区 u16_recv_saveLen = 0; } return; } /** * ************************************************************************ * @brief - 4G 模块发送数据接口 * * @param[in] u8_id - 发送接口ID 0代表不使能分发功能,直接透传发送 1代表像socketA发送数据 2代表像socketB发送数据 * @param[in] u8_sendBuf - 发送数据数组指针 * @param[in] u16_len - 发送数据长度 * * * @author jiankalka * @date 2025-09-01 * ************************************************************************ */ void v_4g_wh5_data_send(U8_T u8_id,U8_T *u8_sendBuf,U16_T u16_len) { U16_T len,u16_checkSum; U8_T send_buf[10]={0}; if(u8_id == 0) //不使用套接字分发 直接发送数据 u16_usart_send(COM_PORT_BS, u8_sendBuf, u16_len); else { //套接字分发组帧头 send_buf[0] = 0x55; send_buf[1] = 0xFD; send_buf[2] = 0xAA; len = u16_len + 2; send_buf[3] = (len >> 8) & 0xFF; send_buf[4] = len & 0xFF; send_buf[5] = 0x60 + u8_id; //SOCKETA为0x61,SOCKETB为0x62 send_buf[6] = 0; //发送帧头 u16_usart_send(COM_PORT_BS, send_buf, 7); //发送数据 u16_usart_send(COM_PORT_BS, u8_sendBuf, u16_len); //计算校验合 发送数据+SOCKET序号 u16_checkSum = u16_crc_checksum(u8_sendBuf, u16_len); u16_checkSum = u16_checkSum + send_buf[5]; send_buf[0] = u16_checkSum&0xFF; u16_usart_send(COM_PORT_BS, send_buf, 1); } } /** * ************************************************************************ * @brief - 4G模块数据接收 接收原始数据 不进行分包解析 * * @param[in] u8_recvBuf - 接收数据缓存数组 * @param[in] u16_len - 接受数组长度 * * @return U16_T - * * @author jiankalka * @date 2025-09-02 * ************************************************************************ */ U16_T u16_4g_wh5_data_recv(U8_T *u8_recvBuf,U16_T u16_len) { U16_T u16_recvLen; memset(u8_recvBuf , 0 , u16_len); u16_recvLen = u16_usart_recv(COM_PORT_BS, u8_recvBuf, u16_len); return u16_recvLen; } #endif #if 1 //公共s收发函数接口 /** * ************************************************************************ * @brief - 公共发送接口 * * @param[in] u8_id - 平台位置 0-1 * @param[in] u8_sendBuf - 发送数据 * @param[in] u16_len - 发送数据长度 * * * @author jiankalka * @date 2025-09-02 * ************************************************************************ */ void v_bs_send(U8_T u8_id,U8_T *u8_sendBuf,U16_T u16_len) { if(s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_netType == 0) //4G联网 { #if WH_GM5_EN if(s_bs_task_ctrl.u8_4g_dispense_en == 1) u8_id+=1; //分发使能 序号加一 v_4g_wh5_data_send(u8_id,u8_sendBuf,u16_len); #endif #if EC200A_4G_EN if(s_bs_task_ctrl.u8_4g_dispense_en == 1) u8_id+=1; #if EC200A_TCP_USE_TRANSPARENT_MODE v_4g_send_data(u8_id,u8_sendBuf,u16_len); #else v_ec200a_tcp_app_send(u8_id,u8_sendBuf,u16_len); #endif #endif } else { } mSleep(Plat_Send_Sleep); s_bs_task_ctrl.u8_sendCnt++; #if BS_PRINTF_EN printf("\n--------------bs send\r\n"); for (int i = 0; i < u16_len; i++) { printf("%c",u8_sendBuf[i]); } printf("\r\n"); for (int i = 0; i < u16_len; i++) { printf("%02x ",u8_sendBuf[i]); } printf("\n---------------\r\n"); #endif } /** * ************************************************************************ * @brief - 公共接收函数 * * @param[in] u8_id - 平台位置 0-1 * @param[in] u8_recvBuf - 接收数据缓存地址 * @param[in] u16_len - 最大接收长度 * * @return U16_T - * * @author jiankalka * @date 2025-09-02 * ************************************************************************ */ U16_T u16_bs_recv(U8_T u8_id,U8_T *u8_recvBuf,U16_T u16_len) { U16_T u16_recvLen = 0; if(s_bs_task_ctrl.s_bs_ctrl[u8_id].u8_netType == 0) //4G联网 { #if WH_GM5_EN u16_recvLen = u16_usart_recv(COM_PORT_BS, u8_recvBuf, u16_len); #endif #if EC200A_4G_EN u16_recvLen = u16_ec200a_tcp_app_recv(u8_recvBuf, u16_len); #endif } else //以太网 { // if(bs_task_ctrl_data.s_bs_ctrl[id].fd >= 0) // u16_recvLen = eth_recv((int)bs_task_ctrl_data.s_bs_ctrl[id].fd, (char *)recvBuf, BS_RECV_BUF_LEN, 1); } #if BS_PRINTF_EN if(u16_recvLen == 0) return u16_recvLen; printf("\n--------------bs recv\r\n"); for (int i = 0; i < u16_recvLen; i++) { printf("%c",u8_recvBuf[i]); } printf("\r\n"); for (int i = 0; i < u16_recvLen; i++) { printf("%02x ",u8_recvBuf[i]); } printf("\n---------------\r\n"); #endif return u16_recvLen; } #endif