在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

你對藍牙協議了解多少?

硬件攻城獅 ? 來源:CSDN ? 作者:喵吉訶德 ? 2022-11-24 14:12 ? 次閱讀

藍牙在我們生活中非常普遍,小到手表,大到電視洗衣機等都有藍牙的身影。

那么,你對藍牙協議了解多少?

Part101 藍牙概述

藍牙技術起源于愛立信在1994年提出的方案,旨在解決移動電話和其他配件之間進行低功耗、低成本的無線通信連接的方法。

60855804-6bae-11ed-8abf-dac502259ad0.jpg

藍牙發展歷史

第一代藍牙主要是指90年代的V1.0~V1.2版本,是關于段距離通信的早期探索,此時還存在許多問題,應用不是特別廣泛

第二代藍牙主要是00年中V2.0~V2.1版本,新增了EDR(Enhanced Data Rate)技術提高傳輸速率,以及體驗及安全

第三代藍牙主要是00年末V3.0版本,新增了802.11 WiFi協議,引入了AMP(Generic Alternate MAC/PHY)交替射頻技術,極大的提高了傳輸速率并降低功耗

第四代藍牙是10年以來的V4.0~V4.2版本,主推LE(Low Energy)低功耗,大約僅消耗十分之一,將三種規格,包括經典藍牙、高速藍牙、和藍牙低功耗,集中在一起形成一套綜合協議規范

第五代藍牙是16年開始提出的V5.0版本,主要是為了支持物聯網,在功耗、傳輸速率、有效傳輸距離、數據包容量方面都做了極大的提升

下面的分析都是基于V4.1版本,方便入門,可以理解很多核心協議的設計思想

Part202 藍牙技術分類

藍牙技術包含藍牙發展過程中的兩套技術,但是這兩套原理和實現都不一樣,也無法實現互通

Basic Rate(BR)/AMP

最初的藍牙技術,包括可選的EDR(Enhanced Data Rate)技術和交替使用的MAC層和PHY層擴展 AMP(Alternate MAC and PHY layer extension)【優化傳輸速度的過程】

解釋:藍牙誕生之初使用的BR技術,傳輸速率很低,隨著發展而變得無法支持,所以引入了EDR,這時還沒有修改軟硬件架構,但是之后又落伍了,所以直接引入了WiFi的底層協議,也就是MAC/PHY擴展,但這部分的實現就無法直接更替,所以BR/EDR只能與AMP交替使用

Low Energy(LE)

藍牙低功耗,則不關心傳輸速率,而是從降低功耗的角度實現的另一套技術,跟前面的協議沒有絲毫關系

Part303 藍牙架構

609fb6d6-6bae-11ed-8abf-dac502259ad0.png

structure

藍牙協議將藍牙整體分成了兩層架構,底層是核心協議,描述了藍牙核心技術的基礎和規范,應用層協議則基于具體需求,使用核心協議提供的機制,實現不同的功能策略

核心協議包含兩部分,Host和Controller,這兩部分在不同的藍牙協議版本中略有區別,但大致上是,Controller完成硬件側的規范制訂,包括信號調制解調,會抽象出用于通信的邏輯鏈路,可能存在一個或多個,如LE Controller、BR/EDR Controller;Host則在邏輯鏈路的基礎上完成更友好的封裝,屏蔽掉技術細節,方便應用層對數據的使用

Part404 藍牙協議

藍牙協議也采用層次結構,自下而上依次為物理層、邏輯層、L2CAP層和應用層

60c255e2-6bae-11ed-8abf-dac502259ad0.png

protocol

應用層(App Layer)為不同場景定義規范,提出Profile(一項服務)的概念,實現各種應用功能

L2CAP(Logical Link Control and Adaptation Protocol Layer)

邏輯鏈路控制和適配協議,負責管理邏輯鏈路,使得不同應用可共享一個邏輯鏈路,類似端口的實現

在邏輯鏈路的基礎上,抽象出與具體技術無關的數據傳輸信道,如單/廣播,然后對上以L2CAP channel endpoints的概念,為不同應用程序提供獨立的傳輸通道

邏輯層(Logical Layer)

提供設備對象之間邏輯傳輸,在物理層的基礎上,建立邏輯信道,主要基于傳輸類型來劃分,包括控制類傳輸(負責底層物理鏈路的管理)、用戶類傳輸(負責用戶數據傳輸)和其他特殊類型的傳輸

不同的邏輯信道(Logical Link)會在下層對應Logical Transport,實現流控、應答、重傳等機制

物理層(Physical Layer)

負責提供數據傳輸的物理通道

物理鏈路(Physical Link):對物理信道的進一步封裝

物理信道(Physical channel):三種藍牙技術都使用相同的頻段和頻率范圍,但是具體實現都不一樣

Advertisement Broadcast Channel:用于設備間無連接廣播通信,包括發現/連接操作

Piconet channel:用于連接狀態下通信

Inquiry Scan Physical Channel:用于發現操作,即搜索/被搜索

Page Scan Physical Channel:用于連接操作,即連接/被連接

Basic Piconet Physical Channel:用于連接狀態下通信,使用79個跳頻點

Adapted Piconet Physical Channel:用于連接狀態下通信,使用較少RF跳頻點

Synchronization Scan Channel:用于無連接的廣播通信

BR/EDR頻段分成了79個channel,每個占1M帶寬;采用跳頻技術(Hopping),即物理信道隨機占用某一channel;定義了五種物理信道,每次只能在一種物理信道上通信,采用時分方式

AMP直接使用WIFI的物理層規范,只有一個物理信道,用于已連接設備之間的高速數據通信

LE頻段分成了40個channel,每個占2M帶寬;有兩種物理信道,每次只能在一種物理信道上通信,采用時分方式

Part505 BLE協議棧

實現一個BLE應用,需要一個支持BLE射頻的芯片,然后基于一個與芯片配套的協議棧,開發藍牙應用。

