This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC3200 MQTT Client Disconnect & Reconnect to Server

Other Parts Discussed in Thread: CC3200, CC3200SDK

Hi,


I am using CC3200 SDK 1.2.0's MQTT Client example, CC3200 works as a MQTT Client.

CCS version: 6.1.2.00015

SDK version: 1.2.0

1) Disconnected by Server and client try re-connect to server

When it was disconnected by the server (using CCS, pause execution in debuggin, such that no PING request is send to server and let the server side regard as keep alive timeout), The MQTT Client example can notify this and execute to a LOOPFOREVER statement.

Since i would like to test CC3200 is able to re-connect to the MQTT server when connection is lost, i modified the code to run from the beginning of the task MqttClient(). But after connection lost and when comes to the sl_ExtLib_MqttClientConnect() again, this function always return fail.

2) Actively executing disconnect function in Client side and the client try re-connect to server

The function sl_ExtLib_MqttClientDisconnect() is added to the main task MqttClient()'s PUSH_BUTTON_SW3_PRESSED response. But when executing this funciton, the program just hang.

Does anyone know to test with the re-connect issue?

Thanks!

Eric

  • Hello Eric,

    I want to understand a bit more on the modifications you did.

    Reconnection test:

    When broker disconnects you, do you get the BROKER_DISCONNECTION event? If so, as you can see, it tests for WiFi connection lost and if WiFi is still connected and it was your only connection, it would end up deinitializing MQTT and exit.

    In your case, it may be that in your test you did not deinitialize and when calling back to MqttClient() from the beginning, you implicitly initialize MQTT again.

    What I suggest for the test is that you call to connect_to_broker label at disconnect as in the example but do make sure WiFi connection is still on.

    BTW, it may be that you did not reconnect because it was your only connection.

    Actively disconnection:

    Where have you added the disconnect? is it on the handler itself (i.e. pushButtonInterruptHandler3) or where PUSH_BUTTON_SW3_PRESSED is handled @MqttClient()? What do you mean by hang? where in the code?

    Regards,

    Shlomi

  • Hi Shlomi,


    Thanks for your reply.

    Reconnection Test  - Being disconnected by server side

    The MQTT event call back handler sl_MqttDisconnect() was able to be executed and send a message through a write to message queue g_PBQueue.
    After this event handler, in the MQTT main task MqttClient() will get this message:

    if(BROKER_DISCONNECTION == RecvQue.event){

    lRetVal = sl_ExtLib_MqttClientCtxDelete(((connect_config*)(RecvQue.hndl))->clt_ctx);

    ...

    ...

                    if(iConnBroker < 1)
                    {
                        //
                        // device not connected to any broker
                        //
                        goto end;
                    }

    end:

        sl_ExtLib_MqttClientExit();

        UART_PRINT("\n\r Exiting the Application\n\r");     <------ I want to go back and try connection again from here
        
        LOOP_FOREVER();

    }

    The example program will goto the end and loop forever status.

    I want the task to go back to try again the connection to server. I added a while loop in the beginning of MQTT Init.

    And the program always fail to connect to MQTT server when comes to the execution of sl_ExtLib_MqttClientConnect().

    Here shows the while loop that is added inside the task MqttClient():

    void MqttClient(void *pvParameters){

    ...

    ...

       //
        // Register Push Button Handlers
        //
        Button_IF_Init(pushButtonInterruptHandler2,pushButtonInterruptHandler3);
        

        while (1){      <--------------- add the while loop here



        //
        // Initialze MQTT client lib
        //
        lRetVal = sl_ExtLib_MqttClientInit(&Mqtt_Client);
        if(lRetVal != 0)
        {
            // lib initialization failed
            UART_PRINT("MQTT Client lib initialization failed\n\r");
            LOOP_FOREVER();
        }

    ...

    ...

    // Cannot connect to MQTT server again...

            if((sl_ExtLib_MqttClientConnect((void*)local_con_conf[iCount].clt_ctx,
                                local_con_conf[iCount].is_clean,
                                local_con_conf[iCount].keep_alive_time) & 0xFF) != 0)
            {
                UART_PRINT("\n\rBroker connect fail for conn no. %d \n\r",iCount+1);
                
                //delete the context for this connection
                lRetVal = sl_ExtLib_MqttClientCtxDelete(local_con_conf[iCount].clt_ctx);
                UART_PRINT("DeleteCtx_R1 = %d\r\n", lRetVal);
                break;
            }
            else
            {
                UART_PRINT("\n\rSuccess: conn to Broker no. %d\n\r ", iCount+1);
                local_con_conf[iCount].is_connected = true;
                iConnBroker++;
            }

    ...

    ...

    end:

        sl_ExtLib_MqttClientExit();

        UART_PRINT("\n\r Exiting the Application\n\r");     <------ I want to go back and try connection again from here
        

    } <--- while loop end here


    //    LOOP_FOREVER();

    }

    Reconnection Test  - By switching off cell phone's AP

    CC3200 is connected to cell phone through Wifi and then through cell phone to the internet.

    when i switch off the AP function of the cell phone, CC3200 can execute the BROKER_DISCONNECTION event successfully.

                else if(BROKER_DISCONNECTION == RecvQue.event)
                {
                    iConnBroker--;


                    /* Derive the value of the local_con_conf or clt_ctx from the message */
                    lRetVal = sl_ExtLib_MqttClientCtxDelete(((connect_config*)(RecvQue.hndl))->clt_ctx);


                    if(!IS_CONNECTED(g_ulStatus))
                    {
                        UART_PRINT("device has disconnected from AP \n\r");

                        UART_PRINT("retry connection to the AP\n\r");

                        while(!(IS_CONNECTED(g_ulStatus)) || !(IS_IP_ACQUIRED(g_ulStatus)))
                        {
                            osi_Sleep(10);
                        }
                        goto connect_to_broker;

                    }
                    if(iConnBroker < 1)
                    {
                        //
                        // device not connected to any broker
                        //
                        goto end;
                    }
                }

    For this case the program will not goto the end; it will wait for the connection to the cell phone and go to connect_to_broker. This time seems works fine.

    Actively disconnection:

    I would like to change the CC3200 from Station Mode to AP Mode by use of the network interface's API: Network_IF_DeInitDriver() - want to call this when receiving a user defined message "Change to AP Mode" through MQTT.

    Network_IF_InitDriver() - want to execute this function to start AP Mode.

    So i want to try this by pressing a push button (which should be the same to receiving a user defined message "Change to AP Mode" through MQTT) and modified the code like this:

    Inside the main task MqttClient():

        for(;;)
        {
            osi_MsgQRead( &g_PBQueue, &RecvQue, OSI_WAIT_FOREVER);

    ....

            else if(PUSH_BUTTON_SW3_PRESSED == RecvQue.event)
            {
                Button_IF_EnableInterrupt(SW3);

                sl_ExtLib_MqttClientDisconnect((void*)local_con_conf[iCount].clt_ctx);  <--- fail here; never return
            }

    ....

    The program never return from sl_ExtLib_MqttClientDisconnect().

    How to de-initiallize the MQTT? And where should i call the network API? i mean the Network_IF_DeInitDriver() & Network_IF_InitDriver(ROLE_AP).

    Thanks for support!

    Best Regards,

    Eric

     

  • Further test on:

    Reconnection Test - By switching off cell phone's AP

    when switching off the cell phone's AP and switching on again, CC3200's uart terminal output the following errors:

    Success: conn to Broker no. 1
    MQP alloc failed - msg type 0x08
    Subscription Error for conn no. 1
    Disconnecting from the broker
    C: FH-B1 0xe0 to net 17, Sent (2 Bytes) [@ 40]
    C: TX closing Net 17 [DISCONN]
    C: Net 17, Raw Error -1, Time Out: N
    C: RX closing Net 17 [-1]
    C: Cleaning session for net 17
    C: Net 17 now closed
    disconnect from broker messagesight.demos.ibm.com



    Best Regards,

    Eric
  • Hello,

    At least for the reconnection scenario, I do not understand why you have not followed my instructions.

    You jumped to the beginning of the function instead of connect_to_broker label at disconnect.

    I tested the same and it works fine to me.

    All I did is added the following line in yellow:

    else if(BROKER_DISCONNECTION == RecvQue.event)
    {
    iConnBroker--;
    /* Derive the value of the local_con_conf or clt_ctx from the message */
    sl_ExtLib_MqttClientCtxDelete(((connect_config*)(RecvQue.hndl))->clt_ctx);

    goto connect_to_broker;

    if(!IS_CONNECTED(g_ulStatus)).....

    What would happen is that the MQTT would be initialized again after being deinitialized and connection to broker should succeed (at least in my experiments).

    You must verify that the WiFi connection is still on so emulate the disconnection not by powering off the access point. Maybe you can do it by disconnecting from the browser that is connected to the broker.

    Please let me know if it works for you.

    Regards,

    Shlomi

  • Hi Eric

    I would recommend you to use auto-connect mode in the CC3200 so you don't have to take care of the Wi-Fi connection, you just have to check if the CC3200 is connected to the Wi-Fi before to try to reconnect to the MQTT broker, with a flag set when the IP address is acquired.

    In my code I wait to reconnect until a flag is set in the next function:

    /*------------------------------------------------------------------------------
     * Routine to manage error conditions in client - close the network connection
     *----------------------------------------------------------------------------*/
    static void do_net_close(struct client_ctx *cl_ctx)
    {
            i32 net = cl_ctx->net;
    
            if(-1 == net)
                    return;  /* network closed already, must not happen */
    
            if(IS_CLN_SESSION(cl_ctx)) {
                    session_delete(cl_ctx);
            } else if(!IS_PROTO_VER31(cl_ctx)){
                    /* Version 3.1.1 doesn't need SUB and UNSUB re-send */
                    session_311fix(cl_ctx);
            }
    
            tx_part_reset(&CLIENT(cl_ctx)->tx_part); /* Part TX, if any */
    
            cl_ctx->flags &= ~(CONNACK_AWAIT_FLAG | NOW_CONNECTED_FLAG |
                               KA_PINGER_RSP_FLAG | USER_PING_RSP_FLAG |
                               NETWORK_CLOSE_FLAG | DO_CONNACK_TO_FLAG);
    
            cl_ctx->net = -1;
            net_ops->close(net);
    
            USR_INFO("C: Net %d now closed\n\r", net);
            
            //********************************************************************//
            //Maya was here and add the next line:
            ConnectedToBroker = false;
            //********************************************************************//
    
            return;
    }

    this function you can find it in C:\ti\CC3200SDK_1.1.0\cc3200-sdk\netapps\mqtt\client\mqtt_client.c
     the code I add is:

    //********************************************************************//

    //Maya was here and add the next line:

    ConnectedToBroker = false;

    //********************************************************************//

    and is just the set of a flag, in my code I'm checking that flag and if is set to false then I try to reconnect to the broker, obviously if the Wi-Fi flag is true too, if not then I wait first to the auto-connect to the Wi-Fi, once true, then I try to connect to the broker.

    I set the flag ConnectedToBroker to true in the connection function:

    int ConnectToBroker(connect_config *local_con_conf)
    {    
        int iConnBroker = 0;     
      
     /******************* connection to the broker ***************************/
        iNumBroker = sizeof(usr_connect_config)/sizeof(connect_config);
        if(iNumBroker > MAX_BROKER_CONN)
        {
            UART_PRINT("Num of brokers are more then max num of brokers\n\r");
            LOOP_FOREVER();
        }
    
        while(iCount < iNumBroker)
        {
            //create client context
            local_con_conf[iCount].clt_ctx =
            sl_ExtLib_MqttClientCtxCreate(&local_con_conf[iCount].broker_config,
                                          &local_con_conf[iCount].CallBAcks,
                                          &(local_con_conf[iCount]));
            if(local_con_conf[iCount].clt_ctx == NULL)
              UART_PRINT("Try to create a client context but a NULL was returned \n\r");
    
            //
            // Set Client ID
            //
            sl_ExtLib_MqttClientSet((void*)local_con_conf[iCount].clt_ctx,
                                SL_MQTT_PARAM_CLIENT_ID,
                                local_con_conf[iCount].client_id,
                                strlen((char*)(local_con_conf[iCount].client_id)));
    
            //
            // Set will Params
            //
            if(local_con_conf[iCount].will_params.will_topic != NULL)
            {
                sl_ExtLib_MqttClientSet((void*)local_con_conf[iCount].clt_ctx,
                                        SL_MQTT_PARAM_WILL_PARAM,
                                        &(local_con_conf[iCount].will_params),
                                        sizeof(SlMqttWill_t));
            }
    
            //
            // setting username and password
            //
            if(local_con_conf[iCount].usr_name != NULL)
            {
                sl_ExtLib_MqttClientSet((void*)local_con_conf[iCount].clt_ctx,
                                    SL_MQTT_PARAM_USER_NAME,
                                    local_con_conf[iCount].usr_name,
                                    strlen((char*)local_con_conf[iCount].usr_name));
    
                if(local_con_conf[iCount].usr_pwd != NULL)
                {
                    sl_ExtLib_MqttClientSet((void*)local_con_conf[iCount].clt_ctx,
                                    SL_MQTT_PARAM_PASS_WORD,
                                    local_con_conf[iCount].usr_pwd,
                                    strlen((char*)local_con_conf[iCount].usr_pwd));
                }
            }
    
            //
            // connectin to the broker
            //
            if((sl_ExtLib_MqttClientConnect((void*)local_con_conf[iCount].clt_ctx,
                                local_con_conf[iCount].is_clean,
                                local_con_conf[iCount].keep_alive_time) & 0xFF) != 0)
            {
                UART_PRINT("\n\rBroker connect fail for conn no. %d \n\r",iCount+1);
                
                //delete the context for this connection
                //sl_ExtLib_MqttClientCtxDelete(local_con_conf[iCount].clt_ctx);
                
                iConnBroker--;
                
                break;
            }
            else
            {
                UART_PRINT("\n\rSuccess: conn to Broker no. %d\n\r ", iCount+1);
                local_con_conf[iCount].is_connected = true;
                iConnBroker++;
            }
    
            //
            // Subscribe to topics
            //
            if(sl_ExtLib_MqttClientSub((void*)local_con_conf[iCount].clt_ctx,
                                       local_con_conf[iCount].topic,
                                       local_con_conf[iCount].qos, TOPIC_COUNT) < 0)
            {
                UART_PRINT("\n\r Subscription Error for conn no. %d\n\r", iCount+1);
                UART_PRINT("Disconnecting from the broker\r\n");
                sl_ExtLib_MqttClientDisconnect(local_con_conf[iCount].clt_ctx);
                local_con_conf[iCount].is_connected = false;
                
                //delete the context for this connection
                sl_ExtLib_MqttClientCtxDelete(local_con_conf[iCount].clt_ctx);
                iConnBroker--;
                break;
            }
            else
            {
                int iSub;
                UART_PRINT("Client subscribed on following topics:\n\r");
                for(iSub = 0; iSub < local_con_conf[iCount].num_topics; iSub++)
                {
                    UART_PRINT("%s\n\r", local_con_conf[iCount].topic[iSub]);
                }
            }
            iCount++;
        }
    
        if(iConnBroker < 1)
        {
            //
            // no succesful connection to broker
            //
            //sl_ExtLib_MqttClientExit();
            UART_PRINT("\n\r Broker Disconnected \n\r");
            
            ConnectedToBroker = false;
            
            iCount = 0;  
            
            return -1;
        } 
        else
        {    
          ConnectedToBroker = true;           
          
          iCount = 0;         
          
          return 0;
        }       
    }

    Now, this is the way I solved the problem of the re-connection automatically
     to the broker, as you can see I used the old SDK and I see that you are using a new one, maybe you don't find the problems I found because I can't remember why I modify the library (I don't know if you have checked the known issues that TI has detected and recommend you to change, here I leave you the link

    Anyway I leave you my suggestions and I hope you can solve your problem, any doubt or question about my code or anything I can help with feel free to ask.


    Regards, Juan

  • Hi Shlomi,

    Thanks for your reply.

    For this scenario - adding "goto connect_to_broker;"  it seems works fine. But is it a reliable? since yesterday i got "MQP alloc failed - msg type 0x08" reply from the serial port.

    I see there are other people's post saying something similar:

    https://e2e.ti.com/support/wireless_connectivity/simplelink_wifi_cc31xx_cc32xx/f/968/t/435369

    Does this issue fixed in SDK 1.2.0?

    When can i use the following API to de-initialize MQTT? Since i would like to change CC3200's working mode from Station Mode to AP Mode. The link to server must be disconnected first. After that CC3200 will go back to Station Mode and start MQTT again.

    sl_ExtLib_MqttClientDisconnect((void*)local_con_conf[iCount].clt_ctx);

    sl_ExtLib_MqttClientExit();

    Network_IF_DeInitDriver();

    Thanks!

    Best Regards,

    Eric

  • Hi Shlomi,

    I see there are defines about MQTT version in the code.

    #define MQTT_3_1_1 false /*MQTT 3.1.1 */ <-- Does this version works fine also?
    #define MQTT_3_1 true /*MQTT 3.1*/
    #define SERVER_MODE MQTT_3_1

    Does the MQTT library support user to use version MQTT_3_1_1 as well ?


    Thanks!

    Best Regards,

    Eric
  • Hello Eric,

    This issue of not being able to allocate a buffer wither for MQTT receive or transmit is not something I experienced.

    If I have to guess, it happend to you earlier since you called MqttClient() again which in turn call to sl_ExtLib_MqttClientInit() which initializes the same pool of MQTT packets. When you tried to just jump to connect_to_broker, you observed that it works fine.

    So if you get to this error of not being able to allocate a buffer for TX/RX, please let us know so we can debug. Although, please note it may happen in cases where you don't have enough packets in the pool (for example, if you are running some instances in parallel and connect to several brokers at the same time).

    The flow would be to initialize once the client via sl_ExtLib_MqttClientInit() and use sl_ExtLib_MqttClientCtxCreate()/sl_ExtLib_MqttClientCtxDelete() each time you establish connection with a broker.sl_ExtLib_MqttClientExit() is the client de-initialization after which you can de-initialize the driver.

    Regards,

    Shlomi

  • Hello,

    Any update on the post?

    Regards,
    Shlomi

  • Hi Shlomi,

    Through the UART terminal, the following can be seen:

    C: Net 16, Raw Error -1, Time Out: Y                                            

    C: FH-B1 0xc0 to net 16, Sent (2 Bytes) [@ 146]  

    C: Rcvd msg Fix-Hdr (Byte1) 0xd0 from net 16 [@ 146]                            

    C: Msg w/ ID 0x0000, processing status: Good  

    What does the Raw Error -1 means?

    Will this cause the unstable behaviour of the MQTT function?

    Best Regards,

    Eric

  • Hello Eric,

    It means that you have a general networking error.

    Does it interfer with the flow? do you see nay implications?

    Regards,

    Shlomi

  • Hi Shlomi,

    CC3200 is seems able to communicate with the MQTT server. But i have no idea whether it is stable or not.



    Since there is only 1 servers is needed to be connected to, when i test this example, i change the MQTT_Client value from 1882 to 0 (it is an option located in main.c), then general networking error is reported.

    SlMqttClientLibCfg_t Mqtt_Client={
    0, // original value is 1882,
    TASK_PRIORITY,
    30,
    true,
    (long(*)(const char *, ...))UART_PRINT
    };


    Will you have the same behavior by using the MQTT client example?

    Best Regards,
    Eric
  • Eric,

    I cannot test at the moment but can you elaborate whether it works with port 1882? Why have you decided to change it to 0?

    Regards,

    Shlomi

  • Hi Shlomi,

    With reference to the mqtt library, it said the loopback_port is needed to set as 0 for single server. Since i only need to connect to only one MQTT server, so i set the loopback_port as 0.

    Copied from MQTT Library:

            /** MQTT Lib structure which holds Initialization Data */
            typedef struct
            {
                    /**< Loopback port is used to manage lib internal functioning in case of connections to
                         multiple servers simultaneously is desired. */
                    _u16  loopback_port;  /**< Loopback port = 0, implies connection to only single server */
                                                    /**< Loopback port != 0, implies connection to multiple servers */
                    _u32   rx_tsk_priority;  /**< Priority of the receive task */
                    _u32    resp_time;        /**< Reasonable response time (seconds) from server */
                    bool  aux_debug_en;               /**< Assert to indicate additional debug info */
                    _i32 (*dbg_print)(const char *pcFormat, ...); /**< Print debug information */

            } SlMqttClientLibCfg_t;

    Best Regards,

    Eric

  • Hello Eric,

    You can leave the original value of 1882, not sure where the 0 for loopback is comming from. I can check that.

    In any case, I am trying to understand how stable it is.

    Can you elaborate what happens in case you get this networking error?

    Does it stop? crash? or does it seem working?

    Regards,

    Shlomi

  • Hello,

    Any update on the post?

    Regards,
    Shlomi

  • Hello,

    I am closing the thread, if issue still exist or you have further related doubts please open a new thread and add a link to this one for reference.

    Regards,
    Shlomi

  • yes ,i will reconnect to the mqtt server while i the mqtt client turn off by some mistake and the mqtt server just on
    working . just add "go connect_to_broker" after "sl_ExtLib_MqttClientCtxDelete(((connect_config*)(RecvQue.hndl))->clt_ctx);".
    But if is the mqtt server restart or shut down by manual ,while the mqtt client detect the server was down and reconnect again imediately,
    i could'nt find the mqtt server ,it will just exit the application . so it is not working while you restart the mqtt server .
  • hello Shlomi :

    since you suggest to add the label after callback function ,but it is not enough,it can deal with the mqtt service restart.

    so i add another same label in mqtt connect function ,if it didn't connect to server successful,it will reconnect to the
    mqtt server again after ten .one by one until it connect successfully.
    //
    // connectin to the broker
    //
    if((sl_ExtLib_MqttClientConnect((void*)local_con_conf[iCount].clt_ctx,
    local_con_conf[iCount].is_clean,
    local_con_conf[iCount].keep_alive_time) & 0xFF) != 0)
    {
    UART_PRINT("\n\rBroker connect fail for conn no. %d \n\r",iCount+1);

    //delete the context for this connection
    sl_ExtLib_MqttClientCtxDelete(local_con_conf[iCount].clt_ctx);

    osi_Sleep(10);

    goto connect_to_broker;

    // break;
    }
    may be there maybe some wifi connect flag choice before start connect to mqtt server.
  • Hello Eric,
    i met the same issue where Rabbitmq mqtt adapter.
    "MqttClient()'s PUSH_BUTTON_SW3_PRESSED , the program just hang".
    hava you solve the problem already? if you done ,please let me know how to solve it .thanks;

    C: FH-B1 0x35 to net 21, Sent (74 Bytes) [@ 7079]

    C: Net 21, Raw Error -1, Time Out: N

    C: RX closing Net 21 [-1]

    C: Cleaning session for net 21

    C: Net 21 now closed

    disconnect from broker 45.79.108.30


    CC3200 Publishes the following message

    Topic: /cc3200/ButtonPressEvtSw2

    Data: Push button sw2 is pressed on CC32XX device

    -----------------------BROKER_DISCONNECTION----------------------------------------------------
  • Hello Eric,
    Since i set the loopback_port as 0 and restart again in debug mode .
    the issue are still there.