Android 低功耗藍(lán)牙(BLE)

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??偣?28位,換算成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之上)?;綰UID由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ù))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容