wordpress 電影moban百度搜索seo優(yōu)化技巧
Beacon藍(lán)牙信標(biāo)簡(jiǎn)介
?Beacon藍(lán)牙信標(biāo)?是一種基于藍(lán)牙低功耗(BLE)技術(shù)的設(shè)備,主要用于提供位置信息和數(shù)據(jù)傳輸服務(wù)。它通過(guò)周期性地廣播信號(hào),能夠在一定范圍內(nèi)與其他藍(lán)牙設(shè)備進(jìn)行通信,從而提供精準(zhǔn)的位置信息和相關(guān)服務(wù)?。
工作原理:Beacon藍(lán)牙信標(biāo)作為藍(lán)牙低功耗協(xié)議中的外圍設(shè)備,持續(xù)向周?chē)鷱V播包含設(shè)備標(biāo)識(shí)的特定數(shù)據(jù)包,但不能和中心設(shè)備建立連接。這些數(shù)據(jù)包通常包含UUID、廣播名稱(chēng)、MAC地址、major、minor、電量信息等?。簡(jiǎn)而言之,不需要建立藍(lán)牙連接便可廣播數(shù)據(jù),如果設(shè)備想要接受數(shù)據(jù),就必須對(duì)特特定的地址進(jìn)行監(jiān)聽(tīng)。
Beacon藍(lán)牙信標(biāo)廣播標(biāo)準(zhǔn)下又分為了若干種廣播格式,此次學(xué)習(xí)便以其中的一種Eddystone格式為例子(ESP32例程中有相關(guān)的,便于學(xué)習(xí))。
Eddystone廣播格式簡(jiǎn)介
Eddystone廣播有四種幀格式,
可以根據(jù)配置,廣播四種不同類(lèi)型的數(shù)據(jù),非常強(qiáng)大。
Eddystone廣播包是裝載于BLE通用廣播包,PDU中的Playload。
引用一張網(wǎng)圖如下(這個(gè)一整大塊就是PDU中的一個(gè)Playload)。
第一個(gè)AD structure是有關(guān)于物理連接功能的配置。
第二個(gè)AD structure是有關(guān)UUID的配置。
第三個(gè)AD structure是有關(guān)服務(wù)數(shù)據(jù)的配置,這里的數(shù)據(jù)包含了UUID和Eddystone的數(shù)據(jù)。既len-1(類(lèi)型占用的一個(gè)字節(jié))=UUID+Eddystone Data;
代碼實(shí)現(xiàn)
這部分網(wǎng)上有一些其他作者已經(jīng)實(shí)現(xiàn),就不再贅述,著重講一下效果部分。以及我個(gè)人的一些理解分析和疑問(wèn)。
主函數(shù)部分:
void app_main(void)
{//初始化ESP_ERROR_CHECK(nvs_flash_init());//釋放經(jīng)典藍(lán)牙ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));//初始化并開(kāi)啟低功耗藍(lán)牙控制器esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_bt_controller_init(&bt_cfg);//開(kāi)啟低功耗BLE控制器esp_bt_controller_enable(ESP_BT_MODE_BLE);//開(kāi)啟eddystone初始化esp_eddystone_init();/*<! set scan parameters *///設(shè)置掃描參數(shù)//esp_ble_gap_set_scan_params(&ble_scan_params);//服務(wù)數(shù)據(jù)封包esp_eddystone_frame_t uid = {0};int len = Eddystone_set_uid(&uid,0,(uint8_t *)"helloworld",(uint8_t *)"123456");if(len==-1){printf("erro\r\n");return;}adv_data.manufacturer_len = len;adv_data.p_manufacturer_data = (uint8_t *)&uid;//設(shè)置廣播數(shù)據(jù)參數(shù)esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);if (ret){ESP_LOGE(DEMO_TAG, "config adv data failed, error code = %x", ret);}//開(kāi)始廣播}
數(shù)據(jù)封裝:
int Eddystone_set_uid(esp_eddystone_frame_t *uid,uint8_t power,uint8_t *name_space,uint8_t *instance)
{if(uid==NULL||name_space==NULL||instance==NULL){return -1;}memset(uid,0,sizeof(esp_eddystone_frame_t));uid->len = sizeof(esp_eddystone_frame_t);uid->uuid = EDDYSTONE_SERVICE_UUID;uid->frame_type = EDDYSTONE_FRAME_TYPE_UID;uid->type = 0x16;uid->u.uid.ranging_data = power;memcpy(uid->u.uid.namespace_id,name_space,10);memcpy(uid->u.uid.instance_id,instance,6);return uid->len;
}
回調(diào)函數(shù):
void app_main(void)
{//初始化ESP_ERROR_CHECK(nvs_flash_init());//釋放經(jīng)典藍(lán)牙ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));//初始化并開(kāi)啟低功耗藍(lán)牙控制器esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();esp_bt_controller_init(&bt_cfg);//開(kāi)啟低功耗BLE控制器esp_bt_controller_enable(ESP_BT_MODE_BLE);//開(kāi)啟eddystone初始化esp_eddystone_init();/*<! set scan parameters *///設(shè)置掃描參數(shù)//esp_ble_gap_set_scan_params(&ble_scan_params);//服務(wù)數(shù)據(jù)封包esp_eddystone_frame_t uid = {0};int len = Eddystone_set_uid(&uid,0,(uint8_t *)"helloworld",(uint8_t *)"123456");if(len==-1){printf("erro\r\n");return;}adv_data.manufacturer_len = len;adv_data.p_manufacturer_data = (uint8_t *)&uid;//設(shè)置廣播數(shù)據(jù)參數(shù)esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);if (ret){ESP_LOGE(DEMO_TAG, "config adv data failed, error code = %x", ret);}//開(kāi)始廣播}
參數(shù)配置:
static uint8_t adv_service_uuid[]={0xfb,0x34,0x9b,0x5f,0x80,0x00,0x00,0x80,0x00,0x10,0x00,0x00,0xaa,0xfe,0x00,0x00
};
//廣播數(shù)據(jù)
static esp_ble_adv_data_t adv_data={.set_scan_rsp = false,.include_name = false,.include_txpower =false,.min_interval = 0x0006,.max_interval = 0x000c,.appearance = 0x00,.manufacturer_len = 0,.p_manufacturer_data = NULL,.service_data_len = 0,.p_service_data = NULL,.service_uuid_len = 16,.p_service_uuid = adv_service_uuid,.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
//廣播參數(shù)
static esp_ble_adv_params_t adv_params = {.adv_int_min = 0x20,.adv_int_max = 0x40,.adv_type = ADV_TYPE_IND,.own_addr_type = BLE_ADDR_TYPE_PUBLIC,//.peer_addr =//.peer_addr_type =.channel_map = ADV_CHNL_ALL,.adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};
效果展示
分析
以上圖手機(jī)抓包的數(shù)據(jù)為例,第一包數(shù)據(jù)就是我們配置的物理連接功能基礎(chǔ)參數(shù)。
對(duì)應(yīng)的參數(shù)支持如下
著重講一下這包數(shù)據(jù),可以發(fā)現(xiàn)在抓包的數(shù)據(jù)中,并沒(méi)有體現(xiàn)這一部分的數(shù)據(jù)。一開(kāi)始我也很奇怪,后來(lái)經(jīng)過(guò)細(xì)致的了解后才明白,這里的配置決定了設(shè)備在廣告或后續(xù)連接過(guò)程中能夠聲明和提供的服務(wù)。注意,是能夠聲明和提供,并不是已經(jīng)聲明和提供,這部分的配置意味著,將BLE藍(lán)牙配置為有哪些功能,至于是否把功能開(kāi)放廣播出來(lái),又是另外一回事。所以如果沒(méi)開(kāi)放廣播,在抓包的時(shí)候自然看不見(jiàn)這部分信息。
最后是
這一包數(shù)據(jù),可能有人會(huì)好奇為什么是封包在這個(gè)manufacturer而不是service這里,我一開(kāi)始也有疑問(wèn),細(xì)細(xì)了解以后發(fā)表一下我的理解。首先eddystone并非是官方的藍(lán)牙協(xié)議,只是廠商制定的一種藍(lán)牙廣播協(xié)議標(biāo)準(zhǔn),所以它包含的應(yīng)該是廠家的特定信息,而這里的manufacture data的意為,制造商數(shù)據(jù)允許設(shè)備在廣告中包含自定義信息,而這些信息對(duì)特定制造商有意義。就如eddystone,是谷歌制造的協(xié)議,屬于廠家自定義的信息,而并不屬于通用的。所以應(yīng)該放在此處。而從我們藍(lán)牙抓包的第二條數(shù)據(jù)也可以看到。類(lèi)型是0xff。
也意為制造商特定數(shù)據(jù)。
因此eddystone的協(xié)議包放在類(lèi)型為0xff的AD structure中也便好理解了。至于包中的內(nèi)容,與eddystone的廣播格式對(duì)應(yīng)即可。
疑問(wèn)
最后,查閱eddystone的協(xié)議規(guī)范發(fā)現(xiàn),標(biāo)準(zhǔn)的eddystone協(xié)議包應(yīng)該包含一位完整的16位的uuid既,len = 0x03 type = 0x03 UUID = 0xFEAA這樣一包數(shù)據(jù),但可以看到esp32發(fā)出的數(shù)據(jù)包并不包含,確不影響到設(shè)備的掃描,但同時(shí)在nRF Connect中也并沒(méi)有把他識(shí)別為一個(gè)標(biāo)準(zhǔn)的eddystone設(shè)備,而是一個(gè)普通藍(lán)牙設(shè)備,不過(guò)不影響數(shù)據(jù)的收發(fā)。協(xié)議中對(duì)于這一包數(shù)據(jù)的解析翻譯如下:該列表必須包含Eddystone服務(wù)UUID(0xFEAA),以便iOS設(shè)備進(jìn)行后臺(tái)掃描。個(gè)人推測(cè)即便不加也不影響基礎(chǔ)的廣播功能。同時(shí)如果各位有啥辦法能夠加上,也不妨可以說(shuō)一聲完善一下(我是試了好多方法都沒(méi)加上去)。