協議棧的作用就是軟件和硬件之間的橋梁,對應用數據進行封包然后生成可以通過射頻發送的空中數據包及其逆向過程。

60de74f2-6bae-11ed-8abf-dac502259ad0.png

BLE-protocol

Physical Layer(PHY)

藍牙通信系統的物理層,是免費ISM頻段,整個頻帶分成40份,每份帶寬2MHz;此外還定義了RF收發相關的特性,如發射功率、調制解調方式等

Link Layer(LL)

解決在有限物理信道上傳輸遠多實際信道數量的數據,即信道共享,然后為通信實體創建看似獨享的邏輯信道,以及解決傳輸過程中的校驗、重傳等問題

LL中的信道設計:BLE系統基于通信場景,在40個物理信道中選取三個作為廣播信道,處理數據量小、發送不頻繁、時延不敏感的場景,存在的問題就是不可靠、效率低、不安全;另外的場景則在剩下的37個信道中選取一個為雙方建立單獨信道,并且為了抗干擾采用跳頻技術

為此,LL為通信雙方實體定義了以下狀態及切換條件

615f9ed8-6bae-11ed-8abf-dac502259ad0.png

BLE-state

- Standby:初始狀態,不收發數據,接受上層協議命令與其他狀態切換
- Advertising:通過廣播發送數據的狀態,建立連接后可進入Connection
- Scanning:接收廣播的數據的狀態
- Initiating:特殊的接收狀態,類似Scanning,接收Advertiser廣播的連接數據,建立連接后進入Connection
- Connection:建立連接后擁有單獨的通道
12345

這里會使用空中接口協議(Air Interface Protocol,AIP)來負責實體之間的數據交換和狀態切換

Host Controller Interface(HCI)

定義Host和Contorller之間的通信協議,如兩個芯片之間的串口

L2CAP

邏輯控制和適配協議的工作就是實現邏輯信道的多路復用(multiplexing),對上層數據進行分割和重組,以及后續的流控、錯誤控制和重傳等

多路復用思想:將要發送的數據分割成一個個數據包(Packet Data Unit,PDU),添加包含特定ID的頭部,接收方解析頭部ID進行重組

多路復用實現

基于連接:L2CAP會為每個邏輯信道分配一個編號(Channel ID,CID),有些CID會有固定用途

基于協議(略)

Attribute Protocol(ATT)

屬性協議主要是針對物聯網場景,核心思想就是將采集的信息或控制的命令以屬性的形式抽象出來,提供接口供遠端設備讀寫

采用C/S形式,信息提供方為ATT Server,如傳感器,訪問方為ATT Client

為每個Attribute定義了三個屬性

Type,即Attribute的類型,使用UUID區分

Handle,服務端用來唯一標識Attribute的16-bit數值

Value,Attribute的值

為每個Attribute定義了一系列權限,方便服務端控制客戶端的行為,包括訪問/加密/認證/授權

對于不同的Attribute,客戶端對服務端的訪問方式也不一樣,包括Find/Read/Write

傳輸過程是在L2CAP的基礎上,使用基于通道的多路復用,CID為0x0004

Generic Attribute Profile(GATT)

通用屬性配置文件,Attribute只是將信息(或者說通信數據)做一下抽象,但是真正對抽象的信息做分類管理則是GATT來完成,形成profile的概念(解決了很多無線協議的兼容問題),profile可以理解成應用場景或者使用方式

GATT提供了這樣一種通用的、信息存儲與共享的profile framework,實現BLE雙向通信

GATT的層次結構

617eafee-6bae-11ed-8abf-dac502259ad0.jpg

GATT_profile_hierarchy

Profile位于最頂層,不是真正存在的配置文件,而是一個或多個場景相關的service的抽象集合

Service(服務)是一種行為的抽象,具有唯一標識UUID,每個service包含一個或多個Characteristic,也可以通過include的方式包含其他service

Characteristic(特征)可以理解成一個屬性,是真正與設備通信相關的,數據發送和接收的最基本單位,通過對特征的讀寫實現藍牙雙向通信,它由一個Propertities(定義Value的使用規范和Descriptor的訪問規范)、一個Value(特征的實際取值)和一個或多個Descriptor(Value相關的描述信息)組成,每個特征也具有自己的唯一標識,但是有三種形式:

16-bit是官方認證,收費,Bluetooth_Base_UUID 為 00000000-0000-1000-8000-00805F9B34FB

16-bit轉128-bit,格式為 0000xxxx-0000-1000-8000-00805F9B34FB

32-bit轉128-bit,格式為 xxxxxxxx-0000-1000-8000-00805F9B34FB

事實上,目前幾乎所有的BLE應用都基于GATT實現通信

GATT通信基于C/S模型,外圍設備作為Server端,維護ATT結構及產出數據,中心設備作為client端,請求連接獲取數據

GATT連接對外圍設備是獨占的,即一個外圍設備同時與一個中心設備建立連接,一個中心設備可同時與多個外圍設備建立連接

Security Manager(SM)

安全管理協議主要負責BLE通信過程中安全相關的內容,包括認證、加密這些過程

Generic Access Profile(GAP)

通用訪問配置文件,定義了藍牙設備的通用的訪問功能,與GATT的數據通信過程對應,處理無連接連接建立過程的通信,也就是為廣播、掃描、發起連接這些過程定義統一規范

定義了用戶接口的基本參數,包括藍牙地址、名稱、pincode、class等概念

定義了設備的角色:

Broadcaster Role:正在發送advertising events的設備

Observer Role:正在接收advertising events的設備

Peripheral Role:接受Link Layer連接的設備(對應Link Layer的slave角色)

Central Role,發起Link Layer連接的設備(對應Link Layer的master角色)

定義了通信的過程和操作模式:

Broadcast mode and observation procedure:實現單向的、無連接的通信

Discovery modes and procedures:實現藍牙設備的發現操作

