其他分享
首页 > 其他分享> > NRF52832学习笔记(36)——iBeacon

NRF52832学习笔记(36)——iBeacon

作者:互联网

一、简介

iBeacon 是苹果公司2013年9月发布的移动设备用 OS(iOS7)上配备的新功能。其工作方式是,配备有 **低功耗蓝牙(BLE)**通信功能的设备使用 BLE 技术向周围发送自己特有的 ID,接收到该 ID 的应用软件会根据该 ID 采取一些行动。比如,在店铺里设置 iBeacon 通信模块的话,便可让 iPhone 和 iPad 上运行一资讯告知服务器,或者由服务器向顾客发送折扣券及进店积分。此外,还可以在家电发生故障或停止工作时使用 iBeacon 向应用软件发送资讯。

二、iBeacon格式

iBeacon 使用的是 BLE 技术,具体而言,利用的是 BLE 中名为“通告帧”(Advertising)的广播帧。通告帧是定期发送的帧,只要是支持 BLE 的设备就可以接收到。iBeacon 通过在这种通告帧的有效负载部分嵌入苹果自主格式的数据来实现。

AD Field LengthTypeCompany IDiBeacon TypeiBeacon LengthUUIDMajorMinorTX Power

AD Field Length: Advertisement Data 的长度,表示有用的广播信息长度
Type: 广播类型
Company ID: 数据字段以两字节的公司 ID 码开始。SIG 将这些 ID 码发放给公司,其中 0x004C 代表的是Apple id(只有这个 ID,设备才会叫 iBeacon)
iBeacon Type: 字节 0x02 代表这个设备是 Beacon
iBeacon Length: 剩下字段的长度
UUID: 规定为 ISO/IEC11578:1996 标准的 128 位标识符
Major、Minor: 由 iBeacon 发布者自行设定,都是 16 位的标识符。比如,连锁店可以在 Major 写入区域资讯,可在 Minor 中写入个别店铺的 ID 等。另外,在家电中嵌入 iBeacon 功能时,可以用 Major 表示产品型号,用 Minor 表示错误代码,用来向外部通知故障
TX Power: APP 通过 iBeacon 发送信号强度估算出的在 1 米的时候 RSSI 强度

三、修改代码

打开工程 SDK\examples\ble_peripheral\ble_app_beacon

首先我们先定义 beacon 相关的数据,其中我们用户需要关注的主要有3个参数,UUID、Major 以及 Minor,其他的参数大家可以理解为固定的格式(格式固定,但数据内容不固定,可能有不同的厂商信息)。另外还有一个值得我们关注的数据,那就是 APP_COMPANY_IDENTIFIER,如果我们定义此参数为 0x004C(也就是 Apple id),那么我们的基站设备就被成为 iBeacon。

// BEACON数据
#define APP_BEACON_INFO_LENGTH          0x17                     // BEACON数据总长度
#define APP_ADV_DATA_LENGTH             0x15                     // BEACON特殊字节的长度
#define APP_DEVICE_TYPE                 0x02                     // 字节0x02代表这个设备是BEACON
#define APP_MEASURED_RSSI               0xC3                     // BEACON在1米距离处的信号强度
#define APP_COMPANY_IDENTIFIER          0x004C                   // 004C代表的是Apple id(只有这个ID,设备才会叫iBeacon)
#define APP_MAJOR_VALUE                 0x01, 0x02               // major
#define APP_MINOR_VALUE                 0x03, 0x04               // minor
#define APP_BEACON_UUID                 0x01, 0x12, 0x23, 0x34, \
                                        0x45, 0x56, 0x67, 0x78, \
                                        0x89, 0x9a, 0xab, 0xbc, \
                                        0xcd, 0xde, 0xef, 0xf0   /**< Proprietary UUID for Beacon. */

// BEACON数据数组,用于初始化广播数据内容
static uint8_t m_beacon_info[APP_BEACON_INFO_LENGTH] = 
{
    APP_DEVICE_TYPE,
    APP_ADV_DATA_LENGTH, 
    APP_BEACON_UUID,
    APP_MAJOR_VALUE,
    APP_MINOR_VALUE,
    APP_MEASURED_RSSI
};

对于 iBeacon 的数据,通过广播形式广播出去,那么其主要设置就是主函数里广播初始化部分(查看NRF52832学习笔记(9)——GAP从机端广播),所有定义的参数必须在广播初始化的时候进行配置。

static void advertising_init(void)
{
    uint32_t      err_code;
    ble_advdata_t advdata;
    uint8_t       flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;  // 广播类型

    ble_advdata_manuf_data_t manuf_specific_data;

    manuf_specific_data.company_identifier = APP_COMPANY_IDENTIFIER;  // 公司ID号

#if defined(USE_UICR_FOR_MAJ_MIN_VALUES)
    // If USE_UICR_FOR_MAJ_MIN_VALUES is defined, the major and minor values will be read from the
    // UICR instead of using the default values. The major and minor values obtained from the UICR
    // are encoded into advertising data in big endian order (MSB First).
    // To set the UICR used by this example to a desired value, write to the address 0x10001080
    // using the nrfjprog tool. The command to be used is as follows.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val <your major/minor value>
    // For example, for a major value and minor value of 0xabcd and 0x0102 respectively, the
    // the following command should be used.
    // nrfjprog --snr <Segger-chip-Serial-Number> --memwr 0x10001080 --val 0xabcd0102
    uint16_t major_value = ((*(uint32_t *)UICR_ADDRESS) & 0xFFFF0000) >> 16;
    uint16_t minor_value = ((*(uint32_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);
#endif

    manuf_specific_data.data.p_data = (uint8_t *) m_beacon_info;  // 数据结构体
    manuf_specific_data.data.size   = APP_BEACON_INFO_LENGTH;  // 数据长度

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type             = BLE_ADVDATA_NO_NAME;
    advdata.flags                 = flags;
    advdata.p_manuf_specific_data = &manuf_specific_data;

    // Initialize advertising parameters (used when starting advertising).
    memset(&m_adv_params, 0, sizeof(m_adv_params));

    m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
    m_adv_params.p_peer_addr     = NULL;    // Undirected advertisement.
    m_adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    m_adv_params.interval        = NON_CONNECTABLE_ADV_INTERVAL;
    m_adv_params.duration        = 0;       // Never time out.

    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &m_adv_params);
    APP_ERROR_CHECK(err_code);
}

在主函数中,调用初始化广播函数 advertising_init(),当函数 advertising_start() 启动广播后,就可以实现广播信息的发出,也就是信标的广播包的广播

int main(void)
{
    // Initialize.
    log_init();
    timers_init();
    leds_init();
    power_management_init();
    ble_stack_init();  // 协议栈初始化
    advertising_init();  // 广播初始化

    // Start execution.
    NRF_LOG_INFO("Beacon example started.");
    advertising_start();  // 开始广播

    // Enter main loop.
    for (;; )
    {
        idle_state_handle();
    }
}

• 由 Leung 写于 2021 年 1 月 6 日

• 参考:青风电子社区

标签:adv,广播,APP,BEACON,36,iBeacon,data,NRF52832
来源: https://blog.csdn.net/qq_36347513/article/details/112260113