手机蓝牙4.0,如果说明书上说支持BLE,则是支持两种不同的无线射频BluetoothSmart Ready设备,其射频被称为双模式射频。
TI的蓝牙芯片,像CC2540/CC2541是蓝牙4.0单模芯片,也就是BLE(Bluetooth Low Energy)。在开发BLE蓝牙时,都是先获取服务也就是UUID, 然后根据服务的属性执行相应操作。这到底是为什么呢?这就要从架构不同的蓝牙的连接特点和通信方式、开发方式讲起。
蓝牙 4.0是蓝牙3.0+HS 规范的补充,有双模和单模之分。蓝牙 4.0 双模可以向下兼容蓝牙 3.0 和蓝牙 2.1(蓝牙 3.0 和蓝牙 2.1,一般叫做经典蓝牙);
蓝牙 4.0 单模就是 BLE(Bluetooth Low Energy),黑色模块里用的是TI公司的CC2541蓝牙芯片,架构是4.0单模BLE,其特点是功耗更低,可以使电池的使用时间更长,成本更低且传输距离更远。
CC2541支持的是4.0单模蓝牙BLE,不是完整的蓝牙4.0,只是一部分。是单模的,所以不能向下兼容。
手机蓝牙是4.0smart向下兼容,而且兼容ble。2541是ble不向下兼容的。
如果使用智能手机想要和一台BLE从设备建立连接,其硬件条件是,蓝牙得至少是低功耗蓝牙版本,然后安卓系统的话,至少得是Android 4.3以上系统才行,因为Google在Android 4.3以上才做了BLE主设备的支持,如果想将智能手机作为BLE从设备,则必须在Android 5.0以上才行。
蓝牙4.0是最新的蓝牙无线技术, 其具备的低耗能特点是Bluetooth Smart设备的基础。蓝牙技术联盟首席营销官Suke Jawanda介绍说,蓝牙4.0支持两种不同的无线射频,BluetoothSmart Ready设备的射频被称为双模式射频,表示其同时支持传统蓝牙无线连接和新蓝牙低耗能连接。Bluetooth Smart设备的射频被称为单模式射频,表示其仅支持新蓝牙低耗能连接。
由此可知,蓝牙的架构支持两种部署方式:双模式和单模式。
双模式中,低功耗蓝牙功能集成在现有的经典蓝牙控制器中,或再在现有经典蓝牙技术(2.1+EDR/3.0+HS)芯片上增加低功耗堆栈,整体架构基本不变,因此成本增加有限。
单模式面向高度集成、紧凑的设备,使用一个轻量级连接层(Link Layer)提供超低功耗的待机模式操作、简单设备恢复和可靠的点对多点数据传输,还能让联网传感器在蓝牙传输中安排好低功耗蓝牙流量的次序,同时还有高级节能和安全加密连接。
相应的芯片供应商如TI、CSR、Broadcom等相应的蓝牙4.0硬件芯片也分为两类。就TI来说,像CC2540/CC2541就是单模芯片,CC2560/2564就是双模芯片。
所以蓝牙4.0规范定义了两类设备:双模(dual mode)设备能够支持低功耗蓝牙以及蓝牙BR/EAR(传统蓝牙技术),而单模(simple mode)设备仅支持低功耗蓝牙。
在蓝牙设备中,存在着物理地址,我们也叫作蓝牙的MAC地址,这个地址是唯一的,就像咱们网络上的IP地址。同时还存在着一个叫做UUID的东西,可以把它理解为是IP地址中的端口号。正如知道了IP地址和端口号,就知道了怎么链接到目标网络服务器位置,知道了蓝牙设备的MAC地址和UUID也就能够确定到具体是哪一台蓝牙设备了,这两者合起来就是蓝牙的唯一身份标识
经典蓝牙和低功耗蓝牙发现设备的方式是有区别的。经典蓝牙设备发现其它经典蓝牙设备的方式是调用BluetoothAdapter的startDiscovery()方法。
而低功耗蓝牙(BLE)中有一个主设备(Central)和从设备(Peripheral,也叫外围设备)的概念。主设备作为发现方,调用发现设备的方法,通过BluetoothAdapter的startLeScan()方法实现。
BluetoothAdapter.startDiscovery在大多数手机上是可以同时发现经典蓝牙和Ble的,但是startDiscovery的回调无法返回Ble的广播,所以无法通过广播识别设备,且startDiscovery扫描Ble的效率比StartLeScan低很多。所以在实际应用中,还是StartDiscovery和StartLeScan分开扫,前者扫传统经典蓝牙,后者扫低功耗蓝牙
另外,经典蓝牙和低功耗蓝牙连接方式是有区别的,经典蓝牙建立连接的方式实际上就是Socket的连接的建立。只不过这里不是直接用Socket,而是BluetoothSocket。获取BluetoothSocket的方式也很简单,利用搜索找到的BluetoothDevice,调用其方法createRfcommSocketToServiceRecord(UUID)。最后,使用获取到的BluetoothDevice调用其方法connect()就建立了经典蓝牙设备之间的连接通道。
经典蓝牙的数据通信:当建立连接后,就可以直接使用BluetoothSocket的getOutputStream()方法获取输出流写入需要发送的数据。读取发送回来的数据,则是调用BluetoothSocket的getInputStream()方法获取输入流读取。这点和Java中的Socket通信几乎是一模一样。
低功耗蓝牙则用了一种看起来比较怪异的方式建立连接。通过BLE连接,读写属性类小数据的Profile通用规范。现在所有的BLE应用Profile都是基于GATT的。而GATT是基于ATT Protocol的。ATT针对BLE设备做了专门的优化,具体就是在传输过程中使用尽量少的数据。每个属性都有一个唯一的UUID,属性将以characteristics and services的形式传输。
而低功耗蓝牙想要实现主设备对从设备的数据发送,则需要直接读取获取到的从设备的Characteristic,而Characteristic又是Service下面的一层,所以操作顺序是:
1)通过BLE从设备相应的Service_UUID获取对应的BluetoothGattService,获取方法是:使用BluetoothDevice的connectGatt(this, false, mGattCallback)方法返回的BluetoothGatt对象,调用BluetoothGatt的方法getService(Service_UUID)获取相应的BluetoothGattService;
2)调用BluetoothGattService和对应的Characteristic的写入UUID获取相应的BluetoothGattCharacteristic,获取方法是:调用BluetoothGattService的getCharacteristic(Characteristic_UUID)方法获得;
3)设置需要发送的命令值,调用BluetoothGatt Characteristic的方法setValue(value)进行设置,其中value一般为byte[];
4)最后,使用BluetoothGatt的写入方法writeCharacteristic(TxChar)完成命令发送可以看到,想要实现BLE的数据通信,步骤相当繁琐,这里只是做一个简单的概念理解,如果想要获取到BLE从设备的返回值,还需要设置Notification,然后调用BluetoothGatt的readCharacteristic(characteristic)方法进行数据的读取。