做購(gòu)物網(wǎng)站 需要手續(xù)百度搜索廣告怎么投放
BLE的基礎(chǔ)知識(shí)
ble的信道和BR/EDR的信道是完全不一樣的。但是范圍是相同的,差不多也都是2.4Ghz的頻道??梢院?jiǎn)單理解為空中有40個(gè)信道0~39信道。兩個(gè)設(shè)備在相同的信道里面可以進(jìn)行相互通信。
而這些信道SIG又重新編號(hào):
這個(gè)編號(hào)就是把37 38 39。 3個(gè)信道抽出來(lái),作為廣播信道,其他都是數(shù)據(jù)信道。這篇文章主要講廣播,所以基本數(shù)據(jù)信息都是圍繞37 38 39這三個(gè)信道上面的通信來(lái)講的。
我們可以看到這3個(gè)信道是分散排列的。大家可以思考下為什么。
其實(shí)看下面一張圖就知道了。
數(shù)據(jù)廣播
廣播組成部分
廣播分為如下幾個(gè)部分:
- 廣播
- 掃描請(qǐng)求
- 掃描響應(yīng)
廣播的報(bào)文格式
{"AD1":{"Length":12,"Data":{"AD_Type":12,"AD_Data":"123123"}},"AD2":{"Length":12,"Data":{"AD_Type":12,"AD_Data":"123123"}}
}
記憶要點(diǎn)
:每個(gè)元素里面有兩個(gè)要素:1. 長(zhǎng)度(length), 2. 數(shù)據(jù)(data)
每個(gè)數(shù)據(jù)里面又包含兩個(gè)元素:1. 類型(type), 2. 數(shù)據(jù)(data)
總結(jié)一下就是一個(gè)L T V模型(length, type, data)
這個(gè)length代表的是后面數(shù)據(jù)有多長(zhǎng),不包含length的長(zhǎng)度。
總的Len一般不超過(guò)31字節(jié)
參考:
2. BLE 廣播和掃描 — bluetoothlover_wiki 0.0.1 文檔 (supperthomas-wiki.readthedocs.io)
AD_Type 官方定義
抓包參考:
APPLE JUICE功能實(shí)現(xiàn)
1.流程梳理
主要需要實(shí)現(xiàn)如下功能點(diǎn):
- ble 廣播開啟和關(guān)閉
- ble GAP層各種參數(shù)的設(shè)置
- ble MAC地址動(dòng)態(tài)修改
2.Zephyr 中相關(guān)接口:
功能接口:
接口名 | 功能描述 | 備注 |
---|---|---|
bt_enable | 開啟BLE功能 | |
bt_le_adv_start | 開啟BLE廣播 | |
bt_le_adv_update_data | 更新BLE廣播內(nèi)容 | 此接口是否實(shí)時(shí)?未找到對(duì)應(yīng)生效CallBack |
bt_le_adv_stop | 關(guān)閉BLE廣播 | |
bt_id_create | 更新廣播隨機(jī)地址 |
注:
上述接口在執(zhí)行完成后均會(huì)拋出回調(diào):
/*
參數(shù)回調(diào)注冊(cè)
*/
void bt_conn_cb_register(struct bt_conn_cb *cb);struct bt_conn_cb {//已建立新連接void (*connected)(struct bt_conn *conn, uint8_t err);//連接已斷開void (*disconnected)(struct bt_conn *conn, uint8_t reason);//LE 連接參數(shù)更新請(qǐng)求bool (*le_param_req)(struct bt_conn *conn,struct bt_le_conn_param *param);//LE 連接的參數(shù)已更新void (*le_param_updated)(struct bt_conn *conn, uint16_t interval,uint16_t latency, uint16_t timeout);
#if defined(CONFIG_BT_SMP)//遠(yuǎn)程身份地址通過(guò)void (*identity_resolved)(struct bt_conn *conn,const bt_addr_le_t *rpa,const bt_addr_le_t *identity);
#endif /* CONFIG_BT_SMP */
#if defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR)//連接的安全級(jí)別已更改void (*security_changed)(struct bt_conn *conn, bt_security_t level,enum bt_security_err err);
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */#if defined(CONFIG_BT_REMOTE_INFO)//遠(yuǎn)程信息程序已完成void (*remote_info_available)(struct bt_conn *conn,struct bt_conn_remote_info *remote_info);
#endif /* defined(CONFIG_BT_REMOTE_INFO) */#if defined(CONFIG_BT_USER_PHY_UPDATE)//連接的 PHY 已更改void (*le_phy_updated)(struct bt_conn *conn,struct bt_conn_le_phy_info *param);
#endif /* defined(CONFIG_BT_USER_PHY_UPDATE) */#if defined(CONFIG_BT_USER_DATA_LEN_UPDATE)//連接的數(shù)據(jù)長(zhǎng)度參數(shù)已更改void (*le_data_len_updated)(struct bt_conn *conn,struct bt_conn_le_data_len_info *info);
#endif /* defined(CONFIG_BT_USER_DATA_LEN_UPDATE) */#if defined(CONFIG_BT_DF_CONNECTION_CTE_RX)void (*cte_report_cb)(struct bt_conn *conn,const struct bt_df_conn_iq_samples_report *iq_report);
#endif /* CONFIG_BT_DF_CONNECTION_CTE_RX */#if defined(CONFIG_BT_TRANSMIT_POWER_CONTROL)void (*tx_power_report)(struct bt_conn *conn,const struct bt_conn_le_tx_power_report *report);
#endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */struct bt_conn_cb *_next;
};
bt_data接口
Zephyr 封裝好了部分gap填充接口,在編寫廣播數(shù)據(jù)(bt_data)數(shù)組的時(shí)候可以通過(guò)以下宏來(lái)輔助:
/*** @brief Construct a new bt data object* * _type: GAP字段的類型* _data: GAP RAW 數(shù)據(jù)* _data_len: RAW數(shù)據(jù)長(zhǎng)度*/
#define BT_DATA(_type, _data, _data_len) \{ \.type = (_type), \.data_len = (_data_len), \.data = (const uint8_t *)(_data), \}/*** @brief Construct a new bt data object* * _type: GAP字段的類型* _bytes: GAP RAW 數(shù)據(jù)*/
#define BT_DATA_BYTES(_type, _bytes...) \BT_DATA(_type, ((uint8_t []) { _bytes }), \sizeof((uint8_t []) { _bytes }))
參考:
5. BLE — BL_MCU_SDK 開發(fā)指南 0.3 文檔 (gitee.io)
Zephyr API文檔:通用訪問(wèn)配置文件(GAP) (zephyrproject.org)
3. 廣播數(shù)據(jù)填充
AD_Data字段:
static const struct bt_data ad[] = {BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20,0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45,0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00)};
開啟廣播的時(shí)候?qū)d傳入,即可完成廣播數(shù)據(jù)設(shè)置。
4.隨機(jī)地址切換
Apple對(duì)于相同MAC地址的設(shè)備僅會(huì)進(jìn)行一次彈窗,因此如果想要讓手機(jī)不斷的彈出設(shè)備提示框就需要定期修改BLE的MAC地址,代碼如下:
bt_addr_le_t local_mac_addr;size_t localmac_size = 1;static bt_addr_le_t myaddr = {.type = BT_ADDR_LE_RANDOM,/* fixed MAC addres */.a = {.val = {0x01, 0x02, 0x03, 0x04, 0x05, 0xc6},},};printk("bt_id_create\r\n");err = bt_id_create(&myaddr, NULL);if (err < 0){printk("bt_id_create err!\r\n");}
小思考:這里思考了下蘋果的設(shè)計(jì)美學(xué),以AirPods
為例。通常情況下設(shè)備為了節(jié)約電池電量并不會(huì)一直進(jìn)行BLE廣播,而是在每次打開電池倉(cāng)時(shí)才喚醒ble芯片,關(guān)閉電池倉(cāng)之后進(jìn)入超低功耗模式。BLE設(shè)備的程序在每次喚醒的時(shí)候程序會(huì)從新啟動(dòng),所以MAC地址發(fā)生改變。
效果演示
問(wèn)題和解決方法
-
問(wèn)題描述:使用
7002DK
開發(fā)板運(yùn)行時(shí)出現(xiàn)如下問(wèn)題。
-
原因分析:默認(rèn)情況下adv字段允許的最大長(zhǎng)度為31字節(jié), 當(dāng)數(shù)據(jù)填充超出會(huì)出現(xiàn)上述報(bào)警。
-
解決方法:可以開啟ble的
拓展廣播
功能來(lái)增加最大數(shù)據(jù)長(zhǎng)度。相關(guān)配置可以參考Demoperiodic_adv
,相關(guān)Menuconfig
修改點(diǎn)如下圖所示:
完整代碼:
/*** @file main.c* @author Argon* @brief BLE Apple * @version 0.1* @date 2024-01-20* * @copyright Copyright (c) 2024* */
#include <zephyr/types.h>
#include <stddef.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sys/util.h>#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>//掃描數(shù)據(jù)段
static const struct bt_data ad[] = {BT_DATA_BYTES(BT_DATA_MANUFACTURER_DATA,0x4c, 0x00, 0x07, 0x19, 0x07, 0x0a, 0x20,0x75, 0xaa, 0x30, 0x01, 0x00, 0x00, 0x45,0x12, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00)};//掃描響應(yīng)數(shù)據(jù)段
static const struct bt_data sd[] = {BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),BT_DATA_BYTES(BT_DATA_PERIPHERAL_INT_RANGE, 0x20, 0x00, 0x40, 0x00),BT_DATA_BYTES(BT_DATA_TX_POWER, 0x09),
};//設(shè)備名
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)int main(void)
{int err;printk("BLE Starting\n");/* Initialize the Bluetooth Subsystem */err = bt_enable(NULL);if (err){printk("Ble init failed (err %d)\n", err);return 0;}printk("Ble initialized\n");do{//開啟廣播printk("Ble adv start\r\n");err = bt_le_adv_start(BT_LE_ADV_NCONN, ad, ARRAY_SIZE(ad),sd, ARRAY_SIZE(sd));if (err){printk("Advertising failed to start (err %d)\n", err);return 0;}k_sleep(K_SECONDS(4));//廣播廣播printk("Ble adv stop\r\n");err = bt_le_adv_stop();if (err){printk("Advertising failed to stop (err %d)\n", err);return 0;}//更新MACbt_addr_le_t local_mac_addr;static bt_addr_le_t myaddr = {.type = BT_ADDR_LE_RANDOM,/* fixed MAC addres */.a = {.val = {0x01, 0x02, 0x03, 0x04, 0x05, 0xc6},},};printk("Ble update MAC address\r\n");err = bt_id_create(&myaddr, NULL);if (err < 0){printk("bt_id_create err!\r\n");}k_sleep(K_SECONDS(4));} while (1);return 0;
}