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.
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.