一、簡介
iBeacon 是蘋果公司2013年9月發(fā)布的移動設(shè)備用 OS(iOS7)上配備的新功能较坛。其工作方式是,配備有 低功耗藍牙(BLE)通信功能的設(shè)備使用 BLE 技術(shù)向周圍發(fā)送自己特有的 ID,接收到該 ID 的應(yīng)用軟件會根據(jù)該 ID 采取一些行動陌凳。比如嗓蘑,在店鋪里設(shè)置 iBeacon 通信模塊的話须肆,便可讓 iPhone 和 iPad 上運行一資訊告知服務(wù)器,或者由服務(wù)器向顧客發(fā)送折扣券及進店積分桩皿。此外豌汇,還可以在家電發(fā)生故障或停止工作時使用 iBeacon 向應(yīng)用軟件發(fā)送資訊。
二泄隔、iBeacon格式
iBeacon 使用的是 BLE 技術(shù)拒贱,具體而言,利用的是 BLE 中名為“通告幀”(Advertising)的廣播幀佛嬉。通告幀是定期發(fā)送的幀逻澳,只要是支持 BLE 的設(shè)備就可以接收到。iBeacon 通過在這種通告幀的有效負載部分嵌入蘋果自主格式的數(shù)據(jù)來實現(xiàn)暖呕。
AD Field Length | Type | Company ID | iBeacon Type | iBeacon Length | UUID | Major | Minor | TX Power |
---|
AD Field Length: Advertisement Data 的長度斜做,表示有用的廣播信息長度
Type: 廣播類型
Company ID: 數(shù)據(jù)字段以兩字節(jié)的公司 ID 碼開始。SIG 將這些 ID 碼發(fā)放給公司湾揽,其中 0x004C 代表的是Apple id(只有這個 ID瓤逼,設(shè)備才會叫 iBeacon)
iBeacon Type: 字節(jié) 0x02 代表這個設(shè)備是 Beacon
iBeacon Length: 剩下字段的長度
UUID: 規(guī)定為 ISO/IEC11578:1996 標準的 128 位標識符
Major、Minor: 由 iBeacon 發(fā)布者自行設(shè)定钝腺,都是 16 位的標識符抛姑。比如,連鎖店可以在 Major 寫入?yún)^(qū)域資訊艳狐,可在 Minor 中寫入個別店鋪的 ID 等定硝。另外,在家電中嵌入 iBeacon 功能時毫目,可以用 Major 表示產(chǎn)品型號蔬啡,用 Minor 表示錯誤代碼诲侮,用來向外部通知故障
TX Power: APP 通過 iBeacon 發(fā)送信號強度估算出的在 1 米的時候 RSSI 強度
三、修改代碼
打開工程 SDK\examples\ble_peripheral\ble_app_beacon
首先我們先定義 beacon 相關(guān)的數(shù)據(jù)箱蟆,其中我們用戶需要關(guān)注的主要有3個參數(shù)沟绪,UUID、Major 以及 Minor空猜,其他的參數(shù)大家可以理解為固定的格式(格式固定绽慈,但數(shù)據(jù)內(nèi)容不固定,可能有不同的廠商信息)辈毯。另外還有一個值得我們關(guān)注的數(shù)據(jù)坝疼,那就是 APP_COMPANY_IDENTIFIER
,如果我們定義此參數(shù)為 0x004C
(也就是 Apple id)谆沃,那么我們的基站設(shè)備就被成為 iBeacon钝凶。
// BEACON數(shù)據(jù)
#define APP_BEACON_INFO_LENGTH 0x17 // BEACON數(shù)據(jù)總長度
#define APP_ADV_DATA_LENGTH 0x15 // BEACON特殊字節(jié)的長度
#define APP_DEVICE_TYPE 0x02 // 字節(jié)0x02代表這個設(shè)備是BEACON
#define APP_MEASURED_RSSI 0xC3 // BEACON在1米距離處的信號強度
#define APP_COMPANY_IDENTIFIER 0x004C // 004C代表的是Apple id(只有這個ID,設(shè)備才會叫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數(shù)據(jù)數(shù)組唁影,用于初始化廣播數(shù)據(jù)內(nèi)容
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 的數(shù)據(jù)耕陷,通過廣播形式廣播出去,那么其主要設(shè)置就是主函數(shù)里廣播初始化部分(查看NRF52832學(xué)習(xí)筆記(9)——GAP從機端廣播)据沈,所有定義的參數(shù)必須在廣播初始化的時候進行配置哟沫。
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; // 數(shù)據(jù)結(jié)構(gòu)體
manuf_specific_data.data.size = APP_BEACON_INFO_LENGTH; // 數(shù)據(jù)長度
// 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);
}
在主函數(shù)中,調(diào)用初始化廣播函數(shù) advertising_init()锌介,當函數(shù) advertising_start() 啟動廣播后南用,就可以實現(xiàn)廣播信息的發(fā)出,也就是信標的廣播包的廣播
int main(void)
{
// Initialize.
log_init();
timers_init();
leds_init();
power_management_init();
ble_stack_init(); // 協(xié)議棧初始化
advertising_init(); // 廣播初始化
// Start execution.
NRF_LOG_INFO("Beacon example started.");
advertising_start(); // 開始廣播
// Enter main loop.
for (;; )
{
idle_state_handle();
}
}
? 由 Leung 寫于 2021 年 1 月 6 日
? 參考:青風(fēng)電子社區(qū)