Connection modes and procedures:實現藍牙設備的連接操作

Bonding modes and procedures:實現藍牙設備的配對操作

Part606 BLE的廣播

使用場景

單向、無連接的數據通信,發送者使用廣播信道發送數據,接受者掃描接收數據

連接建立階段

協議層次

GAP:以應用程序角度進行功能封裝,提供一套統一的、通用的廣播規范

HCI:將LL提供的功能抽象成Command/Events的形式,供上層使用

LL:負責廣播通信相關功能的定義和實現,包括信道選擇、鏈路狀態定義、PDU定義、設備過濾機制等

LL

信道選擇。BLE將藍牙頻段分成了40個物理信道,綜合考慮(抗干擾等)后將其中三個作為廣播信道,頻段為0/12/39,編號是37-39

鏈路狀態。參與廣播的BLE設備,總是處于這三種狀態之一

Advertising:廣播狀態,周期性地廣播,數據發送方

Scanning:掃描狀態,掃描并接受廣播數據,數據接收方

Initiating:初始化狀態,掃描到可連接的廣播時,發起連接請求,連接發起方

PDU(Packet Data Unit)格式

61a73fea-6bae-11ed-8abf-dac502259ad0.png
pdu

Type是指PDU的類型,如不同的狀態下也有不同的消息類型,TxAdd和RxAdd都是地址類型flag,針對不同的type有不同的含義,RFU都是保留字段,Length標明payload的長度

Payload內容

State Type Descriptions Payload length Descriptions
Advertising ADV_IND 常規廣播,可連接可掃描 AdvA 6 address of broadcaster
【后續建立點對點連接,監聽CONNECT_REQ請求】 AdvData 0~31 Broadcast data
ADV_NONCONN_IND 同ADV_IND,不可連接不可掃描 AdvA 6 address of broadcaster
【用于定時傳輸簡單數據】 AdvData 0~31 Broadcast data
ADV_SCAN_IND 同ADV_IND,不可連接可掃描 AdvA 6 address of broadcaster
【用于傳輸額外數據,監聽SCAN_REQ請求】 AdvData 0~31 Broadcast data
ADV_DIRECT_IND 點對點連接,已知雙方藍牙地址,無廣播數據,可被指定設備連接不可掃描 AdvA 6 address of broadcaster
【快速建立連接,不關心廣播數據,監聽CONNECT_REQ請求】 InitA 6 address of receiver/initiater
Scanning SCAN_REQ 接收ADV_IND/ADV_SCAN_IND后,請求更多信息 ScanA 6 address of scanne r
【接收廣播數據后請求更多信息】 AdvA 6 address of broadcaster
SCAN_RSP SCAN_REQ的響應,返回更多信息 AdvA 6 address of broadcaster
ScanRspData 0~31 response data
Initiating CONNECT_REQ 接收ADV_IND/ADV_DIRECT_IND后,請求建立連接 InitA 6 address of receiver/initiater
【請求建立連接】 AdvA 6 address of broadcaster
LLData 22 parameters of connection

BLE設備地址類型

Static Device Address:上電生成,46-bit的random+11,斷電后可變

Private Device Address:進一步提供定時更新和地址加密提高可靠行和安全性

Non-resolvable Private Address:按周期定時更新,46-bit的random+00

Resolvable Private Address:通過隨機數和IRK(Identity Resolving Key)生成,24-bit的hash+22-bit的random+10

Public Device Address:IEEE分配,24-bit的company_id+24-bit的company_assigned,類似MAC

Random Device Address:隨機生成,解決費用和維護、設備身份綁定的問題

HCI

將Link Layer提供的功能封裝成Command/Event組

Command格式

62336f10-6bae-11ed-8abf-dac502259ad0.png

command

OCF(Opcode Command Field)表示特定的HCI命令,OGF(Opcode Group Field)表示該HCI命令所屬組別,他們共同組成16位操作碼;Parameter Total Length表示所有參數總長度

所有BLE相關的HCI Command的OGF都是0x08

Event格式

624d5e48-6bae-11ed-8abf-dac502259ad0.png

event

這些Command/Event包括廣播、掃描、連接建立的相關操作,這些都可以通過hcitool命令進行測試

GAP

會從應用程序角度對各種狀態和操作再一次進行封裝,包括設備角色,通信的模式和操作的定義

與GAP廣播通信相關的是廣播和發現模式

Broadcast mode and observation procedure,廣播模式及對應的解析過程,對應狀態下的角色雙方就是Broadcaster和Observer

Discovery modes and procedures,發現模式及對應的發現過程,對應的角色就是Peripheral和Central

廣播數據格式

626f7622-6bae-11ed-8abf-dac502259ad0.png

adv_data

廣播/掃描應答數據,包含有意義部分和無意義部分(補齊為0),有意義部分是由一個個廣播塊(AD Structure)組成,每個廣播塊包含1字節長度(指示數據部分長度)和剩下的數據部分,數據部分又分為數據類型和數據內容,數據類型會指示真實Data部分的內容,例如0x01表示Data內容是描述設備物理連接狀態,再例如0x08表示Data內容是設備名稱,更多可以參考generic-access-profile

舉個廣播數據的例子

0201060303aafe1716aafe00-10000102030405060708090a0b0e0f00000000
1

02 01 06是一個AD Structure,數據部分長度為2字節,類型是0x01,描述設備物理連接狀態,數據部分0x06,1字節8bit,每bit都是一個標志位([預留]|[預留]|[預留]|[同時支持BLE和BR/EDR(Host)]|[同時支持BLE和BR/EDR(Controller)]|[不支持BR/EDR]|[普通發現模式]|[有限發現模式]),那么這個廣播就是普通發現模式,不支持BR/EDR

03 03 aa fe是第二個AD Structure,數據部分長度為3字節,類型是0x03,表示16-bits的Service UUID

