This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How can I bond with central device only one time?

Hi,

     This is my first time to use Nordic product and I have used nRF52832 based SDK 12.0 and SoftDevice132 v2.0 about 2 months. And the IDE used for devlopment is KEIL MDK.

In my project, I do paring operation configured with static passkey and enable bond. The problem is that after every time I reset nRF52832, my smart phone using andriod system will be asked to input static passkey again when want to connect the nRF52832.

And I used 5 days to search research usefully referrence document in Chinnese website,unfortunately I can not find any useful informations about the problem in China. So,finally I can not solve the problem by self.

I do not know the detailed operations about how to paire and bond with a BLE central device like a smart phone using andriod system only one time until now, even if nRF52832 will be reset we do not need to do bonding operations again.

So, I think I need your useful help to guide me the forever bond operations step by step, as more detailed as possible, when a project need security connectivity like paire operations.

Thanks & Cheers.

The following is my key code about the configure paire and bond operations in my project.


ble_gap_sec_params_t m_sec_params;
ble_gap_sec_keyset_t m_sec_keyset;

ble_gap_enc_key_t m_own_enc_key; //need to be stored in flash
ble_gap_enc_key_t m_peer_enc_key;

static void sec_params_init()
{
memset(&m_sec_params, 0, sizeof(ble_gap_sec_params_t));

//Initialize m_sec_params
m_sec_params.bond = 1;
m_sec_params.mitm = 1;
m_sec_params.io_caps = BLE_GAP_IO_CAPS_DISPLAY_ONLY;
m_sec_params.min_key_size = 7;
m_sec_params.max_key_size = 16;

m_sec_params.kdist_own.enc = 1;
m_sec_params.kdist_own.id = 0;
m_sec_params.kdist_own.sign = 0;

m_sec_params.kdist_peer.enc = 1;
m_sec_params.kdist_peer.id = 0;
m_sec_params.kdist_peer.sign = 0;

memset(&m_sec_keyset, 0, sizeof(ble_gap_sec_keyset_t));
//Initialize m_sec_keyset
m_sec_keyset.keys_own.p_enc_key = &m_own_enc_key;
m_sec_keyset.keys_own.p_id_key = NULL;
m_sec_keyset.keys_own.p_pk = NULL;
m_sec_keyset.keys_own.p_sign_key = NULL;

m_sec_keyset.keys_peer.p_enc_key = &m_peer_enc_key;
m_sec_keyset.keys_peer.p_id_key = NULL;
m_sec_keyset.keys_peer.p_pk = NULL;
m_sec_keyset.keys_peer.p_sign_key = NULL;
}

static void on_ble_evt(ble_evt_t * p_ble_evt)
{
uint32_t err_code;

switch (p_ble_evt->header.evt_id)
{
case BLE_GAP_EVT_CONNECTED:

err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
APP_ERROR_CHECK(err_code);
m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;

err_code = sd_ble_gap_authenticate(m_conn_handle,&m_sec_params);
APP_ERROR_CHECK(err_code);

break;

case BLE_GAP_EVT_DISCONNECTED:
err_code = bsp_indication_set(BSP_INDICATE_IDLE);
APP_ERROR_CHECK(err_code);
m_conn_handle = BLE_CONN_HANDLE_INVALID;
break;

case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
// Pairing not supported
// err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
// APP_ERROR_CHECK(err_code);
sec_params_init();
err_code = sd_ble_gap_sec_params_reply( m_conn_handle,
BLE_GAP_SEC_STATUS_SUCCESS,
&m_sec_params,
&m_sec_keyset);
APP_ERROR_CHECK(err_code);

break;

case BLE_GATTS_EVT_SYS_ATTR_MISSING:
// No system attributes have been stored.
err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
APP_ERROR_CHECK(err_code);
break;

case BLE_GAP_EVT_AUTH_STATUS:
if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status == BLE_GAP_SEC_STATUS_SUCCESS)
{
printf("\r\npair success!!!\r\n");
}
else{
printf("\r\npair failed!!!\r\n");
sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
}

case BLE_GAP_EVT_PASSKEY_DISPLAY:
printf("\r\npasskey: %s\r\n",p_ble_evt->evt.gap_evt.params.passkey_display.passkey);

case BLE_GAP_EVT_SEC_INFO_REQUEST:
sd_ble_gap_sec_info_reply(m_conn_handle, &(m_own_enc_key.enc_info), NULL, NULL);
printf("BLE_GAP_EVT_SEC_INFO_REQUEST\n");
break;

default:
// No implementation needed.
break;
}
}

static void gap_params_init(void)
{
uint32_t err_code;
ble_gap_conn_params_t gap_conn_params;
ble_gap_conn_sec_mode_t sec_mode;

BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);

err_code = sd_ble_gap_device_name_set(&sec_mode,
(const uint8_t *) DEVICE_NAME,
strlen(DEVICE_NAME));
APP_ERROR_CHECK(err_code);

memset(&gap_conn_params, 0, sizeof(gap_conn_params));

gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
gap_conn_params.slave_latency = SLAVE_LATENCY;
gap_conn_params.conn_sup_timeout = CONN_SUP_TIMEOUT;

err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
APP_ERROR_CHECK(err_code);


uint8_t passkey[] = "123456";
m_static_pin_option.gap_opt.passkey.p_passkey = passkey;

err_code=sd_ble_opt_set(BLE_GAP_OPT_PASSKEY,&m_static_pin_option);
APP_ERROR_CHECK(err_code);
}

int main(void)
{
uint32_t err_code;
bool erase_bonds;

// Initialize.
APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);


uart_init();

buttons_leds_init(&erase_bonds); //button 1(@pcb key2,pin14) is used as delete bonding information
ble_stack_init();

gap_params_init();

services_init();
advertising_init();
conn_params_init();

printf("\r\nUART Start!\r\n");
err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
APP_ERROR_CHECK(err_code);

// Enter main loop.
for (;;)
{
power_manage();
}
}

