2
votes

I've looked and followed documentation from LwIP 2.0.2. My project contains the MQTT library supplied in the LwIP 2.0.2. I also found some help at https://dzone.com/articles/mqtt-with-lwip-and-the-nxp-frdm-k64f. I'm unable to get a connection, I've used free public MQTT broker but no hope in connection. I can ping my device. Am I doing something wrong?

static void mqtt_test(mqtt_client_t *mqtt_client)
    if (mqtt_client_is_connected(&mqtt_client) == 1)
    {
        example_subscribe(&mqtt_client, NULL);
    } else {
        mqtt_do_connect(&mqtt_client);
    }
}

when I call this method it always enters mqtt_do_connect() never connecting. Here is mqtt_do_connect

static void mqtt_do_connect(mqtt_client_t *mqtt_client)
{
    ip4_addr_t broker_ipaddr;
    struct mqtt_connect_client_info_t ci;
    err_t err;
    if (ipaddr_aton("52.58.177.181", &broker_ipaddr))
    {
        err = ERR_OK;
    }
    /* Setup an empty client info structure */
    memset( & ci, 0, sizeof(ci));
    /* Minimal amount of information required is client identifier, so set it here */
    ci.client_id = "test";
    /* Initiate client and connect to server, if this fails immediately an error code is returned
      otherwise mqtt_connection_cb will be called with connection result after attempting
      to establish a connection with the server.
      For now MQTT version 3.1.1 is always used */
    err = mqtt_client_connect(mqtt_client, & broker_ipaddr, 1883, mqtt_connection_cb, 0, & ci);
    /* For now just print the result code if something goes wrong */
    if (err != ERR_OK) {
        printf("mqtt_connect return %d\n", err);
    }
}

I've also noticed in the method mqtt_client_connect in mqtt.c that this exists:

/* Any local address, pick random local port number */
    err = tcp_bind(client->conn, IP_ADDR_ANY, 0); 

why is this needed? If I replace IP_ADDR_ANY to my local address of the static IP of the device it runs through without throwing a error but no callback mqtt_connection_cb is then called.

I've also initialized the TCP/IP stack as mentioned with static IP. I'm using NO_SYS as 1 but will move it over to FreeRTOS but baby steps first.

I haven't found much support on MQTT in LwIP implementation, am I missing something obvious, any help will be appreciated.

I've used MQTTfx to run a test or two on the broker with good response but nothing from my embedded device (Atmel SAME54).

1

1 Answers

2
votes

I've found the solution. I ran my TCP setup in a FreeRTOS thread and opened a socket

static void mqtt_start(void *p)
{
    struct sockaddr_in address;
    int                s_create, new_socket;
    int                addrlen = sizeof(address);
    int                opt     = 1;
    int                socket_check;

    sys_sem_t sem;
    err_t     err_sem;
    err_sem = sys_sem_new(&sem, 0); /* Create a new semaphore. */
    tcpip_init(tcpip_init_done, &sem);
    sys_sem_wait(&sem); /* Block until the lwIP stack is initialized. */
    sys_sem_free(&sem); /* Free the semaphore. */

    /*Create a socket*/
    s_create = socket(AF_INET, 1, 0);

    setsockopt(s_create, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));

    address.sin_family      = AF_INET;
    address.sin_addr.s_addr = htonl(IPADDR_ANY);
    address.sin_port        = htons(HTTP_PORT);
    /* bind the connection to port */
    socket_check = bind(s_create, (struct sockaddr *)&address, sizeof(address));

    if (socket_check < 0) {
        LWIP_DEBUGF(LWIP_DBG_ON, ("Bind error=%d\n", socket_check));
        goto socket_close;
    }
    /* tell the connection to listen for incoming connection requests */
    listen(s_create, 3);

    mqtt_connect(&mqtt_client);

    for (;;) {
        new_socket = accept(s_create, (struct sockaddr *)&address, (socklen_t *)&addrlen);
        socket_close:
            close(new_socket);
    }
}

I also had a problem with my initialization of my mqtt client, placed a watch on it and saw the struct wasn't initializing. I initialized it globally

mqtt_client_t mqtt_client;

Then use it later in mqtt_start.