实现ESP8266模块的socket接口,以提供MQTTClient库底层数据收发接口

1. 需要实现哪些函数

MQTTClient库我使用的是 jiejie 写的,GitHub 仓库:

https://github.com/jiejieTop/mqttclient

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

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

实现的代码中,是依赖前面写的 AT 命令收发解析器的代码的,这篇文章有介绍《基于FreeRTOS编写ESP8266的AT命令收发解析器》

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

int platform_net_socket_connect(const char *host, const char *port, int proto)
{
    return 0;
}

int platform_net_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
{
    return 0;
}

int platform_net_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
{
    return 0;
}

int platform_net_socket_close(int fd)
{
    return 0;
}

2. 各个函数的具体实现

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

2.1 网络连接函数

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

	esp8266_init();
	
	while (retry_num--)
	{
		/* disconnect to WiFi AP */
		result = at_exce_cmd("AT+CWQAP", NULL, 1000);
		if (result)
		{
			printf("disconnect WiFi AP fail, status %d\r\n", result);
			continue;
		}
		
		/* send AT commands to connect to WiFi AP */
		/* 命令格式:AT+CWJAP="SSID","password" */
		result = at_exce_cmd("AT+CWJAP=\"" ESP8266_WIFI_SSID "\",\"" ESP8266_WIFI_PASSWORD "\"", NULL, 10*1000);
		if (result)
		{
			printf("esp8266 device connect to WiFi AP fail, check ssid(%s) and password(%s).\r\n", ESP8266_WIFI_SSID, ESP8266_WIFI_PASSWORD);
			continue;
		}

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

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

	        default:
	            printf("not supported socket connect type %d.\r\n", proto);
	            goto __exit;
        }
				
		result = at_exce_cmd(cmd, NULL, 5*1000);
		if (result == AT_RESP_OK)
		{
			break;
		}
		else
		{
			printf("esp8266 device socket connect fail, the socket was not be closed and now will connect retry.\r\n");
			at_exce_cmd("AT+CIPCLOSE", NULL, 300);
			continue;
		}
	}

__exit:
    return result;
}

2.2 网络数据接收

int esp8266_socket_recv_timeout(int fd, unsigned char *buf, int len, int timeout)
{
	int result = 0;
	char ch = 0;
	unsigned int read_index = 0;

	
	for (read_index = 0; read_index < len; read_index++)
	{
		result = at_client_recvchar(&ch, timeout);
		if (result)
		{		
			//printf("esp8266 socket receive fail, return status %d.\r\n", result);
			return result;
		}
		buf[read_index] = ch;
	}

    return read_index;
}

2.3 网络数据发送

int esp8266_socket_write_timeout(int fd, unsigned char *buf, int len, int timeout)
{
	int result = 0;
	unsigned int cur_package_size = 0, send_size = 0;
	char cmd[32] = {0};
		
	while (send_size < len)
	{
		/* 超过最大长度,分包 */
		if (len - send_size < ESP8266_MODULE_SEND_MAX_SIZE)
		{
			cur_package_size = len - send_size;
		}
		else
		{
			cur_package_size = ESP8266_MODULE_SEND_MAX_SIZE;
		}

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

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

		send_size += cur_package_size;
	}
	
    return result ? result : send_size;
}

2.4 断开连接

int esp8266_socket_close(int fd)
{
	int result = 0;

	result = at_exce_cmd("AT+CIPCLOSE", NULL, 300);
	
    return result;
}

完整的工程代码可以去下面的链接下载。

https://download.csdn.net/download/luobeihai/86403607?spm=1001.2014.3001.5503

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用ESP8266来连接到Grbl控制器的串口,并将数据MQTT协议发送到云端。面是一个简单的示例代码,你参考: ```cpp #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <SoftwareSerial.h> // WiFi配置 const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; // MQTT配置 const char* mqtt_server = "mqtt_server_address"; const int mqtt_port = 1883; const char* mqtt_topic = "your_topic"; // Grbl串口配置 const int grbl_rx_pin = D1; // ESP8266的D1引脚作为RX const int grbl_tx_pin = D2; // ESP8266的D2引脚作为TX const int grbl_baudrate = 115200; WiFiClient espClient; PubSubClient client(espClient); SoftwareSerial grblSerial(grbl_rx_pin, grbl_tx_pin); // 使用SoftwareSerial创建软串口 void setup() { // 初始化串口和WiFi连接 Serial.begin(115200); grblSerial.begin(grbl_baudrate); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } // 连接到MQTT服务器 client.setServer(mqtt_server, mqtt_port); while (!client.connected()) { if (client.connect("ESP8266Client")) { Serial.println("Connected to MQTT server"); } else { Serial.print("Failed to connect to MQTT server, rc="); Serial.print(client.state()); Serial.println(" Retrying..."); delay(5000); } } } void loop() { // 读取Grbl串口数据 if (grblSerial.available()) { String grblData = grblSerial.readStringUntil('\n'); // 发布数据MQTT服务器 if (client.connected()) { client.publish(mqtt_topic, grblData.c_str()); } Serial.println(grblData); } // 保持MQTT连接 if (!client.connected()) { reconnect(); } client.loop(); } void reconnect() { while (!client.connected()) { Serial.print("Attempting MQTT connection..."); if (client.connect("ESP8266Client")) { Serial.println("Connected to MQTT server"); } else { Serial.print("Failed to connect to MQTT server, rc="); Serial.print(client.state()); Serial.println(" Retrying..."); delay(5000); } } } ``` 请注意,你需要将代码中的"your_SSID"和"your_PASSWORD"替换为你的WiFi网络的名称和密码,并将"mqtt_server_address"替换为你的MQTT服务器地址。另外,你还需要安装ESP8266WiFi、PubSubClient和SoftwareSerial,以便编译和上传代码到ESP8266开发板。 这是一个基本的示例,你可以根据自己的需求进行修改和扩展。希望能对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值