【stm32片外外设】esp8266的mqtt通信

【stm32片外外设】esp8266的mqtt通信


2024年8月12日

参考一家4G模块公司写的mqtt通信代码,写的一个esp8266的mqtt通信的代码。

介绍啥的就没写了,代码有简单的解释,先发布混混阅读点赞,哈哈哈哈,后面有时间再补。

参考代码

bsp_esp8266.h

/**
 * author:	临木木
 * date:	2024年8月12日
 * 适用于stm32裸机的esp8266的mqtt通信驱动
 * 依赖文件:
 *			#include "./usart/bsp_usart.h"				// 串口
 *			#include "./soft_timer/bsp_soft_timer.h"	// 软件定时器
 *			#include "./cjson/cJSON.h"					// cjson
 * 
 * bsp_esp8266_work()置于主循环内,即可按默认的顺序循环发送信息
 * 可使用以下函数进行有限配置修改
 * bsp_esp8266_wifi_disposition_set()/bsp_esp8266_broker_disposition_set()/bsp_esp8266_publish_data_set()
 */
#ifndef __BSP_ESP8266_H__
#define __BSP_ESP8266_H__


#define DEBUG_HUART						huart1			
#define WIFI_HUART						huart2
#define WIFI_BSP_HUART					BSP_USART_2
#define WIFI_SOFT_TIMER_ID				1
#define WIFI_SOFT_TIMER_ID_2			2


#define ESP8266_POWER_ON_WAIT_TIME 		4000 													/* 开机等待时间 */
#define RST_GPIO_SET_HIGH  				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET)		/* RST复位引脚设置为高电平 */
#define RST_GPIO_SET_LOW   				HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET) 	/* RST复位引脚设置为低电平 */	

/* esp8266用户属性 */
#define MQTT_USER_ID					"client_1"
#define MQTT_USER_NAME					"lin"
#define MQTT_USER_PASSWORD				"12345678"

#define MQTT_SUBSCRIBE_TOPIC			"oo"		/* 订阅主题 */

#define MQTT_PUBLISH_TOPIC				"hello"		/* 发布主题 */

	
int bsp_esp8266_work
	(
	void
	);
	
int bsp_esp8266_wifi_disposition_set
	(
	char 			name[],
	unsigned int 	len_name,
	char 			password[],
	unsigned int 	len_password
	);
	
int bsp_esp8266_broker_disposition_set
	(
	char 			ip[],
	unsigned int 	len_ip,
	char 			port[],
	unsigned int 	len_port
	);
	
int bsp_esp8266_publish_data_set
	(
	char 			data[],
	unsigned int 	len_data
	);
	

#endif

bsp_esp8266.c

#include "./esp8266/bsp_esp8266.h"

#include <string.h>
#include <stdio.h>

#include "gpio.h"
#include "usart.h"

#include "./usart/bsp_usart.h"
#include "./soft_timer/bsp_soft_timer.h"
#include "./cjson/cJSON.h"


#define ESP8266_RECIVE_BUF_SIZE		1024

/* esp8266状态 */
typedef enum ESP8266_STATE
{
	ESP8266_RESET 			= 0,
	ESP8266_SHAKE_HANDS		= 1,
	ESP8266_WIFI_CONNECT	= 2,
	ESP8266_MQTT_INIT		= 3,
	ESP8266_COMMUNICATION	= 4,
	ESP8266_OK				= 0xFE,
	ESP8266_ERROR			= 0xFF
} ESP8266_STATE;


static int 	esp8266_state = 0;
static char esp8266_wifi_name[48] 		= "1315";
static char esp8266_wifi_password[48] 	= "shd13151315";
static char mqtt_broker_ip[16] 			= "192.168.1.100";
static char mqtt_broker_port[8] 		= "1883";
static char esp8266_publish_data[256]	= "hello";

static int recive_len = 0;
static unsigned char recive_buf[ESP8266_RECIVE_BUF_SIZE];

static cJSON *cjson_test	= NULL;
static cJSON *cjson_name	= NULL;
static cJSON *cjson_age		= NULL;


/* bsp_esp8266_at_cmd:esp8266发送at指令
 * cmd			at指令
 * delay		等待指令回复的时间
 * return		到达等待时间返回1,否则返回0 */
