c语言之esp32之mqtt编程开发
static esp_mqtt_client_handle_t mqtt_clients[2] = { NULL, NULL };
static esp_mqtt_client_config_t m_mqtt_cfg[2] = { 0 };
static void mqtt_event_handler_ex(void* handler_args, esp_event_base_t base, int32_t event_id, void* event_data)
{
int link_id = 0;
if (handler_args)
link_id = *(int*)handler_args;
if (!(link_id == 1 || link_id == 2)) {
printf("link id error\r\n");
}
ESP_LOGD(TAG, "Event dispatched from event loop base=%s,event_id=%d,link_id:%d",
base, event_id, link_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
uint8_t respBuf[64] = { 0 };
int msg_id;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
{
free_mqtt_certificates();
memset(respBuf, 0, sizeof(respBuf));
snprintf((char*)respBuf, 64, "+MQTTCONNECTED:%d,%d,%d,\"%s\",%d,%d\r\n",
link_id, 4,
m_mqtt_cfg[link_id - 1].broker.address.transport, m_mqtt_cfg[link_id - 1].broker.address.hostname,
m_mqtt_cfg[link_id - 1].broker.address.port, !m_mqtt_cfg[link_id - 1].network.disable_auto_reconnect);
esp_at_port_write_data(respBuf, strlen((char*)respBuf));
}
break;
case MQTT_EVENT_DISCONNECTED:
free_mqtt_certificates();
snprintf((char*)respBuf, sizeof(respBuf), "+MQTTDISCONNECT:%d\r\n", link_id);
esp_at_port_write_data(respBuf, strlen((char*)respBuf));
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGE(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_UNSUBSCRIBED:
ESP_LOGE(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_PUBLISHED:
ESP_LOGE(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
break;
case MQTT_EVENT_DATA:
free_mqtt_certificates();
int link_id = 1; // 根据实际情况修改
// 计算需要的缓冲区大小(确保足够大)
int buffer_size = 50 + event->topic_len + event->data_len; // 预留额外空间
char* buffer = (char*)malloc(buffer_size);
if (!buffer) {
ESP_LOGE(TAG, "Failed to allocate buffer");
break;
}
// 按照 AT 指令格式拼接字符串
int len = snprintf(
buffer,
buffer_size,
"+MQTTSUBRECV:%d,\"%.*s\",%d,%.*s\r\n",
link_id,
event->topic_len, event->topic,
event->data_len,
event->data_len, event->data
);
// 通过 AT 端口发送
esp_at_port_write_data((uint8_t*)buffer, len);
// 释放缓冲区
free(buffer);
ESP_LOGI(TAG, "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:
ESP_LOGI(TAG, "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;
}
}
//AT+MQTTCONNEX=1,"clinetid","172.16.1.105",1883,0,120,1
static uint8_t at_mqtt_connect_ex(uint8_t para_num) {
int32_t ret = ESP_AT_RESULT_CODE_ERROR;
int32_t cnt = 0;
static int32_t link_id = 0;
printf("at_mqtt_connect_ex start\r\n");
if (esp_at_get_para_as_digit(cnt++, &link_id) != ESP_AT_PARA_PARSE_RESULT_OK) {
printf("link_id error\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(link_id == 1 || link_id == 2)) {
printf("link_id error\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* clinetId = NULL;
if (esp_at_get_para_as_str(cnt++, &clinetId) != ESP_AT_PARA_PARSE_RESULT_OK) {
ESP_LOGE(TAG, "Failed to parse clinetId");
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* host = NULL;
if (esp_at_get_para_as_str(cnt++, &host) != ESP_AT_PARA_PARSE_RESULT_OK) {
ESP_LOGE(TAG, "Failed to parse host");
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t port = 0;
if (esp_at_get_para_as_digit(cnt++, &port) != ESP_AT_PARA_PARSE_RESULT_OK) {
ESP_LOGE(TAG, "Failed to parse port");
return ESP_AT_RESULT_CODE_ERROR;
}
if (port < 0 || port > 65535) {
ESP_LOGE(TAG, "Port out of range: %d", port);
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t disable_clean_session = 0;
if (esp_at_get_para_as_digit(cnt++, &disable_clean_session) != ESP_AT_PARA_PARSE_RESULT_OK) {
ESP_LOGE(TAG, "Failed to parse disable_clean_session");
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(disable_clean_session == 0 || disable_clean_session == 1)) {
printf("disable_clean_session error\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t keepalive = 0;
if (esp_at_get_para_as_digit(cnt++, &keepalive) != ESP_AT_PARA_PARSE_RESULT_OK) {
printf("keepalive error\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
if (keepalive < 0 || keepalive >7200) {
printf("keepalive error\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t use_tls = 0;
if (esp_at_get_para_as_digit(cnt++, &use_tls) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (use_tls < 1 || use_tls > 5) {
ESP_LOGE(TAG, "ERROR: Invalid auth mode. Use 1-5\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
if (cnt != para_num) {
printf("para_num!=cnt %d,%d\r\n", cnt, para_num);
return ESP_AT_RESULT_CODE_ERROR;
}
m_mqtt_cfg[link_id - 1].broker.address.hostname = (const char*)host;
m_mqtt_cfg[link_id - 1].broker.address.port = port;
m_mqtt_cfg[link_id - 1].credentials.client_id = (const char*)clinetId;
m_mqtt_cfg[link_id - 1].session.disable_clean_session = disable_clean_session;
m_mqtt_cfg[link_id - 1].session.keepalive = keepalive;
m_mqtt_cfg[link_id - 1].session.keepalive = keepalive;
m_mqtt_cfg[link_id - 1].broker.address.transport = use_tls;
m_mqtt_cfg[link_id - 1].network.disable_auto_reconnect = 1;
if (mqtt_clients[link_id - 1]) {
esp_mqtt_client_destroy(mqtt_clients[link_id - 1]);
}
mqtt_clients[link_id - 1] = esp_mqtt_client_init(&m_mqtt_cfg[link_id - 1]);
if (mqtt_clients[link_id - 1] == NULL) {
printf("esp_mqtt_client_init failed\r\n");
return ESP_AT_RESULT_CODE_ERROR;
}
ret = esp_mqtt_client_register_event(mqtt_clients[link_id - 1], ESP_EVENT_ANY_ID, mqtt_event_handler_ex, &link_id);
if (ret != ESP_OK)
return ESP_AT_RESULT_CODE_ERROR;
if (esp_mqtt_client_start(mqtt_clients[link_id - 1]) != ESP_AT_PARA_PARSE_RESULT_OK) {
printf("mqtt id:%d connect fail\r\n", link_id);
return ESP_AT_RESULT_CODE_ERROR;
}
else {
printf("mqtt id:%d connect success\r\n", link_id);
}
return ESP_AT_RESULT_CODE_OK;
}
//AT+MQTTDISCONNEX=1
static uint8_t at_mqtt_disconnect_ex(uint8_t para_num)
{
// 参数索引
int32_t cnt = 0;
uint8_t buffer[512] = { 0 };
unsigned short port;
int32_t raw_port;
const int timeout_ms = 5000; // 5秒超时
const int check_interval_ms = 100;
int elapsed_ms = 0;
int32_t link_id = 0;
int ret = 0;
if (esp_at_get_para_as_digit(cnt++, &link_id) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(link_id == 1 || link_id == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (cnt != para_num) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (mqtt_clients[link_id - 1] == NULL)
return ESP_AT_RESULT_CODE_ERROR;
if (esp_mqtt_client_disconnect(mqtt_clients[link_id - 1]) != ESP_AT_PARA_PARSE_RESULT_OK) {
printf("esp_mqtt_client_disconnect fail\r\n");
ret = ESP_AT_RESULT_CODE_ERROR;
}
if (esp_mqtt_client_destroy(mqtt_clients[link_id - 1]) == 0) {
printf("esp_mqtt_client_destroy success\r\n");
mqtt_clients[link_id - 1] = NULL;
return ESP_AT_RESULT_CODE_OK;
}
mqtt_clients[link_id - 1] = NULL;
return ESP_AT_RESULT_CODE_ERROR;
}
//AT+MQTTSUBEX=1,"test",1
static uint8_t at_mqtt_subscribe_ex(uint8_t para_num)
{
int32_t cnt = 0;
uint8_t buffer[512] = { 0 };
unsigned short port;
int32_t raw_port;
int32_t link_id = 0;
if (esp_at_get_para_as_digit(cnt++, &link_id) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(link_id == 1 || link_id == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* topic = NULL;
if (esp_at_get_para_as_str(cnt++, &topic) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t qos = 0;
if (esp_at_get_para_as_digit(cnt++, &qos) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(qos == 0 || qos == 1 || qos == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (cnt != para_num) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (mqtt_clients[link_id - 1] == NULL)
return ESP_AT_RESULT_CODE_ERROR;
int msg_id = esp_mqtt_client_subscribe(
mqtt_clients[link_id - 1],
(const char*)topic,
qos
);
if (msg_id < 0) {
ESP_LOGE(TAG, "Publish failed");
return ESP_AT_RESULT_CODE_ERROR;
}
return ESP_AT_RESULT_CODE_OK;
}
//AT+MQTTPUBEX=0,"test","test",1,0
static uint8_t at_mqtt_publish_ex(uint8_t para_num)
{
int32_t cnt = 0;
uint8_t buffer[512] = { 0 };
unsigned short port;
int32_t raw_port;
int32_t link_id = 0;
if (esp_at_get_para_as_digit(cnt++, &link_id) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(link_id == 1 || link_id == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* topic = NULL;
if (esp_at_get_para_as_str(cnt++, &topic) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t qos = 0;
if (esp_at_get_para_as_digit(cnt++, &qos) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(qos == 0 || qos == 1 || qos == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t retain = 0;
if (esp_at_get_para_as_digit(cnt++, &retain) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(retain == 0 || retain == 1)) {
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* message = NULL;
if (esp_at_get_para_as_str(cnt++, &message) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (cnt != para_num) {
return ESP_AT_RESULT_CODE_ERROR;
}
int msg_id = esp_mqtt_client_publish(
mqtt_clients[link_id - 1],
(const char*)topic,
(const char*)message,
0,
qos,
retain
);
if (msg_id < 0) {
ESP_LOGE(TAG, "Publish failed");
return ESP_AT_RESULT_CODE_ERROR;
}
return ESP_AT_RESULT_CODE_OK;
}
static uint8_t at_mqtt_setwill_ex(uint8_t para_num) {
int32_t cnt = 0;
uint8_t buffer[512] = { 0 };
int32_t link_id = 0;
if (esp_at_get_para_as_digit(cnt++, &link_id) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(link_id == 1 || link_id == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* topic = NULL;
if (esp_at_get_para_as_str(cnt++, &topic) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t qos = 0;
if (esp_at_get_para_as_digit(cnt++, &qos) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(qos == 0 || qos == 1 || qos == 2)) {
return ESP_AT_RESULT_CODE_ERROR;
}
int32_t retain = 0;
if (esp_at_get_para_as_digit(cnt++, &retain) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (!(retain == 0 || retain == 1)) {
return ESP_AT_RESULT_CODE_ERROR;
}
uint8_t* message = NULL;
if (esp_at_get_para_as_str(cnt++, &message) != ESP_AT_PARA_PARSE_RESULT_OK) {
return ESP_AT_RESULT_CODE_ERROR;
}
if (cnt != para_num) {
return ESP_AT_RESULT_CODE_ERROR;
}
m_mqtt_cfg[link_id].session.last_will.qos = qos;
m_mqtt_cfg[link_id].session.last_will.retain = retain;
m_mqtt_cfg[link_id].session.last_will.topic = (const char *)topic;
m_mqtt_cfg[link_id].session.last_will.msg =(const char *) message;
m_mqtt_cfg[link_id].session.last_will.msg_len = strlen((char *)message);
return ESP_AT_RESULT_CODE_OK;
}
测试AT指令:
ATE0
AT+CWMODE=1
AT+CIPMUX=1
AT+CWJAP="sunyard_sz","syd802806"
AT+CWJAP?
AT+MQTTCONNEX=1,"clinetid","172.16.1.105",1883,0,120,1
AT+MQTTSUBEX=1,"test",1
AT+MQTTPUBEX=1,"test",1,0,"test"
AT+MQTTDISCONNEX=1
测试效果: