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

Trying to integrate bonding into uart example, but peer manager event handler never being called

I developed a functioning application that advertises with Nordic UART Service, connects to a smartphone application, then reads various sensor data using the SAADC and transmits data to a smartphone. I now want to integrate bonding into the application. I have done a lot of reading online, checking examples, and borrowed some code from the ble_app_template example. 

This strategy seemed to work on my iPhone with nRF Connect at first. Upon connection, my application would enter the pm_evt_handler() function and the PM_EVT_CONN_SEC_SUCCEEDED case within peer_manager_handler.c, function pm_handler_evt_log(), would be entered. My debug console would log That the connection was secured, with procedure: encryption. I also noticed that my application was listed and available in my iPhone's bluetooth settings, which had never happened before (only appeared in scans through nRF Connect or similar ble applications). I then wanted to experiment with deleting bonds from with my application, but after doing so my program would enter the PM_EVT_CONN_SEC_FAILED case and print the connection security had failed with error 4102. Research pointed towards the error coming from bonds being deleted on my peripheral device, but not the smartphone. So I selected "forget this device" from within my iPhone bluetooth settings. 

I restarted my application without deleting bonds, then received some sort of database error. I cannot remember what the error was exactly and I did not save it, and can no longer reproduce it. I cannot reproduce it because now my application never enters the peer manager event handler function, pm_evt_handler(). The peer manager is being initialized, but my application seems to have lost all functionality with regards to the peer manager and I have not changed the code at all.

Can somebody please help me try to pinpont what I am doing wrong? My application is based off of the uart example, and I integrated peer manager functions from the ble_app_template example project. My application still functions fine with regards to reading SAADC values, timers, regular advertising/connection, etc, but has no peer manager behavior. Below I am pasting my main.c and sdk_config.h files. Please ignore functions related to SAADC, reading values, etc - there are many parts I should clean up and optimize that I am already aware of. 

Code related to peer manager are: lines 136-143, 230-250, 583-612, 616-624, 1212-1234. I began writing this application when I was first learning C, so code as seen in function "format_bluetooh_packet()" is painful to look at and is on my to-do to fix. All i want right now is to get peer manager working and then I can clean up/refactor older code. 

--

main.c

sdk_config.h

Parents
  • Hi,

    I do not see anything wrong with how you are using the peer manager. It seems copy-pasted from other SDK examples, with the only modification that you have added some logging in your pm_evt_handler(). There is nothing missing in your main.c or sdk_config.h related to the peer manger as far as I can see.

    You write that the behavior changed without you modifying the code at all. Obviously something has changed. Are you sure this is the code you are testing, or could there be a mixup of some sort? Do you still have problems if you do a full erase of the nRF device (nrfjprog -e) before you program it and delete the bond on the iOS device and try again? I ask because the error you get 4102 = 0x1006 = PM_CONN_SEC_ERROR_PIN_OR_KEY_MISSING to indicate to me that you have lost bonding information on just one side.

    Note that you can allow repairing if you don't want this to happen again, and are OK with the security implications of it. If so, just add handling of the PM_EVT_CONN_SEC_CONFIG_REQ event to you peer manager event handler:

  • I began experiencing this issue after I deleted bonding information from my iOS device. Now I don't get any debug logs from any peer manager functions. I have tried erasing the DK through Segger Embedded Studios and reflashing, but this does not seem to make a difference. I have also tried with three different phones which were never previously bonded, and tried with two new DKs that I had never flashed this code onto. I don't see the error anymore, or any logs involved to peer manager anymore. 

  • This is what I see in my debug terminal now, whereas previously I would see logs I put in the peer manager handler as well as logs from the default pm_evt_handler_log function logs (where the error/success would be written)

  • Hi,

    Noah said:
    I have tried erasing the DK through Segger Embedded Studios and reflashing

    How did you do it? SES normally just does a sector erase, and in that case, the FDS pages holding the bonding information is left untouched. This is then still valid after you program the application again. So to fix this, either completely erase the chip using "nrfjprog -e" or explicitly allow repairing as I explained in my previous post.

  • I tried fully erasing the DK using nrfjprog -e, and I also explicitly allowed pairing with the example code you provided. I also added another case into pm_evt_handler for "PM_EVT_SEC_SUCCEEDED" in which I simply output text using NRF_LOG_INFO(). However, the behavior still persists and the pm_evt_handler function is never called or entered at all. I even deleted all the peer manager related functions, and re-integrated them from the ble_app_template example. I also checked through the heart rate sensor example and verified I'm using the same function calls/configurations/etc, the heart rate sensor example is almost the same as the ble_app_template with regards to bonding. Also did this for ble_app_bps example.

    When should events be passed to the Peer Manager, and how are they passed? The peer manager is not referenced or mentioned in any other functions. Variable "ble_gap_sec_params_t sec_param" is set inside peer_manager_init(), but how does this function relate to the rest of the program? I know that in older SDK versions, a function called "ble_evt_dispatch" would dispatch events to the peer manager. This is even discussed in a comment within main.c of ble_app_bps example, line 215-217. The comment reads:

    "NOTE: For this to work, make sure ble_bps_on_ble_evt() is called before ble_bondmngr_on_ble_evt() in ble_evt_dispatch()"

    However there are no such functions in any examples within SDK version 15.2.0. 

