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.

CC3220SF-LAUNCHXL: Unable to connect the device to the mobile application when using HTTP.

Part Number: CC3220SF-LAUNCHXL

Hi Support,

I'm using the following modules for my application.
Amazon FreeRTOS -> 202107
FreeRTOS Kernel V10.4.3
AWS IoT Over-the-air Update v3.0.0
SL Host Driver Version 2.0.1.27
Service Pack Version sp_3.14.0.0_2.0.0.0_2.2.0.7.bin

I have a Problem while connecting the device to mobile application when the provisioning FSM reinitializes provisioning after Device got disconnected from AP during initial provisioning process.

After successful cloud confirmation, due to some router issue the device got disconnected from AP. The event WLAN Connection Status:1 is received from the NWP, but the device cannot connect to AP, so the application came into Current: 0, Event: 6, Next: 0 state according to provisioning FSM followed by Current: 0, Event: 0, Next: 1 and Current: 1, Event: 1, Next: 2 states.

When the application is in Current: 1, Event: 1, Next: 2 state, the device started hosting and is visible in the Wi-Fi list, but unable to connect it using mobile application.

I have tried e using various tools like Postman and Httper, but still, it didn't work. It seems like device internal HTTP server unable to connect.

Can you please let me know the reason why I am unable to connect the device to mobile application and suggest a solution for the same.

Thanks,