int bsp_esp8266_at_cmd
	(
	const char 		*cmd,
	unsigned int 	delay
	)
{
	if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_STOPPED)
	{
		bsp_soft_timer_start(WIFI_SOFT_TIMER_ID, SOFT_TIMER_MODE_ONE_SHOT, delay, bsp_soft_timer_nop_callback, NULL, 0);
		HAL_UART_Transmit(&DEBUG_HUART, (const unsigned char*)cmd, (unsigned short int)strlen(cmd), 1000);
		HAL_UART_Transmit(&WIFI_HUART, (const unsigned char*)cmd, (unsigned short int)strlen(cmd), delay);
	}
	
	if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_TIMEOUT)
	{
		return 1;
	}
	
	return 0;
}


/* bsp_esp8266_keyword_matching:应答字符关键字校验
 * keyword		关键字 
 * return		包含关键字返回1,否则返回0 */
int bsp_esp8266_keyword_matching
	(
	char 			*keyword
	)
{
	recive_len = bsp_usart_get(recive_buf, WIFI_BSP_HUART);
	
	if (recive_len != -1)
	{	
		HAL_UART_Transmit(&DEBUG_HUART, recive_buf, recive_len, 1000);
		/* bsp_usart_get()函数的传递方式 */
		recive_buf[recive_len] = '\0';		
		if (strstr((const char*)recive_buf, keyword) != NULL)
		{
			return 1;
		}
		else
		{
			return 0;
		}
	}
	else
	{
	}
	
	return -1;
}


/* bsp_esp8266_reset:esp8266复位操作
 * return		成功返回1,正在复位返回0 */
int bsp_esp8266_reset
	(
	void
	)
{
	static unsigned char state = 0;
	
	switch (state)
	{
		case 0x00:
			state++;
			RST_GPIO_SET_HIGH;
			break;
		
		case 0x01:
			state++;
			RST_GPIO_SET_LOW;
			break;
		
		case 0x02:
			if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_STOPPED)
			{
				bsp_soft_timer_start(WIFI_SOFT_TIMER_ID, SOFT_TIMER_MODE_ONE_SHOT, 1000, bsp_soft_timer_nop_callback, NULL, 0);
			}
			
			if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_TIMEOUT)
			{
				state++;
				RST_GPIO_SET_HIGH;
			}
			break;
			
		case 0x03:
			if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_STOPPED)
			{
				bsp_soft_timer_start(WIFI_SOFT_TIMER_ID, SOFT_TIMER_MODE_ONE_SHOT, ESP8266_POWER_ON_WAIT_TIME, bsp_soft_timer_nop_callback, NULL, 0);
			}
			
			if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_TIMEOUT)
			{
				state = 0x00;
				return 1;
			}
			break;
	}
	
	return 0;
}


/* bsp_esp8266_shake_hands:esp8266握手操作
 * return		成功返回ESP8266_OK,正在握手返回0,错误返回ESP8266_ERROR */
int bsp_esp8266_shake_hands
	(
	void
	)
{
	static unsigned char state = 0;
	static unsigned char error_times = 0;

	switch (state)
	{
		case 0x00:
			if (bsp_esp8266_at_cmd("AT\r\n", 1000) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state = ESP8266_OK;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT");
				}
				else
				{
					/* 三次以上错误,进入复位 */
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
						printf("esp8266: %s ==> ERROR\r\n", "AT");
					}
				}
			}
			break;
			
		case ESP8266_ERROR:
			state = 0x00;
			error_times = 0;
			return ESP8266_ERROR;
		
		case ESP8266_OK:
			state = 0x00;
			return ESP8266_OK;
	}
	
	return 0;
}


/* bsp_esp8266_wifi_connect:esp8266上网操作
 * return		成功返回ESP8266_OK,正在握手返回0,错误返回ESP8266_ERROR */
