藍牙Gatt的詳細解析

一、Gatt的概述

Bluetooth GATT (Generic Attribute Profile) 是藍牙4.0新加入的一項協議,它規定了設備之間基於屬性的通信方式。其主要作用是用於BLE(藍牙低功耗)設備之間的數據傳輸。通過Gatt來完成對設備的控制、設置設備的屬性、進行數據傳輸、監聽設備的屬性變化等。其主要的核心是通過UUID(通用唯一識別碼)來區分不同的服務和特徵(含多個屬性)。Gatt的優勢在於其低功耗、易於使用和大量使用的標準協議。

二、Gatt的體系架構

在Gatt的體系架構中包含了Service、Characteristic和Descriptor三個部分,它們構成了一個完整的Gatt服務。

Service:包含一個或多個Characteristic,一個Service可以包含多個Descriptor,可以理解為一個Service對應於一個設備模塊(如溫度計)或一組相關屬性(如心率服務),每個Service均被分配了一個唯一的16位或128位的UUID。

Characteristic:由於service可能包含多個Characteristic,因此每一個Characteristic都應該包含一個唯一的UUID標識。Characteristic被用來表示一個數據的特徵,一個Characteristic可能包含一個指針,指向當前Characteristic的值,也可能包含多個屬性的集合。包括read(讀取)、write(寫入)、notify(通知)和indicate(指向)等操作。

Descriptor:為了描述一個Characteristics的屬性,曲線求助 Descriptors。Descriptors也是包含一個唯一UUID標識,用來描述某個Characteristic中的一個特徵,可以用於對Characteristic的Permissions(許可權)和Characteristic的Value(數值)進行描述。

三、Gatt的實現方式

Gatt可以通過Android中的BluetoothGatt類進行實現。以下是Gatt實現的示例代碼,其中主要包括了Gatt的連接、服務掃描、數據讀寫等操作。

 /**
     * 確保該操作完成後,才進行下一步操作
     */

    private CountDownLatch countDownLatch = null;

    public void getMtvAllNotification() {
        List supportedGattServices = getSupportedGattServices();
        Logger.i("服務數量 " + supportedGattServices.size());
        for (BluetoothGattService bluetoothGattService : supportedGattServices) {
            if (bluetoothGattService != null) {
                Logger.i("服務uuid " + bluetoothGattService.getUuid().toString());
                List characteristics = bluetoothGattService.getCharacteristics();
                for (BluetoothGattCharacteristic characteristic : characteristics) {
                    if (characteristic != null) {
                        Logger.i("特徵uuid " + characteristic.getUuid().toString());
                        if (countDownLatch != null) {
                            try {
                                countDownLatch.await();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        final int charaProp = characteristic.getProperties();
                        Logger.d("當期操作屬性 " + charaProp);
                        if ((charaProp & BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                            // 據說按照4.4 版本core specification 規定,android 4.3需要做這個特殊處理 不然會出現133錯誤
                            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                                @Override
                                public void run() {
                                    Logger.d("readCharacteristic(characteristic) " + characteristic.getUuid());
                                    readCharacteristic(characteristic);
                                }
                            }, 33);
                        }
                        if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                            boolean isAdded = enableNotification(true, characteristic);
                            if (isAdded) {
                                // 設置同步工具類初始值為1
                                countDownLatch = new CountDownLatch(1);
                            }
                        }
                    }
                }
            }
        }
    } 
    
   private void readCharacteristic(BluetoothGattCharacteristic characteristic) {
        if (bluetoothGatt == null) {
            return;
        }
        boolean isRead = bluetoothGatt.readCharacteristic(characteristic);
        Logger.d("readCharacteristic isRead:" + isRead);
    }
    
    /**
     * 註冊/取消通知
     */
    private List characteristicNotificationList = new ArrayList();

    public boolean enableNotification(boolean enable, BluetoothGattCharacteristic characteristic) {
        if (bluetoothGatt == null || characteristic == null) {
            return false;
        }
        int properties = characteristic.getProperties();
        boolean success = bluetoothGatt.setCharacteristicNotification(characteristic, enable);
        Logger.d("setCharacteristicNotification status = " + success);

        /*
         * 取得描述符
         * 必須要有的代碼,根據已有的uuid創建描述符,特徵描述的UUID是固定的,根據業務邏輯定。
         * 下面描述符的UUID固定為0x2902
         */
        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                UUID.fromString(SampleGattAttributes.DESCRIPTOR_CONFIG));
        if (descriptor != null) {
            if (enable) {
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
            } else {
                descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
            }
            success = bluetoothGatt.writeDescriptor(descriptor);
            Logger.d("writeDescriptor status = " + success);
            if (success) {
                if (enable) {
                    characteristicNotificationList.add(characteristic);
                } else {
                    characteristicNotificationList.remove(characteristic);
                }
            }
        }
        return success;
    }

