Skip to main content
Visitor II
February 25, 2021
Solved

STM32F767 MQTT USING LWIP

  • February 25, 2021
  • 6 replies
  • 9782 views

I am new to LWIP and MQTT. I am trying to use MQTT using LWIP in stm32f767 . I am able to get ethernet connection up and ping also works. I use mqtt_client_connect to connect to the server. The function is as follows:-

mqtt_client_connect(mqtt_client_t *client, const ip_addr_t *ip_addr, u16_t port, mqtt_connection_cb_t cb, void *arg,const struct mqtt_connect_client_info_t *client_info)

{{

 err_t err;

 size_t len;

 u16_t client_id_length;

 /* Length is the sum of 2+"MQTT", protocol level, flags and keep alive */

 u16_t remaining_length = 2 + 4 + 1 + 1 + 2;

 u8_t flags = 0, will_topic_len = 0, will_msg_len = 0;

 LWIP_ASSERT("mqtt_client_connect: client != NULL", client != NULL);

 LWIP_ASSERT("mqtt_client_connect: ip_addr != NULL", ip_addr != NULL);

 LWIP_ASSERT("mqtt_client_connect: client_info != NULL", client_info != NULL);

 LWIP_ASSERT("mqtt_client_connect: client_info->client_id != NULL", client_info->client_id != NULL);

 if (client->conn_state != TCP_DISCONNECTED) {

  LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Already connected\n\r"));

  return ERR_ISCONN;

 }

 /* Wipe clean */

 memset(client, 0, sizeof(mqtt_client_t));

 client->connect_arg = arg;

 client->connect_cb = cb;

 client->keep_alive = client_info->keep_alive;

 mqtt_init_requests(client->req_list);

 /* Build connect message */

 if (client_info->will_topic != NULL && client_info->will_msg != NULL) {

  flags |= MQTT_CONNECT_FLAG_WILL;

  flags |= (client_info->will_qos & 3) << 3;

  if (client_info->will_retain) {

   flags |= MQTT_CONNECT_FLAG_WILL_RETAIN;

  }

  len = strlen(client_info->will_topic);

  LWIP_ERROR("mqtt_client_connect: client_info->will_topic length overflow", len <= 0xFF, return ERR_VAL);

  LWIP_ERROR("mqtt_client_connect: client_info->will_topic length must be > 0", len > 0, return ERR_VAL);

  will_topic_len = (u8_t)len;

  len = strlen(client_info->will_msg);

  LWIP_ERROR("mqtt_client_connect: client_info->will_msg length overflow", len <= 0xFF, return ERR_VAL);

  will_msg_len = (u8_t)len;

  len = remaining_length + 2 + will_topic_len + 2 + will_msg_len;

  LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);

  remaining_length = (u16_t)len;

 }

 /* Don't complicate things, always connect using clean session */

 flags |= MQTT_CONNECT_FLAG_CLEAN_SESSION;

 len = strlen(client_info->client_id);

 LWIP_ERROR("mqtt_client_connect: client_info->client_id length overflow", len <= 0xFFFF, return ERR_VAL);

 client_id_length = (u16_t)len;

 len = remaining_length + 2 + client_id_length;

 LWIP_ERROR("mqtt_client_connect: remaining_length overflow", len <= 0xFFFF, return ERR_VAL);

 remaining_length = (u16_t)len;

 if (mqtt_output_check_space(&client->output, remaining_length) == 0) {

  return ERR_MEM;

 }

 client->conn = tcp_new();

 if (client->conn == NULL) {

  return ERR_MEM;

 }

 /* Set arg pointer for callbacks */

 tcp_arg(client->conn, client);

 /* Any local address, pick random local port number */

 err = tcp_bind(client->conn, IP_ADDR_ANY, 0);

 if (err != ERR_OK) {

  LWIP_DEBUGF(MQTT_DEBUG_WARN,("mqtt_client_connect: Error binding to local ip/port, %d\n\r", err));

  goto tcp_fail;

 }

 LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Connecting to host: %s at port:%"U16_F"\n\r", ipaddr_ntoa(ip_addr), port));

 /* Connect to server */

 err = tcp_connect(client->conn, ip_addr, port, mqtt_tcp_connect_cb);

 if (err != ERR_OK) {

  LWIP_DEBUGF(MQTT_DEBUG_TRACE,("mqtt_client_connect: Error connecting to remote ip/port, %d\n\r", err));

  goto tcp_fail;

 }

 /* Set error callback */

 tcp_err(client->conn, mqtt_tcp_err_cb);

 client->conn_state = TCP_CONNECTING;

 /* Append fixed header */

 mqtt_output_append_fixed_header(&client->output, MQTT_MSG_TYPE_CONNECT, 0, 0, 0, remaining_length);

 /* Append Protocol string */

 mqtt_output_append_string(&client->output, "MQTT", 4);

 /* Append Protocol level */

 mqtt_output_append_u8(&client->output, 4);

 /* Append connect flags */

 mqtt_output_append_u8(&client->output, flags);

 /* Append keep-alive */

 mqtt_output_append_u16(&client->output, client_info->keep_alive);

 /* Append client id */

 mqtt_output_append_string(&client->output, client_info->client_id, client_id_length);

 /* Append will message if used */

 if ((flags & MQTT_CONNECT_FLAG_WILL) != 0) {

  mqtt_output_append_string(&client->output, client_info->will_topic, will_topic_len);

  mqtt_output_append_string(&client->output, client_info->will_msg, will_msg_len);

 }

 return ERR_OK;

tcp_fail:

 tcp_abort(client->conn);

 client->conn = NULL;

 return err;

}

