235 lines
8.7 KiB
C
235 lines
8.7 KiB
C
#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); // 等待网络管理线程启动
|
||
} |