/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2023-05-30 murmur the first version */ #include #include /* 使用BSD socket,需要包含socket.h头文件 */ #include #include #define LOG_TAG "ttTR" #define LOG_LVL LOG_LVL_DBG #include #include #include "ttTR.h" #define BUFSZ 2000 #define RETRYCNT 10 #define URL TTIP #define PORT 8005 static int sock=0; volatile int flag=0; void tcpClose(void) { /* 关闭这个连接 */ if (sock) { closesocket(sock); } flag=0; } int isTCPok(void) { // return sock; return flag; } int tcpInit(void) { int ret; const char *url = URL; int port = PORT; /* 通过函数入口参数url获得host地址(如果是域名,会做域名解析) */ struct hostent *host; host = gethostbyname(url); /* 创建一个socket,类型是SOCKET_STREAM,TCP类型 */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { /* 创建socket失败 */ LOG_E("Socket error"); return RT_ERROR; } /* 初始化预连接的服务端地址 */ struct sockaddr_in server_addr; server_addr.sin_family = AF_INET; server_addr.sin_port = htons(port); server_addr.sin_addr = *((struct in_addr *) host->h_addr); rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); /* 连接到服务端 */ if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1) { /* 连接失败 */ LOG_E("Connect to TT fail!"); tcpClose(); return RT_ERROR; } else { // tcpRecMQ(); flag=1; return RT_EOK; } } static int tcpSend(const rt_uint8_t *send_data, size_t len) { // LOG_HEX("send",27,send_data,len); /* 发送数据到sock连接 */ int ret = send(sock, send_data, len, 0); if (ret == len) { // LOG_D("send %d Bytes ok.",len); ret = RT_EOK; } else { LOG_E("Send error, send function return %d", ret); ret = RT_ERROR; } return ret; } /** * 接收TCP数据 * @param recv_data 接收数据缓存,最小200字节 * @return 接收到的数据长度,-1表示发生了错误。 */ int tcpRec(unsigned char *recv_data) { int ret=RT_ERROR; /* 从sock连接中接收最大BUFSZ字节数据 */ int bytes_received = recv(sock, recv_data, BUFSZ, 0); if (bytes_received) { return bytes_received; } else { LOG_E("received error."); return -RT_ERROR; } } struct rt_messagequeue TTrx_mq; void init_mq(void) { static char msg_pool[1024*1]; /* 初始化消息队列 */ int result = rt_mq_init(&TTrx_mq, "TTrx_mq", msg_pool, /* 存放消息的缓冲区 */ sizeof(TTRx_MSG), /* 一条消息的最大长度 */ sizeof(msg_pool), /* 存放消息的缓冲区大小 */ RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */ if (result != RT_EOK) { rt_kprintf("init message queue failed.\n"); return -1; } } INIT_COMPONENT_EXPORT(init_mq); static uint8_t TCPrxBuffer[BUFSZ]; void readTCPData(uint8_t *dout, size_t cnt) { memcpy(dout,TCPrxBuffer,cnt); } /** * 接收TCP数据,通过消息队列发出通知 * @param recv_data 接收数据缓存,最小200字节 * @return 接收到的数据长度,-1表示发生了错误。 */ void tcpRecMQ_thread_entry(void) { static TTRx_MSG msg; while (1) { if (!isTCPok()) { break; } rt_memset(&msg, 0, sizeof(msg)); /* 从sock连接中接收最大BUFSZ字节数据 */ msg.size = recv(sock, TCPrxBuffer, BUFSZ, 0); // if (msg.size < 0) // { // /* 接收失败,关闭这个连接 */ // tcpClose(); // rt_kprintf("\nreceived error,close the socket.\r\n"); // // /* 释放接收缓冲 */ // break; // } // LOG_D("%d Bytes received.",msg.size); if (msg.size >0 ) { // LOG_D("%d Bytes received.",msg.size); // LOG_HEX("tcpTT", 16, msg.data, msg.size); // resetTM(); int result = rt_mq_send(&TTrx_mq, &msg, sizeof(msg)); if (result == -RT_EFULL) { /* 消息队列满 */ LOG_W("message queue full."); } } else { msg.size=0;//收到数据长度为0表示tcp断开 rt_mq_send(&TTrx_mq, &msg, sizeof(msg)); LOG_W("tcp closed."); tcpClose(); break; } } } /** * 创建接收线程。发生错误后自动退出。 */ void tcpRecMQ(void) { /* 创建 serial 线程 */ rt_thread_t thread = rt_thread_create("tcpRecMQ", tcpRecMQ_thread_entry, RT_NULL, 1024*10, 25, 10); /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); } else { LOG_E("thread 'tcpRecMQ' create failure."); } } //INIT_COMPONENT_EXPORT(tcpRecMQ); /** * 发送数据时TT的ack信号 * @return */ static int tcpAck() { /* 分配用于存放接收数据的缓冲 */ char *recv_data; recv_data = rt_malloc(BUFSZ); if (recv_data == RT_NULL) { LOG_E("No memory."); return RT_ENOMEM; } int ret=RT_ERROR; size_t cnt = RETRYCNT;//尝试次数 while (cnt--) { /* 从sock连接中接收最大BUFSZ - 1字节数据 */ int bytes_received = recv(sock, recv_data, BUFSZ, 0); if (bytes_received) { LOG_HEX("rec data",16,recv_data,bytes_received); //check response rt_uint8_t rec_good[] = { 0x88, 0xAA, 0xBB, 0x88 };//前四字节 if (rt_memcmp(recv_data, rec_good, 4)) { ret = RT_EOK; /* 释放接收缓冲 */ rt_free(recv_data); break; } } else { LOG_E("received error."); /* 释放接收缓冲 */ rt_free(recv_data); break; } rt_thread_delay(100); } return ret; } /** * 发送一维数组 * @param msg 待发数据 * @param len 数组长度 * @return 成功返回0 */ int sendMsg(const rt_uint8_t *msg, size_t len) { if (tcpSend(msg, len) != RT_EOK) { // tcpClose(); return RT_ERROR; } //#define CHK_ACK #ifdef CHK_ACK if (tcpAck() != RT_EOK) { return RT_ERROR; // break; }; #endif // return RT_EOK; //已发送数据存入log文件 // char str[600]; // bytes2str(msg, len, 16, " ", str); // trDataTolog(str, strlen(str), 1); trDataTolog(msg, len, 1); return RT_EOK; } /** * 发送二维数组 * @param msg 待发二维数组 * @param s 各纬度数组长度 * @param row 数组长度 * @return 成功返回0 */ int sendMsgs(const rt_uint8_t (*msg)[200], char *s, size_t row) { int ret = RT_EOK; if (tcpInit() != RT_EOK) { ret = RT_ERROR; return ret; } for (size_t var = 0; var < row; var++) { if (tcpSend(msg[var], s[row]) != RT_EOK) { ret = RT_ERROR; break; } #ifdef CHK_ACK if (tcpAck() != RT_EOK) { ret = RT_ERROR; break; }; #endif } tcpClose(); return ret; }