espressif / esp-mqtt

ESP32 mqtt component
Apache License 2.0
591 stars 254 forks source link

Problem in subscription message at esp32 client end (IDFGH-8347) #236

Closed priya2212 closed 9 months ago

priya2212 commented 1 year ago

Dear @tuanpmt, I am new to esp-idf environment and working over esp32 mqtt - TCP example. The example is working fine with publish and subscription of message. Now, I added one thread in the main program which is just printing on terminal every one second. Now, when I am publishing the messages on esp32 subscribed topic( /topic/qos0) from another client -> ESP32 client randomly stops listening and not able to receive the data. Have you faced this issue? This is normal use case, not developed any application stack yet. Am I missing something in understanding it? It would be really great if whoever reading this can help me.

euripedesrocha commented 1 year ago

Hi @priya2212, Could you share the logs of your running client? And if possible share the relevant parts of your code, so we can evaluate the issue.

priya2212 commented 1 year ago

Hi @euripedesrocha , Thank you for your message. Below is the code snippet -

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);
    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);
        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);
        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:
        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;
    }
}

static void mqtt_app_start(void)
{
    esp_mqtt_client_config_t mqtt_cfg = {
        .uri = CONFIG_BROKER_URL,
    };
#if CONFIG_BROKER_URL_FROM_STDIN
    char line[128];

    if (strcmp(mqtt_cfg.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.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);
    esp_mqtt_client_start(client);
}

void test(void){
    int count = 0;
    while(1){
        count++;
        printf("count is %d \n", count);
        vTaskDelay(1000/portTICK_PERIOD_MS);
    }
}
void app_main(void)
{
    ESP_LOGI(TAG, "[APP] Startup..");
    ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
    ESP_LOGI(TAG, "[APP] IDF version: %s", esp_get_idf_version());

    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set("MQTT_CLIENT", ESP_LOG_VERBOSE);
    esp_log_level_set("MQTT_EXAMPLE", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT_BASE", ESP_LOG_VERBOSE);
    esp_log_level_set("esp-tls", ESP_LOG_VERBOSE);
    esp_log_level_set("TRANSPORT", ESP_LOG_VERBOSE);
    esp_log_level_set("OUTBOX", ESP_LOG_VERBOSE);

    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());

    mqtt_app_start();
    xTaskCreate(test, "test", 2048, NULL, 1, NULL);
}

And attached is the logs captured on screen. I have just added one function test in the thread and MQTT App is running. After sometime, the app stopped receiving the messages from another client (MQTT lens). Please let me know if you need more details.

Screenshot 2022-09-21 at 3 44 17 PM
euripedesrocha commented 1 year ago

@priya2212, from the snippet you shared and the logs, I couldn't spot an issue. Could you describe your test setup that leads to missing messages? What is the message QoS?

priya2212 commented 1 year ago

QoS - 0, tested with 1 as well. Facing same problem. In the logs, even I don't see any issues captured. Just that I have MQTTLens/MQTTBox as another client and ESP32 as one client. Sending the messages from MQTT Lens manually to ESP32, it reads for few minutes, then it suddenly and randomly stops reading the message on subscribed topic. I created one more thread -publish client (where I am continuously publishing the data in period of 1 sec) - just to check if MQTT disconnected or something happened which is not getting captured- the data is getting published successfully. But at the same time, subscription is not working.

Hardware - ESP32 4MB flash.

euripedesrocha commented 9 months ago

Closing, since I couldn't reproduce.

gordonguilloryklx commented 2 months ago

I am having the same issue using esp-idf 4.4.0 (planning to migrate to 5.2 soon, but need this now). Seems that subscription stops receiving messages at some point, which I cannot seem to pinpoint even with debugging on. No connection loss, and no errors popup from the mqtt_client code. To reiterate, everything works perfect for around 2-3 minutes. Publishing and messages received from subscription work perfect, then suddenly the messages from subscription stop, but the publisher continues to work flawlessly. No memory leak detect after monitoring stack and heap.

I am working to try and isolate and create something reproducible.

**Edit: I also noticed that esp_mqtt_client_subscribe with qos of 0 does not receive any messages.