int bsp_esp8266_wifi_connect
	(
	void
	)
{
	static unsigned char state = 0;
	static unsigned char error_times = 0;
	
	char tmp_buf[1024];

	switch (state)
	{
		case 0x00:
			/* 关闭回显 */
			if (bsp_esp8266_at_cmd("ATE0\r\n", 500) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state++;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "ATE0");
				}
				else
				{
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
						printf("esp8266: %s ==> ERROR\r\n", "ATE0");
					}
				}
			}
			break;
		
		case 0x01:
			/* 设置esp8266为station模式 */
			if (bsp_esp8266_at_cmd("AT+CWMODE=1,0\r\n", 500) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state++;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT+CWMODE=1,0");
				}
				else
				{
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
						printf("esp8266: %s ==> ERROR\r\n", "AT+CWMODE=1,0");
					}
				}
			}
			break;
			
		case 0x02:
			/* 连接wifi */
			sprintf(tmp_buf, "AT+CWJAP=\"%s\",\"%s\"\r\n", esp8266_wifi_name, esp8266_wifi_password);
			if (bsp_esp8266_at_cmd(tmp_buf, 4000) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state = ESP8266_OK;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT+CWJAP");
				}
				else
				{
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
						printf("esp8266: %s ==> ERROR\r\n", "AT+CWJAP");
					}
				}
			}
			break;
			
		case ESP8266_ERROR:
			state = 0x00;
			error_times = 0;
			return ESP8266_ERROR;
		
		case ESP8266_OK:
			state = 0x00;
			return ESP8266_OK;
	}
	
	return 0;
}


/* bsp_esp8266_mqtt_init:esp8266 mqtt通信初始化操作
 * return		成功返回ESP8266_OK,正在握手返回0,错误返回ESP8266_ERROR */
int bsp_esp8266_mqtt_init
	(
	void
	)
{
	static unsigned char state = 0;
	static unsigned char error_times = 0;
	
	char tmp_buf[1024];
	
	switch (state)
	{
		case 0x00:
			/* 设置esp8266 mqtt用户属性 */
			sprintf(tmp_buf, "AT+MQTTUSERCFG=0,1,\"%s\",\"%s\",\"%s\",0,0,\"\"\r\n", MQTT_USER_ID, MQTT_USER_NAME, MQTT_USER_PASSWORD);
			if (bsp_esp8266_at_cmd(tmp_buf, 1000) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state++;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT+MQTTUSERCFG");
				}
				else
				{
					printf("esp8266: %s ==> ERROR\r\n", "AT+MQTTUSERCFG");
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
					}
				}
			}
			break;
		
		case 0x01:
			/* 连接mqtt服务器 */
			sprintf(tmp_buf, "AT+MQTTCONN=0,\"%s\",%s,0\r\n", mqtt_broker_ip, mqtt_broker_port);
			if (bsp_esp8266_at_cmd(tmp_buf, 2000) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state++;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT+MQTTCONN");
				}
				else
				{
					printf("esp8266: %s ==> ERROR\r\n", "AT+MQTTCONN");
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
					}
				}
			}
			break;
			
		case 0x02:
			/* 订阅mqtt主题 */
			sprintf(tmp_buf, "AT+MQTTSUB=0,\"%s\",0\r\n", MQTT_SUBSCRIBE_TOPIC);
			if (bsp_esp8266_at_cmd(tmp_buf, 1000) == 1)
			{
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					state = ESP8266_OK;
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT+MQTTSUB");
				}
				else
				{
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
						printf("esp8266: %s ==> ERROR\r\n", "AT+MQTTSUB");
					}
				}
			}
			break;
		
		case ESP8266_ERROR:
			state = 0x00;
			error_times = 0;
			return ESP8266_ERROR;
		
		case ESP8266_OK:
			state = 0x00;
			return ESP8266_OK;
		
	}
	
	return 0;
}


/* bsp_esp8266_communication:esp8266 mqtt通信操作
 * send_time_interval	循环发送mqtt消息的时间间隔	
 * return 				成功返回ESP8266_OK,正在握手返回0,错误返回ESP8266_ERROR */
