【轉】BLE 學習記錄

來源:互聯網
上載者:User

標籤:

原文網址:http://m.blog.csdn.net/blog/chiooo/43985401

BLE 學習記錄

ANROID BLE 開發,基於 bluetoothlegatt 分析

  1. mBluetoothAdapter = mBluetoothManager.getAdapter(); 得到 手機上藍芽主機的適配器 mBluetoothAdapter

    public boolean initialize() { 
    // For API level 18 and above, get a reference to BluetoothAdapter through 
    // BluetoothManager. 
    if (mBluetoothManager == null) { 
    mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); 
    if (mBluetoothManager == null) { 
    Log.e(TAG, “Unable to initialize BluetoothManager.”); 
    return false; 
    } 
    }

    mBluetoothAdapter = mBluetoothManager.getAdapter();if (mBluetoothAdapter == null) {    Log.e(TAG, "Unable to obtain a BluetoothAdapter.");    return false;}return true;

    }

2.獲得mBluetoothGatt,註冊回調

 * Connects to the GATT server hosted on the Bluetooth LE device. * * @param address The device address of the destination device. * * @return Return true if the connection is initiated successfully. The connection result *         is reported asynchronously through the *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} *         callback.public boolean connect(final String address) {    if (mBluetoothAdapter == null || address == null) {        Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");        return false;    }    // Previously connected device.  Try to reconnect.    if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)            && mBluetoothGatt != null) {        Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");        if (mBluetoothGatt.connect()) {            return true;        } else {            return false;        }    }    final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);  得到bluetoothdevice    if (device == null) {        Log.w(TAG, "Device not found.  Unable to connect.");        return false;    }    // We want to directly connect to the device, so we are setting the autoConnect    // parameter to false.    mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback);//bluetoothdevice得到mBluetoothGatt傳進去的是 BluetoothGattCallback,從名字看就是回調。    Log.d(TAG, "Trying to create a new connection.");    mBluetoothDeviceAddress = address;    return true;}

3.讀寫BluetoothGattCharacteristic,使能notification

mBluetoothGatt.readCharacteristic(characteristic); 讀mBluetoothGatt.writeCharacteristic(characteristic);  寫 * Enables or disables notification on a give characteristic. * * @param characteristic Characteristic to act on. * @param enabled If true, enable notification.  False otherwise.public void setCharacteristicNotification(BluetoothGattCharacteristic characteristic,                                          boolean enabled) {    if (mBluetoothAdapter == null || mBluetoothGatt == null) {        Log.w(TAG, "BluetoothAdapter not initialized");        return;    }    mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);}向下寫資料://設定資料內容                gattCharacteristic.setValue("send data->");                //往藍芽模組寫入資料                mBLE.writeCharacteristic(gattCharacteristic);    讀資料:    if(gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)){                                  //測試讀取當前Characteristic資料,會觸發mOnDataAvailable.onCharacteristicRead()                mHandler.postDelayed(new Runnable() {                    @Override                    public void run() {                        mBLE.readCharacteristic(gattCharacteristic);                    }                }, 500);                //接受Characteristic被寫的通知,收到藍芽模組的資料後會觸發mOnDataAvailable.onCharacteristicWrite()                mBLE.setCharacteristicNotification(gattCharacteristic, true);

