一、ESP32的MQTT函数介绍
1、esp_mqtt_client_handle_t esp_mqtt_client_init(const esp_mqtt_client_config_t *config)
函数描述:根据配置创建MQTT客户端句柄
参数esp_mqtt_client_config_t的结构体如下
typedef struct {
mqtt_event_callback_t event_handle; / *!<处理MQTT事件作为传统模式的回调* /
esp_event_loop_handle_t event_loop_handle; / *! user_context`` * /中接收该上下文
int task_prio; / *!
返回值:MQTT句柄 错误的时候返回NULL
使用举例:
esp_mqtt_client_config_t mqtt_cfg = {
.host = "192.168.43.95", //MQTT 地址
.port = 1883, //MQTT端口
.username = "admin",//用户名字
.password = "public",//密码
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
2、sp_err_t esp_mqtt_client_start(esp_mqtt_client_handle_t client)
函数描述:启动MQTT客户端
参数:创建的MQTT句柄
返回值:ESP_OK表示成功ESP_ERR_无效_ARG错误初始化ESP_FERT其他错误
3、esp_err_t esp_mqtt_client_stop(esp_mqtt_client_handle_t client)
函数描述:停止MQTT客户端
参数:创建的MQTT句柄
4、int esp_mqtt_client_subscribe(esp_mqtt_client_handle_t client, const char *topic, int qos)
函数描述:订阅主题
参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄
B、char *topic 订阅的主题
C、Qos级别 0 、1、 2
返回值:成功时订阅消息返回Message_id- 失败返回-1
5、int esp_mqtt_client_unsubscribe(esp_mqtt_client_handle_t client, const char *topic)
函数描述:取消订阅的主题
参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄
B、B、char *topic 订阅的主题
返回值:成功时订阅消息返回Message_id- 失败返回-1
6、int esp_mqtt_client_publish(esp_mqtt_client_handle_t client, const char *topic, const char *data, int len, int qos, int retain)
函数描述:往代理发布消息
参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄
B、char *topic 发布的主题
C、 const char *data 发布的数据
D、int len 数据长度,如果设置为0,则从发布的数据长度
E、Qos级别
F、retain 当我们使用MQTT客户端发布消息(PUBLISH
)时,如果将RETAIN标志位设置为true
,那么MQTT服务器会将最近收到的一条RETAIN标志位为true
的消息保存在服务器端
7、esp_err_t esp_mqtt_client_register_event(esp_mqtt_client_handle_t client, esp_mqtt_event_id_t event, esp_event_handler_t event_handler, void* event_handler_arg)
函数描述:注册MQTT事件
参数:A、esp_mqtt_client_handle_t client 创建的MQTT句柄
B、esp_mqtt_event_id_t event 注册任何事件id的处理程序
C、esp_event_handler_t event_handler 回调函数
D、void* event_handler_arg 处理程序上下文
二、实验内容
1、初始化wifi,并连接wifi
2、初始化MQTT,连接成功发布、订阅主题
1、初始化wifi,并连接wifi
static EventGroupHandle_t wifi_event_group;
/* The event group allows multiple bits for each event,
but we only care about one event - are we connected
to the AP with an IP? */
const int CONNECTED_BIT = BIT0;
//wifi 事件
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch (event->event_id) {
case SYSTEM_EVENT_STA_START:
esp_wifi_connect();
break;
case SYSTEM_EVENT_STA_GOT_IP:
//Mqtt_init();
xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
break;
case SYSTEM_EVENT_STA_DISCONNECTED:
/* This is a workaround as ESP32 WiFi libs don't currently
auto-reassociate. */
esp_wifi_connect();
xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
break;
default:
break;
}
return ESP_OK;
}
//初始化wifi
void app_wifi_initialise(void)
{
tcpip_adapter_init();
wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_event_loop_init(event_handler, NULL));
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
wifi_config_t wifi_config = {
.sta = {
.ssid = "tplingk",
.password = "12345678",
},
};
ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", wifi_config.sta.ssid);
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
}
//等待wifi成功连接
void app_wifi_wait_connected()
{
xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT, false, true, portMAX_DELAY);
}
上面就是初始化wifi ,并且连接wifi.在wifi连接成功里面设置事件标志
2、初始化MQTT,连接成功发布、订阅主题
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
{
esp_mqtt_client_handle_t client = event->client;
int msg_id;
// your_context_t *context = event->context;
switch (event->event_id) {
case MQTT_EVENT_CONNECTED://连接MQTT成功
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id = esp_mqtt_client_publish(client, "/World", "data_3", 0, 1, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic1", 1);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic1", 2);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
//msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1");
//ESP_LOGI(TAG, "sent unsubscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED://断开MQTT
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED://订阅成功
printf("_---------订阅--------\n");
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
msg_id = esp_mqtt_client_publish(client, "/World", "data", 0, 0, 0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED://取消订阅
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED://发布成功
printf("_--------发布----------\n");
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA://数据接收
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("主题长度:%d 数据长度:%d\n",event->topic_len,event->data_len);
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
break;
case MQTT_EVENT_ERROR://MQTT错误
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
return ESP_OK;
}
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
mqtt_event_handler_cb(event_data);
}
static void mqtt_app_start(void)
{
printf("\n______________等待wifi连接____________\n");
app_wifi_wait_connected();
vTaskDelay(5000 / portTICK_PERIOD_MS);
printf("\n______________wifi连接成功____________\n");
esp_mqtt_client_config_t mqtt_cfg = {
.host = "192.168.43.95",//MQTT 地址
.port = 1883, //MQTT端口
.username = "admin",//用户名
.password = "public",//密码
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);//初始化MQTT
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, client);//注册事件
esp_mqtt_client_start(client);//启动mQTT
while(1){
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
在连接成功MQTT之后,发布一个消息,订阅三个消息如下
msg_id = esp_mqtt_client_publish(client, "/World", "data_3", 0, 1, 0);
msg_id = esp_mqtt_client_subscribe(client, "/topic0", 0);
msg_id = esp_mqtt_client_subscribe(client, "/topic1", 1);
msg_id = esp_mqtt_client_subscribe(client, "/topic1", 2);
三、实验结果
连接的是本地搭建的MQTT服务器emqttd,网上很多教程。
连接成功之后就可以在里面看到,ESP32_050F44就是连接成功的设备
发布和订阅的主题
发布和订阅消息
串口打印的数据