17 16 aa fe 00 -10 00 01 02 03 04 05 06 07 08 09 0a 0b 0e 0f 00 00 00 00是最后一個AD Structure,數據部分長度為0x17即23字節,類型是0x16,表示服務數據

AD Type Description AD Data
0x01 設備物理連接狀態 1字節8bit,每個bit都是一個標志位 [預留]|[預留]|[預留]|[同時支持BLE和BR/EDR(Host)]|[同時支持BLE和BR/EDR(Controller)]|[不支持BR/EDR]|[普通發現模式]|[有限發現模式]
0x02 UUID 非完整的16-bit UUID
0x03 UUID 完整的16-bit UUID
0x04 UUID 非完整的32-bit UUID
0x05 UUID 完整的32-bit UUID
0x06 UUID 非完整的128-bit UUID
0x07 UUID 完整的128-bit UUID
0x08 設備名稱 縮寫設備名稱
0x09 設備名稱 完整設備名稱
0x0a TX Power Level TX Power Level
0xff 廠商數據 [廠商ID]|[廠商自定義數據]

Part707 BLE的連接

經典藍牙中保持連接非常耗費資源,但是每次連接建立效率又非常低,為了優化體驗,BLE簡化了連接過程(毫秒級),極大的降低了面向連接通信的代價

藍牙通信系統中,對于連接的定義是:在約定的時間段內,雙方都到一個指定的物理Channel上通信。

LL

角色定義。BLE為處于連接狀態的兩個設備定義了兩個角色,Master和Slave。Master作為連接發起方,定義和連接相關的參數,Slave是連接的接收方,請求連接參數

PDU(Packet Data Unit)格式

629204a8-6bae-11ed-8abf-dac502259ad0.png

DC_PDU

面向連接的通信使用特定的PDU,稱為Data channel PDU

LLID指示Data Channel傳輸的PDU類型,傳輸數據是LL Data PDU,傳輸控制信息是LL Control PDU,NESN(Next Expected Sequence Number)和SN(Sequence Number)用于數據傳輸過程中的應答和流控,MD(More Data)用于關閉連接,RFU是預留位,Length指示有效數據長度,包括Payload和MIC

LLID type Description
01b LL Data PDU 空包或未傳輸完成的消息(被拆包)
10b LL Data PDU (不需拆包)完整消息或第一個包
11b LL Control PDU 用于控制、管理LL連接的數據包,此時Payload為1字節Opcode和剩余的控制數據

建立連接

可連接狀態的設備(Advertiser)按照一定周期廣播可連接數據包

主動連接的設備(Initiator)收到廣播包后回應一個連接請求(約定時間點、物理信道等)

Initiator發送完畢后進入連接狀態,成為Master

Advertiser接收到連接請求后也進入連接狀態,成為Slave

雙方按照參數約定,定時切換到某一物理信道,開始依次收發數據,直至連接斷開

HCI

封裝Link Layer的功能,主要包括連接的建立、關閉、參數設置和管理,以及數據封裝和轉發

GAP

定義設備具有的能力和操作

Part808 BLE安全機制

White List

白名單就是一組藍牙地址列表,通過設置白名單可以允許掃描、連接特定的藍牙設備,以及被掃描、連接

LL Privacy

在白名單的基礎上將設備地址進行加密,轉變成Resolvable Private addresses

本地Resolving List需要保存每一對BLE設備的key/address信息,格式為:Local IRK|Peer IRK|Peer Device Identity Address|Address Type

LL Privacy機制在Controller中完成,即加解密操作對HCI上層是透明的

LL Encryption

數據發送和接收過程進行加解密

加解密操作在Link Layer完成

Host會保存至少1280bit的LTK(根密鑰),啟動加密傳輸時,LL會首先協商出一個128-bit的隨機數SDK(Session Key Diversifier)和64-bit的iv,經過Encryption Engine和LTK生成此次通信的會話密鑰SessionKey

SecurityManager

為BLE設備提供加密連接相關的key,包含以下規范:

定義了配對(Pairing)的相關概念及過程

定義了密碼工具箱,包含配對、加密所需的各種算法

定義了安全管理協議(Security Manager Protocol,SMP),實現配對、密碼傳輸等操作

SMP規范中,配對的定義是,Master和Slave通過協商確定用于加密通信的key的過程,包含三個階段:

階段一、Pairing Feature Exchange,交換雙方配對相關的設置,如配對方法、鑒權方式等

鑒權方式可以采用交換額外的信息(Out of band,OOB),或者彈窗引入人來判定,稱為MITM鑒權,還有輸入配對碼進行對比(Passkey Entry/Numeric Comparison),或者不鑒權(Just Work)

階段二、通過SMP協議進行配對操作,有兩種配對方案,LE Legacy Pairing和LE Secure Connections

階段三、協商好密鑰key,建立加密連接,傳輸密鑰信息(可選)

Part909 Android中的BLE應用

具體可以參考開發的藍牙測試工具:BLETool

BLE,藍牙低功耗(極低的運行和待機功耗)

Android 4.3(API 18) 開始引入 BLE ,即藍牙4.0

Android 4.3 的 BLE 只支持 Central Role(中心設備,掃描并連接外圍設備)

Android 5.0 開始同時支持 Central Role 和 Peripheral Role(外圍設備,向外廣播發送數據)

1、權限

 

 

 


 


2、開啟/關閉藍牙

//判斷支持藍牙功能
if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
//獲取藍牙管理服務
BluetoothManagerbluetoothManager=(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
//獲取藍牙適配器
BluetoothAdapterbluetoothAdapter=bluetoothManager.getAdapter();
if(bluetoothAdapter!=null){
//判斷藍牙是否開啟
if(bluetoothAdapter.isEnabled()){
//關閉藍牙
bluetoothAdapter.disable();
}else{
//1、靜默開啟藍牙
bluetoothAdapter.enable();
//2、顯式請求開啟藍牙
Intentintent=newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent,REQUEST_BLUETOOTH_ENABLE);
}
}
}