Reply
  • I tried fully erasing the DK using nrfjprog -e, and I also explicitly allowed pairing with the example code you provided. I also added another case into pm_evt_handler for "PM_EVT_SEC_SUCCEEDED" in which I simply output text using NRF_LOG_INFO(). However, the behavior still persists and the pm_evt_handler function is never called or entered at all. I even deleted all the peer manager related functions, and re-integrated them from the ble_app_template example. I also checked through the heart rate sensor example and verified I'm using the same function calls/configurations/etc, the heart rate sensor example is almost the same as the ble_app_template with regards to bonding. Also did this for ble_app_bps example.

    When should events be passed to the Peer Manager, and how are they passed? The peer manager is not referenced or mentioned in any other functions. Variable "ble_gap_sec_params_t sec_param" is set inside peer_manager_init(), but how does this function relate to the rest of the program? I know that in older SDK versions, a function called "ble_evt_dispatch" would dispatch events to the peer manager. This is even discussed in a comment within main.c of ble_app_bps example, line 215-217. The comment reads:

    "NOTE: For this to work, make sure ble_bps_on_ble_evt() is called before ble_bondmngr_on_ble_evt() in ble_evt_dispatch()"

    However there are no such functions in any examples within SDK version 15.2.0. 

Children
  • Hi,

    You have described two distinctly different issues:

    • The issue where you deleted bonding information on one side and got error 4102, is caused by only deleting bonding information on the phone, and not the device, as explained in my last two posts.
    • Regarding the issue with no peer manger events:
      • There is no need to pass the event to the peer manager from your application like it was done in older SDK versions. This is because in 15.2, this is handled by the peer manager itself. (Specifically, you can see that peer_manager.c uses the NRF_SDH_BLE_OBSERVER to register it's event handler so that the SoftDevice Handler library forwards the events directly.)
      • I suspect that the phone simply never attempts to pair or bond? Have you double-checked that? iOS will only pair/bond when needed because it attempts to access a characteristic that requires that. Therefore, I suggest you test with Android or nRF Connect for Dekstop first (if you have an additional nRF52 DK or dongle) to see if it works, since there you can manually trigger pairing.
  • Yes you are correct, however I already know how to handle error 4102. I already knew that this is caused by deleting bonds on the nRF52 DK and not the phone. Is the correct way to delete bonds on an iPhone to select "forget this device" from within my iOS bluetooth settings menu? If so, I already tried that before making this post. After selecting "forget this device" from within my iphone, I then experience the behavior of peer manager never being called.

    Do I need to include Bond Manager Service in addition to Nordic UART Service? Or does adding the peer manager code shown above now require bonding to read/write to UART characteristics? Because my application still functions, with the code included in the original post my application advertises, connects, and sends UART data as if the peer manager functions are not even there. It has not impacted my application at all. I will try on the nRF Connect android and desktop applications, that is a good idea

  • Hi,

    Noah said:
    then experience the behavior of peer manager never being called.

    I see. But are you sure the phone attempts to pair bond? Please either check with a sniffer or just use nRF Connect or an Android phone and explicitly try to pair or bond. Alternatively, replace SEC_OPEN where you find it in ble_nus.c. with SEC_JUST_WORKS, so that the iPhone will initiate bonding automatically when it attempts to use the NUS service. An important point here is tha tiOS will not pair or bond automatically unless it needs to (which is when it gets access denied to read or write to a characteristic due to a too low security level).

    Noah said:
    Do I need to include Bond Manager Service in addition to Nordic UART Service?

    No.

    Noah said:
    Or does adding the peer manager code shown above now require bonding to read/write to UART characteristics?

    No. But by doing the modifications I suggested earlier in this post in ble_nus.c, bonding or pairing will be required.

    Noah said:
    Because my application still functions, with the code included in the original post my application advertises, connects, and sends UART data as if the peer manager functions are not even there. It has not impacted my application at all.

    It will not have any effect unless the pairing procedure is initiated. Which it probably is not in your test setup.

    Noah said:
    I will try on the nRF Connect android and desktop applications, that is a good idea

    Yes it is Slight smile (since android has API's for the application to specifically pair or bond, which is then possible through the nRF Connect app on Android).

  • Your suggestion to set security parameters to SEC_JUST_WORKS did the trick! Now I am able to bond and pair with my device very reliably, thank you so much for all the help