Parents
  • Hi Tianfei, 

    It's hard to tell what could be wrong here. But have you made sure you managed to bond on the first connection ?  If you test with nRFConnect do you see the status change to "Bonded" ?

    Do you have a particular reason of handling the bonding process on your own without using the peer manager library ? You can find the library used in most of our example in the SDK\example\ble_peripheral\ folder. I would suggest you to try the ble_app_proximity example. 

  • Dear Hung Bui,

            When testing and debuging the code, I used the nRFConnect  software in my smart phone. Everytime after I entered the satic key in my smartphone, the nRFConnect  shows bonded. And after disconnect with nRF52832, when I connect nRF52832 again, it will not need any pairing operations. 

            But every time I reset nRF52832, when my smart phone connect nRF52832, the phone also need to carry out pairing and bonding operations.

           The "ble_app_proximity " example I have refered in last week and I found it do not use static key when pairing. So this example can not solve my puzzled problem. 

    Thanks very much for your help.

    Best regards,

    Tianfei

  • Dear Hung Bui,

           In the past few days, I have been learning the infocenter's instructive documents which you provied for me. Because of my poor English, the learning progress is slow. I consider much more days will be hoped for me to understand the library's architecture before I can use it.

           Many thanks for your kind help. 

           Best regards,

           Tianfei

  • Dear Hung Bui,
             After reading your provided documents, I have resolved the problem which I posted at the first time by adding some codes as following, but without using the peer manager.


    #define MY_ENC_INFO_ADDR (0x70004)
    uint32_t * const p_dst=(uint32_t *)MY_ENC_INFO_ADDR;
    uint8_t  read_flash_flag=0;

    static void on_ble_evt(ble_evt_t * p_ble_evt)
    {
        uint32_t err_code;

        uint8_t i;
        uint8_t static temp[50];
        uint8_t static *p_temp=(uint8_t *)(&(m_own_enc_key.enc_info));

        memset(temp, 0, sizeof(temp));

       switch (p_ble_evt->header.evt_id)
       {
            case BLE_GAP_EVT_CONNECTED:
                     err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                     APP_ERROR_CHECK(err_code);
                    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                    err_code = sd_ble_gap_authenticate(m_conn_handle,&m_sec_params);
                    printf("\r\nexecute sd_ble_gap_authenticate()\r\n");
                    APP_ERROR_CHECK(err_code);
                    break;

            case BLE_GAP_EVT_DISCONNECTED:
                    err_code = bsp_indication_set(BSP_INDICATE_IDLE);
                    APP_ERROR_CHECK(err_code);
                    m_conn_handle = BLE_CONN_HANDLE_INVALID;
                    break;

            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                  sec_params_init();
                  err_code = sd_ble_gap_sec_params_reply( m_conn_handle,
                                                                                              BLE_GAP_SEC_STATUS_SUCCESS,
                                                                                              &m_sec_params,
                                                                                              &m_sec_keyset);
                  printf("\r\nexecute sd_ble_gap_sec_params_reply()\r\n");

                  APP_ERROR_CHECK(err_code);
                  break;

          case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                  // No system attributes have been stored.
                 err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                 APP_ERROR_CHECK(err_code);
                 break;
         case BLE_GAP_EVT_AUTH_STATUS:       

              if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status==BLE_GAP_SEC_STATUS_SUCCESS)           {
                    printf("\r\npair success@case BLE_GAP_EVT_AUTH_STATUS!!!\r\n");

                    if(0==read_flash_flag){
                          for(i=0;i<BLE_GAP_SEC_KEY_LEN;i++){
                                   printf("\r\n@case BLE_GAP_EVT_SEC_PARAMS_REQUEST,                            

                                   m_own_enc_key.enc_info.ltk[%d]=0x%X\r\n",i,m_own_enc_key.enc_info.ltk[i]);
                           }

                           p_temp=(uint8_t *)(&(m_own_enc_key.enc_info));
                           for(i=0;i<sizeof(ble_gap_enc_info_t);i++){
                                   temp[i]=*p_temp++;
                                   printf("\r\ntemp[%d]=%d \r\n",i,temp[i]);
                                   SEGGER_RTT_printf(0,"\r\ntemp[%d]=%d \r\n",i,temp[i]);
                            }
                           while((err_code=sd_flash_write(p_dst,(uint32_t *)temp,5))==NRF_ERROR_BUSY); 


                           printf("\r\nsd_flash_write(),return value is %d \r\n",err_code);
                            read_flash_flag=1;
                      }
            }
           else{
                  printf("\r\npair failed@case BLE_GAP_EVT_AUTH_STATUS!!!\r\n");
                  sd_ble_gap_disconnect(m_conn_handle,                

                                                             BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
            }

        case BLE_GAP_EVT_PASSKEY_DISPLAY:
                // printf("\r\npasskey: %s\r\n",p_ble_evt->evt.gap_evt.params.passkey_display.passkey);

        case BLE_GAP_EVT_SEC_INFO_REQUEST:
             printf("\r\n@case BLE_GAP_EVT_SEC_INFO_REQUEST\r\n");
             sd_ble_gap_sec_info_reply(m_conn_handle, &(m_own_enc_key.enc_info), NULL, NULL);

             for(i=0;i<BLE_GAP_SEC_KEY_LEN;i++){
                         printf("\r\n@case BLE_GAP_EVT_SEC_INFO_REQUEST,

                                    m_own_enc_key.enc_info.ltk[%d]=0x%X\r\n",i,m_own_enc_key.enc_info.ltk[i]);
             }
             break;
       default:
       // No implementation needed.
            break;
       }
    }

    int main(void)
    {
    uint32_t err_code;
    bool erase_bonds;
    uint8_t i;
    uint8_t *p_flash=(uint8_t *)MY_ENC_INFO_ADDR;

    // Initialize.
    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_OP_QUEUE_SIZE, false);
    uart_init();
    buttons_leds_init(&erase_bonds);
    ble_stack_init();

    gap_params_init(); //including configuring static key.
    services_init();
    advertising_init();
    conn_params_init();

    printf("\r\nUART Start!\r\n");
    err_code = ble_advertising_start(BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);

    #ifdef RTT_DEBUG_EN
    SEGGER_RTT_Init();
    #endif

    if(*p_dst!=0xffffffff){
        m_own_enc_key.enc_info=*((ble_gap_enc_info_t *)MY_ENC_INFO_ADDR);

        for(i=0;i<BLE_GAP_SEC_KEY_LEN;i++){
              printf("\r\n@program initialize, m_own_enc_key.enc_info.ltk[%d]=0x%X\r\n",

                          i,m_own_enc_key.enc_info.ltk[i]);
        }
        read_flash_flag=1;
    }
    else{
        read_flash_flag=0;
    }

    for (;;)
    {
       nrf_delay_ms(7000);
       p_flash=(uint8_t *)MY_ENC_INFO_ADDR;


       for(i=0;i<sizeof(ble_gap_enc_info_t);i++){
             SEGGER_RTT_printf(0,"flash address 0x%X is 0x%X \r\n",MY_ENC_INFO_ADDR+i,*(p_flash));
             p_flash++;
       }
       SEGGER_RTT_printf(0,"**************The end**************\r\n\r\n\r\n");
       power_manage();
     }
    }

              But now I have found a new problem. When I use the function "sd_flash_write()", I find it can only write the same flash address one time,if you want to use the function to write the same address of flash again ,the operation will take no effect, eventhough I have changed the value which will be written to flash. But meanwhile the return value is NRF_SUCCESS, the result makes me very confused.

              I do not know what's the reason of me in using the function "sd_flash_write()" to execute storing some datas in flash. Wish you can give some useful guidance.

    Thanks very much for your help.
    Best regards,
    Tianfei

  • Hi Tianfei, 

    You would need to erase the flash before you can write again to the same location. It's the nature of the flash. It can only change from 1 to 0. If you want to change from 0 to 1 you need to erase it first. 

    Please be aware that when you call sd_flash_* functions, they are not a blocking functions. They will return immediately after the command has been queued in the softdevice not when the flash actually be written or erased. You would need to wait for a call back. Please follow the softdevice specification. 

  • Dear Hung Bui,

             After resolveing storing the bonding information, now I want to add the whitelist feature in my project. But I do not know how to use it and how to configure it step by step.

             I hope you can give me some instructional documents which can teach me how to use and configure the whitelist provided by SDK step by step.

           Thanks very much for your help.

            Best regards.

           Tianfei

  • Hi Tianfei, 

    What you are doing is like building the peer manager from scratch. I don't see a reason why you can't use the peer manager instead of having to write everything yourself. 

    We don't have a step by step guide about whitelist, but I don't think it's too complicated. You would need to follow the documentation of the function sd_ble_gap_adv_start(), sd_ble_gap_scan_start() and sd_ble_gap_connect() 

    I, long ago, wrote a tutorial that has the code of using whitelist to advertise, you can have a look here

Reply
  • Hi Tianfei, 

    What you are doing is like building the peer manager from scratch. I don't see a reason why you can't use the peer manager instead of having to write everything yourself. 

    We don't have a step by step guide about whitelist, but I don't think it's too complicated. You would need to follow the documentation of the function sd_ble_gap_adv_start(), sd_ble_gap_scan_start() and sd_ble_gap_connect() 

    I, long ago, wrote a tutorial that has the code of using whitelist to advertise, you can have a look here

Children
No Data
Related