Search code examples
mqttethernetstm32cubeidelwipstm32f7

MQTT on STM32CubeIDE (hardware STM32F756ZGT6 nucleo-144)


I am very new to stm32cubeIDE and am trying to create a mqtt connection with my stm, first with my computer to try, then it will be used with a raspberry pi. I already have a state machine running on my Raspberry Pi, but not enough ports for my application, that's why I need to migrate to stm32.

I've set up the ethernet and I can ping the static IP address I declared for my stm, using LwIP(v2.1.2). I'm also using a USB port to debug to which I've redirected the output printf. I followed this and some lwip doc and managed to create a mqtt client, connect to a broker (for my testing I'll be using mosquitto broker: "test.mosquitto.org"->91.121.93.94) and send a message, at least that what says the log. The issue is that I'm unable to see the message.

My method is: I connect to a command line and I run this

mosquitto_sub -h 91.121.93.94 -t pub_topic

When I try to publish from another command line I receive the message on the first one, but for some reason it's not working to receive the ones from my stm32. Also, when I try to send multiple messages it stops at 4 and I get

Publish err: -1

It's an Out of memory error, and I get that even when I'm modifying MQTT_REQ_MAX_IN_FLIGHT (from 4 to 10 for example) so I guess my message is not really sent because it should have emptied the buffer ? And I'm annoyed that mqtt_publish() nor mqtt_output_send() doesn't really help to check if the message is really sent, so idk what to do now.

Here is my code for reference, idk if I should as well send my config

Creation of my mqtt client and connection to the broker

void mqtt_new(mqtt_client_t *client){
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, 0);
    HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, 0);
    HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
    HAL_Delay(2500);//let time to open app to see output from printf redirected to usb
    HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 0);
    printf("mqtt_new client\n");
    client = mqtt_client_new();
    if (NULL != client){
        mqtt_connect(client);
    }
    else{
        printf("impossible to create a mqtt client\n");
    }
}

//1.2: Establish Connection with server

void mqtt_connect(mqtt_client_t *client){
  ip_addr_t broker_ip;
  struct mqtt_connect_client_info_t ci;
  err_t err;
  memset(&ci, 0, sizeof(ci));
  ci.client_id = "lwip_test";
  IP4_ADDR(&broker_ip, 91,121,93,94);//ipaddr_aton("91.121.93.94",&broker_ip);
  err = mqtt_client_connect(client, &broker_ip, MQTT_PORT, mqtt_connection_cb, 0, &ci);
  while (err != ERR_OK)
  {
      printf("mqtt_connect err : %d ; retry\n",err);
      err = mqtt_client_connect(client, &broker_ip, MQTT_PORT, mqtt_connection_cb, 0, &ci);
      HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
      HAL_Delay(500);
  }
  if(ERR_OK == err){
      printf("mqtt_connect: connected to broker\n");
      HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, SET);
      for(int i=0;i<15;i++){
          example_publish(client, 0);
      }
      //example_publish(client, 0);
  }
}

Callback function for connection an subscription

static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
{
    HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
    //HAL_Delay(300);
    err_t err;
    if(status == MQTT_CONNECT_ACCEPTED) {
        /* Setup callback for incoming publish requests */
        mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);

        /* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */
        err = mqtt_subscribe(client, "cb_subtopic", 1, mqtt_sub_request_cb, arg);

        if(err != ERR_OK) {
            printf("mqtt_subscribe return: %d\n", err);
        }
        else{
            printf("mqtt_subscribe in cb\n");
        }
    }
    else {
          printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);//status = 256 = MQTT_CONNECT_DISCONNECTED
          HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
          /* Its more nice to be connected, so try to reconnect */
          mqtt_connect(client);
    }
}

This is untouched from the previous link about mqtt

static int inpub_id;
static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
{
    printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);

    /* Decode topic string into a user defined reference */
    if(strcmp(topic, "print_payload") == 0) {
        inpub_id = 0;
    } else if(topic[0] == 'A') {
        /* All topics starting with 'A' might be handled at the same way */
        inpub_id = 1;
    } else {
        /* For all other topics */
        inpub_id = 2;
    }
}

static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
    {
    printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);

    if(flags & MQTT_DATA_FLAG_LAST) {
        /* Last fragment of payload received (or whole part if payload fits receive buffer
        See MQTT_VAR_HEADER_BUFFER_LEN)  */
        /* Call function or do action depending on reference, in this case inpub_id */
        if(inpub_id == 0) {
            /* Don't trust the publisher, check zero termination */
            if(data[len-1] == 0) {
                printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
            }
        } else if(inpub_id == 1) {
            /* Call an 'A' function... */
        } else {
            printf("mqtt_incoming_data_cb: Ignoring payload...\n");
        }
     } else {
        /* Handle fragmented payload, store in buffer, write to file or whatever */
     }
}

And then the publish part

void example_publish(mqtt_client_t *client, void *arg)
{
      const char *pub_payload= "this is the message";
      err_t err;
      u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
      u8_t retain = 0;
      err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
      if(err != ERR_OK) {
          printf("Publish err: %d\n", err);
      }
      else{
            printf("Published\n");
            for(int i=0;i<2;i++){
                HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 1);
                HAL_Delay(100);
                HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, 0);
                HAL_Delay(100);
            }
      }
}
/* Called when publish is complete either with success or failure */
static void mqtt_pub_request_cb(void *arg, err_t result)
{
      if(result != ERR_OK) {
          printf("Publish result: %d\n", result);
      }
}

Please let me know if I'm doing it wrong or if you have an idea about what should I change in my code. Thanks for all the help provided.


Solution

  • Well I solved it, everything on the card was ok, I just didn't have the right permissions on the public broker test.mosquitto.org, I tried with a broker configured on my Rpi and now I can receive messages from the stm on a command line. Now I'm going to try to send info from my computer to the stm I'll keep you updated.