图55.3.1.1 程序流程图
55.3.2 程序解析
在本章节中,我们主要关注两个文件:lwip_demo.c和lwip_demo.h。lwip_demo.h文件主要定义了阿里云提供的三元组内容和计算得出的MQTT参数,这部分内容请参考阿里云提供的手册 “如何计算MQTT签名参数”章节,所以作者暂不详细解释。主要关注点是lwip_demo.c文件中的函数。在lwip_demo函数中,我们配置了相关的MQTT参数,并创建了一个名为mqtt_event_handler的事件回调函数。这个事件回调函数通过获取MQTT事件ID来处理连接过程中所需的操作。接下来,我们将分别详细解释lwip_demo函数和mqtt_event_handler事件回调函数。
/**
* @retval 无
*/
void lwip_demo(void)
{
char mqtt_publish_data[] = "alientek esp32-s3";
/* 设置客户端的信息量 */
esp_mqtt_client_config_t mqtt_cfg = {
.broker.address.hostname = HOST_NAME, /* MQTT地址 */
.broker.address.port = HOST_PORT, /* MQTT端口号 */
.broker.address.transport = MQTT_TRANSPORT_OVER_TCP, /* TCP模式 */
.credentials.client_id = CLIENT_ID, /* 设备名称 */
.credentials.username = (char*)USER_NAME, /* 产品ID */
.credentials.authentication.password = PASSWORD, /* 计算出来的密码 */
};
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID,
mqtt_event_handler, NULL);
esp_mqtt_client_start(client);
while(1)
{
if (g_publish_flag == 1)
{
esp_mqtt_client_publish(client,DEVICE_PUBLISH,
(char *)mqtt_publish_data,strlen(mqtt_publish_data),1,0);
}
vTaskDelay(1000);
}
}
这个函数主要负责MQTT的连接配置。它首先创建了一个MQTT控制块,用于存储配置参数以及发送和接收数据。接着,它定义了一个回调函数,用于处理和响应MQTT连接过程中的各种事件。最后,它启动MQTT并发送连接请求到服务器。一旦成功连接到MQTT服务器,它就可以开始循环发布数据。现在,让我们深入了解这个回调函数的工作原理。
/**
* @brief 错误日记
* @param message :错误消息
* @param error_code :错误码
* @retval 无
*/
static void log_error_if_nonzero(const char *message, int error_code)
{
if (error_code != 0)
{
ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
}
}
/**
* @brief 注册接收MQTT事件的事件处理程序
* @param handler_args:注册到事件的用户数据
* @param base :处理程序的事件库
* @param event_id :接收到的事件的id
* @param event_data :事件的数据
* @retval 无
*/
static void mqtt_event_handler(void *handler_args, esp_event_base_t base,
int32_t event_id, void *event_data)
{
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED: /* 连接事件 */
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
msg_id=esp_mqtt_client_publish(client,"/topic/qos1","data_3",0,1,0);
ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1);
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);
g_publish_flag = 1;
/* 订阅主题 */
msg_id = esp_mqtt_client_subscribe(client, DEVICE_SUBSCRIBE, 0);
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
break;
case MQTT_EVENT_DISCONNECTED: /* 断开连接事件 */
break;
case MQTT_EVENT_SUBSCRIBED: /* 订阅事件 */
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
msg_id=esp_mqtt_client_publish(client,"/topic/qos0","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: /* 发布事件 */
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA: /* 接收数据事件 */
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:
if (event->error_handle->error_type
== MQTT_ERROR_TYPE_TCP_TRANSPORT)
{
log_error_if_nonzero("reported from esp-tls",
event->error_handle->esp_tls_last_esp_err);
log_error_if_nonzero("reported from tls stack",
event->error_handle->esp_tls_stack_err);
log_error_if_nonzero("captured as transport's socket errno",
event->error_handle->esp_transport_sock_errno);
ESP_LOGI(TAG, "Last errno string (%s)",
strerror(event->error_handle->esp_transport_sock_errno));
}
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
}
在这个回调函数中,主要处理与MQTT的交互过程。当系统接收到MQTT服务器的连接应答时,它会发送订阅主题报文。当系统接收到MQTT服务器的订阅应答报文时,它会发布一个订阅完成报文。因此,每个状态事件都需要读者根据项目需求进行相应的修改。
55.4 下载验证
程序下载成功后,打开阿里云平台的物联网平台设备管理,可以看到此时的设备处于连接状态,如下图所示。
图55.4.1 设备处于连接
MQTT连接成功后,可在日记服务中找到ESP32-S3设备发布的数据,如下图所示。
图55.4.2 设备发布的数据
我们可点击上图中的查看,可看到设备发布的消息内容,如下图所示。