Here we need to pass IP address of the server to which we want to connect. I want to use hostname instead of IP address. What changes will i need to do so that it takes the hostname like "broker.mqttdashboard.com" ??

Thank you for the help.

    This topic has been closed for replies.
    Best answer by Vangelis Fortounas

    Hello

    cubemx memory settings are very conservative and guarantee the min functionality (ICMP and small tcp/udp packets)

    Try, as an emergency workaround, not optimized: (assuming that use CUBEMX)

    increase segment size TCP_MSS to 1460 (this is max for ethernet)

    increase PBUF_POOL_BUFSIZE to 1600 (mss+headers+etc) Send buffer (TCP_SND_BUF) will increase automatically.

    and MEM_SIZE to 16000 (it seems too high but trimming is a time consuming procedure. Make it after, when project is operative)

    6 replies

    Visitor II
    February 25, 2021

    Hello

    LWIP_DNS need to be be defined as 1 inside lwipopts.h to use DNS functionality. (#define LWIP_DNS 1)

    The function dns_gethostbyname(..) or dns_gethostbyname_addrtype(...) functions resolve hostnames to addresses, V4 ,V6

    Theese functions teturn imediately and use callbacks when succeed or have errors.

    Inside dns.c module will find how to use theese functions

    Suggest also to set DNS_TABLE_SIZE above zero , so the resolved addresses will keep in local database until some internal timeout expiration. Then any requst for name resolving will be handled localy.

    sne_123Author
    Visitor II
    February 26, 2021

    @Vangelis Fortounas​  Thank you Sir, will try this today and get back.

    sne_123Author
    Visitor II
    March 8, 2021

    @Vangelis Fortounas​ @Piranha​ Hello Sir, As you said I am able to resolve the DNS properly. Using the IP I try to connect to the MQTT server but my data is not being posted. Seems like my device is not getting connected to MQTT server. Here's the log

    netif: netmask of interface set to 255.255.255.0

    netif: GW address of interface set to 192.168.0.1

    netif_set_ipaddr: netif address being changed

    netif: IP address of interface set to 192.168.0.155

    netif: added interface st IP addr 192.168.0.155 netmask 255.255.255.0 gw 192.168.0.1

    netif: setting default interface st

    m15.cloudmqtt.com: 115.23.0.5

                   ip_string is 115.23.0.5

    115.23.0.5

    inside example_do_connect

    mqtt_client_connect: Connecting to host: 115.23.0.5 at port:1883

    mqtt_publish: Publish with payload length 576 to topic "aeplIN/sidabc12/test"

    Publish err: -1.

    mqtt_tcp_err_cb: TCP error callback: error -13, arg: 20000150

    mqtt_connection_cb entered

    status is 256

    mqtt_connection_cb: Disconnected, reason: 256

    inside example_do_connect

    mqtt_client_connect: Connecting to host: 115.23.0.5 at port:18973

    mqtt_tcp_err_cb: TCP error callback: error -13, arg: 20000150

    mqtt_connection_cb entered

    status is 256

    mqtt_connection_cb: Disconnected, reason: 256

    inside example_do_connect

    mqtt_client_connect: Connecting to host: 115.23.0.5 at port:18973

    mqtt_tcp_err_cb: TCP error callback: error -13, arg: 20000150

    mqtt_connection_cb entered

    status is 256

    what might be the issue? The above log was for payload of 576 length.

     when I try to send a small payload like "hello world" I get the following output.

    netif: netmask of interface set to 255.255.255.0

    netif: GW address of interface set to 192.168.0.1

    netif_set_ipaddr: netif address being changed

    netif: IP address of interface set to 192.168.0.155

    netif: added interface st IP addr 192.168.0.155 netmask 255.255.255.0 gw 192.168.0.1

    netif: setting default interface st

    m15.cloudmqtt.com: 115.23.0.5

                   ip_string is 115.23.0.5

    115.23.0.5

    inside example_do_connect

    mqtt_client_connect: Connecting to host: 115.23.0.5 at port:1883

    mqtt_publish: Publish with payload length 15 to topic "aeplIN/sidabc12/test"

    mqtt_output_send: tcp_sndbuf: 1072 bytes, ringbuf_linear_available: 88, get 0, put 88

    Publish Success.

    mqtt_tcp_err_cb: TCP error callback: error -13, arg: 20000150

    mqtt_connection_cb entered

    status is 256

    mqtt_connection_cb: Disconnected, reason: 256

    inside example_do_connect

    mqtt_client_connect: Connecting to host: 115.23.0.5 at port:1883

    mqtt_tcp_err_cb: TCP error callback: error -13, arg: 20000150

    mqtt_connection_cb entered

    status is 256

    mqtt_connection_cb: Disconnected, reason: 256

    Seems like "mqtt_output_send" is not getting called. Dont know for what reason.

    Visitor II
    March 26, 2021

    Hello @sne_123​ I am having DNS problem in my code. Could you please share What steps you followed to resolve DNS problem.

    I can not get proporly resolved DNS address in callback function.

    sne_123Author
    Visitor II
    March 26, 2021

    @voyvoda .​  Hello... As the above mentors suggested LWIP_DNS need to be be defined as 1 inside lwipopts.h to use DNS functionality. (#define LWIP_DNS 1)

    Have you set the dns server ip address?? Even I had this issue but dns got resolved after I added proper dns server address...I am using code below:-

    dns_init();

    ip_addr_t primaryDnsServer;

        ip4_addr_set_u32(&primaryDnsServer, ipaddr_addr("192.168.0.1")); // here set your dns server address

       dns_setserver(0, &primaryDnsServer);

    char* dnsname = "www.freertos.com";

    ip_addr_t dnsresp;

    dns_gethostbyname(dnsname, &dnsresp, dns_found, 0);

     dns_found(dnsname, &dnsresp, 0);

    and my dns_found is callback here:-

    void dns_found(const char *name, ip_addr_t *addr, void *arg)

    {

    char ip_string[20];char* token1;

      LWIP_UNUSED_ARG(arg);

      printf("%s: %s\n", name, addr ? ip_ntoa(addr) : "<not found>");

    sprintf(ip_string,"%s",addr ? ip_ntoa(addr): "<not found>");

    printf("ip_string is %s\n\r",ip_string);

    }

    sne_123Author
    Visitor II
    March 8, 2021

    OK I got it it was issue of the buffer size,changed MQTT_OUTPUT_RINGBUF_SIZE from 256 to 1024 and now its going ahead and showing me publish success. But I am not able to view data on the server.

    sne_123Author
    Visitor II
    March 9, 2021

    @Vangelis Fortounas​  When publishing message I get an error as follows:-

    tcp_write : could not allocate memory for pbuf copy size 88

    mqtt_output_send: Send failed with err -1 ("Out of memory error.")

    Why am I getting this error?

    Visitor II
    March 15, 2021

    Hello

    seems that memory is exhausted .

    possible causes are

    small MEM_SIZE -> increase it generously

    not freed buffers inside receive callbacks . It is programmers responsibility under certain conditions to frees (pbuf_free(p)) the buffers (struct pbuf p) that passed to receive callbacks (udp_recv_fn and tcp_recv_fn) functions.

    sne_123Author
    Visitor II
    March 16, 2021

    MEM_SIZE  configured in the device is 2000. should I increase it? the data which I am sending is "Hello World", only 11 bytes.

    sne_123Author
    Visitor II
    March 15, 2021

    can anyone help me solve the issue please??

    Graduate II
    March 15, 2021

    What are you compiling with?

    How large is the Heap?​

    sne_123Author
    Visitor II
    March 16, 2021

    I am compiling in keil and heap size is 0x4000