espressif / esp-mqtt

ESP32 mqtt component
Apache License 2.0
609 stars 257 forks source link

missed use of client_id in MQTT-Broker (IDFGH-13712) #286

Open rk-sTEk opened 1 month ago

rk-sTEk commented 1 month ago

Checklist

How often does this bug occurs?

always

Expected behavior

I tried to make a MQTT5-client. Everything is fine, but the client_id isn't used by the esp-board. The MQTT-Explorer only shows an empty device/client ("blank field without a name) - the following topic is named like written in code. Here is my code:

Actual behavior (suspected bug)

esp_mqtt_client_handle_t client = NULL;
static void mqtt5_app_start(void)
{
    esp_mqtt5_connection_property_config_t connect_property = {
        .session_expiry_interval = 10,
        .maximum_packet_size = 1024,
        .receive_maximum = 65535,
        .topic_alias_maximum = 2,
        .request_resp_info = true,
        .request_problem_info = true,
        .will_delay_interval = 10,
        .payload_format_indicator = true,
        .message_expiry_interval = 10,
        .response_topic = "/test/response",
        .correlation_data = "123456",
        .correlation_data_len = 6,
    };

    esp_mqtt_client_config_t mqtt5_cfg = {
        .broker.address.uri = "mqtt://****",
        .session.protocol_ver = MQTT_PROTOCOL_V_5,
        .network.disable_auto_reconnect = true,
        .credentials.username = "****",
        .credentials.authentication.password = "****",
        .credentials.client_id = "sTEkSensor1",
        .credentials.set_null_client_id = false,
        .session.last_will.topic = "/topic/will",
        .session.last_will.msg = "i will leave",
        .session.last_will.msg_len = 12,
        .session.last_will.qos = 1,
        .session.last_will.retain = true,
    };

    ESP_LOGI(TAG2, "Client Init");
    ESP_LOGI(TAG2, "Client Init - ID: %s", mqtt5_cfg.credentials.client_id);

    client = esp_mqtt_client_init(&mqtt5_cfg);

    /* Set connection properties and user properties */
    esp_mqtt5_client_set_user_property(&connect_property.user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
    esp_mqtt5_client_set_user_property(&connect_property.will_user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
    esp_mqtt5_client_set_connect_property(client, &connect_property);

    /* If you call esp_mqtt5_client_set_user_property to set user properties, DO NOT forget to delete them.
     * esp_mqtt5_client_set_connect_property will malloc buffer to store the user_property and you can delete it after
     */
    esp_mqtt5_client_delete_user_property(connect_property.user_property);
    esp_mqtt5_client_delete_user_property(connect_property.will_user_property);

    /* 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, mqtt5_event_handler, NULL);
    esp_mqtt_client_start(client);
}

Error logs or terminal output

No response

Steps to reproduce the behavior

normaly compiled

Project release version

espidf 5.3.1

System architecture

other (details in Additional context)

Operating system

Linux

Operating system version

Debian

Shell

Bash

Additional context

It seems that the

.credentials.client_id = "sTEkSensor1",

isn't used in connection creation.

euripedesrocha commented 1 month ago

@rk-sTEk thanks for reporting. Could you check the MQTT-Explorer settings? I did an inspection in the code and tested with a local mosquitto instance and the client id is correctly placed in the control messages.

rk-sTEk commented 1 month ago

Hi, thanks for your answer.

Here are two lines of my MQTT-Broker-Log:

1726687870: New client connected from 10.x.x.100:51935 as sTEkSensor1 (p5, c1, k120, u'xxxsTEk').
...
1726687870: Received PUBLISH from sTEkSensor1 (d0, q1, r1, m1, '/messwerte/temperatur', ... (21 bytes))

It's seems, that the broker gets only the topic from the ESP. My other MQTT-devices are sending themself in the 5th parameter, like:

1726689367: Received PUBLISH from shelly1 (d0, q1, r0, m801, 'shelly1/events/rpc', ... (523 bytes))

Here is a screenshot from the MQTT-Explorer. Bildschirmfoto_2024-09-18_22-07-14

I'v got the sending routine from the example:

static void MQTT_Sende_Werte() {
    int msg_id;
        //print_user_property(event->property->user_property);
        esp_mqtt5_client_set_user_property(&publish_property.user_property, user_property_arr, USE_PROPERTY_ARR_SIZE);
        esp_mqtt5_client_set_publish_property(client, &publish_property);
        msg_id = esp_mqtt_client_publish(client, "/messwerte/temperatur", "{\"temperature\":15.34}", 0, 1, 1);
        esp_mqtt5_client_delete_user_property(publish_property.user_property);
        publish_property.user_property = NULL;
        ESP_LOGI(TAG3, "sent publish successful, msg_id=%d", msg_id);
}
euripedesrocha commented 1 month ago

@rk-sTEk I'm not following exactly what you are missing, as I can see the client id stated in the connection log you show.

Could you explain further and add a more complete reproducer?

rk-sTEk commented 1 month ago

Ah...okay...let me specify my "problem". Like you wrote, my ESP-MQTT-client is connecting with the broker and the client ID is visible in the log. But, when the client publishes a message, the client id is missing in the "path" and so an empty "root" is shown in the explorer and so. The reason is visible in the log. Other clients insert their own id in the transmitted path - like in the example with a Shelly device (green). But my ESP-client doesn't do this and so the root in the path is empty (red).

Bildschirmfoto_2024-09-19_21-50-36

Bildschirmfoto_2024-09-19_21-42-55

rk-sTEk commented 1 month ago

Argh...I solved my issue - but I don't know why the MQTT-library isn't auto expand the "path". When I write the client id without preceded slash in the function _esp_mqtt_clientpublish() everything looks fine.

msg_id = esp_mqtt_client_publish(client, "sTEkSensor1/messwerte/temperatur", "{\"temperature\":15.34}", 0, 1, 1);

Is there a chance to get the value from "mqtt_state.connection.information.client_id" which is in client in the main app? Both case, client. and client->, end with an error.

euripedesrocha commented 1 month ago

Hi @rk-sTEk, the mqtt client is written to support all operations required by the specification. There are many possible ways of building a topic string. If we put the client id as a prefix, we would be imposing this decision to systems that don't require it. At this moment, we don't have a way to recover this information. A simple workaround is to pass it as a configuration and keep the information to build the topic string.