Correct process to shutdown BLE and bring it back up?

I’ve modified the demo code quite a bit. I want to shut the BLE libs down, and bring them back up after a button press.

I see this, and it appears this code DID NOT make it in to the 202002.00 release?

Right now I’m locally calling the _cleanup() from iot_demo_freertos.c

static void _cleanup( void )
{
    AwsIotNetworkManager_DisableNetwork( configENABLED_NETWORKS );
    /* Remove network manager subscription */
    AwsIotNetworkManager_RemoveSubscription( subscription );
    IotSemaphore_Destroy( &demoNetworkSemaphore );
    IotSdk_Cleanup();
}

Which works except calling _initialize() again gets me to _waitForNetworkConnection() where it blocks waiting for a semaphore that never comes. It seems the network state change callback isn’t triggered on a second connect.

Am I doing something wrong? Is there a recommended process to shut BLE down and bring it back up? Manually calling AwsIotNetworkManager_DisableNetwork(AWSIOT_NETWORK_TYPE_BLE); and re-enable causes errors where BLE is hard-down, no advertisiment, etc.

Thanks for posting your query.

To help us troubleshoot further, could you mention which board are you using ?

Please note, the callback will only be triggered only upon a successful BLE connection , that is a BLE central has connected to the device. Are you seeing BLE advertisement from the peripheral after disabling and enabling BLE ?

Nordic nrf52840DK

And yes. If I just call cleanup to deinit what it can, it does come back to advertising. It does connect on BLE. However… see log:

24 787 [xx] [INFO ][MQTT][7870] (MQTT connection 2001c1c8, SUBSCRIBE operation 2001c470) Wait complete with result SUCCESS.
29 1216 [BLE] [INFO ][DEMO][12160] BLE disconnected with remote device, connId = 0 

30 6781 [xx] [ERROR][BLE_TXRX][67810] TX Failed, channel closed.
31 6781 [xx] [ERROR][MQTT][67810] (MQTT connection 2001c1c8) Failed to send PINGREQ.
32 6781 [xx] [INFO ][MQTT][67810] (MQTT connection 2001c1c8) Network connection closed.
35 6807 [xx] [INFO ][MQTT][68070] MQTT library cleanup done.
36 6807 [xx] [INFO ][INIT][68070] SDK cleanup done.
39 6847 [xx] [INFO ][INIT][68470] SDK successfully initialized.
40 6847 [xx] [INFO ][DEMO][68470] No networks connected for the demo. Waiting for a network connection. 
41 8137 [BLE] [ERROR][BLE_HAL][81370] PM_UNKNOWN, 0.
42 8137 [BLE] [ERROR][BLE_HAL][81370] sd_ble_gattc_exchange_mtu_request() on connection 0x0 returned busy, will retry.
43 8137 [BLE] [INFO ][DEMO][81370] BLE Connected to remote device, connId = 0

44 8166 [BLE] [INFO ][BLE_TXRX][81660] MTU changed, changing transmit length for data transfer service from 244 to 182

45 8207 [BLE] [ERROR][BLE_HAL][82070] UNKNOWN BLE EVENT 34.
46 8211 [BLE] [ERROR][BLE_HAL][82110] UNKNOWN BLE EVENT 35.

And that’s it. Hangs there at EVENT34/35 (fix btw?)… Never gets the callback and thus semaphore that connection was re-established.

I pulled some lines of that log out, lines my program put in for debug.

24 - normal process up to this point just subbed to a topic
29 - I disconnect phone by shutting app down
30 - Takes 60 seconds for program to timeout, haven’t messed with this yet
35 - loss is detected in my program, starts cleanups
39 - cleaned up, now starts reinit
40 - back to waiting for BLE connection
41 - I connect with app, goes through the process and connects actually, no callback triggered

Now, if I call AwsIotNetworkManager_DisableNetwork(AWSIOT_NETWORK_TYPE_BLE); then cleanup, then re-enable, no the advertising doesn’t come back and the log has errors to the same effect.

Any thoughts Ravi?

Hi,

I am able to reproduce this after modifying the demo runner code as you mentioned above. It seems the events are received, but the state variable in the demorunner is not in sync. There seems to be 2 modifications you want to do for this:

  1. When BLE is disabled by calling AwsIotNetworkManager_DisableNetwork() , it transitions to network state eNetworkStateUnknown but the demorunner is not expecting that. So you need to modify the _onNetworkStateChangeCallback function here as follows:
else if( ( state == eNetworkStateDisabled || state == eNetworkStateUnknown ) 
             && ( demoConnectedNetwork == network ) )
    {
  1. Cleanup function performs AwsIotNetworkManager_RemoveSubscription() and IotSdk_Cleanup() immediately after disabling network. But the network state change events are scheduled asynchronously using taskpool, so you should perform this only once after the whole application is cleaned up.

Hope this helps. Please feel free to get back if you have questions.

Ravi,

Still having issues with it. I added the state_unknown. But if I disable BLE, cleanup, then reenable, I get this:

...
35 6736 [xx] [INFO ][MQTT][67360] MQTT library cleanup done.
36 6836 [xx] [INFO ][INIT][68360] SDK cleanup done.
39 7076 [xx] [INFO ][INIT][70760] SDK successfully initialized.
40 7076 [xx] [ERROR][BLE_HAL][70760] Failed to start advertisement.
41 7076 [xx] [ERROR][DEMO][70760] Failed to toggle BLE on.
42 7076 [xx] [ERROR][DEMO][70760] Failed to intialize all the networks configured for the device.

That’s using some form of this, with sledgehammer vTaskDelay just to see if it would ever work anywhere.

AwsIotNetworkManager_DisableNetwork(AWSIOT_NETWORK_TYPE_BLE);
vTaskDelay(100);
ble_aws_cleanup();
vTaskDelay(100);
AwsIotNetworkManager_EnableNetwork(AWSIOT_NETWORK_TYPE_BLE);
vTaskDelay(100);

Interesting to me, if I leave out the disable, I get the same log. If I don’t disable or enable, I get the same lack of state semaphore - despite adding the lines you suggested. I put a breakpoint of that line just to see, and I’m never getting to _onNetworkStateChangeCallback() at all. I’m looking at the ERROR 34 / 35 lines, but never got to where state is checked at all.

The logs:

45 8207 [BLE] [ERROR][BLE_HAL][82070] UNKNOWN BLE EVENT 34.
46 8211 [BLE] [ERROR][BLE_HAL][82110] UNKNOWN BLE EVENT 35.

These are for events for which porting layer does not have a handler for and can be ignored for now.

There was an issue in Nordic porting layer which caused timer to be not recreated on re-enabling BLE. This caused following error for me in re-enable:

Failed to toggle BLE on.
Failed to initialize all the networks configured for the device.

I have raised a PR to fix this in Nordic porting layer (link )

With this patch and as mentioned in point #2 in above post, I am able to renable BLE for Nordic and re-run demo multiple times.