nRF52832藍牙iBeacon廣播


開發環境

SDK版本:nRF5_SDK_15.0.0

芯片:nRF52832-QFAA

藍牙iBeacon實現

iBeacon的核心就是廣播,不需要進行連接,通過在廣播包中插入信息然后廣播出去。

廣播數據包最多僅可以包含31字節數據,所以設計者必須慎重選擇需要包含的數據。藍牙SIG組織在Core Specification Supplement (CSS)文件中將這31個字節數據分成多個AD Type結構,每個AD Type都有相同的結構,分別為長度字節,類型字節以及數據域。
Beacon設備可以在一個或多個標准廣播數據包中編碼數據,傳遞信息。但是編碼原理可能有所差異,即幀格式不同。目前主流的三種幀格式分別為蘋果公司的iBeacon,Radius Networks公司的AltBeacon以及谷歌公司的Eddystone。
因此為了與不同的beacon設備進行交互,應用開發者在開發beacon應用時需要了解對應設備的幀格式。

iBeacon幀格式

AD Field Length 表示 advertisement data的長度,即廣播包有用信息的總長度;

Type 廣播類型

Company ID  廠商數據字段的數據域前2字節為公司識別碼。由藍牙SIG組織分配給各公司,指示后續數據的解碼方式。在上圖中,0x004C為蘋果公司的ID。

0x02 指明該設備為“proximity beacon”,該值在iBeacon設備中均為0x02。

UUID指明擁有該beacon設備的機構。

Major 和 Minor 主次字段用來編碼位置信息,通常主字段指明某個建築,而次字段指明在這棟建築中的特定位置。例如“倫敦中心商場,運動產品區”。

Tx Power 發送功率字段幫助應用進行距離估算。

有關iBeacon的詳細內容可以參考Getting started with iBeacon

具體代碼實現

#if (GNT_IBEACON_EN)
#define APP_BEACON_INFO_LENGTH          0x17                               /**< Total length of information advertised by the Beacon. */
#define APP_ADV_DATA_LENGTH             0x15                               /**< Length of manufacturer specific data in the advertisement. */
#define APP_DEVICE_TYPE                 0x02                               /**< 0x02 refers to Beacon. */
#define APP_MEASURED_RSSI               0xC3                               /**< The Beacon's measured RSSI at 1 meter distance in dBm. */
#define APP_COMPANY_IDENTIFIER          0x0059                             /**< Company identifier for Nordic Semiconductor ASA. as per www.bluetooth.org. */
#define APP_MAJOR_VALUE                 0x01, 0x02                         /**< Major value used to identify Beacons. */
#define APP_MINOR_VALUE                 0x03, 0x04                         /**< Minor value used to identify Beacons. */
#define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                        0x45, 0x56, 0x67, 0x78, \
                                        0x89, 0x9a, 0xab, 0xbc, \
                                        0xcd, 0xde, 0xef, 0xf0            /**< Proprietary UUID for Beacon. */

#define MAJ_VAL_OFFSET_IN_BEACON_INFO   18                                 /**< Position of the MSB of the Major Value in m_beacon_info array. */
#define UICR_ADDRESS                    0x10001080                         /**< Address of the UICR register used by this example. The major and minor versions to be encoded into the advertising data will be picked up from this location. */

static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] =                    /**< Information advertised by the Beacon. */
{
    APP_DEVICE_TYPE,     // Manufacturer specific information. Specifies the device type in this
                         // implementation.
    APP_ADV_DATA_LENGTH, // Manufacturer specific information. Specifies the length of the
                         // manufacturer specific data in this implementation.
    APP_BEACON_UUID,     // 128 bit UUID value.
    APP_MAJOR_VALUE,     // Major arbitrary value that can be used to distinguish between Beacons.
    APP_MINOR_VALUE,     // Minor arbitrary value that can be used to distinguish between Beacons.
    APP_MEASURED_RSSI    // Manufacturer specific information. The Beacon's measured TX power in
                         // this implementation.
};
#endif

/**@brief Function for initializing the Advertising functionality. */
static void advertising_init(void)
{
    ret_code_t             err_code;
    ble_advertising_init_t init;

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

// 使用iBeacon廣播,由於廣播包長度需要控制好,部分信息可放置到廣播應答包中    
#if (GNT_IBEACON_EN)
    ble_advdata_manuf_data_t manuf_specific_data;        //廠商自定義信息
    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;    //廠商ID
    uint16_t major_value = (uint16_t)((UICR_ADDRESS & 0xFFFF0000) >> 16);
    uint16_t minor_value = (uint16_t)(UICR_ADDRESS & 0x0000FFFF);

    uint8_t index = MAJ_VAL_OFFSET_IN_BEACON_INFO;

    m_beacon_info[index++] = MSB_16(major_value);
    m_beacon_info[index++] = LSB_16(major_value);

    m_beacon_info[index++] = MSB_16(minor_value);
    m_beacon_info[index++] = LSB_16(minor_value);
    
    NRF_LOG_HEXDUMP_INFO(m_beacon_info, APP_BEACON_INFO_LENGTH);
    
    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;
    init.advdata.p_manuf_specific_data     = &manuf_specific_data;
#endif
    //注意advdata長度不能超過 BLE_GAP_ADV_SET_DATA_SIZE_MAX (31)
    init.advdata.name_type               = BLE_ADVDATA_NO_NAME;       //廣播iBeacon信息,長度有限 --廣播時的名稱顯示類型(全名)BLE_ADVDATA_FULL_NAME
//    init.advdata.include_appearance      = true;                    //是否需要圖標
    init.advdata.flags                   = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;     //藍牙設備普通發現模式 BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED   BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE
//    init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);    //廣播UUID
//    init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
//    init.advdata.p_tx_power_level        = &tx_power_level;       //設置發射功率
    
    init.srdata.name_type                 = BLE_ADVDATA_FULL_NAME;
    
    init.config.ble_adv_fast_enabled  = true;                       //快速廣播使能
    init.config.ble_adv_fast_interval = APP_FAST_ADV_INTERVAL;      //快速廣播間隔 30ms
    init.config.ble_adv_fast_timeout  = APP_FAST_ADV_DURATION;      //默認快速廣播超時 20s
    
    init.config.ble_adv_slow_enabled  = true;                       //慢速廣播使能
    init.config.ble_adv_slow_interval = APP_SLOW_ADV_INTERVAL;      //慢速廣播間隔 200ms
//    init.config.ble_adv_slow_timeout  = APP_SLOW_ADV_DURATION;      //默認慢速廣播超時 40s
    
    if(nrf_gpio_pin_read(USBVIN_CHECK) == 1)    //USB插入
    {
        gnt_led_indication_set(LED_USB_IN);
        g_gnt_info.gnt_usbvin_flag = 1;
        init.config.ble_adv_slow_timeout = 0;
    }
    else
    {
        gnt_led_indication_set(LED_USB_OUT);
        g_gnt_info.gnt_usbvin_flag = 0;
        init.config.ble_adv_slow_timeout  = APP_SLOW_ADV_DURATION;   //默認慢速廣播超時 40s
    }

    init.evt_handler = on_adv_evt;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM