How to display manufacturer-specific data on peripheral devices that are scanning advertisements?

Hi Experts,
I used the ble_central_client_scan sample and the UART PC tool. The serial terminal can continuously print a list of scanned devices. The device name, IP address and RSSI can be displayed on the serial terminal, so I would like to ask whether it is possible to display manufacturer-specific data(GAP_AD_TYPE_MANU_SPECIFIC_DATA = 0xFF /Manufacturer specific data/) on the serial terminal.

I look forward to your reply.
Thank you.

Hi,

Displaying Manufacturer Specific Data can be done using a very similar function to what parses the device name in our ble_central_client_scan sample.

By taking the Advertising Data received during an Advertising Report Event and passing it into the function shared below, it will return the size of the Manufacturer Specific Data (or 0 if none is found), as well as filling an array with the received Manufacturer Specific Data (by passing in the address to a pointer). This is achieved by looking for the Manufacturer Specific Data flag at the beginning of each data portion, and then using the portion length to parse to the next flag in the packet.

uint8_t SCAN_AdvReport_ExtractManuSpecInfo (const uint8_t* data, 
                                                  uint8_t size, 
                                                  uint8_t *result)
{
    uint8_t len = 0;
    uint8_t type;

    for (uint8_t i = 0; i < size;  i += len+1)
    {
        len = data[i];
        type = data[i+1];

        if (type == GAP_AD_TYPE_MANU_SPECIFIC_DATA)
        {
            memcpy(&result[0], (uint8_t*)(&data[i+2]), len-1);
            return (len);
        }
    }
}

This function can then be used to save the information by adding a call within the SCAN_AdvReportInd_Handler() function, which can save the result by adding a variable in the adv_report_list, very similar to how adv_report_list.data is used to save the device name. The information can finally be printed by updating the SCAN_ScreenUpdateTimeout() function to include the newly created variable in the snprintf() call.

Thank you for using our Community Forum.

Excuse me,
I modified the original function, but I had some problems to build the program.

I’m not sure how to save the information by adding a call within the SCAN_AdvReportInd_Handler() function and the information which is printed by updating the SCAN_ScreenUpdateTimeout( )function.

Do you have more detailed instructions for reference?

I use the ble_peripheral_server_bond sample, I want to show the Manufacturer Specific Data on the serial terminal.

1610345446156

The following is my result.
1610345265007

Hi,

Please make following changes in app_scan.c

  1. Add Manufacture Specific Data global variable:
uint8_t manu_specific_info[ADV_REPORT_LIST_MAX][GAP_ADV_DATA_LEN];
  1. Update SCAN_AdvReportInd_Handler() as follows:
void SCAN_AdvReportInd_Handler(const struct gapm_adv_report_ind *p)
{
    for (uint8_t i = 0; i < adv_report_list_size + 1; i++)
    {
        /* Check if the address is already in the list. If so update RSSI */
        if(!memcmp(p->report.adv_addr.addr, adv_report_list[i].adv_addr.addr, BD_ADDR_LEN))
        {
            adv_report_list[i].rssi = p->report.rssi;
            return;
        }
    }

    if(adv_report_list_size < ADV_REPORT_LIST_MAX)
    {
        /* Add adv report to the list, sorted by RSSI */
        memcpy(&adv_report_list[adv_report_list_size], &(p->report), sizeof(adv_report_t));

        /* Search payload for short name or name and update name field */
        SCAN_AdvReport_ExtractName(p->report.data, p->report.data_len, adv_report_list[adv_report_list_size].data);

        /* Search payload for short name or name and update name field */
        SCAN_AdvReport_ExtractManuSpecificData(p->report.data, p->report.data_len, manu_specific_info[adv_report_list_size]);

        adv_report_list_size++;
    }
}
  1. Add the following function definition:
void SCAN_AdvReport_ExtractManuSpecificData(const uint8_t* data, uint8_t size,
                                uint8_t *result)
{
    uint8_t len = 0;
    uint8_t type;

    for (uint8_t i = 0; i < size;  i += len+1)
    {
        len = data[i];
        type = data[i+1];
        if (type == GAP_AD_TYPE_MANU_SPECIFIC_DATA)
        {
            memcpy(&result[0], (uint8_t*)(&data[i+2]), len - 1);
            result[len - 1] = '\0';
            return;
        }
    }

    /* Didn't find a name */
    sprintf((char*)result, "N/A\0");
}
  1. Update SCAN_ScreenUpdateTimeout() as follows:
void SCAN_ScreenUpdateTimeout(void)
{
    /* VT100 codes for clearing the screen. Works on VT100 terminals only */
    /* Clear ("\033[2J") and move cursor ("\033[0;0H") */
    SCAN_UART_SendString("\033[2J\033[0;0H");
    SCAN_UART_SendString("Scanned devices:\n\r");

    for (int i = 0; i < adv_report_list_size; i++)
    {
        const uint8_t* addr = adv_report_list[i].adv_addr.addr;
        /* Create a UART string entry with device index, rssi, address, device name */
        /* Indicate which device was selected for a connection */
        snprintf(uart_tx_buffer, UART_TX_BUFFER_SIZE,
                 "[ ] %02d | %02d dBm | 0x%02x%02x%02x%02x%02x%02x | %s | %s\n\r", i+1, adv_report_list[i].rssi,
                 addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], adv_report_list[i].data, manu_specific_info[i]);

        if(i == device_selection)
        {
            uart_tx_buffer[1] = 'X';
        }

        SCAN_UART_SendString(uart_tx_buffer);
    }

    SCAN_UART_SendString("\nConnected devices:\n\r");

Above mentioned changes should help to get following results:

Project files:
ble_central_client_scan_MANUINFO.zip (128.4 KB)

Thank you for using our Community Forum.

Hi,
I’m very grateful that your team can provide this example code so that it can help me to better understand display manufacturer-specific data.

1610452381767

Thank you :heart_eyes:

Hi,

You are welcome.

Thank you for using our Community Forum.

Excuse me,I have another question for you.

I have a BLE sensor whose manufacturer specific data changes every second.How to update manufacturer-specific data like RSSI and display it on the serial terminal?

I look forward to your reply.
Thank you.

Hi,

Please refer to thread How to update manufacturer-specific data like RSSI and display it on the serial terminal?

Thank you for using our Community Forum