4.得到 supported services

 * Retrieves a list of supported GATT services on the connected device. This should be * invoked only after {@code BluetoothGatt#discoverServices()} completes successfully. * * @return A {@code List} of supported services.public List<BluetoothGattService> getSupportedGattServices() {    if (mBluetoothGatt == null) return null;    return mBluetoothGatt.getServices();}

5.關係

BluetoothGatt 代表一個串連,裡麵包含一個或者多個 BluetoothGattService , 而每個BluetoothGattService 包含多個BluetoothGattCharacteristic , 一個 BluetoothGattCharacteristic 裡面可能包含0個或者多個 BluetoothGattDescriptor

6.BLE 裝置端LOG 
條件: 
主機端:BLEGATTLE 參考程式, 
裝置端: NODIC官方BLE UART 程式

串口端LOG:

 main start traceuart_init..\main.c:leds_init:137> enter_now..\main.c:timers_init:149> enter_now..\main.c:ble_stack_init:457> enter_now..\main.c:gap_params_init:166> enter_nowStart.....\main.c:advertising_start:331> enter_now..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:16// connect eventp_ble_evt->header.evt_id:16 p_ble_evt->header.evt_id:16 ..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:20 p_ble_evt->header.evt_id:20// BLE_GAP_EVT_SEC_INFO_REQUESTp_ble_evt->header.evt_id:20 ..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:19 p_ble_evt->header.evt_id:19// BLE_GAP_EVT_SEC_PARAMS_REQUESTp_ble_evt->header.evt_id:19 ..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:80  // write eventp_ble_evt->header.evt_id:80 p_ble_evt->header.evt_id:80 ..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:80 // write eventp_ble_evt->header.evt_id:80 ..\main.c:nus_data_handler:224> enter_nowsend data->                         // received datap_ble_evt->header.evt_id:80     // write event..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:24//   BLE_GAP_EVT_AUTH_STATUSp_ble_evt->header.evt_id:24 p_ble_evt->header.evt_id:24 ..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:23  //   BLE_GAP_EVT_AUTH_KEY_REQUESTp_ble_evt->header.evt_id:23 p_ble_evt->header.evt_id:23 ..\main.c:ble_evt_dispatch:442> enter_nowp_ble_evt->header.evt_id:18 ..\main.c:on_conn_params_evt:279> enter_nowp_ble_evt->header.evt_id:18   //  BLE_GAP_EVT_CONN_PARAM_UPDATEp_ble_evt->header.evt_id:18

7.BLE串連參數

#define MIN_CONN_INTERVALMSEC_TO_UNITS(500, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.5 seconds). */6~3200, 就是說7.5MS~ 4S, 1.25MS單位。連線時間間隔。#define MAX_CONN_INTERVALMSEC_TO_UNITS(1000, UNIT_1_25_MS)/**< Maximum acceptable connection interval (1 second). */ #define SLAVE_LATENCY0 跳過串連事件/**< Slave latency. */#define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS)  /**< Connection supervisory timeout (4 seconds). */  管理逾時,如果超過此時間沒有串連成功事件,則認為是串連丟失。

實驗驗證:

#define MIN_CONN_INTERVAL               16                                          /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */#define MAX_CONN_INTERVAL               500                                          /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */#define SLAVE_LATENCY                   0                                          /**< slave latency. */#define CONN_SUP_TIMEOUT                2000                                         /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(20000, APP_TIMER_PRESCALER)  /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000, APP_TIMER_PRESCALER) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */#define MAX_CONN_PARAMS_UPDATE_COUNT    3  

測試記錄:

當APP剛串連上時,這之間用得串連參數是由手機端決定的,經過FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS 後,手機端會發新的參數過來,我測試過的,手機端都是MAX_CONN_INTERVAL 來決定,SLAVE_LATENCY 不管我改成多少,下發的都是0。

網路上討論

  1. 對於IOS裝置來說, 蘋果設定了一系列規定, 不允許從裝置的配置超出這些範圍. 其他主裝置來說目前還沒有聽說有什麼具體範圍設定. Android裝置目前google也還沒有明確規定. 所以換句話說, 只要符合主裝置的要求, 從裝置是可以在主裝置規定的範圍內請求主裝置對connection interval進行改變的.
  2. 你通過GAP_SetParamValue()只是設定了參數, 最後是需要通過發送到主裝置那裡去請求修改的. 所以這裡不正確.請參考 GAPRole_SetParameter( GAPROLE_PARAM_UPDATE_ENABLE, ..) 函數的做法.
  3. 你可以通過packet sniffer抓包, 在時間戳記上很清楚能看到connection interval. 或者你也可以自己加點代碼, 從程式裡面擷取, 或者以notify方式發給主裝置, 從主裝置看, 總之, 方法很多哈. 
    另外附上蘋果對connection interval的要求, 其實還有其他的串連參數要求, 比如slave latency, supervision timeout, 如果不滿足這些, IOS裝置會拒絕.

    The connection parameter request may be rejected if it does not comply with all of these rules: 
    Interval Max * (Slave Latency + 1) ≤ 2 seconds 
    Interval Min ≥ 20 ms 
    Interval Min + 20 ms ≤ Interval Max 
    Slave Latency ≤ 4 
    connSupervisionTimeout ≤ 6 seconds 
    Interval Max * (Slave Latency + 1) * 3 < connSupervisionTimeout

8.從裝置怎麼主動中斷連線

你可以直接調用 GAPRole_TerminateConnection() 來主動中斷連線。 
那個函數調用後,串連順利斷開後會收到 GAP_LINK_TERMINATED_EVENT 事件。 
在這個事件之後,你再重新啟動廣播,即可

【轉】BLE 學習記錄

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.