• 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);
    }
  • 相关阅读:
    lc377完全背包问题
    lc650
    lc583
    java static序列化
    lc90回溯
    lc78回溯
    Java基础之常量池
    语法与语义
    数据结构之复杂度分析
    数据结构与算法前言
  • 原文地址:https://www.cnblogs.com/silencehuan/p/10955008.html
Copyright © 2020-2023  润新知