返回列表 发新帖我要提问本帖赏金: 20.00元(功能说明)

[应用方案] APM32实现MQTT通信(二)_实现ESP8266模块的socket接口函数,以提供MQTTClient库底层数据收发接口

[复制链接]
 楼主| luobeihai 发表于 2024-12-12 00:31 | 显示全部楼层 |阅读模式
<

#申请原创# @21小跑堂

上一篇文章(https://bbs.21ic.com/icview-3420436-1-1.html),我们已经移植好了MQTTClient源码,这篇文件将介绍实现MQTTClient源码,基于ESP8266模块的Socket函数接口,从而提供底层的数据收发接口给MQTTClient库。

1. 需要实现哪些函数

MQTTClient库我使用的是 jiejie 写的,GitHub 仓库:https://github.com/jiejieTop/mqttclient

其中,里面有一个与平台相关的目录下,platform_net_socket.c 这个C文件里面的一些函数是需要实现,才能真的的去连接 MQTT 服务器、收发数据等。

image-20241212002524129.png

打开这个文件,里面已经使用了 LwIP 的接口实现了这些函数了,但是我这里是需要使用 ESP8266 WIFI 模块进行网络连接,数据收发等功能,所以我需要使用 ESP8266 的来实现这些平台 socket 相关的接口函数。

实现的代码中,是依赖前面写的 AT 命令收发解析器的代码的,《APM32F407+FreeRTOS实现AT模块的命令解析器》这篇文件中有介绍,链接:https://bbs.21ic.com/icview-3418740-1-1.html

这个文件里面定义了有8个函数,但实际其实只要实现4个函数即可,分别是:socket 连接、数据收发、socket 关闭这四个函数,如下:

  1. int platform_net_socket_connect(const char *host, const char *port, int proto)
  2. {
  3.     return 0;
  4. }

  5. int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
  6. {
  7.     return 0;
  8. }

  9. int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
  10. {
  11.     return 0;
  12. }

  13. int platform_net_socket_close(int fd)
  14. {
  15.     return 0;
  16. }

2. 各个函数的具体实现

把实现的代码单独写为一个C文件,at_socket_esp8266.c ,然后按照上面 mqtt 平台相关的那4个函数类型,实现4个与 esp8266 模块的 socket 函数,从而给上面的平台网络层代码调用。

2.1 网络连接函数

  1. int esp8266_socket_connect(const char *host, const char *port, int proto)
  2. {
  3.         int result = 0;
  4.         char cmd[64] = {0};
  5.         unsigned char retry_num = 5;

  6.         esp8266_init();
  7.        
  8.         while (retry_num--)
  9.         {
  10.                 /* disconnect to WiFi AP */
  11.                 result = at_exce_cmd("AT+CWQAP", NULL, 1000);
  12.                 if (result)
  13.                 {
  14.                         printf("disconnect WiFi AP fail, status %d\r\n", result);
  15.                         continue;
  16.                 }
  17.                
  18.                 /* send AT commands to connect to WiFi AP */
  19.                 /* 命令格式:AT+CWJAP="SSID","password" */
  20.                 result = at_exce_cmd("AT+CWJAP="" ESP8266_WIFI_SSID "","" ESP8266_WIFI_PASSWORD """, NULL, 10*1000);
  21.                 if (result)
  22.                 {
  23.                         printf("esp8266 device connect to WiFi AP fail, check ssid(%s) and password(%s).\r\n", ESP8266_WIFI_SSID, ESP8266_WIFI_PASSWORD);
  24.                         continue;
  25.                 }

  26.                 /* send AT commands to connect to server  */
  27.                 /* 命令格式:AT+CIPSTART="TCP","192.168.3.116",8080 */
  28.                 switch (proto)
  29.         {
  30.                 case PLATFORM_NET_PROTO_TCP:
  31.                                 sprintf(cmd, "AT+CIPSTART="TCP","%s",%s", host, port);
  32.                     break;

  33.                 case PLATFORM_NET_PROTO_UDP:
  34.                                 sprintf(cmd, "AT+CIPSTART="UDP","%s",%s", host, port);
  35.                     break;

  36.                 default:
  37.                     printf("not supported socket connect type %d.\r\n", proto);
  38.                     goto __exit;
  39.         }
  40.                                
  41.                 result = at_exce_cmd(cmd, NULL, 5*1000);
  42.                 if (result == AT_RESP_OK)
  43.                 {
  44.                         break;
  45.                 }
  46.                 else
  47.                 {
  48.                         printf("esp8266 device socket connect fail, the socket was not be closed and now will connect retry.\r\n");
  49.                         at_exce_cmd("AT+CIPCLOSE", NULL, 300);
  50.                         continue;
  51.                 }
  52.         }

  53. __exit:
  54.     return result;
  55. }


2.2 网络数据接收

  1. int esp8266_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
  2. {
  3.         int result = 0;
  4.         char ch = 0;
  5.         unsigned int read_index = 0;

  6.        
  7.         for (read_index = 0; read_index < len; read_index++)
  8.         {
  9.                 result = at_client_recvchar(&ch, timeout);
  10.                 if (result)
  11.                 {               
  12.                         //printf("esp8266 socket receive fail, return status %d.\r\n", result);
  13.                         return result;
  14.                 }
  15.                 buf[read_index] = ch;
  16.         }

  17.     return read_index;
  18. }


2.3 网络数据发送

  1. int esp8266_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
  2. {
  3.         int result = 0;
  4.         unsigned int cur_package_size = 0, send_size = 0;
  5.         char cmd[32] = {0};
  6.                
  7.         while (send_size < len)
  8.         {
  9.                 /* 超过最大长度,分包 */
  10.                 if (len - send_size < ESP8266_MODULE_SEND_MAX_SIZE)
  11.                 {
  12.                         cur_package_size = len - send_size;
  13.                 }
  14.                 else
  15.                 {
  16.                         cur_package_size = ESP8266_MODULE_SEND_MAX_SIZE;
  17.                 }

  18.                 /* 发送 AT+CIPSEND=7 命令,等待回复 '>' 这个字符( 测试发现回复的是 "OK\r\n>" ) */
  19.                 /* 如果断开了和服务器的网络连接之后,调用此命令回复的是:      "link is not valid\r\nERROR" */
  20.                 sprintf(cmd, "AT+CIPSEND=%d", cur_package_size);
  21.                 result = at_exce_cmd(cmd, NULL, timeout);
  22.                 if (result)
  23.                 {
  24.                         printf("send cmd(%s) error or timeout.\r\n", cmd);
  25.                         return result;
  26.                 }

  27.                 /* 发送真正数据,回复 Recv n bytes\r\nSEND OK\r\n 说明发送成功 */
  28.                 result = at_client_senddata((char *)buf + send_size, cur_package_size, timeout);
  29.                 if (result)
  30.                 {
  31.                         printf("send data fali or timeout, return status %d.\r\n", result);
  32.                         return result;
  33.                 }

  34.                 send_size += cur_package_size;
  35.         }
  36.        
  37.     return result ? result : send_size;
  38. }


2.4 网络断开连接

  1. int esp8266_socket_close(int fd)
  2. {
  3.         int result = 0;

  4.         result = at_exce_cmd("AT+CIPCLOSE", NULL, 300);
  5.        
  6.     return result;
  7. }





打赏榜单

21小跑堂 打赏了 20.00 元 2024-12-18
理由:恭喜通过原创审核!期待您更多的原创作品~~

评论

ESP8266 实现socket 相关的接口函数。为MQTTClient库底层数据收发提供接口。  发表于 2024-12-18 17:49
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

101

帖子

4

粉丝
快速回复 在线客服 返回列表 返回顶部