MQTT publish via Mongoose

mjmorrison
Posts: 26
Joined: Thu Nov 03, 2016 9:06 pm

MQTT publish via Mongoose

Postby mjmorrison » Thu Jan 05, 2017 9:02 pm

Hey all,

I'm using the following code to try to set up an mqtt connection and publish. As you can see I'm using arduino as a component for the ESP-IDF.

My event handler never receives any events, which started me digging down this path. It looks like there may be a socket issue? But it may be that one issue causes the other... Any help would be appreciated!

Code: Select all

#include <string.h>

#include "Arduino.h"
#include <WiFi.h>

#include "mongoose.h"

#include "esp_spiffs.h"
#include "esp_spiffs.c"
#include "spiffs.h"
#include "spiffs_vfs.h"
#include "esp_vfs.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"

#include "esp_system.h"
#include "esp_log.h"

// RTOS stuff
int CONNECTION_CHECK_RATE = 5000;
int DEFAULT_TASK_DELAY = 1000;
int DEFAULT_SMPHR_WAIT = 500;


// connection stuff
const char* ssid = "mywifi";
const char* pass = "mypassword";

bool mqtt_initialized = false;
bool wifi_initialized = false;

const struct mg_mqtt_topic_expression test_topic = { "/variousthings", 1 }; //"{topic, QOS}"

static void mongoose_event_handler( struct mg_connection *nc, int ev, void *evData )
{   
    printf("inside event handler\n");
    switch( ev )
    {
        case MG_EV_CONNECT      :   printf("MG_EV_CONNECT\n");
                                    break;
                                    
        case MG_EV_MQTT_CONNACK :   printf("MG_EV_MQTT_CONNACK\n");
                                    printf( "we connected" );
                                    // mg_mqtt_subscribe( &mqtt_connection, &test_topic, 1, 42 );
                                    break;

        case MG_EV_MQTT_PUBACK  :   printf("MG_EV_MQTT_PUBACK");
                                    break;
    }
}

// static const char *s_address = "test.mosquitto.org:1883";
static const char *s_address = "tcp://37.187.106.16:1883";

void init_mongoose()
{
	struct mg_mgr mgr;
	mg_mgr_init( &mgr, NULL );
    
    struct mg_connection *mqtt_connection = mg_connect( &mgr, s_address, mongoose_event_handler );
    mg_set_protocol_mqtt( mqtt_connection ); // attach built in event handler

	if( mqtt_connection != NULL )
	{
		printf("mg_connection created successfully\n");
	}
	else
	{
		printf("mg_connection not created\n");
	}	
	mg_mqtt_publish( mqtt_connection, "/variousthings", 1, MG_MQTT_QOS(0), "apples", 6 ); // breaks things

    mqtt_initialized = true;
}

/*
 * maintains wifi and mqtt connections
 */

void manage_connection_task( void *p )
{
    while( true )
    { 
        if ( WiFi.status() == WL_CONNECTED && !mqtt_initialized )
        {
            printf("initting mongoose\n");
            init_mongoose();
        }
        else if( WiFi.status() != WL_CONNECTED && !wifi_initialized )
        {
            printf("initting wifi\n");
            WiFi.begin( ssid, pass );
            wifi_initialized = true;
        }
        else if ( WiFi.status() == WL_CONNECTED && wifi_initialized && mqtt_initialized )
        {
            struct mg_mgr mgr;
            mg_mgr_poll( &mgr, 1000 );
            //printf("num ifaces: %d\n", mgr.num_ifaces);
        }
        vTaskDelay( 250 / portTICK_PERIOD_MS );
    }
}

int idx = 0;

extern "C" void app_main()
{

    struct timeval time;
    gettimeofday( &time, NULL );
    printf( "%ld", time.tv_sec );
    initArduino();
    
    xTaskCreate( &manage_connection_task,
                 "manage_connection_task",
                 2048,
                 NULL,
                 5,
                 NULL );
}
When I try to poll for work, I see this:

Code: Select all

mg_mgr_poll          cannot poll: no interfaces
So I turned on debugging, and the following is the output:

Code: Select all

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0x00
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3ffc0008,len:0
load:0x3ffc0008,len:1964
load:0x40078000,len:3696
ho 0 tail 12 room 4
load:0x40080000,len:260
entry 0x40080034
I (689) heap_alloc_caps: Initializing heap allocator:
I (689) heap_alloc_caps: Region 19: 3FFC1288 len 0001ED78 tag 0
I (690) heap_alloc_caps: Region 25: 3FFE8000 len 00018000 tag 1
I (701) cpu_start: Pro cpu up.
I (706) cpu_start: Single core mode
I (713) cpu_start: Pro cpu start user code
W (809) cpu_start: failed to load RF calibration data, falling back to full calibration
I (2261) phy: phy_version: 258, Nov 29 2016, 15:51:07, 0, 2
I (2928) cpu_start: Starting scheduler on PRO CPU.
1tcpip_task_hdlxxx : 3ffc4e20, prio:18,stack:2048
I (2937) wifi: frc2_timer_task_hdl:3ffc68d8, prio:22, stack:2048
I (2946) wifi: pp_task_hdl : 3ffc9148, prio:23, stack:8192
initting wifi
I (2948) wifi: mode : softAP (24:0a:c4:00:03:6d)
dhcp server start:(ip: 192.168.4.1, mask: 255.255.255.0, gw: 192.168.4.1)
I (2958) wifi: mode : sta (24:0a:c4:00:03:6c) + softAP (24:0a:c4:00:03:6d)
I (4589) wifi: ap channel adjust o:1,1 n:11,2
I (4589) wifi: n:11 0, o:1 0, ap:11 2, sta:11 0, prof:1
I (5237) wifi: state: init -> auth (b0)
I (5239) wifi: state: auth -> assoc (0)
I (5247) wifi: state: assoc -> run (10)
I (5356) wifi: connected with JUSTICE, channel 11
I (8039) event: ip: 172.20.10.9, mask: 255.255.255.240, gw: 172.20.10.1
initting mongoose
mg_socket_if_init    0x3ffca490 using select()
mg_mgr_init_opt      ==================================
mg_mgr_init_opt      init mgr=0x3ffca490
mg_do_connect        0x3ffc30b0 tcp://37.187.106.16:1883
mg_socket_if_connect_tcp 0x3ffc30b0 sock 0 rc -1 errno 119 err 0
mg_add_conn          0x3ffca490 0x3ffc30b0
mg_connection created successfully
mg_mgr_poll          cannot poll: no interfaces
mg_mgr_poll          cannot poll: no interfaces
Did some digging and errno 119 for lwip means no XENIX semaphores available.

No idea what that means! I'm pretty sure I want to use MQTT without sockets, but not sure if that is possible with mongoose.

User avatar
kolban
Posts: 1683
Joined: Mon Nov 16, 2015 4:43 pm
Location: Texas, USA

Re: MQTT publish via Mongoose

Postby kolban » Wed Jan 11, 2017 5:49 pm

I think if we look at your logic there may be an issue. When you issue mg_mgr_init() you pass in a struct mg_mgr ... great. However, when you later call mg_mgr_poll(), you are passing a different and un-initialized version of a struct mg_mgr. Normally, you would have one instance of struct mg_mgr that is used throughout your application.

If this is the case, then this wasn't an ESP32 issue but a Mongoose API issue ... not a problem posting here ... but just wanted to say that to point out that when working with varied libraries, some issues and challenges will be ESP32 related and some will be related to the usage of those libraries themselves.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32

mjmorrison
Posts: 26
Joined: Thu Nov 03, 2016 9:06 pm

Re: MQTT publish via Mongoose

Postby mjmorrison » Wed Jan 11, 2017 8:14 pm

Ah, yes that makes sense! Forgive the noob-ishness, I'm getting up to speed with c/cpp etc.

Compiler was throwing errors that manager wasn't defined, so that was an attempt to forward declare. I see now that it created an entirely new instance instead.

Perhaps that's not the best way and I should move some code around instead... I had hesitated to make the manager have global scope because reasons, but that may be the way forward until I get organized.

Thank you!

mjmorrison
Posts: 26
Joined: Thu Nov 03, 2016 9:06 pm

Re: MQTT publish via Mongoose

Postby mjmorrison » Fri Jan 13, 2017 1:45 am

And the saga continues:

Events are streaming in fine now that the correct manager is being referenced.

Now I'm trying to publish periodically from a freeRTOS task.

I tried to pass in a pointer to the connection and dereference inside and got these errors:

Code: Select all