int bsp_esp8266_communication
	(
	unsigned int send_time_interval
	)
{
	static unsigned char state = 0x00;
	static unsigned char error_times = 0;
	static unsigned char recive_enable_flag = 1;
	
	static char *recive_topic;
	static int recive_data_len = 0;
	
	static char tmp_buf[512] = "AT+MQTTPUB=0,\"hello\",\"hello world\",1,0\r\n";
	static char tmp_buf_2[256] = "";
	
	static unsigned int count = 0;
	
	switch (state)
	{
		/* 发送消息 */
		case 0x00:
			state++;
		
			if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID) == SOFT_TIMER_STOPPED)
			{
				bsp_soft_timer_start(WIFI_SOFT_TIMER_ID, SOFT_TIMER_MODE_ONE_SHOT, send_time_interval, bsp_soft_timer_nop_callback, NULL, 0);
				
				sprintf(esp8266_publish_data, "count: %d", count++);
				sprintf(tmp_buf, "AT+MQTTPUB=0,\"%s\",\"%s\",1,0\r\n", MQTT_PUBLISH_TOPIC, esp8266_publish_data);
				HAL_UART_Transmit(&WIFI_HUART, (const unsigned char*)tmp_buf, (unsigned short int)strlen(tmp_buf), send_time_interval);
				HAL_UART_Transmit(&DEBUG_HUART, (const unsigned char*)tmp_buf, (unsigned short int)strlen(tmp_buf), 1000);
			
				bsp_soft_timer_start(WIFI_SOFT_TIMER_ID_2, SOFT_TIMER_MODE_ONE_SHOT, 50, bsp_soft_timer_nop_callback, NULL, 0);
				recive_enable_flag = 0;
			}
			
			if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID_2) == SOFT_TIMER_TIMEOUT)
			{				
				if (bsp_esp8266_keyword_matching("OK") == 1)
				{
					error_times = 0;
					printf("esp8266: %s ==> OK\r\n", "AT+MQTTPUB");
				}
				else
				{
					printf("esp8266: %s ==> ERROR\r\n", "AT+MQTTPUB");
					if (++error_times > 3)
					{
						state = ESP8266_ERROR;
					}
				}
				
				recive_enable_flag = 1;
			}
			break;
		
		/* 接收消息 */
		case 0x01:
			state--;
		
			if (recive_enable_flag == 1)
			{
				recive_len = bsp_usart_get(recive_buf, WIFI_BSP_HUART);
				if (recive_len != -1)
				{	
					recive_topic = strstr((const char*)recive_buf, MQTT_SUBSCRIBE_TOPIC);
					if (recive_topic == NULL)
					{
						printf("esp8266: %s ==> ERROR\r\n", "json parse_1");
						return 0;
					}
					sscanf((const char*)recive_topic + strlen(MQTT_SUBSCRIBE_TOPIC) + 2, "%d,%s", &recive_data_len, tmp_buf_2);
					
					cjson_test = cJSON_Parse((const char*)tmp_buf_2);
					if(cjson_test == NULL)
					{
						HAL_UART_Transmit(&DEBUG_HUART, recive_buf, recive_len, 1000);
						printf("esp8266: %s ==> ERROR\r\n", "json parse_2");
						return 0;
					}
					
					cjson_name = cJSON_GetObjectItem(cjson_test, "name");
					cjson_age  = cJSON_GetObjectItem(cjson_test, "age");
					
					printf("name: %s\r\n", cjson_name->valuestring);
					printf("age: %d\r\n", cjson_age->valueint);
				}
			}
			/* 软件定时器的状态刷新时,会遇到的bug,所以这里这样设计 */
			else
			{
				if (bsp_soft_timer_state_get(WIFI_SOFT_TIMER_ID_2) == SOFT_TIMER_TIMEOUT)
				{
					if (bsp_esp8266_keyword_matching("OK") == 1)
					{
						error_times = 0;
						printf("esp8266: %s ==> OK\r\n", "AT+MQTTPUB");
					}
					else
					{
						printf("esp8266: %s ==> ERROR\r\n", "AT+MQTTPUB");
						if (++error_times > 3)
						{
							state = ESP8266_ERROR;
						}
					}
					
					recive_enable_flag = 1;
				}
			}
			break;
		
		case ESP8266_ERROR:
			error_times = 0;
			state = 0x00;
			return ESP8266_ERROR;
	}
	
	return 0;
}


/* bsp_esp8266_work:esp8266工作函数
 * return 		返回esp8266当前工作状态 */
