Open PING020903 opened 1 month ago
I created a new project and ported the code over and found that when I send a publish message on a subscribe event it reproduces the issue 100%, as long as I don't publish the message there is no problem. By the way, I just copied the example and changed it.
https://github.com/espressif/esp-idf/blob/master/examples/protocols/mqtt/tcp/main/app_main.c
/*
* @brief Event handler registered to receive MQTT events
*
* This function is called by the MQTT client event loop.
*
* @param handler_args user data registered to the event.
* @param base Event base for the handler(always MQTT Base in this example).
* @param event_id The id for the received event.
* @param event_data The data for the event, esp_mqtt_event_handle_t.
*/
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=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id = 0;
char devInfo[128] = {0};
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
// 连接后先解除订阅貌似会导致一些预料以外的结果
msg_id = esp_mqtt_client_unsubscribe(client, TITLE_UPDATA_REPLY);
msg_id = esp_mqtt_client_unsubscribe(client, UART_TFT_STRINGS_SUB);
msg_id = esp_mqtt_client_subscribe(client, TITLE_UPDATA_REPLY, 2);
msg_id = esp_mqtt_client_subscribe(client, UART_TFT_STRINGS_SUB, 2);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
#if 0
msg_id = esp_mqtt_client_publish(client,
TITLE_UPDATA,
sub_deviceTiltlePadding(devInfo, sizeof(devInfo),
NULL, 0),
0,
2,
0);
printf("sent: %s\r\n", devInfo);
printf("--1--\r\n");
#if 0
msg_id = esp_mqtt_client_publish(client,
UART_TFT_STRINGS_PUB,
"\"hello\"",
0,
2,
0);
#endif
#if 0
printf("--2--\r\n");
msg_id = esp_mqtt_client_publish(client,
USER_UPDATE_PUB,
" ",
0,
2,
0);
printf("--3--\r\n");
#endif
#endif
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:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
printf("--5--\r\n");
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
printf("--6--\r\n");
memset(MQTT_topicRecive, 0, sizeof(MQTT_topicRecive));
UserStrcat(MQTT_topicRecive, event->topic, event->topic_len, 0U);
printf("--7--\r\n");
memset(MQTT_dataRecive, 0, sizeof(MQTT_dataRecive));
UserStrcat(MQTT_dataRecive, event->data, event->data_len, 0U);
printf("--8--\r\n");
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;
case MQTT_EVENT_BEFORE_CONNECT:
ESP_LOGI(TAG, "MQTT_EVENT_BEFORE_CONNECT");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
printf("--4--\r\n");
}
Used an unexpected way to solve the problem, but still wanted an explanation.
static void mqttSUB_task(void *arg)
{
int msg_id = 0;
char devInfo[128] = {0};
vTaskDelay(1);
#if 1
msg_id = esp_mqtt_client_publish((esp_mqtt_client_handle_t)arg,
TITLE_UPDATA,
sub_deviceTiltlePadding(devInfo, sizeof(devInfo),
NULL, 0),
0,
2,
0);
printf("sent: %s\r\n", devInfo);
printf("--1--\r\n");
#if 0
msg_id = esp_mqtt_client_publish(client,
UART_TFT_STRINGS_PUB,
"\"hello\"",
0,
2,
0);
#endif
#if 1
printf("--2--\r\n");
msg_id = esp_mqtt_client_publish((esp_mqtt_client_handle_t)arg,
USER_UPDATE_PUB,
" ",
0,
2,
0);
printf("--3--\r\n");
#endif
#endif
vTaskDelete(NULL);
}
/*
* @brief Event handler registered to receive MQTT events
*
* This function is called by the MQTT client event loop.
*
* @param handler_args user data registered to the event.
* @param base Event base for the handler(always MQTT Base in this example).
* @param event_id The id for the received event.
* @param event_data The data for the event, esp_mqtt_event_handle_t.
*/
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=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id = 0;
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
// 连接后先解除订阅貌似会导致一些预料以外的结果
msg_id = esp_mqtt_client_unsubscribe(client, TITLE_UPDATA_REPLY);
msg_id = esp_mqtt_client_unsubscribe(client, UART_TFT_STRINGS_SUB);
msg_id = esp_mqtt_client_subscribe(client, TITLE_UPDATA_REPLY, 2);
msg_id = esp_mqtt_client_subscribe(client, UART_TFT_STRINGS_SUB, 2);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
#if 1 // 不能直接在触发订阅主题的事件里发布多个topic消息, 故此创建了任务延时发布
xTaskCreatePinnedToCore(mqttSUB_task,
"main_task",
1024 * 2,
client,
configMAX_PRIORITIES - 10,
NULL,
0);
#endif
#if 0
msg_id = esp_mqtt_client_publish(client,
TITLE_UPDATA,
sub_deviceTiltlePadding(devInfo, sizeof(devInfo),
NULL, 0),
0,
2,
0);
printf("sent: %s\r\n", devInfo);
printf("--1--\r\n");
#if 0
msg_id = esp_mqtt_client_publish(client,
UART_TFT_STRINGS_PUB,
"\"hello\"",
0,
2,
0);
#endif
#if 0
printf("--2--\r\n");
msg_id = esp_mqtt_client_publish(client,
USER_UPDATE_PUB,
" ",
0,
2,
0);
printf("--3--\r\n");
#endif
#endif
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:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
// 只有在接收的时候topic才不为空
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
memset(MQTT_topicRecive, 0, sizeof(MQTT_topicRecive));
UserStrcat(MQTT_topicRecive, event->topic, event->topic_len, 0U);
memset(MQTT_dataRecive, 0, sizeof(MQTT_dataRecive));
UserStrcat(MQTT_dataRecive, event->data, event->data_len, 0U);
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;
case MQTT_EVENT_BEFORE_CONNECT:
ESP_LOGI(TAG, "MQTT_EVENT_BEFORE_CONNECT");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
printf("--4--\r\n");
}
Maybe you're using too much of mqtt_task
's stack memory?
Maybe you're using too much of 's stack memory?
mqtt_task
i think, the reason it is not you think.
Even if I manually resize the task stack, it still encounters the above problem
AP_MAC:d4:da:21:b7:91:24, bitmap:0x7
I (5448) TestMQTT: MQTT_EVENT_BEFORE_CONNECT
I (5454) main_task: Returned from app_main()
I (5480) wifi:<ba-add>idx:1 (ifx:0, d4:da:21:b7:91:24), tid:0, ssn:0, winSize:64
I (5836) TestMQTT: MQTT_EVENT_CONNECTED
I (5928) TestMQTT: MQTT_EVENT_UNSUBSCRIBED, msg_id=52300
I (6013) TestMQTT: MQTT_EVENT_UNSUBSCRIBED, msg_id=35968
I (6038) TestMQTT: MQTT_EVENT_SUBSCRIBED, msg_id=62854
sent: {"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:50.000"}],"method":"thing.deviceinfo.update"}
Guru Meditation Error: Core 1 panic'ed (Double exception).
Core 1 register dump:
PC : 0x4008ceea PS : 0x00040136 A0 : 0x8016b07d A1 : 0x3ffcb7b0
A2 : 0x3ffc8520 A3 : 0x3f405848 A4 : 0x2e676e69 A5 : 0x69766564
A6 : 0x6e696563 A7 : 0x752e6f66 A8 : 0x800d8448 A9 : 0x3ffcb770
A10 : 0x0000bea3 A11 : 0x3ffc842c A12 : 0x3f40499e A13 : 0xffffffd5
A14 : 0x00000002 A15 : 0x00000000 SAR : 0x0000000a EXCCAUSE: 0x00000002
EXCVADDR: 0xffffffc5 LBEG : 0x4000c2e0 LEND : 0x4000c2f6 LCOUNT : 0xffffffff
Backtrace: 0x4008cee7:0x3ffcb7b0 0x4016b07a:0x3ffc8838 |<-CORRUPTED
ELF file SHA256: 7acf4369aff5080f
Rebooting...
ets Jul 29 2019 12:21:46
rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7084
ho 0 tail 12 room 4
load:0x40078000,len:15584
load:0x40080400,len:4
load:0x40080404,len:3876
entry 0x4008064c
I (31) boot: ESP-IDF v5.1.2-dirty 2nd stage bootloader
I (31) boot: compile time Aug 8 2024 21:20:22
Maybe you're using too much of 's stack memory?
mqtt_task
if the stack overflow, I run into problems when I perform the following operations
A double exception is an exception that happens while handling a previous exception. I've had that happen to me once, and the issue was a buffer overrun of a global array that turned out to have been sized insufficiently. I suggest you look into that, considering you decided to roll out your own JSON construction and strcat implementations.
@PING020903 thanks for reporting.
Could you double-check the function sub_deviceTiltlePadding
?
Your solution of creating a different task to handle could be the solution because you would be corrupting a different stack than the mqtt client.
I've run the steps you suggested using the mqtt client example and the fixed topic and publish data, and it works just fine. From the logs the problem is not in unsubscribe/subscribe, but in the handling of the SUBSCRIBED event in the publish call.
If you can provide a topic + data that reproduces it, I will be glad to give it a try to identify if we have some issue in the mqtt client.
@PING020903 thanks for reporting. Could you double-check the function
sub_deviceTiltlePadding
? Your solution of creating a different task to handle could be the solution because you would be corrupting a different stack than the mqtt client.I've run the steps you suggested using the mqtt client example and the fixed topic and publish data, and it works just fine. From the logs the problem is not in unsubscribe/subscribe, but in the handling of the SUBSCRIBED event in the publish call.
If you can provide a topic + data that reproduces it, I will be glad to give it a try to identify if we have some issue in the mqtt client.
Here is my code, thanks. mqtt_test.zip
Hi @PING020903 thanks for the code.
But looking into the shared code, it is still using sub_deviceTiltlePadding
to generate the data. Could you provide some code that reproduces the issue, without using that function?
Hi @PING020903 thanks for the code. But looking into the shared code, it is still using
sub_deviceTiltlePadding
to generate the data. Could you provide some code that reproduces the issue, without using that function?
You just need to enable the commented code to reproduce the problem without using the task of mqttSUB_task
@PING020903 I understand that. But I need to have code that does not use your function sub_deviceTitlePadding
since I want to isolate if we have a problem in the mqtt client.
@PING020903 I understand that. But I need to have code that does not use your function
sub_deviceTitlePadding
since I want to isolate if we have a problem in the mqtt client.
I know, as you can see in my picture, I just used a personal topic and the fixed strings. Try replacing the other topic and string data.
I know, as you can see in my picture, I just used a personal topic and the fixed strings. Try replacing the other topic and string data.
From the shared code, I was only able to reproduce the issue when the function sub_deviceTitlePadding
is involved. All scenarios work just fine. I suggest that you double-check and test the function implementation.
I know, as you can see in my picture, I just used a personal topic and the fixed strings. Try replacing the other topic and string data.
From the shared code, I was only able to reproduce the issue when the function
sub_deviceTitlePadding
is involved. All scenarios work just fine. I suggest that you double-check and test the function implementation.
I don't think there's anything wrong with my function. The crux of the matter is that the string variable created inside the mqtt_event_handler, when I set this string variable as a static global variable, it's fine.
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "esp_event.h"
#include "mqtt_client.h"
#include "User_string.h"
#include "User_SNTP.h"
#include "TestMQTT.h"
#define CONFIG_BROKER_URL_FROM_STDIN 0
#define MQTTS_PROTOCOL "mqtts://"
#define MQTT_PROTOCOL "mqtt://"
#define TIME_STR_MAX_LEN (32)
/* MQTT Base Topic (基础通信) */
#define DEVICE_NAME "WJP_esp32"
#define PRODUCT_KEY "k1mopgbwe56"
#define DEVICE_TITLE "/" PRODUCT_KEY "/" DEVICE_NAME "/thing/deviceinfo" // 设备标签信息
#define TITLE_UPDATA "/sys" DEVICE_TITLE "/update" // 设备标签更新
#define TITLE_UPDATA_REPLY "/sys" DEVICE_TITLE "/update_reply" // 设备标签更新订阅
#define TITLE_DELETE "" DEVICE_TITLE "/delete"
#define TITLE_DELETE_REPLY "" DEVICE_TITLE "/delete_reply"
#define TITLE_ID "\"id\":"
#define TITLE_ID_LEN (5)
#define TITLE_VERSION "\"version\":"
#define TITLE_VERSION_LEN (10)
#define TITLE_SYS "\"sys\":"
#define TITLE_SYS_LEN (6)
#define DEVICE_STATUS "/as/mqtt/status/" PRODUCT_KEY "/" DEVICE_NAME ""
#define UART_TFT_STRINGS_SUB "/" PRODUCT_KEY "/" DEVICE_NAME "/user/uartTFTsringsSUB"
#define UART_TFT_STRINGS_PUB "/" PRODUCT_KEY "/" DEVICE_NAME "/user/uartTFTsringsPUB"
#define USER_UPDATE_PUB "/" PRODUCT_KEY "/" DEVICE_NAME "/user/update"
#define INFO_STATUS "\"status\""
#define INFO_STATUS_LEN (8)
#define INFO_IOTID "\"iotid\""
#define INFO_IOTID_LEN (7)
#define INFO_PRODUCTKEY "\"productKey\""
#define INFO_PRODUCTKEY_LEN (12)
#define INFO_DEVICENAME "\"deviceName\""
#define INFO_DEVICENAME_LEN (12)
#define INFO_TIME "\"time\""
#define INFO_TIME_LEN (6)
#define INFO_UTCTIME "\"utcTime\""
#define INFO_UTCTIME_LEN (9)
#define INFO_LASTTIME "\"lastTime\""
#define INFO_LASTTIME_LEN (10)
#define INFO_UTCLASTTIME "\"utcLastTime\""
#define INFO_UTCLASTTIME_LEN (13)
#define INFO_CLIENTIP "\"clientIp\""
#define INFO_CLIENTIP_LEN (10)
#define DATA_NULL "\r\n"
#define DATA_NULL_LEN (2)
#define ONLINE_STATUS "\"online\""
#define ONLINE_STATUS_LEN (8)
#define OFFLINE_STATUS "\"offline\""
#define OFFLINE_STATUS_LEN (9)
static const char *TAG = "TestMQTT";
static char *localIp = "120.230.164.69"; // 公网出口IP
static char MQTT_topicRecive[128] = {0}; // DATA_EVENT topic接收
static char MQTT_dataRecive[1024] = {0}; // DATA_EVENT data接收
static char devInfo[128] = {0};
/// @brief 获取设备信息数据格式的长度
/// @param
/// @return LEN:获取到的数据长度
size_t AllInfoLen_online(void)
{
char time[] = "\"2018-08-31 15:32:28.195\"";
char utctime[] = "\"2018-08-31T07:32:28.195Z\"";
char iotID[] = "\"4z819VQHk6VSLmmBJfrf00107e****\"";
char clientIP[] = "\"192.168.111.111\"";
size_t semicolons = 0, double_quote = 0;
size_t len = strlen(INFO_STATUS);
len += strlen(ONLINE_STATUS);
semicolons++;
len += strlen(INFO_IOTID);
len += strlen(iotID);
semicolons++;
len += strlen(INFO_PRODUCTKEY);
len += strlen(PRODUCT_KEY);
double_quote += 2;
semicolons++;
len += strlen(INFO_DEVICENAME);
len += strlen(DEVICE_NAME);
double_quote += 2;
semicolons++;
len += strlen(INFO_TIME);
len += strlen(INFO_UTCTIME);
semicolons++;
len += strlen(INFO_LASTTIME);
len += strlen(INFO_UTCLASTTIME);
semicolons++;
len += (strlen(time) * 2);
len += (strlen(utctime) * 2);
len += strlen(INFO_CLIENTIP);
len += strlen(clientIP);
return len + semicolons + double_quote;
}
/// @brief 设备信息填充
/// @param mqttDeviceInfo 要被填充的字符串
/// @param len 字符串长度
/// @return STRINGS:填充后的字符串
/// @note 不可将标准POSIX函数strcat频繁调用, 需用自定义的strcat
char *deviceInfoPadding(char *mqttDeviceInfo, const size_t len)
{
size_t pos = 0, ch_len = 0;
ch_len = AllInfoLen_online();
if (mqttDeviceInfo == NULL || len < ch_len)
{
return NULL;
}
char timeStr[TIME_STR_MAX_LEN] = {0};
wait_time:
if (!getTimeData_ready()) // 等待SNTP更新时间
{
vTaskDelay(1);
goto wait_time;
}
mqttDeviceInfo[pos++] = '{';
UserStrcat(mqttDeviceInfo, INFO_STATUS, INFO_STATUS_LEN, pos);
pos += INFO_STATUS_LEN;
mqttDeviceInfo[pos++] = ':';
UserStrcat(mqttDeviceInfo, ONLINE_STATUS, ONLINE_STATUS_LEN, pos);
pos += ONLINE_STATUS_LEN;
mqttDeviceInfo[pos++] = ',';
UserStrcat(mqttDeviceInfo, INFO_IOTID, INFO_IOTID_LEN, pos);
pos += INFO_IOTID_LEN;
mqttDeviceInfo[pos++] = ':';
UserStrcat(mqttDeviceInfo, DATA_NULL, DATA_NULL_LEN, pos);
pos += DATA_NULL_LEN;
mqttDeviceInfo[pos++] = ',';
UserStrcat(mqttDeviceInfo, INFO_PRODUCTKEY, INFO_PRODUCTKEY_LEN, pos);
pos += INFO_PRODUCTKEY_LEN;
mqttDeviceInfo[pos++] = ':';
mqttDeviceInfo[pos++] = '\"';
UserStrcat(mqttDeviceInfo, PRODUCT_KEY, strlen(PRODUCT_KEY), pos);
pos += strlen(PRODUCT_KEY);
mqttDeviceInfo[pos++] = '\"';
mqttDeviceInfo[pos++] = ',';
UserStrcat(mqttDeviceInfo, INFO_DEVICENAME, INFO_DEVICENAME_LEN, pos);
pos += INFO_DEVICENAME_LEN;
mqttDeviceInfo[pos++] = ':';
mqttDeviceInfo[pos++] = '\"';
UserStrcat(mqttDeviceInfo, DEVICE_NAME, strlen(DEVICE_NAME), pos);
pos += strlen(DEVICE_NAME);
mqttDeviceInfo[pos++] = '\"';
mqttDeviceInfo[pos++] = ',';
UserStrcat(mqttDeviceInfo, INFO_TIME, INFO_TIME_LEN, pos);
pos += INFO_TIME_LEN;
mqttDeviceInfo[pos++] = ':';
UserStrcat(mqttDeviceInfo,
User_tmToStrings(8, timeStr, TIME_STR_MAX_LEN),
TIME_STR_MAX_LEN,
pos);
pos += strlen(timeStr);
mqttDeviceInfo[pos++] = ',';
UserStrcat(mqttDeviceInfo, INFO_UTCTIME, INFO_UTCTIME_LEN, pos);
pos += INFO_UTCTIME_LEN;
mqttDeviceInfo[pos++] = ':';
UserStrcat(mqttDeviceInfo,
User_tmToStrings(0, timeStr, TIME_STR_MAX_LEN),
TIME_STR_MAX_LEN,
pos);
pos += strlen(timeStr);
mqttDeviceInfo[pos++] = ',';
UserStrcat(mqttDeviceInfo, INFO_CLIENTIP, INFO_CLIENTIP_LEN, pos);
pos += INFO_CLIENTIP_LEN;
mqttDeviceInfo[pos++] = ':';
mqttDeviceInfo[pos++] = '\"';
UserStrcat(mqttDeviceInfo, localIp, strlen(localIp), pos);
pos += strlen(localIp);
mqttDeviceInfo[pos++] = '\"';
mqttDeviceInfo[pos++] = '}';
return mqttDeviceInfo;
}
/// @brief 订阅设备标签字符串填充
/// @param str 传入字符串指针
/// @param len 字符串长度( 没有上传的data时应不少于128bytes, 否则会越界访问 )
/// @param upLoadData 要上传的data
/// @param dataLen 要上传的data长度
/// @return STRINGS:填充好的字符串
char *sub_deviceTiltlePadding(char *str, size_t len, char *upLoadData, size_t dataLen)
{
if (str == NULL || len == 0)
{
ESP_LOGE(TAG, "%s Incorrect pointer or length (add)%p (len)%u", __func__, str, len);
return str;
}
char time_str[TIME_STR_MAX_LEN] = {0};
size_t pos = 0;
str[pos++] = '{';
UserStrcat(str, TITLE_ID, TITLE_ID_LEN, pos);
pos += TITLE_ID_LEN;
UserStrcat(str, "\"111\"", strlen("\"111\""), pos);
pos += strlen("\"111\"");
str[pos++] = ',';
UserStrcat(str, TITLE_VERSION, TITLE_VERSION_LEN, pos);
pos += TITLE_VERSION_LEN;
UserStrcat(str, "\"1.0\"", strlen("\"1.0\""), pos);
pos += strlen("\"1.0\"");
str[pos++] = ',';
UserStrcat(str, TITLE_SYS, TITLE_SYS_LEN, pos);
pos += TITLE_SYS_LEN;
str[pos++] = '{';
// 此处放置要上传的数据
UserStrcat(str, "\"ack\"", strlen("\"ack\""), pos);
pos += strlen("\"ack\"");
str[pos++] = ':';
str[pos++] = '0';
str[pos++] = '}';
str[pos++] = ',';
UserStrcat(str, "\"params\":", strlen("\"params\":"), pos);
pos += strlen("\"params\":");
str[pos++] = '[';
str[pos++] = '{';
UserStrcat(str, "\"attrKey\":", strlen("\"attrKey\":"), pos);
pos += strlen("\"attrKey\":");
UserStrcat(str, "\"localTime\"", strlen("\"localTime\""), pos);
pos += strlen("\"localTime\""); // "attrKey": "localTime"
UserStrcat(str, "\"attrValue\":", strlen("\"attrValue\":"), pos);
pos += strlen("\"attrValue\":");
UserStrcat(str, User_tmToStrings(8, time_str, sizeof(time_str)), strlen(time_str), pos);
pos += strlen(time_str); // "attrValue": "yyyy-mm-dd hh:mm:ss.ms"
str[pos++] = '}';
str[pos++] = ']';
str[pos++] = ',';
UserStrcat(str, "\"method\":", strlen("\"method\":"), pos);
pos += strlen("\"method\":");
UserStrcat(str, "\"thing.deviceinfo.update\":", strlen("\"thing.deviceinfo.update\":"), pos);
pos += strlen("\"thing.deviceinfo.update\"");
str[pos++] = '}';
return str;
}
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);
}
}
#if 0
static void mqttSUB_task(void *arg)
{
int msg_id = 0;
char devInfo[128] = {0};
vTaskDelay(1);
#if 1
msg_id = esp_mqtt_client_publish((esp_mqtt_client_handle_t)arg,
TITLE_UPDATA,
sub_deviceTiltlePadding(devInfo, sizeof(devInfo),
NULL, 0),
0,
2,
0);
printf("sent: %s\r\n", devInfo);
printf("--1--\r\n");
#if 0
msg_id = esp_mqtt_client_publish(client,
UART_TFT_STRINGS_PUB,
"\"hello\"",
0,
2,
0);
#endif
#if 1
printf("--2--\r\n");
msg_id = esp_mqtt_client_publish((esp_mqtt_client_handle_t)arg,
USER_UPDATE_PUB,
" ",
0,
2,
0);
printf("--3--\r\n");
#endif
#endif
vTaskDelete(NULL);
}
#endif
/*
* @brief Event handler registered to receive MQTT events
*
* This function is called by the MQTT client event loop.
*
* @param handler_args user data registered to the event.
* @param base Event base for the handler(always MQTT Base in this example).
* @param event_id The id for the received event.
* @param event_data The data for the event, esp_mqtt_event_handle_t.
*/
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=%" PRIi32 "", base, event_id);
esp_mqtt_event_handle_t event = event_data;
esp_mqtt_client_handle_t client = event->client;
int msg_id = 0;
memset(devInfo, 0, sizeof(devInfo));
sub_deviceTiltlePadding(devInfo, sizeof(devInfo), NULL, 0);
printf("%s\r\n", devInfo);
switch ((esp_mqtt_event_id_t)event_id)
{
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
// 连接后先解除订阅貌似会导致一些预料以外的结果
msg_id = esp_mqtt_client_unsubscribe(client, TITLE_UPDATA_REPLY);
msg_id = esp_mqtt_client_unsubscribe(client, UART_TFT_STRINGS_SUB);
msg_id = esp_mqtt_client_subscribe(client, TITLE_UPDATA_REPLY, 2);
msg_id = esp_mqtt_client_subscribe(client, UART_TFT_STRINGS_SUB, 2);
break;
case MQTT_EVENT_DISCONNECTED:
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
break;
case MQTT_EVENT_SUBSCRIBED:
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
#if 0 // 不能直接在触发订阅主题的事件里订阅多个topic, 故此创建了任务延时发布
xTaskCreatePinnedToCore(mqttSUB_task,
"main_task",
1024 * 2,
client,
configMAX_PRIORITIES - 10,
NULL,
0);
#endif
#if 1
msg_id = esp_mqtt_client_publish(client,
TITLE_UPDATA,
devInfo,
0,
2,
0);
printf("sent: %s\r\n", devInfo);
printf("--1--\r\n");
#endif
#if 0
msg_id = esp_mqtt_client_publish(client,
UART_TFT_STRINGS_PUB,
"\"hello\"",
0,
2,
0);
#endif
#if 0
printf("--2--\r\n");
msg_id = esp_mqtt_client_publish(client,
USER_UPDATE_PUB,
" ",
0,
2,
0);
printf("--3--\r\n");
#endif
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:
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
// 只有在接收的时候topic才不为空
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
printf("DATA=%.*s\r\n", event->data_len, event->data);
memset(MQTT_topicRecive, 0, sizeof(MQTT_topicRecive));
UserStrcat(MQTT_topicRecive, event->topic, event->topic_len, 0U);
memset(MQTT_dataRecive, 0, sizeof(MQTT_dataRecive));
UserStrcat(MQTT_dataRecive, event->data, event->data_len, 0U);
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;
case MQTT_EVENT_BEFORE_CONNECT:
ESP_LOGI(TAG, "MQTT_EVENT_BEFORE_CONNECT");
break;
default:
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
break;
}
printf("--4--\r\n");
}
/// @brief MQTT客户端初始化
/// @param
void mqtt_client_init(void)
{
/*
{"
{"clientId":"k1mopgbwe56.WJP_esp32|securemode=2,signmethod=hmacsha256,timestamp=1722877509058|",
"username":"WJP_esp32&k1mopgbwe56",
"mqttHostUrl":"iot-06z00doqpm9whvw.mqtt.iothub.aliyuncs.com",
"passwd":"0002f264787d9e8766f4a65d413c51add4324324d46bf05953e0b9c725d6b2b6",
"port":1883}
*/
// ps: 每次在服务器web端点击"MQTT连接参数"都会导致password&clientId改变,所以每次都需要重新初始化
esp_mqtt_client_config_t mqtt_cfg = {
.broker.verification.use_global_ca_store = 0,
.broker.verification.skip_cert_common_name_check = 0,
.broker.address.uri = "" MQTT_PROTOCOL "iot-06z00doqpm9whvw.mqtt.iothub.aliyuncs.com",
.broker.address.port = 1883,
.credentials.username = "WJP_esp32&k1mopgbwe56",
.credentials.client_id = "k1mopgbwe56.WJP_esp32|securemode=2,signmethod=hmacsha256,timestamp=1722877509058|",
.credentials.authentication.use_secure_element = 0,
.credentials.authentication.password = "0002f264787d9e8766f4a65d413c51add4324324d46bf05953e0b9c725d6b2b6",
.session.disable_keepalive = 0,
.session.disable_clean_session = 0,
};
#if CONFIG_BROKER_URL_FROM_STDIN
char line[128];
if (strcmp(mqtt_cfg.broker.address.uri, "FROM_STDIN") == 0)
{
int count = 0;
printf("Please enter url of mqtt broker\n");
while (count < 128)
{
int c = fgetc(stdin);
if (c == '\n')
{
line[count] = '\0';
break;
}
else if (c > 0 && c < 127)
{
line[count] = c;
++count;
}
vTaskDelay(10 / portTICK_PERIOD_MS);
}
mqtt_cfg.broker.address.uri = line;
printf("Broker url: %s\n", line);
}
else
{
ESP_LOGE(TAG, "Configuration mismatch: wrong broker url");
abort();
}
#endif /* CONFIG_BROKER_URL_FROM_STDIN */
esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
/* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
size_t ret = esp_mqtt_client_start(client);
if (ret == ESP_FAIL)
return;
// char tempStr[512] = {0};
// ESP_LOGI(TAG, "deviceInfo:\n%s", deviceInfoPadding(tempStr, sizeof(tempStr)));
}
/// @brief topic对比处理
/// @param
/// @return 返回topic所对应的值
/// @return ZERO: 0, null
/// @return ONE: 1, TITLE_UPDATA_REPLY
/// @return THREE: 2, UART_TFT_STRINGS_SUB
int topic_handle(void)
{
char *ret_point = NULL;
ret_point = strstr(MQTT_topicRecive, TITLE_UPDATA_REPLY);
if (ret_point != NULL)
return 1;
ret_point = strstr(MQTT_topicRecive, UART_TFT_STRINGS_SUB);
if (ret_point != NULL)
return 2;
return 0;
}
#if 0
/// @brief 根据topic列表值选择不同方式的数据处理
/// @param select topic列表中的值
/// @return
dataInfo_fromMQTT dataParse(const int select)
{
switch (select)
{
case 0:
return;
}
}
#endif
/// @brief 释放dataInfo_fromMQTT的字符串
/// @param data
/// @return OK:0
/// @return FAIL:
int free_userStr(dataInfo_fromMQTT data)
{
free(data.userStr);
return 0;
}
Could it be that I created a variable that exceeded the default stack size? Could it be that the string variable I created exceeds the default stack size? If so, won't the overflow cause the OS to reboot when entering the MQTT stack?
--- esp-idf-monitor 1.4.0 on \\.\COM6 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FL�ets Jul 29 2019 12:21:46
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7084
ho 0 tail 12 room 4
load:0x40078000,len:15584
load:0x40080400,len:4
0x40080400: _init at ??:?
load:0x40080404,len:3876
entry 0x4008064c
I (31) boot: ESP-IDF v5.1.2-dirty 2nd stage bootloader
I (31) boot: compile time Aug 8 2024 20:08:53
I (31) boot: Multicore bootloader
I (36) boot: chip revision: v3.1
I (40) boot.esp32: SPI Speed : 40MHz
I (44) boot.esp32: SPI Mode : DIO
I (49) boot.esp32: SPI Flash Size : 2MB
I (53) boot: Enabling RNG early entropy source...
I (59) boot: Partition Table:
I (62) boot: ## Label Usage Type ST Offset Length
I (70) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (77) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (85) boot: 2 factory factory app 00 00 00010000 00100000
I (92) boot: End of partition table
I (96) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=253d8h (152536) map
I (160) esp_image: segment 1: paddr=00035400 vaddr=3ffb0000 size=03acch ( 15052) load
I (166) esp_image: segment 2: paddr=00038ed4 vaddr=40080000 size=07144h ( 28996) load
I (178) esp_image: segment 3: paddr=00040020 vaddr=400d0020 size=9ac0ch (633868) map
I (407) esp_image: segment 4: paddr=000dac34 vaddr=40087144 size=0eb30h ( 60208) load
I (444) boot: Loaded app from partition at offset 0x10000
I (444) boot: Disabling RNG early entropy source...
I (455) cpu_start: Multicore app
I (456) cpu_start: Pro cpu up.
I (456) cpu_start: Starting app cpu, entry point is 0x400813a4
0x400813a4: call_start_cpu1 at D:/ESP_MCU_tool/ESP_IDF_TOOLS/Espressif/frameworks/esp-idf-v5.1.2/components/esp_system/port/cpu_start.c:157
I (0) cpu_start: App cpu up.
I (474) cpu_start: Pro cpu start user code
I (474) cpu_start: cpu freq: 160000000 Hz
I (474) cpu_start: Application information:
I (478) cpu_start: Project name: mqtt_test
I (483) cpu_start: App version: 1
I (488) cpu_start: Compile time: Aug 8 2024 20:11:56
I (494) cpu_start: ELF file SHA256: f3043fc2dda4275e...
I (500) cpu_start: ESP-IDF: v5.1.2-dirty
I (505) cpu_start: Min chip rev: v0.0
I (510) cpu_start: Max chip rev: v3.99
I (515) cpu_start: Chip rev: v3.1
I (520) heap_init: Initializing. RAM available for dynamic allocation:
I (527) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (533) heap_init: At 3FFB86C0 len 00027940 (158 KiB): DRAM
I (539) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (545) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (552) heap_init: At 40095C74 len 0000A38C (40 KiB): IRAM
I (560) spi_flash: detected chip: generic
I (563) spi_flash: flash io: dio
W (567) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (581) app_start: Starting scheduler on CPU0
I (585) app_start: Starting scheduler on CPU1
I (585) main_task: Started on CPU0
I (595) main_task: Calling app_main()
I (645) wifi:wifi driver task: 3ffc0d94, prio:23, stack:6656, core=0
I (665) wifi:wifi firmware version: 91b9630
I (665) wifi:wifi certification version: v7.0
I (665) wifi:config NVS flash: enabled
I (665) wifi:config nano formating: disabled
I (675) wifi:Init data frame dynamic rx buffer num: 32
I (675) wifi:Init static rx mgmt buffer num: 5
I (675) wifi:Init management short buffer num: 32
I (685) wifi:Init dynamic tx buffer num: 32
I (685) wifi:Init static rx buffer size: 1600
I (695) wifi:Init static rx buffer num: 10
I (695) wifi:Init dynamic rx buffer num: 32
I (705) wifi_init: rx ba win: 6
I (705) wifi_init: tcpip mbox: 32
I (705) wifi_init: udp mbox: 6
I (715) wifi_init: tcp mbox: 6
I (715) wifi_init: tcp tx win: 5744
I (715) wifi_init: tcp rx win: 5744
I (725) wifi_init: tcp mss: 1440
I (725) wifi_init: WiFi IRAM OP enabled
I (735) wifi_init: WiFi RX IRAM OP enabled
I (745) phy_init: phy_version 4780,16b31a7,Sep 22 2023,20:42:16
I (835) wifi:mode : sta (fc:b4:67:4e:bd:8c)
I (835) wifi:enable tsf
I (835) User_WIFI: WIFI_EVENT_STA_START
I (2595) main: test MQTT...Minimum free heap size: 228112 bytes
I (3335) User_WIFI: wifi scan done
I (3375) wifi:new:<1,0>, old:<1,0>, ap:<255,255>, sta:<1,0>, prof:1
I (3375) wifi:state: init -> auth (b0)
I (3385) wifi:state: auth -> assoc (0)
I (3395) wifi:state: assoc -> run (10)
I (3425) wifi:connected with pP, aid = 2, channel 1, BW20, bssid = d4:da:21:b7:91:24
I (3425) wifi:security: WPA2-PSK, phy: bgn, rssi: -52
I (3425) wifi:pm start, type: 1
I (3435) User_WIFI: WIFI_EVENT_STA_CONNECTED ! ! !
I (3455) wifi:<ba-add>idx:0 (ifx:0, d4:da:21:b7:91:24), tid:6, ssn:2, winSize:64
I (3475) wifi:AP's beacon interval = 102400 us, DTIM period = 1
I (4595) main: test MQTT...Minimum free heap size: 224996 bytes
I (4935) esp_netif_handlers: sta ip: 192.168.31.177, mask: 255.255.255.0, gw: 192.168.31.1
I (4935) User_WIFI: got ip:192.168.31.177
I (4935) User_WIFI: connected to ap SSID:pP AP_MAC:d4:da:21:b7:91:24, bitmap:0x7
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:04.000"}],"method":"thing.deviceinfo.update"}
I (4955) TestMQTT: MQTT_EVENT_BEFORE_CONNECT
--4--
I (4965) main_task: Returned from app_main()
I (4985) wifi:<ba-add>idx:1 (ifx:0, d4:da:21:b7:91:24), tid:0, ssn:0, winSize:64
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:04.000"}],"method":"thing.deviceinfo.update"}
I (5245) TestMQTT: MQTT_EVENT_CONNECTED
--4--
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:04.000"}],"method":"thing.deviceinfo.update"}
I (5435) TestMQTT: MQTT_EVENT_UNSUBSCRIBED, msg_id=52181
--4--
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:05.000"}],"method":"thing.deviceinfo.update"}
I (5545) TestMQTT: MQTT_EVENT_UNSUBSCRIBED, msg_id=4886
--4--
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:05.000"}],"method":"thing.deviceinfo.update"}
I (5565) TestMQTT: MQTT_EVENT_SUBSCRIBED, msg_id=19002
sent: {"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:05.000"}],"method":"thing.deviceinfo.update"}
--1--
--4--
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:05.000"}],"method":"thing.deviceinfo.update"}
I (5595) TestMQTT: MQTT_EVENT_SUBSCRIBED, msg_id=4205
sent: {"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:05.000"}],"method":"thing.deviceinfo.update"}
--1--
--4--
I (6595) main: test MQTT...Minimum free heap size: 214820 bytes
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:06.000"}],"method":"thing.deviceinfo.update"}
I (6975) TestMQTT: MQTT_EVENT_DATA
TOPIC=/sys/k1mopgbwe56/WJP_esp32/thing/deviceinfo/update_reply
DATA={"code":6207,"data":{},"id":"","message":"payload must be json format","version":"1.0"}
--4--
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:06.000"}],"method":"thing.deviceinfo.update"}
I (7085) TestMQTT: MQTT_EVENT_DATA
TOPIC=/sys/k1mopgbwe56/WJP_esp32/thing/deviceinfo/update_reply
DATA={"code":6207,"data":{},"id":"","message":"payload must be json format","version":"1.0"}
--4--
{"id":"111","version":"1.0","sys":{"ack":0},"params":[{"attrKey":"localTime""attrValue":"1970-01-01 08:00:06.000"}],"method":"thing.deviceinfo.update"}
I (7125) TestMQTT: MQTT_EVENT_DATA
TOPIC=/sys/k1mopgbwe56/WJP_esp32/thing/deviceinfo/update_reply
DATA={"code":6207,"data":{},"id":"","message":"payload must be json format","version":"1.0"}
--4--
I (8595) main: test MQTT...Minimum free heap size: 214820 bytes
I (10595) main: test MQTT...Minimum free heap size: 214820 bytes
I (12595) main: test MQTT...Minimum free heap size: 214820 bytes
PS C:\Users\12566\Desktop\get-started\mqtt_test>
Answers checklist.
IDF version.
esp-idf-v5.1.2
Espressif SoC revision.
ESP-WROOM-32
Operating System used.
Windows
How did you build your project?
VS Code IDE
If you are using Windows, please specify command line type.
PowerShell
Development Kit.
ESP-WROVER-KIT 3.3V
Power Supply used.
USB
What is the expected behavior?
system will no reset, and Successful subscription.
What is the actual behavior?
It's still the same after many attempts
Until I commented out the functions![image](https://github.com/user-attachments/assets/a5f3a3b0-d8a2-470f-ba3c-7babc301ed18)
esp_mqtt_client_subscribe
andesp_mqtt_client_unsubscribe
I've tried building the project after clearing the files, but it doesn't work...
Steps to reproduce.
Debug Logs.
More Information.
there is my code of "mqtt_event_handle"