/Users/.../build/main/libmain.a(main.o):(.literal.app_main+0x28): undefined reference to `__cxa_guard_acquire'
/Users/.../build/main/libmain.a(main.o):(.literal.app_main+0x2c): undefined reference to `__cxa_guard_release'
/Users/.../build/main/libmain.a(main.o): In function `app_main':
/Users/.../main/./main.cpp:117: undefined reference to `__cxa_guard_acquire'
/Users/.../main/./main.cpp:119: undefined reference to `__cxa_guard_release'
So I figured it must be something I did, and looked around the mongoose docs and found a way to access connections through the manager, using mg_next(). Did so, and now I'm getting the same group of errors as above!

I traced the error to this file:
https://github.com/espressif/esp-idf/bl ... guards.cpp

And saw that tip about the build flag at the bottom. So I added the appropriate flag to component.mk and the errors persist! Very exciting. Here is my code for reference.

Code: Select all

#include <string>
#include <time.h>
#include <sys/time.h>

#include "Arduino.h"
#include <WiFi.h>

#include "mongoose.h"

#include "esp_spiffs.h"
#include "esp_spiffs.c"
#include "spiffs.h"
#include "spiffs_vfs.h"
#include "esp_vfs.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"

#include "esp_system.h"
#include "esp_log.h"

#include "apps/sntp/sntp.h"

// RTOS stuff
int CONNECTION_CHECK_RATE = 5000;
int DEFAULT_TASK_DELAY = 1000;
int DEFAULT_SMPHR_WAIT = 500;

// connection stuff
const char* ssid = "mywifi";
const char* pass = "mypass";

bool mongoose_initialized = false;
bool wifi_initialized = false;
bool wifi_got_ip = false;

void WiFiEvent( WiFiEvent_t event )
{
    printf("[WiFi-Event] (%d) ", event );

    switch( event )
    {
        case SYSTEM_EVENT_STA_GOT_IP:
            printf( "WiFi connected\n" );
            wifi_got_ip = true;
            break;

        case SYSTEM_EVENT_STA_DISCONNECTED:
            WiFi.reconnect();
            printf( "WiFi lost connection\n" );
            wifi_got_ip = false;
            break;

        default:
            break;
    }
}

const struct mg_mqtt_topic_expression test_topic = { "/variousthings", 1 }; //"{topic, QOS}"

static void mongoose_event_handler( struct mg_connection *nc, int ev, void *evData )
{   
    printf("[MG---Event] (%d) ", ev );
    switch( ev )
    {
        case MG_EV_CONNECT:
        {
            printf( "MG_EV_CONNECT\n" );
            mongoose_initialized = true;
            char hello_message[] = "first message :D";
            mg_mqtt_publish( nc,"/variousthings", 1, MG_MQTT_QOS(1),
                (const void *) hello_message, 12 );
            mg_mqtt_subscribe( nc, &test_topic, 1, 42 );
            break;
        }
                                    
        case MG_EV_MQTT_CONNACK:
            printf( "MG_EV_MQTT_CONNACK\n" );
            break;

        case MG_EV_MQTT_PUBACK:
            printf( "MG_EV_MQTT_PUBACK\n" );
            break;

    }
}

struct mg_mgr mgr;
void mongoose_task( void *p )
{
    while( true )
    {
        if( WiFi.status() == WL_CONNECTED && mongoose_initialized )
        {
            printf("routine publish\n");
            mg_mgr_poll( &mgr, 1000 );
            for( struct mg_connection *c = mg_next( &mgr, NULL ); c != NULL; c = mg_next( &mgr, c) )
            {
                mg_mqtt_publish( c, "/variousthings", 1, MG_MQTT_QOS(0), "apples", 6 );
            }
        }
    }
}

int idx = 0;

extern "C" void app_main()
{
    initArduino();

    WiFi.onEvent( WiFiEvent );
    WiFi.begin( ssid, pass );

    
    mg_mgr_init( &mgr, NULL );  
    static const char *s_address = "tcp://37.187.106.16:1883";
    static struct mg_connection *mqtt_connection = mg_connect( &mgr, s_address, mongoose_event_handler );
    mg_set_protocol_mqtt( mqtt_connection );
    
    xTaskCreate( &mongoose_task,
                 "mongoose_task",
                 5096,
                 NULL,
                 5,
                 NULL );
}

Who is online

Users browsing this forum: No registered users and 121 guests