美文网首页
Android 低功耗蓝牙(BLE)

Android 低功耗蓝牙(BLE)

作者: 涛涛123759 | 来源:发表于2017-11-20 20:20 被阅读63次

    BLE分为三部分Service、Characteristic、Descriptor,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。一般来说,Characteristic是手机与BLE终端交换数据的关键,Characteristic有较多的跟权限相关的字段,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY,本文所用的BLE蓝牙模块竟然没有标准的Characteristic的PERMISSION。Characteristic的PROPERTY可以通过位运算符组合来设置读写属性,例如READ|WRITE、READ|WRITE_NO_RESPONSE|NOTIFY,因此读取PROPERTY后要分解成所用的组合(本文代码已含此分解方法)。

    处理Service发送过来的各种时间.

    ACTION_GATT_CONNECTED: 连接上了一个GATT服务.
    ACTION_GATT_DISCONNECTED: 断开了一个GATT服务.
    ACTION_GATT_SERVICES_DISCOVERED: 发现了GATT服务.
    ACTION_DATA_AVAILABLE: 从设备接收到数据. 这里可能是一个读取或者通知操作的结果。

    BluetoothAdapter.ACTION_STATE_CHANGED 蓝牙状态值发生改变
    BluetoothAdapter.ACTION_SCAN_MODE_CHANGED 蓝牙扫描状态(SCAN_MODE)发生改变
    BluetoothAdapter.ACTION_DISCOVERY_STARTED 蓝牙扫描过程开始
    BluetoothAdapter.ACTION_DISCOVERY_FINISHED 蓝牙扫描过程结束
    BluetoothAdapter. ACTION_LOCAL_NAME_CHANGED 蓝牙设备Name发生改变
    BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE 请求用户选择是否使该蓝牙能被扫描
    PS:如果蓝牙没有开启,用户点击确定后,会首先开启蓝牙,继而设置蓝牙能被扫描。
    BluetoothAdapter. ACTION_REQUEST_ENABLE 请求用户选择是否打开蓝牙

    BluetoothDevice.ACTION_FOUND (该常量字段位于BluetoothDevice类中,稍后讲到)
    说明:蓝牙扫描时,扫描到任一远程蓝牙设备时,会发送此广播。

    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 状态值 , 即开关状态

              int STATE_OFF        蓝牙已经关闭
              int STATE_ON        蓝牙已经打开
              int STATE_TURNING_OFF      蓝牙处于关闭过程中 ,关闭ing
              int STATE_TURNING_ON        蓝牙处于打开过程中 ,打开ing
    

    2、在这里首先要了解对蓝牙操作一个核心类BluetoothAdapter

    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();  
    //直接打开系统的蓝牙设置面板  
    Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
    startActivityForResult(intent, 0x1);  
    //直接打开蓝牙  
    adapter.enable();  
    //关闭蓝牙  
    adapter.disable();  
    //打开本机的蓝牙发现功能(默认打开120秒,可以将时间最多延长至300秒)  
    Intent discoveryIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);  
    discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);//设置持续时间(最多300秒)  
    

    3、搜索蓝牙设备

    使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备
    startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。

    请求Discovery后,系统开始搜索蓝牙设备,在这个过程中,系统会发送以下三个广播:
    ACTION_DISCOVERY_START:开始搜索
    ACTION_DISCOVERY_FINISHED:搜索结束
    ACTION_FOUND:找到设备,这个Intent中包含两个extra fields:EXTRA_DEVICE和EXTRA_CLASS,分别包含BluetooDevice和BluetoothClass。



    GATT层中定义的所有属性都有一个UUID值,UUID是全球唯一的128位的号码,它用来识别不同的特性。
    首先来说明一下含义:
    GATT(Generic Attribute Profile),通用属性配置文件,其中的数据都是实际发送的,也就是蓝牙事件所产生的协议栈事件都是在这里发生的。
    UUID(Universally Unique Identifier),通用唯一识别码。
    UUID一般可以分为两种:1、蓝牙技术联盟UUIDs;2、供应商特定的UUID

    1、蓝牙技术联盟UUIDs

    蓝牙核心规范制定了两种不同的UUID,1、基本的UUID;2、代替基本UUID的16位UUID。

    注意:所有的蓝牙技术联盟定义UUID共用了一个基本的UUID:0x0000xxxx-0000-1000-8000-00805F9B34FB。总共128位,换算成8位位组(octet)也就是16个8位位组(8*16=128嘛)。为了进一步简化基本UUID,每一个蓝牙技术联盟定义的属性有一个唯一的16位UUID,以代替上面的基本UUID的‘x’部分,也就是第12、13个八位位组。

    2、供应商特定的UUID

    与蓝牙技术联盟定义的UUID类似,供应商特定的UUID也有基本UUID和16位的UUID(类似一个别名,再加载在基本UUID之上)。基本UUID由nRFgo Studio产生,16位UUID可以按照自己的意图来任意分配。
    因此,按照上述原则,nRF51822的SDK关于UUID的数据结构如下所示:

    /** @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;  
    

    结构体ble_uuid128_t内部只有一个结构体成员,其中结构体成员为一个包含16个无符号字符型元素的一维数组,也就是16个8位位组,刚好能够表示128位UUID。
    按照SDK中的注释,结构体ble_uuid_t是低功耗蓝牙UUID类型,压缩了16位和128位UUID。其中,包含两个结构体成员,1、无符号16位整型数uuid,也就是16位UUID值或者128位UUID的第12-13个八位位组;2、无符号8位整型数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:蓝牙兴趣小组的UUID。
    3、BLE_UUID_TYPE_VENDOR_BEGIN:供应商UUID类型开始在这个指针(128位)。

    通过如下协议栈函数可以添加一个供应商特定的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字节并不会被内部直接使用,因为他们通常被ble_uuid_t中的16位UUID位域代替。


    5、手机的BLE默认有2个服务

    (1)Service 通用属性规范 00001801-0000-1000-8000-00805f9b34fb (null) 
             a)Characteristic 服务改变 00002a05-0000-1000-8000-00805f9b34fb 
    (2)Service 通用接入规范 00001800-0000-1000-8000-00805f9b34fb 
             a)Characteristic 设备名称 00002a00-0000-1000-8000-00805f9b34fb 
             b)Characteristic 设备外观 00002a01-0000-1000-8000-00805f9b34fb (00 00) 
             c)Characteristic 设备外观 00002aa6-0000-1000-8000-00805f9b34fb (01) 
    

    注意:因为00002aa6不在定义中,因此可以认为是厂商或者用户自定义的特征(或服务)

    相关文章

      网友评论

          本文标题:Android 低功耗蓝牙(BLE)

          本文链接:https://www.haomeiwen.com/subject/nzgtattx.html