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漩绵≈雇拢總共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ù))

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末醇王,一起剝皮案震驚了整個濱河市根暑,隨后出現(xiàn)的幾起案子缰犁,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倦淀,死亡現(xiàn)場離奇詭異愿棋,居然都是意外死亡见秤,警方通過查閱死者的電腦和手機乎澄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來紊服,“玉大人,你說我怎么就攤上這事吆玖。” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸠儿。 經(jīng)常有香客問我屹蚊,道長,這世上最難降的妖魔是什么肉瓦? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上巢价,老公的妹妹穿的比我還像新娘并齐。我一直安慰自己熬北,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布讶隐。 她就那樣靜靜地躺著起胰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪巫延。 梳的紋絲不亂的頭發(fā)上效五,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天,我揣著相機與錄音炉峰,去河邊找鬼畏妖。 笑死,一個胖子當(dāng)著我的面吹牛疼阔,可吹牛的內(nèi)容都是我干的戒劫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼婆廊,長吁一口氣:“原來是場噩夢啊……” “哼迅细!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起淘邻,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤茵典,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后宾舅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體统阿,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡枚尼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了砂吞。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡崎溃,死狀恐怖蜻直,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情袁串,我是刑警寧澤概而,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站囱修,受9級特大地震影響赎瑰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜破镰,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一餐曼、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鲜漩,春花似錦源譬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喉祭,卻和暖如春养渴,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泛烙。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工理卑, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人胶惰。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓傻工,卻偏偏與公主長得像,于是被迫代替她去往敵國和親孵滞。 傳聞我的和親對象是個殘疾皇子中捆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容