3、掃描與監聽

if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)){
//獲取藍牙管理服務
BluetoothManagerbluetoothManager=(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
//獲取藍牙適配器
BluetoothAdapterbluetoothAdapter=bluetoothManager.getAdapter();
if(bluetoothAdapter!=null){
//判斷藍牙是否開啟
if(bluetoothAdapter.isEnabled()){
//獲取掃描器實例
BluetoothLeScannerbluetoothLeScanner=bluetoothAdapter.getBluetoothLeScanner();
booleanisScanning=false;
if(bluetoothLeScanner!=null){
if(isScanning){
//停止掃描
isScanning=false;
bluetoothLeScanner.stopScan(scanCallback);
}else{
//開始掃描
isScanning=true;
bluetoothLeScanner.startScan(scanCallback);
}
}
}
}
}

Android 8 開始提供一個后臺持續掃描的API,應用殺死后也可以繼續掃描,直到關閉藍牙【待驗證】

publicintstartScan(Listfilters,ScanSettingssettings,PendingIntentcallbackIntent);

//設置攔截器和掃描選項
bluetoothLeScanner.startScan(scanFilters,scanSettings,scanCallback);

初始化掃描過濾器

scanFilters=newArrayList<>();
ScanFilterscanFilter=newScanFilter.Builder()
.setDeviceName("lalala")
.setServiceUuid(newParcelUuid(UUID.randomUUID()))
.build();
scanFilters.add(scanFilter);

初始化掃描設置

scanSettings=newScanSettings.Builder()
//設置掃描模式
.setScanMode(ScanSettings.SCAN_MODE_BALANCED)
//設置回調類型
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
//設置配對模式
.setMatchMode(ScanSettings.MATCH_MODE_STICKY)
//設置報告延遲
.setReportDelay(0)
.build();

兩個類都是通過 Builder 構造,提供系列函數用于參數設置,如 setDeviceName()、setScanMode()、setMatchMode() 等

4、掃描回調

scanCallback=newScanCallback{
@Override
publicvoidonScanResult(intcallbackType,ScanResultresult){
super.onScanResult(callbackType,result);
}

@Override
publicvoidonScanFailed(interrorCode){
super.onScanFailed(errorCode);
}

@Override
publicvoidonBatchScanResults(Listresults){
super.onBatchScanResults(results);
}
}

其中 onBatchScanResults() 是批量返回掃描結果。可通過下面的接口判斷藍牙芯片是否支持批處理

Bluetoothadapter.isOffloadedScanBatchingSupported();
1

注意 onScanResult() 和 onBatchScanResults() 是互斥的,ScanSettings 中 setReportDelay() 設置為0(默認)則通過 onScanResult() 返回掃描結果,否則開啟批處理掃描模式,并觸發 onBatchScanResults() 回調。

5、廣播數據解析

掃描成功會返回 ScanResult 廣播數據類,然后進一步解析

//返回遠程設備類
BluetoothDevicedevice=scanResult.getDevice();
//返回掃描記錄,包含廣播和掃描響應
ScanRecordscanRecord=scanResult.getScanRecord();
//返回信號強度,[-127,126]
intrssi=scanResult.getRssi()

BluetoothDevice 是設備信息類,常用的方法有

//獲取硬件地址
Stringaddress=device.getAddress();
//獲取藍牙名稱
Stringname=device.getName();
//獲取設備類型,如DEVICE_TYPE_CLASSIC、DEVICE_TYPE_LE、DEVICE_TYPE_DUAL、DEVICE_TYPE_UNKNOWN
inttype=device.getType();
//獲取綁定狀態,如BOND_NONE、BOND_BONDING、BOND_BONDED
intstate=device.getBondState();

6、連接設備

掃描返回的廣播消息中可以獲取到遠程設備的MAC地址,可用于設備的連接

if(bluetoothAdapter.isEnabled()){
//獲取遠程設備對象
BluetoothDevicebluetoothDevice=bluetoothAdapter.getRemoteDevice(address);
if(bluetoothDevice!=null){
handler.post(newRunnable(){
@Override
publicvoidrun(){
BluetoothGattbluetoothGatt;
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
//連接遠程設備
bluetoothGatt=bluetoothDevice.connectGatt(context,false,bluetoothGattCallback,BluetoothDevice.TRANSPORT_LE);
}else{
bluetoothGatt=bluetoothDevice.connectGatt(context,false,bluetoothGattCallback);
}
}
});
}
}

bluetoothGatt 是藍牙通用屬性協議的封裝,定義了BLE通信的一些基本規則和連接通信操作

7、連接回調

bluetoothGattCallback 則是 bluetoothGatt 連接的回調類,通知客戶端連接狀態和結果

bluetoothGattCallback=newBluetoothGattCallback{
@Override
publicvoidonConnectionStateChange(BluetoothGattgatt,finalintstatus,finalintnewState){
super.onConnectionStateChange(gatt,status,newState);
}

@Override
publicvoidonServicesDiscovered(BluetoothGattgatt,finalintstatus){
super.onServicesDiscovered(gatt,status);
}

@Override
publicvoidonCharacteristicChanged(BluetoothGattgatt,finalBluetoothGattCharacteristiccharacteristic){
super.onCharacteristicChanged(gatt,characteristic);
}

@Override
publicvoidonCharacteristicRead(BluetoothGattgatt,finalBluetoothGattCharacteristiccharacteristic,finalintstatus){
super.onCharacteristicRead(gatt,characteristic,status);
}

@Override
publicvoidonCharacteristicWrite(BluetoothGattgatt,finalBluetoothGattCharacteristiccharacteristic,finalintstatus){
super.onCharacteristicWrite(gatt,characteristic,status);
}

@Override
publicvoidonDescriptorRead(BluetoothGattgatt,finalBluetoothGattDescriptordescriptor,finalintstatus){
super.onDescriptorRead(gatt,descriptor,status);
}

@Override
publicvoidonDescriptorWrite(BluetoothGattgatt,finalBluetoothGattDescriptordescriptor,finalintstatus){
super.onDescriptorWrite(gatt,descriptor,status);
}
}

