nRF52832藍牙iBeacon廣播

開發環境

SDK版本:nRF5_SDK_15.0.0app

芯片:nRF52832-QFAAide

藍牙iBeacon實現

iBeacon的核心就是廣播,不須要進行鏈接,經過在廣播包中插入信息而後廣播出去。ui

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

iBeacon幀格式

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

Type 廣播類型spa

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

0x02 指明該設備爲「proximity beacon」,該值在iBeacon設備中均爲0x02。code

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

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

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);
}
相關文章
相關標籤/搜索