BLE分為三部分Service粘舟、Characteristic熔脂、Descriptor霞揉,這三部分都由UUID作為唯一標(biāo)示符零聚。一個藍(lán)牙4.0的終端可以包含多個Service,一個Service可以包含多個Characteristic政模,一個Characteristic包含一個Value和多個Descriptor,一個Descriptor包含一個Value耗式。一般來說刊咳,Characteristic是手機與BLE終端交換數(shù)據(jù)的關(guān)鍵娱挨,Characteristic有較多的跟權(quán)限相關(guān)的字段捕犬,例如PERMISSION和PROPERTY碉碉,而其中最常用的是PROPERTY,本文所用的BLE藍(lán)牙模塊竟然沒有標(biāo)準(zhǔn)的Characteristic的PERMISSION贴届。Characteristic的PROPERTY可以通過位運算符組合來設(shè)置讀寫屬性毫蚓,例如READ|WRITE斩跌、READ|WRITE_NO_RESPONSE|NOTIFY耀鸦,因此讀取PROPERTY后要分解成所用的組合(本文代碼已含此分解方法)啸澡。
處理Service發(fā)送過來的各種時間.
ACTION_GATT_CONNECTED: 連接上了一個GATT服務(wù).
ACTION_GATT_DISCONNECTED: 斷開了一個GATT服務(wù).
ACTION_GATT_SERVICES_DISCOVERED: 發(fā)現(xiàn)了GATT服務(wù).
ACTION_DATA_AVAILABLE: 從設(shè)備接收到數(shù)據(jù). 這里可能是一個讀取或者通知操作的結(jié)果嗅虏。
BluetoothAdapter.ACTION_STATE_CHANGED 藍(lán)牙狀態(tài)值發(fā)生改變
BluetoothAdapter.ACTION_SCAN_MODE_CHANGED 藍(lán)牙掃描狀態(tài)(SCAN_MODE)發(fā)生改變
BluetoothAdapter.ACTION_DISCOVERY_STARTED 藍(lán)牙掃描過程開始
BluetoothAdapter.ACTION_DISCOVERY_FINISHED 藍(lán)牙掃描過程結(jié)束
BluetoothAdapter. ACTION_LOCAL_NAME_CHANGED 藍(lán)牙設(shè)備Name發(fā)生改變
BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE 請求用戶選擇是否使該藍(lán)牙能被掃描
PS:如果藍(lán)牙沒有開啟,用戶點擊確定后参咙,會首先開啟藍(lán)牙,繼而設(shè)置藍(lán)牙能被掃描择同。
BluetoothAdapter. ACTION_REQUEST_ENABLE 請求用戶選擇是否打開藍(lán)牙
BluetoothDevice.ACTION_FOUND (該常量字段位于BluetoothDevice類中敲才,稍后講到)
說明:藍(lán)牙掃描時择葡,掃描到任一遠(yuǎn)程藍(lán)牙設(shè)備時,會發(fā)送此廣播阻星。
private final BroadcastReceiver mGattUpdateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (BluetoothLeService.ACTION_GATT_CONNECTED.equals(action)) {
mConnected = true;
updateConnectionState(R.string.connected);
invalidateOptionsMenu();
} else if (BluetoothLeService.ACTION_GATT_DISCONNECTED.equals(action)) {
mConnected = false;
updateConnectionState(R.string.disconnected);
invalidateOptionsMenu();
clearUI();
} else if (BluetoothLeService.
ACTION_GATT_SERVICES_DISCOVERED.equals(action)) {
// 顯示所有支持的service和characteristic迫横。
displayGattServices(mBluetoothLeService.getSupportedGattServices());
} else if (BluetoothLeService.ACTION_DATA_AVAILABLE.equals(action)) {
displayData(intent.getStringExtra(BluetoothLeService.EXTRA_DATA));
}else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() == BluetoothDevice.BOND_BONDED) {
addBandDevices(device);
} else {
addUnbondDevices(device);
}
}
}
};
1矾踱、BluetoothAdapter STATE 狀態(tài)值 呛讲, 即開關(guān)狀態(tài)
int STATE_OFF 藍(lán)牙已經(jīng)關(guān)閉
int STATE_ON 藍(lán)牙已經(jīng)打開
int STATE_TURNING_OFF 藍(lán)牙處于關(guān)閉過程中 贝搁,關(guān)閉ing
int STATE_TURNING_ON 藍(lán)牙處于打開過程中 芽偏,打開ing
2污尉、在這里首先要了解對藍(lán)牙操作一個核心類BluetoothAdapter
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
//直接打開系統(tǒng)的藍(lán)牙設(shè)置面板
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 0x1);
//直接打開藍(lán)牙
adapter.enable();
//關(guān)閉藍(lán)牙
adapter.disable();
//打開本機的藍(lán)牙發(fā)現(xiàn)功能(默認(rèn)打開120秒,可以將時間最多延長至300秒)
Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//設(shè)置持續(xù)時間(最多300秒)
3某宪、搜索藍(lán)牙設(shè)備
使用BluetoothAdapter的startDiscovery()方法來搜索藍(lán)牙設(shè)備
startDiscovery()方法是一個異步方法兴喂,調(diào)用后會立即返回。該方法會進(jìn)行對其他藍(lán)牙設(shè)備的搜索畏鼓,該過程會持續(xù)12秒滴肿。該方法調(diào)用后佃迄,搜索過程實際上是在一個System Service中進(jìn)行的呵俏,所以可以調(diào)用cancelDiscovery()方法來停止搜索(該方法可以在未執(zhí)行discovery請求時調(diào)用)普碎。
請求Discovery后录平,系統(tǒng)開始搜索藍(lán)牙設(shè)備斗这,在這個過程中表箭,系統(tǒng)會發(fā)送以下三個廣播:
ACTION_DISCOVERY_START:開始搜索
ACTION_DISCOVERY_FINISHED:搜索結(jié)束
ACTION_FOUND:找到設(shè)備免钻,這個Intent中包含兩個extra fields:EXTRA_DEVICE和EXTRA_CLASS,分別包含BluetooDevice和BluetoothClass凤覆。
GATT層中定義的所有屬性都有一個UUID值盯桦,UUID是全球唯一的128位的號碼慈俯,它用來識別不同的特性肥卡。
首先來說明一下含義:
GATT(Generic Attribute Profile)步鉴,通用屬性配置文件璃哟,其中的數(shù)據(jù)都是實際發(fā)送的随闪,也就是藍(lán)牙事件所產(chǎn)生的協(xié)議棧事件都是在這里發(fā)生的。
UUID(Universally Unique Identifier)撮奏,通用唯一識別碼畜吊。
UUID一般可以分為兩種:1玲献、藍(lán)牙技術(shù)聯(lián)盟UUIDs梯浪;2挂洛、供應(yīng)商特定的UUID
1、藍(lán)牙技術(shù)聯(lián)盟UUIDs
藍(lán)牙核心規(guī)范制定了兩種不同的UUID逆瑞,1获高、基本的UUID念秧;2布疼、代替基本UUID的16位UUID。
注意:所有的藍(lán)牙技術(shù)聯(lián)盟定義UUID共用了一個基本的UUID:0x0000xxxx-0000-1000-8000-00805F9B34FB漩绵≈雇拢總共128位碍扔,換算成8位位組(octet)也就是16個8位位組(8*16=128嘛)秕重。為了進(jìn)一步簡化基本UUID溶耘,每一個藍(lán)牙技術(shù)聯(lián)盟定義的屬性有一個唯一的16位UUID,以代替上面的基本UUID的‘x’部分卓鹿,也就是第12、13個八位位組澜倦。
2、供應(yīng)商特定的UUID
與藍(lán)牙技術(shù)聯(lián)盟定義的UUID類似碘勉,供應(yīng)商特定的UUID也有基本UUID和16位的UUID(類似一個別名验靡,再加載在基本UUID之上)雏节〈侵荩基本UUID由nRFgo Studio產(chǎn)生寥粹,16位UUID可以按照自己的意圖來任意分配。
因此岛杀,按照上述原則,nRF51822的SDK關(guān)于UUID的數(shù)據(jù)結(jié)構(gòu)如下所示:
/** @brief 128 bit UUID values. */
typedef struct
{
unsigned char uuid128[16];
} ble_uuid128_t;
/** @brief Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */
typedef struct
{
uint16_t uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */
uint8_t type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */
} ble_uuid_t;
結(jié)構(gòu)體ble_uuid128_t內(nèi)部只有一個結(jié)構(gòu)體成員崭孤,其中結(jié)構(gòu)體成員為一個包含16個無符號字符型元素的一維數(shù)組类嗤,也就是16個8位位組,剛好能夠表示128位UUID裳瘪。
按照SDK中的注釋土浸,結(jié)構(gòu)體ble_uuid_t是低功耗藍(lán)牙UUID類型,壓縮了16位和128位UUID彭羹。其中黄伊,包含兩個結(jié)構(gòu)體成員,1派殷、無符號16位整型數(shù)uuid还最,也就是16位UUID值或者128位UUID的第12-13個八位位組;2毡惜、無符號8位整型數(shù)type拓轻,也就是UUID類型枣氧,其值有如下三種情況:
/** @defgroup BLE_UUID_TYPES Types of UUID
* @{ */
#define BLE_UUID_TYPE_UNKNOWN 0x00 /**< Invalid UUID type. */
#define BLE_UUID_TYPE_BLE 0x01 /**< Bluetooth SIG UUID (16-bit). */
#define BLE_UUID_TYPE_VENDOR_BEGIN 0x02 /**< Vendor UUID types start at this index (128-bit). */
/** @} */
1荒典、BLE_UUID_TYPE_UNKNOWN:不可用的UUID類型,這也與ble_uuid_t中的如果類型是BLE_UUID_TYPE_UNKNOWN,UUID值是未定義的踢械。
2、BLE_UUID_TYPE_BLE:藍(lán)牙興趣小組的UUID。
3、BLE_UUID_TYPE_VENDOR_BEGIN:供應(yīng)商UUID類型開始在這個指針(128位)。
通過如下協(xié)議棧函數(shù)可以添加一個供應(yīng)商特定的UUID同窘。
uint32_t sd_ble_uuid_vs_add| ( ble_uuid128_t const *const p_vs_uuid)
Note
Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by the 16-bit uuid field inble_uuid_t
Parameters
[in] p_vs_uuid Pointer to a 16-octet (128-bit) little endian Vendor Specific UUID disregarding bytes 12 and 13.
[out] p_uuid_type Pointer where the type field inble_uuid_tcorresponding to this UUID will be stored.
由注意可以知道,提供的UUID的12、13字節(jié)并不會被內(nèi)部直接使用灿椅,因為他們通常被ble_uuid_t中的16位UUID位域代替。
5骨坑、手機的BLE默認(rèn)有2個服務(wù)
(1)Service 通用屬性規(guī)范 00001801-0000-1000-8000-00805f9b34fb (null)
a)Characteristic 服務(wù)改變 00002a05-0000-1000-8000-00805f9b34fb
(2)Service 通用接入規(guī)范 00001800-0000-1000-8000-00805f9b34fb
a)Characteristic 設(shè)備名稱 00002a00-0000-1000-8000-00805f9b34fb
b)Characteristic 設(shè)備外觀 00002a01-0000-1000-8000-00805f9b34fb (00 00)
c)Characteristic 設(shè)備外觀 00002aa6-0000-1000-8000-00805f9b34fb (01)
注意:因為00002aa6不在定義中礁遣,因此可以認(rèn)為是廠商或者用戶自定義的特征(或服務(wù))