【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;
}