int bsp_esp8266_work
	(
	void
	)
{	
	int ret = 0;
	
	switch (esp8266_state)
	{
		/* 复位 */
		case ESP8266_RESET:
			if (bsp_esp8266_reset() == 1)		
			{
				esp8266_state = ESP8266_SHAKE_HANDS;
				recive_len = bsp_usart_get(recive_buf, WIFI_BSP_HUART);
				if (recive_len != -1)
				{	
					HAL_UART_Transmit(&DEBUG_HUART, recive_buf, recive_len, 1000);
					recive_buf[recive_len] = '\0';
				}
				printf("esp8266: %s  ==> OK\r\n", "ESP8266_RESET");
			}
			break;
			
		/* 握手 */
		case ESP8266_SHAKE_HANDS:
			ret = bsp_esp8266_shake_hands();
			if (ret == ESP8266_OK)
			{
				esp8266_state = ESP8266_WIFI_CONNECT;
			}
			else if (ret == ESP8266_ERROR)
			{		
				esp8266_state = ESP8266_ERROR;
			}
			break;
		
		/* 上网 */
		case ESP8266_WIFI_CONNECT:
			ret = bsp_esp8266_wifi_connect();
			if (ret == ESP8266_OK)
			{
				esp8266_state = ESP8266_MQTT_INIT;
			}
			else if (ret == ESP8266_ERROR)
			{		
				esp8266_state = ESP8266_ERROR;
			}
			break;
			
		/* mqtt通信初始化 */
		case ESP8266_MQTT_INIT:
			ret = bsp_esp8266_mqtt_init();
			if (ret == ESP8266_OK)
			{
				esp8266_state = ESP8266_COMMUNICATION;
			}
			else if (ret == ESP8266_ERROR)
			{		
				esp8266_state = ESP8266_ERROR;
			}
			break;
		/* mqtt通信 */
		case ESP8266_COMMUNICATION:
			ret = bsp_esp8266_communication(3000);
			if (ret == ESP8266_ERROR)
			{
				esp8266_state = ESP8266_ERROR;
			}
			break;
		
		/* 错误跳转到复位 */
		case ESP8266_ERROR:
			esp8266_state = ESP8266_RESET;
			break;
		
		default:
			break;
	}
	
	return esp8266_state;
}


/* bsp_esp8266_wifi_disposition_set:esp8266设置连接WiFi名称及密码函数
 * name 			wifi名称
 * len_name			wifi名称长度 
 * password			wifi密码
 * len_password		wifi密码长度 */
int bsp_esp8266_wifi_disposition_set
	(
	char 			name[],
	unsigned int 	len_name,
	char 			password[],
	unsigned int 	len_password
	)
{
	memset(esp8266_wifi_name, '\0', 48);
	memset(esp8266_wifi_password, '\0', 48);
	strncpy(esp8266_wifi_name, name, len_name); 
	strncpy(esp8266_wifi_password, password, len_password); 
	
	esp8266_state = ESP8266_RESET;
	
	return 0;
}


/* bsp_esp8266_broker_disposition_set:esp8266设置连接mqtt服务器ip及端口函数
 * ip 			mqtt服务器ip
 * len_ip		mqtt服务器ip长度 
 * port			mqtt服务器端口
 * len_port		mqtt服务器端口长度 */
int bsp_esp8266_broker_disposition_set
	(
	char 			ip[],
	unsigned int 	len_ip,
	char 			port[],
	unsigned int 	len_port
	)
{
	memset(mqtt_broker_ip, '\0', 16);
	memset(mqtt_broker_port, '\0', 8);
	strncpy(mqtt_broker_ip, ip, len_ip); 
	strncpy(mqtt_broker_port, port, len_port); 
	
	esp8266_state = ESP8266_RESET;
	
	return 0;
}


/* bsp_esp8266_publish_data_set:esp8266设置发送的mqtt消息函数
 * data 		mqtt消息
 * len_data		mqtt消息长度 */
int bsp_esp8266_publish_data_set
	(
	char 			data[],
	unsigned int 	len_data
	)
{
	memset(esp8266_publish_data, '\0', 256);
	strncpy(esp8266_publish_data, data, len_data); 
	
	return 0;
}
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值