4G_module/custom/tcp_client/src/tcp_client.c

241 lines
9.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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; // 断开连接信号量
#define RECV_MAX_LEN (1024) // 接收最大长度
// TCP接收线程
static void tcp_recv_task(void){
int ret = 0;
fd_set sets;
struct timeval timeout;
uint8_t buf[RECV_MAX_LEN] = {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");
if(ret > RECV_MAX_LEN){
DEBUG("tcp_read recv too long:%d\n", ret);
ret = RECV_MAX_LEN;
}
// 处理接收到的数据
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_pkg_send(ID_GetTermAttrResp, 0); // 发送终端属性查询应答包
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); // 等待网络管理线程启动
}