連接成功及其他連接狀態改變都會調用 onConnectionStateChange() 方法。status 表示這個操作的狀態,是 BluetoothGatt.GATT_SUCCESS 或者讀寫受限、超過范圍等其他錯誤狀態。newState 則表示當前設備的連接狀態,連接成功為 BluetoothProfile.STATE_CONNECTED,連接失敗是BluetoothProfile.STATE_DISCONNECTED。

8、發現服務

連接成功后就可以開始通信,從請求服務開始(Profile只是一系列具有共同業務需求的服務的抽象集合,服務才是實體)

bluetoothGatt.discoverServices();
1

發現服務后會觸發 onServicesDiscovered() 回調,然后繼續獲取服務

//獲取所有服務
ListbleServiceList=bluetoothGatt.getServices();
//通過uuid獲取特定的服務
BluetoothGattServicebleService=bluetoothGatt.getService(serviceUuid);

BluetoothGattService 是藍牙服務類,是與某個場景相關的一系列行為的抽象,具有一個唯一的UUID,然后服務類型,如SERVICE_TYPE_PRIMARY、SERVICE_TYPE_SECONDARY(主要服務可以包含二級服務),包含的特征列表

9、獲取特征

//獲取所有特征
ListbleCharacteristicList=bleService.getCharacteristics();
//通過uuid獲取特定的特征
BluetoothGattCharacteristicbleCharacteristic=bleService.getCharacteristic(characteristicUuid);

BluetoothGattCharacteristic 是藍牙特征類,是通信的基本數據單位,包含標志特征的唯一的UUID,描述特征訪問權限的特性,如PROPERTY_BROADCAST、PROPERTY_READ、PROPERTY_WRITE等,特征的實際取值,以及特征的描述

10、讀寫特征

//讀取特征
bluetoothGatt.readCharacteristic(bleCharacteristic);
//設置并寫入特征
bleCharacteristic.setValue("XXX");
bluetoothGatt.writeCharacteristic(bleCharacteristic);

這里的讀寫特征函數都是返回布爾類型表示是否操作成功,如果成功真正的值會在 onCharacteristicRead/onCharacteristicWrite 回調中讀取/寫入

@Override
publicvoidonCharacteristicRead(BluetoothGattgatt,BluetoothGattCharacteristiccharacteristic,intstatus){
switch(status){
caseGATT_SUCCESS:
StringvalueStr=BLEUtils.byte2HexString(characteristic.getValue());
break;
caseGATT_READ_NOT_PERMITTED:
ToastUtils.showShort(context,"GATT_READ_NOT_PERMITTED");
break;
default:
ToastUtils.showShort(context,"CHARACTERISTIC_READ_FAILED");
break;
}
}

@Override
publicvoidonCharacteristicWrite(BluetoothGattgatt,BluetoothGattCharacteristiccharacteristic,intstatus){
switch(status){
caseGATT_SUCCESS:
StringvalueStr=BLEUtils.byte2HexString(characteristic.getValue());
break;
default:
ToastUtils.showShort(context,"CHARACTERISTIC_WRITE_FAILED");
break;
}
}

11、監聽特征

真正要實現通信除了單方面讀寫,還需要對數據變化進行監聽,這樣就可以進行數據交換

//設置特征監聽為true,且要求特征具有NOTIFY屬性
bluetoothGatt.setCharacteristicNotification(characteristic,true);

這樣,自己或對方特征改變時就會回調函數從而獲取改變后的特征值

@Override
publicvoidonCharacteristicChanged(BluetoothGattCharacteristiccharacteristic){
Log.d("bledemo","uuid="+characteristic.getUuid().toString());
Log.d("bledemo","value=0x"+BLEUtils.byte2HexString(characteristic.getValue()));
}

12、獲取描述

//獲取所有描述
ListbleDescriptorList=bleCharacteristic.getDescriptors();
//通過uuid獲取特定的描述
BluetoothGattDescriptorbleDescriptor=bleCharacteristic.getDescriptor(descriptorUuid);

BluetoothGattDescriptor 是藍牙特征描述類,包含對特征的一些額外描述信息

13、讀寫描述

//讀取描述
bluetoothGatt.readDescriptor(bleDescriptor);
//設置并寫入描述
bleDescriptor.setValue("XXX");
bluetoothGatt.writeDescriptor(bleDescriptor);

同樣讀寫成功會觸發onDescriptorRead/onDescriptorWrite 回調

@Override
publicvoidonDescriptorRead(BluetoothGattDescriptordescriptor,intstatus){
switch(status){
caseGATT_SUCCESS:
StringvalueStr=BLEUtils.byte2HexString(descriptor.getValue());
break;
caseGATT_READ_NOT_PERMITTED:
ToastUtils.showShort(context,"GATT_READ_NOT_PERMITTED");
break;
default:
ToastUtils.showShort(context,"DESCRIPTOR_READ_FAILED");
break;
}
}

@Override
publicvoidonDescriptorWrite(BluetoothGattDescriptordescriptor,intstatus){
switch(status){
caseGATT_SUCCESS:
StringvalueStr=BLEUtils.byte2HexString(descriptor.getValue());
break;
default:
ToastUtils.showShort(context,"DESCRIPTOR_WRITE_FAILED");
break;
}
}

14、斷開連接

//斷開連接,會觸發onConnectionStateChange()回調
bluetoothGatt.disconnect();
//關閉連接,不會觸發回調
bluetoothGatt.close();
1234

15、開啟/關閉廣播

