Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to decode stored data of a bonded peer retrieved with pm_peer_data_load()

Hi, 

I would like to get the stored CCCD values of a bonded peer using pm_peer_data_load()

uint32_t peerCount = pm_peer_count();
if (peerCount <= MAX_NUMBER_OF_BONDS)
{
	pm_peer_id_t peerList[MAX_NUMBER_OF_BONDS] = {0U};
	if (NRF_SUCCESS == pm_peer_id_list(&peerList[0], &peerCount, PM_PEER_ID_INVALID, PM_PEER_ID_LIST_ALL_ID))
	{
		for (uint8_t i = 0U; i < peerCount; i++)
		{
			uint32_t peerDataGattLocal[128] = {0U};
			uint32_t peerDataGattLocalLen = sizeof(peerDataGattLocal);
			NSDS_t_nrferrorCode errorCode = pm_peer_data_load(peerList[i], PM_PEER_DATA_ID_GATT_LOCAL, &peerDataGattLocal[0], &peerDataGattLocalLen);
			switch (errorCode)
			{
				case NRF_SUCCESS:
					NRF_LOG_INFO("pm_peer_data_load returned %d bytes:", peerDataGattLocalLen);
					NRF_LOG_HEXDUMP_INFO(uint8_t*) &peerDataGattLocal[0], peerDataGattLocalLen);
					break;            
				case NRF_ERROR_INVALID_PARAM:
				case NRF_ERROR_NULL:       
				case NRF_ERROR_NOT_FOUND:
				case NRF_ERROR_DATA_SIZE: 
				case NRF_ERROR_INVALID_STATE:
				default:
					NRF_LOG_INFO("pm_peer_data_load returned\t0x%x", errorCode);
					break; 
			}
		}
	}
}

I am currently struggling with the format of the data returned by pm_peer_data_load(). The output looks like this:

pm_peer_data_load returned 512 bytes:
03 00 00 00 44 00 0D 00|....D...
02 00 02 00 20 00 02 00|.... ...
02 00 23 00 02 00 02 00|..#.....
27 00 02 00 02 00 2A 00|'.....*.
02 00 02 00 2D 00 02 00|....-...
02 00 32 00 02 00 02 00|..2.....
35 00 02 00 02 00 38 00|5.....8.
02 00 01 00 3B 00 02 00|....;...
02 00 3E 00 02 00 01 00|..>.....
00 1D 00 00 00 00 00 00|........
 

I see that the data contains CCCD Handle / Value pairs but I would like to understand the format in detail. Unfortunately I can't find something about it in the documentation. Could you please guide me into the right direction? 

Thanks 

Florian 

Parents
  • Hello,

    So pm_peer_data_load() loads the data of one peer with the given peer_id.

    ret_code_t pm_peer_data_load(pm_peer_id_t       peer_id,
                                 pm_peer_data_id_t  data_id,
                                 void             * p_data,
                                 uint32_t         * p_length)

    I'll use the parameter names given here.

    The data is stored in the p_data pointer, and has the type given by the data_id. If you are loading the type PM_PEER_DATA_ID_GATT_LOCAL, it means that the data is on the form pm_peer_data_local_gatt_db_t (check out the enum pm_peer_data_id_t in peer_manager_types.h).

    So try casting the resulting p_data to a pm_peer_data_local_gatt_db_t type,  and look at it's parameters (given in the struct pm_peer_data_local_gatt_db_t struct in peer_manager_types.h.

    I have not tested, but something like this:

    err_code = pm_peer_data_load(peer_id, data_id, p_data, p_length);
    APP_ERROR_CHECK(err_code);
    
    pm_peer_data_local_gatt_db_t * my_data_pointer = (pm_peer_data_local_gatt_db_t)p_data;
    
    NRF_LOG_INFO("data: flags 0x%02x, len %d", my_data_pointer->flags, my_data_pointer->len);
    
    for (uint16_t i=0; i<my_data_pointer->len; i++)
    {
        NRF_LOG_RAW_INFO("%02x:", my_data_pointer->data[i]);
        if (i%8==0)
        {
            NRF_LOG_RAW_INFO("\r\n");
        }
    }
    
    

    The storage format of my_data_pointer->data[i]; i am not sure about. See how it is stored when the peer data is stored. 

    Best regards,

    Edvin

  • Thanks a lot for your quick reply. I tested with the sample code you provided and it looks like the storage format of my_data_pointer->data[i] follows the format described here: 

    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s132.api.v7.0.0/group___b_l_e___g_a_t_t_s___s_y_s___a_t_t_r_s___f_o_r_m_a_t.html

    Can you confirm this?

    Best regards from Germany 

    Florian

  • Hello Florian,

    It is a bit tricky to link to infocenter, because when you click a link, the URL from your browser will not work. You can copy links by right clicking a link that leads there. I assume you tried to link to:
    https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s132.api.v7.2.0/structble__gatts__attr__t.html

    Can you confirm?

    What exactly are you trying to acheive? Do you want to restore the CCCD values (notifications/indications that are enabled)? If so, the peer manager should already handle this. 

    I believe this is done using gscm_local_db_cache_apply() in gatts_cache_manager.c(). You can later fetch the cccd values by using sd_ble_gatts_value_get().

    I believe this is called from local_db_apply_in_evt in gcm_im_evt_handler() -> case PM_EVT_BONDED_PEER_CONNECTED.

    Best regards,

    Edvin

  • Yes, I was trying to provide a link to section "User memory layout for System Attributes" at the bottom of the page you referenced in your reply.

    What exactly are you trying to acheive?


    We have a multiprocessor system und use control point procedures. In this scenario the communication MCU (nRF52) forwards incoming write requests to the application MCU which has to check if the CCCD value is set correctly before sending subsequent indications or notifications. The result of this check is part of the Write Response.
    We already implemented a mechanism to inform the application MCU whenever a CCCD is written by the peer. When it comes to bonded peers the CCCDs are not written again over the air but restored by the peer manager. Therefore we would like to inform the application MCU about the stored values of the CCCDs already on startup, so that the application MCU is in sync.

Reply
  • Yes, I was trying to provide a link to section "User memory layout for System Attributes" at the bottom of the page you referenced in your reply.

    What exactly are you trying to acheive?


    We have a multiprocessor system und use control point procedures. In this scenario the communication MCU (nRF52) forwards incoming write requests to the application MCU which has to check if the CCCD value is set correctly before sending subsequent indications or notifications. The result of this check is part of the Write Response.
    We already implemented a mechanism to inform the application MCU whenever a CCCD is written by the peer. When it comes to bonded peers the CCCDs are not written again over the air but restored by the peer manager. Therefore we would like to inform the application MCU about the stored values of the CCCDs already on startup, so that the application MCU is in sync.

Children
Related