Vaishnavi

  • Please give more details as you are using Amazon FreeRTOS code which is not directly supported by us.

    I'm not sure what is provisioning mechanism they are using.

    where is the state machine that you are referring to?

    If i understand correctly: the mobile device connected to the CC3220 (in provisioning soft AP mode (after it was disconnected from the local network) and got the IP address. Then it failed during HTTP connection. Can you confirm?

  • Hi Kobi,

     
    Thanks for your response. 

     
    I am trying to re-write the problem statement below in a clear manner.

     

    I'm using External confirmation, based on the claim status of the Shadow document, cloud connectivity is getting established.

     

     


    Following steps are performed to reproduce the issue (Still random issue)

     

    1. Get the shadow document

     

    2. Shadow success

     

    3.  Unfortunately, the device disconnected from the AP, (Device disconnected from the AP on an ERROR..!! )

     

    4. Provisioning stopped.

      

    5. As provisioning failed, cannot connect to AP (Cannot connect to AP or profile does not exist)

      

    6. Again start provisioning (Device stated as AP role).

      
    The problem is, in step-6 the device is hosting, and able to see the device as AP in the Wi-Fi list as well. But with the mobile app (trying to establish HTTP connection), Device is not responding at all. 

     

     

    Provisioning process is the same as the TI example code. 

      

    Please find the provisioning.c file attached.
     provisioning.c  

          

       
    Please find the debug logs for your reference.

     

    SET TO FIXED FREQUENCY.
    Simple Link task created
    Device came up in Station mode
    [OCR_RecordAndClear] ManufacturingTestEnabledflag : 0 , ProvisioningCommandedRestartflag : 0.
    Device came up in Station mode
    [Provisioning task] Provisioninig task initialized
    [Provisioning task] Device started as STATION
    [Provisioning task] validateLocalLinkConnection() sem wait
    [Provisioning task] validateLocalLinkConnection() sem exit ret=0, status=0
    [Provisioning task] Cannot connect to AP or profile does not exist
    [Provisioning task] detected device is CC3220SF
    [NETAPP EVENT] IP Acquired: IP=10.123.45.1 , Gateway=10.123.45.1
    [Provisioning task] Device is configured in default state
    [Provisioning task] Current: 0, Event: 0, Next: 1
    [Provisioning task] Device started in AP role
    [NETAPP EVENT] IP Acquired: IP=10.123.45.1 , Gateway=10.123.45.1
    [Provisioning task] Host Driver Version: 2.0.1.27
    [Provisioning task] Build Version 3.14.0.0.31.2.0.0.0.2.2.0.7
    [Provisioning task] Starting Provisioning -
    [Provisioning task] in mode 2 (0 = AP, 1 = SC, 2 = AP+SC)
    [Provisioning task] Provisioning Started. Waiting to be provisioned..!!
    [Provisioning task] Current: 1, Event: 1, Next: 2
    [WLAN EVENT] Profile Added
    [WLAN EVENT] Connection to AP succeeded
    [WLAN EVENT] IP address acquired
    MQTT library successfully initialized.
    Shadow library successfully initialized.
    Establishing new MQTT connection.
    Shadow GET of was ACCEPTED.
    adiSmsGetShadowInfo(): acquired shadow document:
    Shadow UPDATE was ACCEPTED.
    sent new state report.
    Disconnecting connection.
    Connection disconnected.
    Network connection closed.
    Network connection destroyed.
    
    
    
    
    Device disconnected from the AP on an ERROR..!!
    
    
    
    Device disconnected from the AP on an ERROR..!!
    
    
    
    Device disconnected from the AP on an ERROR..!!
    
    
    
    
    [Provisioning task] Current: 2, Event: 3, Next: 3
    [WLAN EVENT] Provisioning stopped
    [WLAN EVENT] - WLAN Connection Status:1
    [Provisioning task] Cannot connect to AP or profile does not exist
    [Provisioning task] Current: 0, Event: 6, Next: 0
    [NETAPP EVENT] IP Acquired: IP=10.123.45.1 , Gateway=10.123.45.1
    [Provisioning task] Device is configured in default state
    [Provisioning task] Current: 0, Event: 0, Next: 1
    [Provisioning task] Device started in AP role
    [NETAPP EVENT] IP Acquired: IP=10.123.45.1 , Gateway=10.123.45.1
    [Provisioning task] Host Driver Version: 2.0.1.27
    [Provisioning task] Build Version 3.14.0.0.31.2.0.0.0.2.2.0.7
    [Provisioning task] Starting Provisioning -
    [Provisioning task] in mode 2 (0 = AP, 1 = SC, 2 = AP+SC)
    [Provisioning task] Provisioning Started. Waiting to be provisioned..!!
    [Provisioning task] Current: 1, Event: 1, Next: 2
    
    
    
    -->>>>>>>>> HERE HTTP is not working, but able to see the device name <<<<<<<<------

  • some of the prints are not matching the code:

    Event 3 (DISCONNECT), received in the state 2 (WAIT_FOIR_IP) should lead to state 1 (WAIT FOR CONNECTION) and not 3.

    Event 6 is PROVISIONING_SUCCESS - that doesn't correlates to the prints.

    Are you causing the the disconnection from the AP or it just happens? What is the reason code (it can be found in the SimplelinkWlanEventHandler)?

  • Sorry, attaching the proper file (please note that this is a code snippet, some definitions maybe missing)

    /*
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /* standard includes */
    #include <stdlib.h>
    #include <string.h>
    
    /* Set up logging for this demo. */
    #include "iot_demo_logging.h"
    
    /* FreeRTOS includes. */
    #include "FreeRTOS_POSIX.h"
    #include "FreeRTOS_POSIX/unistd.h"
    
    /* driverlib Header files */
    #include <ti/devices/cc32xx/inc/hw_types.h>
    #include <ti/devices/cc32xx/inc/hw_memmap.h>
    #include <ti/devices/cc32xx/inc/hw_gprcm.h>
    #include <ti/devices/cc32xx/driverlib/prcm.h>
    
    /* TI-DRIVERS Header files */
    #include <Board.h>
    #include <uart_term.h>
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/net/wifi/simplelink.h>
    #include <ti/drivers/net/wifi/wlan.h>
    #include <ti/drivers/power/PowerCC32XX.h>
    
    /* Example/Board Header files */
    #include "platform.h"
    #include "network_if.h"
    
    //#include "mqtt_app_client.h"
    //#include "provisioning_task.h"
    #include "platform/iot_threads.h"
    
    
    /* POSIX Header files */
    #include <pthread.h>
    #include <time.h>
    
    #include "stdio.h"
    #include "core_json.h"
    #include "jsmn.h"
    
    /*!
     *  \brief  Application state's context
     */
    Provisioning_AppContext gAppCtx;
    Provisioning_CB Provisioning_ControlBlock;
    
    PROVISION_INFO* gProvisionServiceInfo;
    
    extern ProvisioningStateMachineStruct ProvisioningStateMachine[MQTT_SERVICE_MAX];
    
    #if (defined LOCAL_PROVISION_ENABLE && LOCAL_PROVISION_ENABLE==1)
    extern bool local_provisioning;
    #endif
    
    #if (defined PROVISION_GET_POST_ENABLE && PROVISION_GET_POST_ENABLE == 1)
    
    extern volatile int g_PostHibernateCmd; 
    extern volatile int g_HibernateTimeBeforeCommand;
    
    volatile int g_isProvisionInProgress = 0;
    volatile int gisGETReqPending = 0;
    volatile uint16_t gHandle = 0;
    uint8_t *g_certFileBuf = NULL;
    int g_certFileLen = 0;
    uint8_t *g_SMSConfigBuf = NULL;
    int g_SMSConfigLen = 0;
    volatile bool isPendingConfigUpdated = false;
    
    #endif // PROVISION_GET_POST_ENABLE
    
    //bool isInternetConnectError = false;
    #if (defined EXTERNAL_CLOUD_CONFIRMATION && EXTERNAL_CLOUD_CONFIRMATION == 1)
    extern bool IsIpAccuired;
    #endif /* EXTERNAL_CLOUD_CONFIRMATION */
    char *pthingNamebuf = NULL;
    char *pCloudUrl = NULL;
    
    
    extern bool gProvisionComplete;
    extern bool gProvisionStart;
    
    
    bool isWrongProfAdded = false;
    
    jsmn_parser parser;
    jsmntok_t tokens[256];
    
    
    /*!
     *  \brief   Application lookup/transition table
     */
    const s_TblEntry gProvisioningTransitionTable[PrvnState_Max][PrvnEvent_Max] =
    {
        /* PrvnState_Init */
        {
            /* Event: PrvnEvent_Triggered */
            {provisioningStart, PrvnState_Idle                    },
            /* Event: PrvnEvent_Started */
            {ReportError, PrvnState_Error                         },
            /* Event: PrvnEvent_StartFailed */
            {ReportError, PrvnState_Error                         },
            /* Event: PrvnEvent_ConfirmationSuccess */
            /* special case where confirmation is received after application is
            restarted and NWP is still in provisioning */           
            {ReportSM, PrvnState_Completed                         },
            /* in this case, need to move to COMPLETED state */
            /* Event: PrvnEvent_ConfirmationFailed */
            {ReportError, PrvnState_Error                         },
            /* Event: PrvnEvent_Stopped */
            /* in case of auto provisioning */
            {ReportSM, PrvnState_Init                             },
            /* Event: PrvnEvent_WaitForConn */
            {ReportSM, PrvnState_Error                            },
            /* Event: PrvnEvent_Timeout */
            {ReportError, PrvnState_Error                         },
            /* Event: PrvnEvent_Error */
            {ReportError, PrvnState_Error                         },
        },
        /* PrvnState_Idle */
        {
            /* Event: PrvnEvent_Triggered */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Started */
            {HandleStrtdEvt, PrvnState_WaitForConfirmation         },
            /* Event: PrvnEvent_StartFailed */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_ConfirmationSuccess */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_ConfirmationFailed */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Stopped */ 
            {ReportSM, PrvnState_Init                              },
            /* Event: PrvnEvent_WaitForConn */
            {ReportSM, PrvnState_Error                             },
            /* Event: PrvnEvent_Timeout */ 
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Error */
            {ReportError, PrvnState_Error                          },
        },
        /* PrvnState_WaitForConfirmation */
        {
            /* Event: PrvnEvent_Triggered */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Started */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_StartFailed */
            {ReportSM, PrvnState_Idle                              },
            /* Event: PrvnEvent_ConfirmationSuccess */
            {ReportSM, PrvnState_Completed                         },
            /* Event: PrvnEvent_ConfirmationFailed */
            {ReportSM, PrvnState_WaitForConfirmation               },
            /* Event: PrvnEvent_Stopped */
            {ReportSM, PrvnState_Init                              },
            /* Event: PrvnEvent_WaitForConn */
            {ReportSM, PrvnState_Error                             },
            /* Event: PrvnEvent_Timeout */ 
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Error */
            {ReportError, PrvnState_Error                          },
        },
        /* PrvnState_Completed */
        {
            /* Event: PrvnEvent_Triggered */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Started */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_StartFailed */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_ConfirmationSuccess */
            {ReportError, PrvnState_Error                          }, 
            /* Event: PrvnEvent_ConfirmationFailed */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Stopped */
            {ReportSuccess, PrvnState_Init                         },
            /* Event: PrvnEvent_WaitForConn */
            /* this state should cover cases where
            feedback failed but profile exists */
            {WaitForConn, PrvnState_Init                           },
            /* Event: PrvnEvent_Timeout */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Error */
            {ReportError, PrvnState_Error                          },
        },
        /* PrvnState_Error */
        {
            /* Event: PrvnEvent_Triggered */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Started */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_StartFailed */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_ConfirmationSuccess */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_ConfirmationFailed */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Stopped */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_WaitForConn */
            {ReportSM, PrvnState_Error                             },
            /* Event: PrvnEvent_Timeout */
            {ReportError, PrvnState_Error                          },
            /* Event: PrvnEvent_Error */
            {ReportError, PrvnState_Error                          },
        }
    };
    
    /// <summary>
    /// SimpleLinkInitCallback
    /// </summary>
    /// <param name="uint32_t"> </param>
    /// <param name="SlDeviceInitInfo_t *"> </param>
    /// <returns>void</returns>
    //****************************************************************************
    void SimpleLinkInitCallback(uint32_t status,
                                SlDeviceInitInfo_t *DeviceInitInfo)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
    
        IotLogInfo("[Provisioning task] Device started in %s role",
                   (0 == status) ? "Station" : \
                   ((2 == status) ? "AP" : "P2P"));
    
        /** While provisioning is ongoing, the appropriate role is choosen by the
         * device itself, and host can remain agnostic to these details
         */
        if(pCtx->role == ROLE_SELECTION_BY_SL)
        {
            SignalProvisioningEvent(PrvnEvent_Started);
        }
        else
        {
            /* Either trigger an error/started event here */
            if(pCtx->role == status)
            {
                SignalProvisioningEvent(PrvnEvent_Started);
            }
            else
            {
               IotLogInfo("[Provisioning task] But the intended role is %s \n\r", \
                           (0 == pCtx->role) ? "Station" : \
                           ((2 == pCtx->role) ? "AP" : "P2P"));
                SignalProvisioningEvent(PrvnEvent_Error);
            }
        }
    }
    
    //*****************************************************************************
    /// <summary>
    /// InitSimplelink
    /// </summary>
    /// <param name="uint8_t"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    static int32_t InitSimplelink(uint8_t const role)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        int32_t retVal = -1;
    
        pCtx->role = role;
        pCtx->pendingEvents = 0;
    
        retVal = sl_Start(0, 0, (P_INIT_CALLBACK)SimpleLinkInitCallback);
        ASSERT_ON_ERROR(retVal);
    
        /* Start timer */
        pCtx->asyncEvtTimeout = ASYNC_EVT_TIMEOUT;
        retVal = StartAsyncEvtTimer(pCtx->asyncEvtTimeout);
        ASSERT_ON_ERROR(retVal);
    
        return(retVal);
    }
    
    //*****************************************************************************
    /// <summary>
    /// provisioningStart
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    int32_t provisioningStart(void)
    {
        int32_t retVal = 0;
        Provisioning_AppContext *const pCtx = &gAppCtx;
        SlDeviceVersion_t ver = {0};
        uint8_t configOpt = 0;
        uint16_t configLen = 0;
    
        /* check if provisioning is running */
        /* if auto provisioning - the command stops it automatically */
        /* in case host triggered provisioning - need to stop it explicitly */
        configOpt = SL_DEVICE_GENERAL_VERSION;
        configLen = sizeof(ver);
        retVal =
            sl_DeviceGet(SL_DEVICE_GENERAL, &configOpt, &configLen,
                         (uint8_t *)(&ver));
        if(SL_RET_CODE_PROVISIONING_IN_PROGRESS == retVal)
        {
            IotLogError(
                "[Provisioning task] Provisioning is already running,"
                " stopping it...\r\n");
            
    #if (defined EXTERNAL_CLOUD_CONFIRMATION && EXTERNAL_CLOUD_CONFIRMATION == 1)
            /* set SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION Flag for new prov schema */
            retVal =
                ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP, ROLE_STA, 0, NULL,
                                    SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION);
    
    #else
            
            retVal =
                ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP,ROLE_STA,0,NULL,
                                    0);
    
    #endif /* EXTERNAL_CLOUD_CONFIRMATION */
    
            /* return  SL_RET_CODE_PROVISIONING_IN_PROGRESS to indicate the SM 
                to stay in the same state*/
            return(SL_RET_CODE_PROVISIONING_IN_PROGRESS);
        }
    
        /*
            IMPORTANT NOTE - This is an example reset function, user must update
                             this function to match the application settings.
         */
        retVal = ConfigureSimpleLinkToDefaultState();
    
        if(retVal < 0)
        {
            IotLogError(
                "[Provisioning task] Failed to configure the device in its default "
                "state \n\r");
            return(retVal);
        }
    
        IotLogInfo("[Provisioning task] Device is configured in default state");
    
        /* Provisioning has not started yet */
        pCtx->provisioningStatus = PrvsnStatus_Stopped;
    
        /* Set the LED toggling timeout before starting the timer */
        pCtx->ledToggleTimeout = LED_TOGGLE_CONFIGURATION_TIMEOUT;
        StartLedEvtTimer(pCtx->ledToggleTimeout);
    
        retVal = InitSimplelink(pCtx->defaultRole);
        if(retVal < 0)
        {
            IotLogError("[Provisioning task] Failed to initialize the device\n\r");
            return(retVal);
        }
    
        return(retVal);
    }
    
    //*****************************************************************************
    /// <summary>
    /// HandleStrtdEvt
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    
    static int32_t HandleStrtdEvt(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        int32_t retVal = 0;
    
        /** If provisioning has already started, don't do anything here
         * The state-machine shall keep waiting for the provisioning status
         */
        if(PrvsnStatus_Stopped == pCtx->provisioningStatus)
        {
            SlDeviceVersion_t firmwareVersion = {0};
    
            uint8_t ucConfigOpt = 0;
            uint16_t ucConfigLen = 0;
    
            /* Get the device's version-information */
            ucConfigOpt = SL_DEVICE_GENERAL_VERSION;
            ucConfigLen = sizeof(firmwareVersion);
            retVal = sl_DeviceGet(SL_DEVICE_GENERAL, &ucConfigOpt, \
                                  &ucConfigLen,
                                  (uint8_t *)(&firmwareVersion));
            ASSERT_ON_ERROR(retVal);
    
            IotLogInfo("[Provisioning task] Host Driver Version: %s",
                       SL_DRIVER_VERSION);
            IotLogInfo(
                "[Provisioning task] Build Version "
                "%d.%d.%d.%d.31.%d.%d.%d.%d.%d.%d.%d.%d", \
                firmwareVersion.NwpVersion[0],  \
                firmwareVersion.NwpVersion[1],  \
                firmwareVersion.NwpVersion[2],  \
                firmwareVersion.NwpVersion[3],  \
                firmwareVersion.FwVersion[0],   \
                firmwareVersion.FwVersion[1],   \
                firmwareVersion.FwVersion[2],   \
                firmwareVersion.FwVersion[3],   \
                firmwareVersion.PhyVersion[0],  \
                firmwareVersion.PhyVersion[1],  \
                firmwareVersion.PhyVersion[2],  \
                firmwareVersion.PhyVersion[3]);
    
            
    
            /* Start provisioning process */
            IotLogInfo("[Provisioning task] Starting Provisioning - ");
            IotLogInfo(
                "[Provisioning task] in mode %d (0 = AP, 1 = SC, 2 = AP+SC)",
                pCtx->provisioningMode);
            
            
    #if (defined LOCAL_PROVISION_ENABLE && LOCAL_PROVISION_ENABLE==1)
            if(local_provisioning == true)
            {
                IotLogInfo("[local Provisioning] waits for %d seconds", LOCAL_PROVISIONING_INACTIVITY_TIMEOUT);
                
    #if (defined EXTERNAL_CLOUD_CONFIRMATION && EXTERNAL_CLOUD_CONFIRMATION == 1)
                /* set SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION Flag for new prov schema */
                retVal = ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(pCtx->provisioningMode, ROLE_STA, LOCAL_PROVISIONING_INACTIVITY_TIMEOUT, NULL, SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION);
    #else
                retVal = ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(pCtx->provisioningMode, ROLE_STA, LOCAL_PROVISIONING_INACTIVITY_TIMEOUT, NULL,0);
    #endif /* EXTERNAL_CLOUD_CONFIRMATION */
                
            } 
            else
    #endif /* LOCAL_PROVISION_ENABLE */
    
            {
            
                IotLogInfo("[Provisioning] waits for %d seconds", PROVISIONING_INACTIVITY_TIMEOUT);
    
    #if (defined EXTERNAL_CLOUD_CONFIRMATION && EXTERNAL_CLOUD_CONFIRMATION == 1)
                /* set SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION Flag for new prov schema */
                retVal = ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(pCtx->provisioningMode, ROLE_STA, PROVISIONING_INACTIVITY_TIMEOUT, NULL, SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION);
    #else
                retVal = ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(pCtx->provisioningMode, ROLE_STA,
                                         PROVISIONING_INACTIVITY_TIMEOUT, NULL,0);
    #endif /* EXTERNAL_CLOUD_CONFIRMATION */
                
            }
                
            ASSERT_ON_ERROR(retVal);
    
            pCtx->provisioningStatus = PrvsnStatus_InProgress;
            IotLogInfo(
                "[Provisioning task] Provisioning Started. Waiting to "
                "be provisioned..!!");
        }
        
        gProvisionStart = true;
    
        return(retVal);
    }
    
    //*****************************************************************************
    /// <summary>
    /// ReportError
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    static int32_t ReportError(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        uint16_t eventIdx = 0;
    
        for(eventIdx = 0; eventIdx < PrvnEvent_Max; eventIdx++)
        {
            if(0 != (pCtx->pendingEvents & (1 << eventIdx)))
            {
                break;
            }
        }
    
        IotLogError("[Provisioning task]"
        " Unexpected SM: State = %d, Event = %d\n\r",\
                   pCtx->currentState, eventIdx);
        return(-1);
    }
    
    //*****************************************************************************
    /// <summary>
    /// ReportSM
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    static int32_t ReportSM(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        uint16_t eventIdx = 0;
    
        for(eventIdx = 0; eventIdx < PrvnEvent_Max; eventIdx++)
        {
            if(0 != (pCtx->pendingEvents & (1 << eventIdx)))
            {
                break;
            }
        }
    
        if(PrvnEvent_Stopped == eventIdx)
        {
            StopLedEvtTimer();
            Board_LedOff();
        }
    
        return(0);
    }
    
    //*****************************************************************************
    /// <summary>
    /// ReportSuccess
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    static int32_t ReportSuccess(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        uint16_t ConfigOpt;
        uint16_t ipLen;
        SlNetCfgIpV4Args_t ipV4 = {0};
        int32_t retVal;
    
    /* v1.0 POST and GET Feature Enabled */
     #if (defined PROVISION_GET_POST_ENABLE && PROVISION_GET_POST_ENABLE == 1)
        if(isPendingConfigUpdated == false)
        { 
            /* Configuration not yet updated */
            UpdatePendingConfig();
        }
        RestAPI_Notify(ProvisioningProvisioned,NULL);
    #endif
        
    
    
        IotLogInfo("[Provisioning task] "
                   "Provisioning completed successfully..!");
        pCtx->provisioningStatus = PrvsnStatus_Stopped;
        StopLedEvtTimer();
    
        /* Get the device's IP address */
        ipLen = sizeof(SlNetCfgIpV4Args_t);
        ConfigOpt = 0;
        retVal =
            sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE,&ConfigOpt,&ipLen,
                         (uint8_t *)&ipV4);
        if(retVal == 0)
        {
            IotLogInfo("[Provisioning task] IP address is %d.%d.%d.%d", \
                       SL_IPV4_BYTE(ipV4.Ip,3),  \
                       SL_IPV4_BYTE(ipV4.Ip,2),  \
                       SL_IPV4_BYTE(ipV4.Ip,1),  \
                       SL_IPV4_BYTE(ipV4.Ip,0));
    
        }
        Board_LedOn();
    
        gProvisionComplete = true;
        
    #if 1
        /* signal to linklocal task */
        IotSemaphore_Post(&Provisioning_ControlBlock.provisioningDoneSignal);
    
        /* signal to report server task */
        IotSemaphore_Post(&Provisioning_ControlBlock.provisioningConnDoneToOtaServerSignal);
    #endif
    
        return(0);
    }
    
    //*****************************************************************************
    /// <summary>
    /// WaitForConn
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    static int32_t WaitForConn(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        //struct timespec ts;
        //int32_t retVal;
        bool retBool;
    
        while(((!IS_IPV6L_ACQUIRED(ControlBlock.status) ||
                !IS_IPV6G_ACQUIRED(ControlBlock.status)) &&
               !IS_IP_ACQUIRED(ControlBlock.status)) ||
              !IS_CONNECTED(ControlBlock.status))
        {
    //        clock_gettime(CLOCK_REALTIME, &ts);
    //        ts.tv_sec += PROFILE_ASYNC_EVT_TIMEOUT;
            uint32_t ts = 10000;
            retBool = IotSemaphore_TimedWait(&Provisioning_ControlBlock.connectionAsyncEvent,
                                   ts);
            
            /* freertos return false in case of timeout */
            if(retBool == false)           
            {
                IotLogError(
                    "[Provisioning task] Cannot connect to AP or profile does"
                    " not exist");
                Board_LedOff();
                
                 /* this state is set so that PrvnEvent_Triggered 
                 would invoke provisioning again */
                pCtx->currentState = PrvnState_Init;               
                SignalProvisioningEvent(PrvnEvent_Triggered);
    
                return(0);
            }
        }
    
        IotLogInfo("[Provisioning task] Connection to AP succeeded");
    
        return(ReportSuccess());
    }
    
    //*****************************************************************************
    /// <summary>
    /// getDeviceType
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>uint32_t</returns>
    //****************************************************************************
    uint32_t getDeviceType(void)
    {
        uint32_t deviceType;
        uint16_t configSize = 0;
        uint8_t  configOpt  = SL_DEVICE_GENERAL_VERSION;
        SlDeviceVersion_t ver = {0};
        configSize = sizeof(SlDeviceVersion_t);
    
        /* Print device version info. */
        sl_DeviceGet(SL_DEVICE_GENERAL, &configOpt, &configSize, (uint8_t*)(&ver));
    
        deviceType = ver.ChipId & 0xFF;
        /* Update deviceType to 323XX or 3220X */
        if((HWREG(GPRCM_BASE + GPRCM_O_GPRCM_DIEID_READ_REG4) >> 24) & 0x02)
        {
            deviceType |= (0x01 << 8);
        }
    
        switch(deviceType)
        {
            case DEV_TYPE_CC323XR:  // 323xR
                IotLogInfo("[Provisioning task] detected device is CC323xR\n\r");
                break;
            case DEV_TYPE_CC323XRS: // 323xRS
                IotLogInfo("[Provisioning task] detected device is CC323xRS\n\r");
                break;
            case DEV_TYPE_CC323XFS: // 323xFS
                IotLogInfo("[Provisioning task] detected device is CC323xSF\n\r");
                break;
            case DEV_TYPE_CC3220R:  // 3220R
                IotLogInfo("[Provisioning task] detected device is CC3220R\n\r");
                break;
            case DEV_TYPE_CC3220RS: // 3220RS
                IotLogInfo("[Provisioning task] detected device is CC3220RS\n\r");
                break;
            case DEV_TYPE_CC3220FS: // 3220FS
                IotLogInfo("[Provisioning task] detected device is CC3220SF");
                break;
            default:
                break;
        }
    
        return(deviceType);
    }
    
    //*****************************************************************************
    /// <summary>
    /// validateLocalLinkConnection
    /// </summary>
    /// <param name="SlWlanMode_e *"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    int32_t validateLocalLinkConnection(SlWlanMode_e *deviceRole)
    {
        uint16_t ConfigOpt;
        uint16_t ipLen;
        SlNetCfgIpV4Args_t ipV4 = {0};
        int32_t retVal;
        bool retBool;
    
        retVal = ROLE_AP;
    //    retVal = sl_Start(0, 0, 0);
    //    /* when calibration fails, reboot is required */
    //    if(SL_ERROR_CALIB_FAIL == retVal)           
    //    {
    //        mcuReboot();
    //    }
    //    else
    //    {
    //        ASSERT_ON_ERROR(retVal);
    //    }
    
        /* if in AP role
         * 1) check OCP register value
         * 2) if set, it means user set AP mode via switch.
         *       check for IP_ACQUIRED to indicate NWP is running
         * 4) if not set, procede with STATION role
         */
        if(retVal == ROLE_AP)
        {
            *deviceRole = ROLE_AP;
            if(OCR_SingleBitCheckClear(OCR_REGISTER_ROLE_OFFSET, FALSE))
            {
                if(IS_IP_ACQUIRED(ControlBlock.status))
                {
                    return(0);
                }
                else
                {
    //                clock_gettime(CLOCK_REALTIME, &ts);
    //                ts.tv_sec += PROFILE_ASYNC_EVT_TIMEOUT;
    
                    uint32_t ts = 10000;
                    retBool = IotSemaphore_TimedWait(&Provisioning_ControlBlock.connectionAsyncEvent,
                                   ts);
    
                    /* freertos return false in case of timeout */
                    if(retBool == false)                    
                    {
                        IotLogError(
                           "[Provisioning task] AP role failed to initialize\n\r");
                        Board_LedOff();
                        retVal = -1;
                    }
                    return(retVal);
                }
            }
        }
    
        if(retVal != ROLE_STA)
        {
            retVal = sl_WlanSetMode(ROLE_STA);
            ASSERT_ON_ERROR(retVal);
    
            retVal = sl_Stop(SL_STOP_TIMEOUT);
            ASSERT_ON_ERROR(retVal);
    
            Network_IF_InitializeAppVariables();
            
            retVal = sl_Start(0, 0, 0);
            if(retVal < 0 || (retVal != ROLE_STA))
            {
                ASSERT_ON_ERROR(retVal);
            }
            IotLogInfo("[Provisioning task] Device started as STATION");
        }
    
        *deviceRole = ROLE_STA;
    
        while(((!IS_IPV6L_ACQUIRED(ControlBlock.status) ||
                !IS_IPV6G_ACQUIRED(ControlBlock.status)) &&
               !IS_IP_ACQUIRED(ControlBlock.status)) ||
              !IS_CONNECTED(ControlBlock.status))
        {
    //        clock_gettime(CLOCK_REALTIME, &ts);
    //        ts.tv_sec += PROFILE_ASYNC_EVT_TIMEOUT;
            IotLogInfo("[Provisioning task] validateLocalLinkConnection() sem wait");
            uint32_t ts = 10000;
            retBool = IotSemaphore_TimedWait(&Provisioning_ControlBlock.connectionAsyncEvent,
                                            ts);
            
            IotLogInfo("[Provisioning task] validateLocalLinkConnection() sem exit ret=%d, status=%x",
                       (int)retBool, ControlBlock.status);
            
            /* freertos return false in case of timeout */
            if(retBool == false)           
            {
                IotLogError(
                    "[Provisioning task] Cannot connect to AP or"
                    " profile does not exist\n\r");
                Board_LedOff();
                retVal = -1;
    
                return(retVal);
            }
        }
    
        IotLogInfo("[Provisioning task] Connection to AP succeeded");
    
        /* Get the device's IP address */
        ipLen = sizeof(SlNetCfgIpV4Args_t);
        ConfigOpt = 0;
        sl_NetCfgGet(SL_NETCFG_IPV4_STA_ADDR_MODE,&ConfigOpt,&ipLen,
                     (uint8_t *)&ipV4);
    
        IotLogInfo("[Provisioning task] IP address is %d.%d.%d.%d", \
                   SL_IPV4_BYTE(ipV4.Ip,3),  \
                   SL_IPV4_BYTE(ipV4.Ip,2),  \
                   SL_IPV4_BYTE(ipV4.Ip,1),  \
                   SL_IPV4_BYTE(ipV4.Ip,0));
    
        return(0);
    }
    
    
    /// <summary>
    /// OpenProvisioningSession
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>void</returns>
    void OpenProvisioningSession(void* param)
    {
        gProvisionServiceInfo = (PROVISION_INFO *)param;
        SignalProvisioningEvent(PrvnEvent_Triggered);
    }
    
    //*****************************************************************************
    /// <summary>
    /// StartAsyncEvtTimer
    /// </summary>
    /// <param name="uint32_t"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    static int32_t StartAsyncEvtTimer(uint32_t timeout)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
    
        pCtx->asyncEvtTimeout = timeout;
        // Platform_TimerStart(pCtx->asyncEvtTimeout, gAsyncEventTimer, 0);
        return(0);
    }
    
    //*****************************************************************************
    /// <summary>
    /// StopAsyncEvtTimer
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    int32_t StopAsyncEvtTimer(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
    
        if(0 != pCtx->asyncEvtTimeout)
        {
            // Platform_TimerStop(gAsyncEventTimer);
            pCtx->asyncEvtTimeout = 0;
        }
    
        return(0);
    }
    
    
    //! \brief This function puts the device in its default state. It:
    //!           - Set the mode to AP
    //!           - Configures connection policy to Auto
    //!           - Deletes all the stored profiles
    //!           - Enables DHCP
    //!          - Disable IPV6
    //!           - Disables Scan policy
    //!           - Sets Tx power to maximum
    //!           - Sets power policy to normal
    //!           - Unregister mDNS services
    //!           - Remove all filters
    //!
    //!           IMPORTANT NOTE - This is an example reset function, user must
    //!           update this function to match the application settings.
    //!
    //! \param   none
    //! \return  On success, zero is returned. On error, negative is returned
    //*****************************************************************************
    
    /// <summary>
    /// ConfigureSimpleLinkToDefaultState
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    static int32_t ConfigureSimpleLinkToDefaultState(void)
    {
        SlWlanRxFilterOperationCommandBuff_t RxFilterIdMask;
    
        uint8_t ucConfigOpt = 0;
        uint16_t ifBitmap = 0;
        //uint8_t ucPower = 0;
    
        int32_t ret = -1;
        int32_t mode = -1;
    
        memset(&RxFilterIdMask,0,sizeof(SlWlanRxFilterOperationCommandBuff_t));
    
        /* Start Simplelink - Blocking mode */
        mode = sl_Start(0, 0, 0);
        if(SL_RET_CODE_DEV_ALREADY_STARTED != mode)
        {
            ASSERT_ON_ERROR(mode);
        }
    
        /* If the device is not in AP mode, try configuring it in AP mode
           in case device is already started 
           (got SL_RET_CODE_DEV_ALREADY_STARTED error code), then mode would remain
           -1 and in this case we do not know the role. Move to AP role anyway  */
        if(ROLE_AP != mode)
        {
            /* Switch to AP role and restart */
            ret = sl_WlanSetMode(ROLE_AP);
            ASSERT_ON_ERROR(ret);
    
            ret = sl_Stop(SL_STOP_TIMEOUT);
            ASSERT_ON_ERROR(ret);
    
            ret = sl_Start(0, 0, 0);
            ASSERT_ON_ERROR(ret);
    
            /* Check if the device is in AP again */
            if(ROLE_AP != ret)
            {
                return(ret);
            }
        }
    
        /* Set connection policy to Auto (no AutoProvisioning)  */
        ret = sl_WlanPolicySet(SL_WLAN_POLICY_CONNECTION,
                               SL_WLAN_CONNECTION_POLICY(1, 0, 0, 0), NULL, 0);
        ASSERT_ON_ERROR(ret);
    
        /* Remove all profiles */
        //ret = sl_WlanProfileDel(0xFF);
        //ASSERT_ON_ERROR(ret);
    
        /* Enable DHCP client */
        ret = sl_NetCfgSet(SL_NETCFG_IPV4_STA_ADDR_MODE,SL_NETCFG_ADDR_DHCP,0,0);
        ASSERT_ON_ERROR(ret);
    
        /* Disable IPV6 */
        ifBitmap = 0;
        ret =
            sl_NetCfgSet(SL_NETCFG_IF, SL_NETCFG_IF_STATE, sizeof(ifBitmap),
                         (uint8_t *)&ifBitmap);
        ASSERT_ON_ERROR(ret);
    
        /* Disable scan */
        ucConfigOpt = SL_WLAN_SCAN_POLICY(0, 0);
        ret = sl_WlanPolicySet(SL_WLAN_POLICY_SCAN, ucConfigOpt, NULL, 0);
        ASSERT_ON_ERROR(ret);
    
        /* Set Tx power level for station mode
           Number between 0-15, as dB offset from max power - 0 will
           set max power */
    //    ucPower = 0;
    //    ret = sl_WlanSet(SL_WLAN_CFG_GENERAL_PARAM_ID,
    //                     SL_WLAN_GENERAL_PARAM_OPT_STA_TX_POWER, 1,
    //                     (uint8_t *)&ucPower);
    //    ASSERT_ON_ERROR(ret);
    
        /* Set PM policy to normal */
        ret = sl_WlanPolicySet(SL_WLAN_POLICY_PM, SL_WLAN_NORMAL_POLICY, NULL, 0);
        ASSERT_ON_ERROR(ret);
    
        /* Unregister mDNS services */
        ret = sl_NetAppMDNSUnRegisterService(0, 0, 0);
        ASSERT_ON_ERROR(ret);
    
        /* Remove  all 64 filters (8*8) */
        memset(RxFilterIdMask.FilterBitmap, 0xFF, 8);
        ret = sl_WlanSet(SL_WLAN_RX_FILTERS_ID,
                         SL_WLAN_RX_FILTER_REMOVE,
                         sizeof(SlWlanRxFilterOperationCommandBuff_t),
                         (uint8_t *)&RxFilterIdMask);
        ASSERT_ON_ERROR(ret);
    
        ret = sl_Stop(SL_STOP_TIMEOUT);
        ASSERT_ON_ERROR(ret);
    
        return(ret);
    }
    
    //*****************************************************************************
    /// <summary>
    /// StartLedEvtTimer
    /// </summary>
    /// <param name="uint32_t"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    int32_t StartLedEvtTimer(uint32_t timeout)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
    
        pCtx->ledToggleTimeout = timeout;
        // Platform_TimerStart(pCtx->ledToggleTimeout, gLedTimer, 1);
    
        return(0);
    }
    
    //*****************************************************************************
    /// <summary>
    /// StopLedEvtTimer
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    int32_t StopLedEvtTimer(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
    
        if(0 != pCtx->ledToggleTimeout)
        {
            // Platform_TimerStop(gLedTimer);
            pCtx->ledToggleTimeout = 0;
        }
    
        return(0);
    }
    
    
    //****************************************************************************
    /// <summary>
    /// provisioningInit
    /// </summary>
    /// <param name="PrvsnMode"> </param>
    /// <returns>void</returns>
    //****************************************************************************
    void provisioningInit(PrvsnMode provisioningMode)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
    
        //Platform_TimerInit(AsyncEvtTimerIntHandler, &gAsyncEventTimer);
    
        /** By default, setting the provisioning mode to AP + Smart Config.
         * Other values could be PrvsnMode_SC or PrvsnMode_AP
         */
        pCtx->provisioningMode = provisioningMode;//PROVISIONING_MODE;
        switch(pCtx->provisioningMode)
        {
        case PrvsnMode_APSC: pCtx->defaultRole = ROLE_AP;
            break;
    
        case PrvsnMode_AP: pCtx->defaultRole = ROLE_AP;
            break;
    
        case PrvsnMode_SC: pCtx->defaultRole = ROLE_STA;
            break;
        }
    
        /* Provisioning has not started yet */
        pCtx->provisioningStatus = PrvsnStatus_Stopped;
        pCtx->currentState = PrvnState_Init;
        
        
        /* Configure Provisioning Toggle LED  */
        Board_LedOff();
    
    //    Platform_TimerInit(LedTimerIntHandler, &gLedTimer);
    
        /* Set the LED toggling timeout before starting the timer */
        pCtx->ledToggleTimeout = LED_TOGGLE_CONFIRMATION_TIMEOUT;
    
        StartLedEvtTimer(pCtx->ledToggleTimeout);
    }
    
    
    //*****************************************************************************
    /// <summary>
    /// provisioningClose
    /// </summary>
    /// <param name="void"> </param>
    /// <returns>int32_t</returns>
    //****************************************************************************
    int32_t provisioningClose(void)
    {
        Provisioning_AppContext *const pCtx = &gAppCtx;
        int32_t retVal = 0;
        //PrvnState provisioningState;
        SlDeviceVersion_t ver = {0};
        uint8_t configOpt = 0;
        uint16_t configLen = 0;
    
        /* check if provisioning is running */
        configOpt = SL_DEVICE_GENERAL_VERSION;
        configLen = sizeof(ver);
        retVal =
            sl_DeviceGet(SL_DEVICE_GENERAL, &configOpt, &configLen,
                         (uint8_t *)(&ver));
        if(SL_RET_CODE_PROVISIONING_IN_PROGRESS == retVal)
        {
            IotLogError(
                "[Provisioning task]  Provisioning is already running, "
                "stopping it...\r\n");
            
            
    #if (defined EXTERNAL_CLOUD_CONFIRMATION && EXTERNAL_CLOUD_CONFIRMATION == 1)
            /* set SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION Flag for stopping new prov schema */
    
            retVal =
                ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP, ROLE_STA, 0, NULL,
                                    SL_WLAN_PROVISIONING_CMD_FLAG_EXTERNAL_CONFIRMATION);
    
    #else
            retVal =
                ProvisioningStateMachine[0].ProvisioningAPI.sl_WlanProvisioning(SL_WLAN_PROVISIONING_CMD_STOP, ROLE_STA, 0, NULL,
                                    0);
    #endif /* EXTERNAL_CLOUD_CONFIRMATION */
    
            ASSERT_ON_ERROR(retVal);
            
            if(retVal == 0)
            {
                IotLogInfo("stopped provsioning\n\r");
            }
            else
            {
                IotLogError("provisioningClose() Failed to stop provsioning\n\r");
            }
    
            pCtx->provisioningStatus = PrvsnStatus_Stopped;
        }
        else if(retVal < 0)
        {
            return(retVal);
        }
        else
        {
            retVal = 0;
        }
    
        return(retVal);
    }
    
    
    //*****************************************************************************
    /// <summary>
    /// NetAppSendError
    /// </summary>
    /// <param name="SlNetAppRequest_t*"> </param>
    /// <param name="SlNetAppResponse_t*"> </param>
    /// <param name="int"> </param>
    /// <param name="char*"> </param>
    /// <returns>void</returns>
    //****************************************************************************
    static void NetAppSendError(SlNetAppRequest_t *pNetAppRequest, 
                                   SlNetAppResponse_t *pNetAppResponse, int eCode, char *error)
    {
        char *contentType = "text/html";
        unsigned char *pMetadata;
        unsigned char *pResponseText;
        
        pMetadata = (unsigned char *)malloc(128);
        pResponseText = (unsigned char *)malloc(64);
        
        pNetAppResponse->Status = SL_NETAPP_HTTP_RESPONSE_200_OK;
        /* Write the content type TLV to buffer */
        pNetAppResponse->ResponseData.pMetadata = pMetadata;
        *pMetadata =
            (_u8)SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_TYPE;
        pMetadata++;
        *(_u16 *)pMetadata = (_u16)strlen(contentType);
        pMetadata += 2;
        memcpy(pMetadata, contentType, strlen(contentType));
        pMetadata += strlen(contentType);
        /* Write the content length TLV to buffer */
        *pMetadata = SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_LEN;
        pMetadata++;
        *(_u16 *)pMetadata = 2;
        pMetadata += 2;
        pNetAppResponse->ResponseData.Flags = 0;
        
        IotLogInfo("NetAppSendError() : [%s] \r\n", error);
        sprintf((char *)pResponseText, HTTP_POST_RESPONSE, eCode, error);
        
        *(_u16 *)pMetadata = (_u16)strlen((char*)pResponseText);
        pMetadata += 2;
        /* Calculate and write the total length of meta data */
        pNetAppResponse->ResponseData.MetadataLen =
            pMetadata - pNetAppResponse->ResponseData.pMetadata;
        /* Write the text of the response */
        pNetAppResponse->ResponseData.PayloadLen = (_u16)strlen((char *)pResponseText);
        pNetAppResponse->ResponseData.pPayload = pResponseText;
        return;
    }
    
    
    //*****************************************************************************
    /// <summary>
    /// HandleNetAppCloudConfigURL
    /// </summary>
    /// <param name="SlNetAppRequest_t*"> </param>
    /// <param name="SlNetAppResponse_t*"> </param>
    /// <returns>void</returns>
    //****************************************************************************
    static void HandleNetAppCloudConfigURL(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
    {
        const char *pUrl = NULL;
        size_t UrlLength = 0;
        
        char *contentType = "text/html";
        unsigned char *pMetadata;
        unsigned char *pResponseText;
        int fileLen = 0;
        uint8_t *fileBuf;
        const char *pThingName = NULL;
        size_t thingNameLength = 0;
        jsmn_init(&parser);
        int jsonret;
        
        
    
        /* JSON format verification */
        IotLogInfo("Received Json From HTTP-POST : [%s]",pNetAppRequest->requestData.pPayload);
        if((pNetAppRequest->requestData.PayloadLen < 3) || 
           (pNetAppRequest->requestData.pPayload[0] != '{') || 
               (pNetAppRequest->requestData.pPayload[pNetAppRequest->requestData.PayloadLen-1] != '}'))
        {
            IotLogError("Invalid Json [%s]\n", pNetAppRequest->requestData.pPayload);
            NetAppSendError(pNetAppRequest, pNetAppResponse, 204, "Invalid Json");
            return;
        }
        /* JSON format verification */
        jsonret = jsmn_parse(&parser, (char const *)pNetAppRequest->requestData.pPayload, pNetAppRequest->requestData.PayloadLen, tokens, 256);
        if(jsonret < 0 ){
            IotLogError("Invalid Json [%s]\n", pNetAppRequest->requestData.pPayload);
            NetAppSendError(pNetAppRequest, pNetAppResponse, 204, "Invalid Json");
            return;
        }
        
        /* Extract URL configuration from JSON buffer */
        if (false == JSON_Search((const char *)pNetAppRequest->requestData.pPayload,
                                                pNetAppRequest->requestData.PayloadLen,
                                                "url",
                                                3,
                                                &pUrl,
                                                &UrlLength))
        {
            NetAppSendError(pNetAppRequest, pNetAppResponse, 204, "Invalid Json");
            return;
        }
        
        /* verify Device config file length which is read from device - flash  */
        if(g_ConfigLen <= 0)
        {
            NetAppSendError(pNetAppRequest, pNetAppResponse, 500, "Internal Server error");
            return;
        }
        
        /* Write the URL to config */
        pMetadata = (unsigned char *)malloc(128);
        pResponseText = (unsigned char *)malloc(64);
        
        sprintf((char *)pResponseText, HTTP_POST_RESPONSE, 200, "");
        pCloudUrl = (char *) malloc(UrlLength+1); 
        
        if(pCloudUrl != NULL)
        {
            memcpy(pCloudUrl, pUrl, UrlLength);
            pCloudUrl[UrlLength] = '\0';
        }
    
    
        pNetAppResponse->Status = SL_NETAPP_HTTP_RESPONSE_200_OK;
        /* Write the content type TLV to buffer */
        pNetAppResponse->ResponseData.pMetadata = pMetadata;
        *pMetadata =
            (_u8)SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_TYPE;
        pMetadata++;
        *(uint16_t *)pMetadata = (uint16_t)strlen(contentType);
        pMetadata += 2;
        memcpy(pMetadata, contentType, strlen(contentType));
        pMetadata += strlen(contentType);
        /* Write the content length TLV to buffer */
        *pMetadata = SL_NETAPP_REQUEST_METADATA_TYPE_HTTP_CONTENT_LEN;
        pMetadata++;
        *(uint16_t *)pMetadata = 2;
        pMetadata += 2;
        pNetAppResponse->ResponseData.Flags = 0;
        
        //IotLogInfo("SL_NETAPP_REQUEST_HTTP_POST : handle [%d], payload len [%d] , payload[%s] \n\r",
        //           gHandle, pNetAppRequest->requestData.PayloadLen, pNetAppRequest->requestData.pPayload);
        
        fileBuf = g_ConfigBuf;
        fileLen = g_ConfigLen;
        
        /* Extract thingName from config file which is fetched from device flash */
        if (JSON_Search((const char *)fileBuf,
                                       fileLen,
                                       "thingName",
                                       9,
                                       &pThingName,
                                       &thingNameLength))
        {  
            pthingNamebuf = (char *) malloc(thingNameLength+1); 
            memcpy(pthingNamebuf, pThingName, thingNameLength);
            pthingNamebuf[thingNameLength] = '\0';
    #endif
        }
        else
        {
            IotLogError("HandleNetAppCloudConfigURL() Thing Name Not found");
        }
        char *config_buf;
        
        config_buf = (char *)pvPortMalloc(sizeof(uint8_t) * 256);
        
        if(pCloudUrl != NULL)
        {
            /* Create complete buffer and write to device configuration */
            sprintf(config_buf, FS_FORMATTER_CONFIG, pCloudUrl, pthingNamebuf);
            IotLogInfo("Updating Configuaration file : %s", config_buf);
        }
        
        UpdateConfigBuf(config_buf);
        *(uint16_t *)pMetadata = (uint16_t)strlen((char *)pResponseText);
        pMetadata += 2;
        /* Calculate and write the total length of meta data */
        pNetAppResponse->ResponseData.MetadataLen =
            pMetadata - pNetAppResponse->ResponseData.pMetadata;
        /* Write the text of the response */
        pNetAppResponse->ResponseData.PayloadLen = (uint16_t)strlen((char *)pResponseText);
        pNetAppResponse->ResponseData.pPayload = pResponseText;
        
    }
    
    //*****************************************************************************
    /// <summary>
    /// StartAsyncEvtTimer
    /// </summary>
    /// <param name="SlNetAppRequest_t*"> </param>
    /// <param name="SlNetAppResponse_t*"> </param>
    /// <param name="int"> </param>
    /// <returns>int</returns>
    //****************************************************************************
    int HandleNetAppGET(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse, int watchdogHandle)
    {
        _u8 UrlPath[128] = {0};
        
        /* Extract  MetaData and fetche REST API Path information */
        ExtractURLFromMetaData(pNetAppRequest->requestData.pMetadata, pNetAppRequest->requestData.MetadataLen, UrlPath);
        
        /* Compare API Path information */
    #if (defined HTTP_GET_VERSION_ERROR_INFO && HTTP_GET_VERSION_ERROR_INFO == 1)
        if ((strcmp((const char *)UrlPath, DEFINED_CLIENT_CERT_URL) == 0) ||
            (strcmp((const char *)UrlPath, DEFINED_VERSION_REQUEST) == 0) ||
            (strcmp((const char *)UrlPath, DEFINED_VERSION_ERROR_INFO) == 0))
    #else
        if (strcmp((const char *)UrlPath, DEFINED_CLIENT_CERT_URL) == 0)
    #endif /* HTTP_GET_VERSION_ERROR_INFO */
        {
        
            pNetAppResponse->Status = SL_NETAPP_RESPONSE_PENDING;
            /* Will be handled in provisioning_task.c based on below flag */
            if (strcmp((const char *)UrlPath, DEFINED_CLIENT_CERT_URL) == 0)
            {
                /* Get certificate will be handled in provisioning_task.c based on below flag */
                gisGETReqPending = 1;
            }
    
    #if (defined HTTP_GET_VERSION_ERROR_INFO && HTTP_GET_VERSION_ERROR_INFO == 1)
            else if (strcmp((const char *)UrlPath, DEFINED_VERSION_REQUEST) == 0)
            {
                /* Send version number */
                gisGETReqPending = 8;
            }
        
            else if (strcmp((const char *)UrlPath, DEFINED_VERSION_ERROR_INFO) == 0)
            {
                /* send error info */
                gisGETReqPending = 9;
            }
    #endif /* HTTP_GET_VERSION_ERROR_INFO */
                
                /* Pass the handler to provisioning_task.c to process */
            gHandle = pNetAppRequest->Handle;
            
            /* Prepare response */
            pNetAppResponse->ResponseData.pMetadata = NULL;
            pNetAppResponse->ResponseData.MetadataLen = 0;
            pNetAppResponse->ResponseData.pPayload = NULL;
            pNetAppResponse->ResponseData.PayloadLen = 0;
            pNetAppResponse->ResponseData.Flags = 0;
            
            /* Copy to some global buffer any relevant info from pNetAppRequest (the handle
            In particular) and signal the user application that a new HTTP request has arrived. */
            
            return 0x1;
        }
        else
        {
            /* Send success reponse handle nothing */
            //pNetAppResponse->Status = SL_NETAPP_HTTP_RESPONSE_200_OK;
            return 0x0;
        }
    }
    
    //*****************************************************************************
    /// <summary>
    /// HandleNetAppPOST
    /// </summary>
    /// <param name="SlNetAppRequest_t*"> </param>
    /// <param name="SlNetAppResponse_t*"> </param>
    /// <returns>int</returns>
    //****************************************************************************
    int HandleNetAppPOST(SlNetAppRequest_t *pNetAppRequest, SlNetAppResponse_t *pNetAppResponse)
    {
        _u8 UrlPath[128] = {0};
        
        /* Extract  MetaData and fetche REST API Path information */
        ExtractURLFromMetaData(pNetAppRequest->requestData.pMetadata,
                                  pNetAppRequest->requestData.MetadataLen, UrlPath);
        
        /* Compare API Path information */
        if (strcmp((const char *)UrlPath, DEFINED_CLOUD_CONFIG_URL) == 0)
        {
            /* Process the configuration URL received from HTTP-POST */
            HandleNetAppCloudConfigURL(pNetAppRequest, pNetAppResponse);
            return 0x1;
        }
        else
        {
            //NetAppSendError(pNetAppRequest, pNetAppResponse, 204, "Unsupported URL");
            /* process if any other response */
            return 0x0;
        }
    }
    
    

     

    Disconnection from AP is done manually, as part of firmware testing.

    Thanks

  • I'm not sure what exactly is happening but it seems related to the application.

    During provisioning, (after the configuration is set) the mobile device is expected to leave the AP (i guess the  "Device disconnected from the AP on an ERROR..!!" is related - i couldn't find this in your code). 

    I also see that the event confirmation success is received ("[Provisioning task] Current: 2, Event: 3, Next: 3")

    Then instead of being is state 3 (PrvnState_Completed), the next event (6 = WaitForConn -> what is the trigger to this event?) is received in state 0 (?)

  • Hi Kobi,

    Regarding your question

    Then instead of being is state 3 (PrvnState_Completed), the next event (6 = WaitForConn -> what is the trigger to this event?) is received in state 0 (?)

    following sequence of events was observed when debugged on hardware.

    Step Current State Event Next State
    1 PrvnState_Init  PrvnEvent_Triggered  PrvnState_Idle
    2 PrvnState_Idle PrvnEvent_Started  PrvnState_WaitForConfirmation
    3 PrvnState_WaitForConfirmation PrvnEvent_ConfirmationSuccess  PrvnState_Completed
    4 PrvnState_Init  PrvnEvent_WaitForConn  PrvnState_Init 
    5 PrvnState_Init  PrvnEvent_Triggered  PrvnState_Idle

     

    In this process, during step 3, PrvnEvent_ConfirmationSuccess is received, and Provisioning stop command is sent to network processor. When we get the Provisioning stopped event from the network processor (see in logs [WLAN EVENT] Provisioning stopped), at that time if WLAN status is NOT CONNECTED, then PrvnEvent_WaitForConn event is sent. Hence the function WaitForConn() is called. In this function again provisioning is initialized (see line 641 and 642 in new_provisioning.c).

    To make sure network processor is not creating the issue, I did a network processor reboot before line 641 in new_provisioning.c. But that didn't solve.

    I checked the application code based on your inputs, but this issue doesn't seem to be related to the application.

    Please guide me on how to initialize the HTTP server for second time, or what can be the possible solution for this issue.

  • It is hard for me to follow the code with all the changes you've made - so i'll stick to questions about the the expected behavior and event from the NWP.

    When the provisioning is completed successfully - how do get that the status is NOT CONNECTED? this doesn't make sense - the device is supposed to be connected if the provisioning was successful. (are you turning off the router?)

    I think you are just waiting for another connection event and the following provisioning is redundant which might cause issues. 

  • Hi Kobi,

    (are you turning off the router?)

    Yes, I'm turning off the router right after provisioning is successful. See step 7 below.


    I'm explaining the device behavior and the problem statements in different words. Hope this helps.

    Steps to reproduce the issue:

    1. Device is flashed with the required binary and logs are captured using Teraterm
    2. Device boots up, initializes the peripherals and goes to provisioning mode and waits.
    3. From the mobile app, I will connect to the device and read the HW and FW versions. This is done using HTTP.
    4. Now I will add the profile of the router from mobile app.
    5. Device gets connected to the router.
    6. Device downloads the Shadow document from cloud using MQTT (for external cloud confirmation).
    7. Just after device downloads Shadow document, I'm turning off the router.
    8. Since the profile is no longer available (even though the provisioning is successful), the device goes into provisioning mode (hosting as Access point) again and is waiting.
    9. Now again from the mobile app I'm trying to connect to device and read the HW and FW versions. This time mobile app is not able to connect to the device.

    In step 9, the device is expected to connect to the mobile app and provisioning should be done again.

    Please help me with the below queries:

    1. I'm suspecting that in step 9, the device is not connected to mobile app due to some issue in HTTP server (in device side). Is that correct? If not, what might be the reason for failure.
    2. If the issue is due to HTTP server, how to resolve it?

    Thanks for your time.

    Regards,

    Vaishnavi

  • Are you verifying the return code of sl_WlanProvisioning?

    Do you have more info (preferably a sniffer log) to better understand the issue in the HTTP connection?

    You can try resetting the NWP or the HTTP Server:

    //NWP RESET
    sl_Stop(200); sl_Start(0,0,0);
    
    // HTTP SERVER RESET
    sl_NetAppStop(SL_NETAPP_HTTP_SERVER_ID); 
    sl_NetAppStart(SL_NETAPP_HTTP_SERVER_ID)