if(bluetoothAdapter.isEnabled()){
//設置廣播設備的名稱,方便搜索
bluetoothAdapter.setName("XXX");
//獲取廣播類
BluetoothLeAdvertiserbluetoothLeAdvertiser=bluetoothAdapter.getBluetoothLeAdvertiser();
if(bluetoothLeAdvertiser!=null){
if(isAdvertising){
//關閉廣播
bluetoothLeAdvertiser.stopAdvertising(advertiseCallback);
}else{
//開始廣播
bluetoothLeAdvertiser.startAdvertising(advertiseSetting,advertiseData,advertiseCallback);
}
}
}

還可以發送帶響應報文的廣播包

bluetoothLeAdvertiser.startAdvertising(advertiseSetting,advertiseData,advertiseResData,advertiseCallback);
1

其中 advertiseSetting 為廣播設置類對象

advertiseSetting=newAdvertiseSettings.Builder()
//廣播模式,控制廣播功率和延遲
.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY)
//廣播發射功率級別
.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH)
//廣播超時時間,最大值為3*60*1000毫秒,為0時禁用超時,默認無限廣播
.setTimeout(advertiseTimeout)
//廣播連接類型
.setConnectable(true)
.build();
12345678910

advertiseData、advertiseResData 為廣播包

advertiseData=newAdvertiseData.Builder()
//廣播是否包含設備名稱
.setIncludeDeviceName(true)
//廣播是否包含發射功率
.setIncludeTxPowerLevel(true)
//添加服務uuid
.addServiceUuid(newParcelUuid(UUID.randomUUID()))
.build();

advertiseResData=newAdvertiseData.Builder()
//添加自定義服務數據
.addServiceData(newParcelUuid(UUID.randomUUID()),newbyte[]{1,2,3,4})
//添加自定義廠商數據
.addManufacturerData(0x06,newbyte[]{5,6,7,8})
.build();

16、廣播回調

advertiseCallback 是廣播回調

advertiseCallback=newAdvertiseCallback{
@Override
publicvoidonStartSuccess(AdvertiseSettingssettingsInEffect){
super.onStartSuccess(settingsInEffect);
}

@Override
publicvoidonStartFailure(interrorCode){
super.onStartFailure(errorCode);
}
}

17、啟動GATT服務

只有廣播仍然不夠,作為外圍角色的設備還需要啟動GATT服務,等待中心設備與之建立連接之后就可以通過服務通信

//啟動Gatt服務
bluetoothGattServer=bluetoothManager.openGattServer(context,bluetoothGattServerCallback);
12

接下來可以向啟動的GATT服務中添加Service

//構造服務
BluetoothGattServicebluetoothGattService=newBluetoothGattService(UUID.randomUUID(),BluetoothGattService.SERVICE_TYPE_PRIMARY);

//構造特征
BluetoothGattCharacteristicbluetoothGattCharacteristic=newBluetoothGattCharacteristic(UUID.randomUUID(),BluetoothGattCharacteristic.PROPERTY_READ|BluetoothGattCharacteristic.PERMISSION_WRITE|BluetoothGattCharacteristic.PROPERTY_NOTIFY,BluetoothGattCharacteristic.PERMISSION_WRITE|BluetoothGattCharacteristic.PERMISSION_READ);
bluetoothGattCharacteristic.setValue("character_test_value");

//構造描述
BluetoothGattDescriptorbluetoothGattDescriptor=newBluetoothGattDescriptor(UUID.randomUUID(),BluetoothGattDescriptor.PERMISSION_READ|BluetoothGattDescriptor.PERMISSION_WRITE);
bluetoothGattDescriptor.setValue("descriptor_test_value".getBytes());

//添加描述到特征中
bluetoothGattCharacteristic.addDescriptor(bluetoothGattDescriptor);
//添加特征到服務中
bluetoothGattService.addCharacteristic(bluetoothGattCharacteristic);
//添加服務
bluetoothGattServer.addService(bluetoothGattService);

18、GATT服務回調

bluetoothGattServerCallback 是GATT服務的回調,當設備被連接、通信(讀寫特征)時都會觸發響應的回調函數