四、Gatt的相關注意事項

在使用Gatt時,需要注意以下事項:

1、Gatt的操作為非同步操作,需要處理好操作完成後的回調;

2、Gatt的連接錯誤碼較多,需要根據實際情況進行處理;

3、Gatt在傳輸數據時需要確保數據格式正確,如endian的問題;

4、Gatt的模式分為GATT、ATT,其中GATT區分操作和數據,ATT不區分操作和數據;

5、Gatt中的許可權問題需要注意,需要確保應用有足夠的許可權進行Gatt操作。

五、Gatt的應用場景

Gatt主要應用於一些低功耗、易於連接和易於控制的設備中,如智能家居、智能穿戴、健康檢測設備等。它可以通過傳輸數據來進行設備之間的通訊和控制,具有廣泛的應用前景。

原創文章,作者:LHIZ,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/149692.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
LHIZ的頭像LHIZ
上一篇 2024-11-05 16:54
下一篇 2024-11-05 16:54

相關推薦

  • index.html怎麼打開 – 詳細解析

    一、index.html怎麼打開看 1、如果你已經擁有了index.html文件,那麼你可以直接使用任何一個現代瀏覽器打開index.html文件,比如Google Chrome、…

    編程 2025-04-25
  • Resetful API的詳細闡述

    一、Resetful API簡介 Resetful(REpresentational State Transfer)是一種基於HTTP協議的Web API設計風格,它是一種輕量級的…

    編程 2025-04-25
  • 關鍵路徑的詳細闡述

    關鍵路徑是項目管理中非常重要的一個概念,它通常指的是項目中最長的一條路徑,它決定了整個項目的完成時間。在這篇文章中,我們將從多個方面對關鍵路徑做詳細的闡述。 一、概念 關鍵路徑是指…

    編程 2025-04-25
  • neo4j菜鳥教程詳細闡述

    一、neo4j介紹 neo4j是一種圖形資料庫,以實現高效的圖操作為設計目標。neo4j使用圖形模型來存儲數據,數據的表述方式類似於實際世界中的網路。neo4j具有高效的讀和寫操作…

    編程 2025-04-25
  • AXI DMA的詳細闡述

    一、AXI DMA概述 AXI DMA是指Advanced eXtensible Interface Direct Memory Access,是Xilinx公司提供的基於AMBA…

    編程 2025-04-25
  • c++ explicit的詳細闡述

    一、explicit的作用 在C++中,explicit關鍵字可以在構造函數聲明前加上,防止編譯器進行自動類型轉換,強制要求調用者必須強制類型轉換才能調用該函數,避免了將一個參數類…

    編程 2025-04-25
  • HTMLButton屬性及其詳細闡述

    一、button屬性介紹 button屬性是HTML5新增的屬性,表示指定文本框擁有可供點擊的按鈕。該屬性包括以下幾個取值: 按鈕文本 提交 重置 其中,type屬性表示按鈕類型,…

    編程 2025-04-25
  • Vim使用教程詳細指南

    一、Vim使用教程 Vim是一個高度可定製的文本編輯器,可以在Linux,Mac和Windows等不同的平台上運行。它具有快速移動,複製,粘貼,查找和替換等強大功能,尤其在面對大型…

    編程 2025-04-25
  • crontab測試的詳細闡述

    一、crontab的概念 1、crontab是什麼:crontab是linux操作系統中實現定時任務的程序,它能夠定時執行與系統預設時間相符的指定任務。 2、crontab的使用場…

    編程 2025-04-25
  • 網站測試工具的詳細闡述

    一、測試工具的概述 在軟體開發的過程中,測試工具是一個非常重要的環節。測試工具可以快速、有效地檢測軟體中的缺陷,提高軟體的質量和穩定性。與此同時,測試工具還可以提高軟體開發的效率,…

    編程 2025-04-25

發表回復

登錄後才能評論