#include "lwip/lwip/netdb.h" #include "lwip/lwip/sockets.h" #include "cm_modem.h" #include "cm_pm.h" #include "jt808_msg_pkg.h" #include "jt808_msg_parse.h" #include "jt808_pkg_transmit.h" #include "jt808_set_TermParam.h" #include "tcp_client.h" #include "app_common.h" #include "local_tts.h" #define TCP_CLIENT_ENABLE 0 #if TCP_CLIENT_ENABLE #include "app_uart.h" #define DEBUG(fmt, args...) app_printf("[TCP]" fmt, ##args) #else #define DEBUG(fmt, arg...) #endif static int tcp_client_sock = -1; static osThreadId_t tcp_recv_ThreadId = NULL; static osThreadId_t net_manage_ThreadId = NULL; osSemaphoreId_t netconn_disconnect_sem = NULL; // 断开连接信号量 // TCP接收线程 static void tcp_recv_task(void){ int ret = 0; fd_set sets; struct timeval timeout; uint8_t buf[128] = {0}; while(1){ FD_ZERO(&sets); FD_SET(tcp_client_sock, &sets); timeout.tv_sec = 10; timeout.tv_usec = 0; ret = select(tcp_client_sock + 1, &sets, NULL, NULL, &timeout);//监听套接字 if(ret > 0){ // 发生状态变化,可以进行读取、写入或者有异常事件 // DEBUG("tcp_read select ret %d\n", ret); if(FD_ISSET(tcp_client_sock, &sets)){ // 套接字可读 ret = recv(tcp_client_sock, buf, sizeof(buf), 0); if(ret > 0){ // DEBUG("tcp_read recv:%d\n", ret); // for(int i = 0; i < ret; i++){ // app_printf("%02x ", buf[i]); // } // app_printf("\n\n"); // 处理接收到的数据 jt808_pkg_handle(buf, ret); memset(buf, 0, sizeof(buf)); }else if(ret <= 0){// 连接已断开或发生错误,客户端需要执行close操作 DEBUG("tcp_read closed %d\n", errno); close(tcp_client_sock); } } }else if(ret == 0){// select 等待超时 // TODO DEBUG("tcp_read_test select timeout %d\n", errno); }else{// 走到这时当前socket已关闭,此时select将一直报错,故而挂起线程,等待重新连接后再次恢复线程 DEBUG("tcp_recv_task Suspend %d\n", errno); close(tcp_client_sock); osSemaphoreRelease(netconn_disconnect_sem); // 发送断开连接信号 osThreadSuspend(tcp_recv_ThreadId); } } } // TCP连接 // host:服务地址,port:服务端口 int tcp_client_connect(const char *host, int port) { int ret = 0; tcp_client_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (tcp_client_sock == -1){ DEBUG("tcp socket create error\n"); return -1; } DEBUG("tcp connect:%s, %d\n", host, port); struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_len = sizeof(server_addr); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); //端口 server_addr.sin_addr.s_addr = inet_addr(host); //服务地址 ret = connect(tcp_client_sock, (const struct sockaddr *)&server_addr, sizeof(server_addr)); if (ret == -1){ DEBUG("tcp connect error\n"); close(tcp_client_sock); return -1; }else if (ret == 0){ /* 建立新的线程供select异步读取*/ DEBUG("tcp connect ok\n"); if (tcp_recv_ThreadId == NULL){ osThreadAttr_t tcp_recv_task_attr = {0}; tcp_recv_task_attr.name = "tcp_recv_task"; tcp_recv_task_attr.stack_size = 4096*4; tcp_recv_task_attr.priority = osPriorityNormal; tcp_recv_ThreadId = osThreadNew((osThreadFunc_t)tcp_recv_task, 0, &tcp_recv_task_attr); }else{ DEBUG("tcp_recv_task Resume %d\n", errno); osThreadResume(tcp_recv_ThreadId); //恢复线程 } } return 0; } // TCP发送数据 int tcp_client_send(const uint8_t *buf, uint16_t len){ // 不可加打印 int ret = 0; ret = send(tcp_client_sock, (char *)buf, len, 0); if(ret < 0){ DEBUG("tcp send error\n"); // close(tcp_client_sock); return -1; } // DEBUG("tcp send %d bytes\n", ret); return 0; } void tcp_client_close(void){ if(tcp_client_sock != -1){ close(tcp_client_sock); tcp_client_sock = -1; } if(tcp_recv_ThreadId != NULL){ osThreadSuspend(tcp_recv_ThreadId); //挂起线程 // tcp_recv_ThreadId = NULL; } } // 网络管理线程 static void net_manage_task(void *arg){ // osThreadState_t state; DEBUG("net_manage_task!\r\n"); int ret = 0; cm_cereg_state_t cereg_state = {0}; uint8_t error_time_out = 0; while(1){ TCP_DISABLE: error_time_out = 0; do{// 连接服务器 while(1){ // 等待插入SIM卡并建立网络连接 osDelay(1000/5); error_time_out++; if(error_time_out > 15){ // 超时退出 DEBUG("network connect timeout!\n"); cm_pm_reboot(); } if(0 == cm_modem_get_cpin()){ // 插入SIM卡 DEBUG("sim card ready!\r\n"); }else{ DEBUG("waiting for sim card...\r\n"); } if(0 ==cm_modem_get_cereg_state(&cereg_state)){ // 获取PS网络注册状态 DEBUG("cereg_state:%d\n",cereg_state.state); // 注册状态 if(cereg_state.state == 1){ // 已注册 DEBUG("network ready\n"); break; }else{ DEBUG("waiting for network...\n"); } }else{ DEBUG("cereg_get_state fail!\n\n"); } // if(cm_modem_get_pdp_state(1) == 1){ // 网络就绪 // app_printf("network ready\n"); // }else{ // app_printf("waiting for network...\n"); // } } }while(0 != tcp_client_connect((char *)(PrsResult.term_param_item->set_term_param.MainServerAddr) , PrsResult.term_param_item->set_term_param.ServerPort)); // 连接到TCP服务器 DEBUG("tcp_client_connect success!\r\n"); for(uint8_t i = 0; i < 3; i++){ // 发送3次注册、鉴权、参数设置、上报参数 ret =jt808_pkg_send(ID_Term_Reg,8000/5);//注册终端 超时:8S if(0 == ret){ // 0:成功;1:车辆已被注册;2:数据库中无该车辆;3:终端已被注册;4:数据库中无该终端 DEBUG("send ID_Term_Reg success!\n"); for(uint8_t i = 0; i < 5; i++){ ret =jt808_pkg_send(ID_Term_Auth,10000/5);//终端鉴权 超时:10S if(0 == ret){ DEBUG("send ID_Term_Auth success!\n"); break; }else{ DEBUG("send ID_Term_Auth fail:%d!\n",ret); if((ret == -1)||(i == 3)){ goto TCP_DISABLE; } } } break; }else{ DEBUG("send ID_Term_Reg fail:%d!\n",ret); if(ret == -1){ // 发送失败 goto TCP_DISABLE; } } } jt808_Autoreport_param_start();//开启自动上报参数设置 led_set_event(EVENT_NETWORK_READY); // 网络连接成功 DEBUG("NetwarK connected!\r\n"); // local_tts_set(5, 15, CM_LOCAL_TTS_DIGIT_AUTO); local_tts_text_play("网络已连接",0,0); local_tts_text_play("欢迎使用莱昂特智能终端设备...。",0,0); // 0:表示自动计算字符串长度,10000表示最大等待时间 osSemaphoreAcquire(netconn_disconnect_sem, osWaitForever); // 等待断开连接信号 jt808_Autoreport_param_stop();//停止自动上报参数设置 led_set_event(EVENT_NETWORK_DISCONNECT); // 网络断开连接 DEBUG("NetwarK disconnected!\r\n"); // local_tts_set(5, 15, CM_LOCAL_TTS_DIGIT_AUTO); local_tts_text_play("网络已断开",0,0); } } void tcp_client_init(void){ osThreadAttr_t net_manage_task_attr={ .name = "net_manage_task", .stack_size = 4096*4, .priority = osPriorityNormal, }; DEBUG("tcp_client_init!\r\n"); if(netconn_disconnect_sem == NULL){ netconn_disconnect_sem = osSemaphoreNew(1, 0, NULL); } net_manage_ThreadId = osThreadNew((osThreadFunc_t)net_manage_task, 0, &net_manage_task_attr); // osDelay(300/5); // 等待网络管理线程启动 }