bluetoothGattServerCallback=newBluetoothGattServerCallback{
@Override
publicvoidonConnectionStateChange(BluetoothDevicedevice,intstatus,intnewState){
super.onConnectionStateChange(device,status,newState);
}

@Override
publicvoidonServiceAdded(intstatus,BluetoothGattServiceservice){
super.onServiceAdded(status,service);
}

@Override
publicvoidonCharacteristicReadRequest(BluetoothDevicedevice,intrequestId,intoffset,
BluetoothGattCharacteristiccharacteristic){
super.onCharacteristicReadRequest(device,requestId,offset,characteristic);
}

@Override
publicvoidonCharacteristicWriteRequest(BluetoothDevicedevice,intrequestId,
BluetoothGattCharacteristiccharacteristic,
booleanpreparedWrite,booleanresponseNeeded,
intoffset,byte[]value){
super.onCharacteristicWriteRequest(device,requestId,characteristic,preparedWrite,
responseNeeded,offset,value);
}

@Override
publicvoidonDescriptorReadRequest(BluetoothDevicedevice,intrequestId,
intoffset,BluetoothGattDescriptordescriptor){
super.onDescriptorReadRequest(device,requestId,offset,descriptor);
}

@Override
publicvoidonDescriptorWriteRequest(BluetoothDevicedevice,intrequestId,
BluetoothGattDescriptordescriptor,
booleanpreparedWrite,booleanresponseNeeded,
intoffset,byte[]value){
super.onDescriptorWriteRequest(device,requestId,descriptor,preparedWrite,responseNeeded,
offset,value);
}


@Override
publicvoidonNotificationSent(BluetoothDevicedevice,intstatus){
super.onNotificationSent(device,status);
}




審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 藍牙技術
    +關注

    關注

    45

    文章

    342

    瀏覽量

    52941
  • BLE協議棧
    +關注

    關注

    0

    文章

    5

    瀏覽量

    4766
  • EDR
    EDR
    +關注

    關注

    0

    文章

    23

    瀏覽量

    1996
收藏 人收藏

    評論

    相關推薦

    高通優化藍牙5.0協議藍牙耳機用戶體驗將增加

    雖然藍牙耳機使用起來比有線耳機更加方便,但音質可能稍有欠缺,還得擔心耳機的續航問題。但憑借著上周發布的驍龍845處理器,高通想要對藍牙音頻帶來一些提升。除了支持更穩定的藍牙5.0
    的頭像 發表于 01-11 09:32 ?7896次閱讀

    程序員必須要了解藍牙協議規范?

    藍牙規范包括核心協議與應用框架兩個文件。一部分協議規范還定義了藍牙各層通信協議,應用框架指的是如何應用這些
    發表于 10-19 18:23

    主流協議族TCP/IP協議,對此了解多少

    主流協議族TCP/IP協議,對此了解多少現在Internet(因特網)使用的主流協議族是TCP/IP
    發表于 08-27 16:13

    詳解那個不盡知的BLE藍牙

    提起物聯網無線連接技術,相信大家都知道藍牙,而對物聯網領域了解不深的朋友很容易對傳統藍牙和低功耗藍牙(BLE)混淆,甚至以為這兩個名詞指的是同一事物,其實不然。本文將分享關于BLE的一
    發表于 10-17 17:12

    利用藍牙技術實現的這些功能,了解幾個?

    `藍牙是很基本數據傳輸工具,可以實現藍牙設備之間的無線傳輸,但是隨著智能機的出現,很多人覺得現在的手機藍牙功能很雞肋,其實藍牙還有很多強大功能,只是
    發表于 03-07 17:06

    CC2540的應用是否需要全面了解藍牙協議

    現在打算用這個IC來開發一些產品,但是感覺入門挺高的,不知如何下手。請各位指導一二!用這個來開發,是否需要全面了解藍牙協議,對于藍牙協議,該
    發表于 08-19 07:39

    關于藍牙協議棧的應用

    新手剛學藍牙,想問開源的藍牙協議棧是對于所有的藍牙芯片通用嗎?比如我有 ATSAMB11XR/ZR藍牙芯片,我能使用Btstack
    發表于 08-01 10:34

    了解下Wi-Fi、Zigbee、Thread 、藍牙等這些協議

    了解下Wi-Fi、Zigbee、Thread 、藍牙等這些協議都是 2.4 GHz ISM 頻段,為何不是其他的頻段,比如2.8G,3.4G等頻段
    發表于 10-24 15:00

    聽過藍牙的知識產權嗎?關于藍牙的知識產權了解多少?

    聽過藍牙的知識產權嗎?關于藍牙的知識產權了解多少?藍牙的測試認證可以分為哪幾個方向?
    發表于 06-17 08:04

    CAN-FD協議了解多少

    關注+星標公眾號,不錯過精彩內容來源 |安富萊電子編排 |strongerHuang之前給大家分享過很多關于CAN的文章:CANOpen系列教程CAN-FD協議了解多少?第三代CAN...
    發表于 08-19 08:13

    藍牙協議棧iAP和AAP區別

    藍牙協議棧iAP和AAP區別一,iAP Profile:iPod Accesory Profile,Apple外設通訊協議Brief: 可以理解為蘋果手機的SPP協議,且很多蘋果手機特
    發表于 04-11 09:26

    藍牙協議測試

    藍牙協議測試 “藍牙質量鑒定程序”方面的詳細協議測試對每個投放市場的新無線電模塊來說是絕對必要的。本文結合精確設
    發表于 09-17 10:56 ?1981次閱讀
    <b class='flag-5'>藍牙</b><b class='flag-5'>協議</b>測試

    使用串口模塊需要了解藍牙協議

    家電產品等。未來,隨著價格便宜、質量穩定、供貨穩定的國產藍牙串口模塊的市場占有率逐步提高,必將進一步提高整個電子產品行業的智能化和物聯化。關于藍牙串口模塊QAQ:使用串口模塊需要了解藍牙
    的頭像 發表于 11-15 18:12 ?4115次閱讀

    CAN-FD協議了解多少 ?

    CAN-FD協議了解多少?
    的頭像 發表于 03-08 15:40 ?1.7w次閱讀

    藍牙協議版本解析:不同類型的藍牙協議及其作用

    藍牙技術作為一種無線通信技術,隨著時間的推移不斷發展演進。不同的藍牙協議版本為各類設備提供了不同的功能和應用特性。本文將深入解析不同類型的藍牙協議
    的頭像 發表于 12-28 11:17 ?2371次閱讀
    主站蜘蛛池模板: 一级毛片在线看在线播放| 男女吃奶一进一出动态图| 女bbbbxxxx毛片视频丶| 色综合色综合| 天天爽夜夜爽人人爽一区二区| 天天综合网天天综合色| 天天插天天插天天插| 欧美女同在线观看| 九色九色九色在线综合888| 91学院派女神| 1314酒色网| 欲色网站| 色妞基地| 久久免费国产视频| 成年免费大片黄在线观看免费| 亚洲午夜视频| 久久dvd| se01亚洲| 2021色噜噜狠狠综曰曰曰| 速度与激情一| 免费毛片软件| freesexvideo性欧美2| 手机在线看片国产日韩生活片| 干中文字幕| 男人j进人女人j 的视频| 五月婷婷六月婷婷| 美女黄页黄频| 亚洲三级色| 福利视频网址| 李老汉的性生生活2| 四虎国产精品永久免费网址| 六月天婷婷| 亚洲在线a| 91大神大战高跟丝袜美女| 美女无遮挡拍拍拍免费视频| 四虎永久在线日韩精品观看| 久久精品综合视频| 天天碰天天操| 在线观看日本一区| 天堂中文字幕在线| 国内黄色录像|