Event handler for mqtt connected / reconnected

When using mosquitto server, I would like to publish to a topic whenever a successful connection / reconnection is made. I checked the mongoose-os/fw/src/mgos_mqtt.c file, I found MG_EV_MQTT_CONNACK, but I don't know how to add a handler for it. Any hints please?

Comments

  • rojerrojer Dublin, Ireland

    mgos_mqtt_add_global_handler.

  • Thanks! I'll try using ffi() in js.

  • I put these in init.js:

    let add_global_handler = ffi('void mgos_mqtt_add_global_handler(void (*)(void *, int, userdata), userdata)');
    let conn_eh = function(conn, ev, ev_data) {
        print('conn_eh fire on ev=', ev);
    };
    add_global_handler(conn_eh, null);
    

    But got this error:

    mgos_app_init        MJS exec error: failed to call FFI signature "void mgos_mqtt_add_global_handler(void (*)(void *, int, userdata), userdata)": cannot resolve function ca
    

    Any hints please?

  • Ok, the error is fixed by building the firmware with the function call included in ffi export.

  • But once the handler is used in init.js , system crashes repeatedly:

    ---- END CORE DUMP ----
    rebooting
    
     ets Jan  8 2013,rst cause:2, boot mode:(3,7)
    
    load 0x40100000, len 1720, room 16 
    tail 8
    chksum 0xe7
    load 0x3ffe8000, len 784, room 0 
    tail 0
    chksum 0xd0
    !�� � �n��r��n|� �lrl��r�l��mode : softAP(a2:20:a6:15:81:88)�� �I-A%��-!E�!� -�Q�Any+!�v-I-9� �YNQ 5Y 
    a
    esp_mgos_init2       mjs_base 1.0 (20170312-092911/???)
    esp_mgos_init2       Mongoose OS Firmware 2017031209 (20170312-092911/???)
    esp_mgos_init2       SDK 2.0.0(656edbf), RAM: 53056 total, 49756 free
    esp_print_reset_info Reset cause: 4 (soft reset)
    fs_mount             Mounting FS: 131072 @ 0xdb000
    mgos_sys_config_init MAC: A220A6158188
    mgos_sys_config_init WDT: 30 seconds
    bcn 0
    del if1
    usl
    mode : null
    mgos_wifi_set_mode   WiFi mode: STA
    mode : sta(a0:20:a6:15:81:88)
    add if0
    mgos_wifi_setup_sta  WiFi STA: Connecting to TOTO_2G
    mgos_i2c_create      I2C GPIO init ok (SDA: 12, SCL: 14)
    mgos_sys_config_init HTTP server started on [80]
    mg_rpc_channel_mqtt  0x3ffef3e4 wd-001/rpc/#
    mg_rpc_channel_uart  0x3ffefb0c UART0
    mgos_app_init        mJS memory stat: before init: 47432 after init: 46448 after init.js: 36252
    mgos_init            Init done, RAM: 36252 free, 32760 min free
    scandone
    state: 0 -> 2 (b0)
    state: 2 -> 3 (0)
    state: 3 -> 5 (10)
    add 0
    aid 1
    cnt 
    
    connected with TOTO_2G, channel 3
    dhcp client start...
    mgos_wifi_on_change_ Wifi: connected
    ip:192.168.0.231,mask:255.255.255.0,gw:192.168.0.1
    mgos_wifi_on_change_ WiFi: ready, IP 192.168.0.231
    mqtt_global_reconnec MQTT connecting after 1990 ms
    
    Exception 28 @ 0x402737d2, vaddr 0x0000008d
     A0: 0x402736ff  A1: 0x3ffffd20  A2: 0x00000008  A3: 0x00002089
     A4: 0x00000000  A5: 0x00000000  A6: 0x00ff0000  A7: 0xff000000
     A8: 0x00000000  A9: 0x3ffffd94 A10: 0x3ffe9050 A11: 0xffff8000
    A12: 0x0000008d A13: 0x00000004 A14: 0x00000056 A15: 0x00000002
    
    (exc SP: 0x3ffffb80)
    
    --- BEGIN CORE DUMP ---
    {"arch": "ESP8266",
    "REGS": {"addr": 1073740720, "data": "
    /zYnQCD9/z8IAAAAiSAAAAAAAAAAAAAAAAD/AAAAAP8AAAAAlP3/P1CQ/j8AgP//jQAAAAQAAABWAAAAAgAAANI3J0AQAAAAAAAAAAAAAAAAAAAAMAAAAA==", "crc32": 1804639329},
    "DRAM": {"addr": 1073643520, "data": "
    AAAAADcTIkAKIiFAHyIhQDMiIUAKIiFAHyIhQKAAAAABAAAA3JUhQG4ZAABt9n8VeAAAAP8AAAABAAAAAwAAAAQAAAAAAAAABgAAAAcAAAAAAAAAK8AAACzAAAAAAAAABgAAAAUAAAAEAAAAAAAAAAwTIUAAAAAA
    
  • SergeySergey Dublin, Ireland

    That's expected, because Mongoose handlers do not expect userdata.
    Only callbacks that expect userdata can be ffi-ed.
    Let us discuss what's the best way to deal with it.

  • I am no expert on Mongoose. As a user, the most attractive feature is to be able to do things using js only.

    Perhaps you can add a global handler to pass the event to a ffi compatible function which we can use to register our own js handler code to do things.

  • I have an ad-hoc solution by referencing the c_mqtt build example, just in case someone is interested, the diff is here:

    diff --git a/fw/examples/mjs_base/src/conf_schema.yaml b/fw/examples/mjs_base/src/conf_schema.yaml
    index 8b3db34..2eea69a 100644
    --- a/fw/examples/mjs_base/src/conf_schema.yaml
    +++ b/fw/examples/mjs_base/src/conf_schema.yaml
    @@ -1,4 +1,5 @@
     [
       ["mqtt.server", "test.mosquitto.org:1883"],
       ["i2c.enable", true],
    +  ["mqtt.pub", "s", "/online", {title: "Online topic"}],
     ]
    diff --git a/fw/examples/mjs_base/src/main.c b/fw/examples/mjs_base/src/main.c
    index 0eff8ef..f3b65e0 100644
    --- a/fw/examples/mjs_base/src/main.c
    +++ b/fw/examples/mjs_base/src/main.c
    @@ -8,6 +8,7 @@
     #include "fw/src/mgos_timers.h"
     #include "fw/src/mgos_hal.h"
     #include "fw/src/mgos_dlsym.h"
    +#include "fw/src/mgos_mqtt.h"
     #include "mjs.h"
    
     #if CS_PLATFORM == CS_P_ESP8266
    @@ -30,6 +31,31 @@ int get_led_gpio_pin(void) {
       return LED_GPIO;
     }
    
    +static void pub(struct mg_connection *c, const char *fmt, ...) {
    +  char msg[200];
    +  struct json_out jmo = JSON_OUT_BUF(msg, sizeof(msg));
    +  va_list ap;
    +  int n;
    +  va_start(ap, fmt);
    +  n = json_vprintf(&jmo, fmt, ap);
    +  va_end(ap);
    +  mg_mqtt_publish(c, get_cfg()->mqtt.pub, 0, MG_MQTT_QOS(0), msg, n);
    +  LOG(LL_INFO, ("%s -> %s", get_cfg()->mqtt.pub, msg));
    +}
    +
    +static void mqtt_ev_handler(struct mg_connection *c, int ev, void *p) {
    +  struct mg_mqtt_message *msg = (struct mg_mqtt_message *) p;
    +
    +  if (ev == MG_EV_MQTT_CONNACK) {
    +    LOG(LL_INFO, ("CONNACK: %d", msg->connack_ret_code));
    +    if (get_cfg()->mqtt.pub == NULL) {
    +      LOG(LL_ERROR, ("Run 'mos config-set mqtt.pub=... '"));
    +    } else {
    +      pub(c, "%s", "{\"online\":1}");
    +    }
    +  }
    +}
    +
     enum mgos_app_init_result mgos_app_init(void) {
       /* Initialize JavaScript engine */
       int mem1, mem2, mem3;
    @@ -45,5 +71,6 @@ enum mgos_app_init_result mgos_app_init(void) {
       LOG(LL_INFO, ("mJS memory stat: before init: %d "
                     "after init: %d after init.js: %d",
                     mem1, mem2, mem3));
    +  mgos_mqtt_add_global_handler(mqtt_ev_handler, NULL);
       return MGOS_APP_INIT_SUCCESS;
     }
    
    
  • SergeySergey Dublin, Ireland

    Yes, in C everything is possible.
    We'll make a change in mongoose to let its callbacks be directly ffi-able.

Sign In or Register to comment.