win7如何搜索蓝牙设备4.0 BLE 设备

今天看啥 热点:
iOS开发 之 可穿戴设备 蓝牙4.0 BLE 开发,iosble
当前有越来越多的可穿戴设备使用了蓝牙4.0 BLE(Bluetooth Low Energy)。对于iOS开发而言,Apple之前专门推出CoreBluetooth的Framework来支持BLE的开发。对于硬件开发有了解的朋友应该知道,在之前使用低版本的蓝牙的设备,要连接到iOS设备上,需要注册MFI,拥有MFI协议才能进行相应的开发。如果大家关注我之前对LEGO EV3的研究,就可以发现,EV3是使用了蓝牙2.1,因此需要MFI协议来进行开发。
本文将一步一步讲解如何使用CoreBluetooth框架来与各种可穿戴设备进行通信,使用 小米手环 来进行基本的测试。
2 开发环境
1 Macbook Pro Mac OS X 10.10
2 Xcode 6.3.2
3 iPhone 5s v8.1
4 小米手环
3 基本流程
要开发蓝牙,需要对整个通讯过程有个基本了解。这里我摘录一些Apple官方的文档Core Bluetooth Programming Guide的图片来加以说明。这个文档其实对于开发的流程写的是非常的清楚,大家最好可以看一下。
3.1 可穿戴设备与iOS互联方式
从上面这幅图可以看到,我们的iOS设备是Central,用来接收数据和发送命令,而外设比如小米手环是Peripheral,向外传输数据和接收命令。我们要做的就是通过Central来连接Peripheral,然后实现数据的接收和控制指令的发送。在做到这一步之后,再根据具体的硬件,对接收到的数据进行parse解析。
3.2 可穿戴设备蓝牙的数据结构
这里用的是心率设备来做说明,每个外设Peripheral都有对应的服务Service,比如这里是心率Service。一个外设可以有不止一个s、Service。每个service里面可以有多个属性Characteristic,比如这里有两个Characteristic,一个是用来测量心率,一个是用来定位位置。
那么很关键的一点是每个Service,每个Characteristic都是用UUID来确定的。UUID就是每个Service或Characteristic的identifier。
大家可以在iPhone上下载LightBlue这个应用。可以在这里查看一些设备的UUID。
在实际使用中,我们都是要通过UUID来获取数据。这点非常重要。
在CoreBluetooth中,其具体的数据结构图如下:
4 Step-By-Step 上手BLE开发
4.1 Step 1 创建CBCentralManager
从名字上大家可以很清楚的知道,这个类是用来管理BLE的。我们也就是通过这个类来实现连接。
先创建一个:
@property (nonatomic,strong) CBCentralManager *centralM
dispatch_queue_t centralQueue = dispatch_queue_create("com.manmanlai", DISPATCH_QUEUE_SERIAL);
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:centralQueue];
然后关键在于CBCentralManagerDelegate的使用。这个之后再讲。
4.2 Step 2 寻找CBPeripheral外设
有了CBCentralManager,接下来就是寻找CBPeripheral外设,方法很简单:
[self.centralManager scanForPeripheralsWithServices:@[] options:nil];
这里的Service就是对应的UUID,如果为空,这scan所有service。
4.3 Step 3 连接CBPeripheral
在上一步中,如果找到了设备,则CBCentralManager的delegate会调用下面的方法:
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
NSLog(@"name:%@",peripheral);
if (!peripheral || !peripheral.name || ([peripheral.name isEqualToString:@""])) {
if (!self.peripheral || (self.peripheral.state == CBPeripheralStateDisconnected)) {
self.peripheral =
self.peripheral.delegate = self;
NSLog(@"connect peripheral");
[self.centralManager connectPeripheral:peripheral options:nil];
我们在这里创建了一个CBPeripheral的对象,然后直接连接
CBPeripheral的对象也需要设置delegate.
4.4 Step 4 寻找Service
如果Peripheral连接成功的话,就会调用delegate的方法:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
if (!peripheral) {
[self.centralManager stopScan];
NSLog(@"peripheral did connect");
[self.peripheral discoverServices:nil];
我们这里先停止Scan,然后让Peripheral外设寻找其Service。
4.5 Step 5 寻找Characteristic
找到Service后会调用下面的方法:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
NSArray *services = nil;
if (peripheral != self.peripheral) {
NSLog(@"Wrong Peripheral.\n");
if (error != nil) {
NSLog(@"Error %@\n", error);
services = [peripheral services];
if (!services || ![services count]) {
NSLog(@"No Services");
for (CBService *service in services) {
NSLog(@"service:%@",service.UUID);
[peripheral discoverCharacteristics:nil forService:service];
我们根据找到的service寻找其对应的Characteristic。
4.6 Step 6 找到Characteristic后读取数据
找到Characteristic后会调用下面的delegate方法:
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
NSLog(@"characteristics:%@",[service characteristics]);
NSArray *characteristics = [service characteristics];
if (peripheral != self.peripheral) {
NSLog(@"Wrong Peripheral.\n");
if (error != nil) {
NSLog(@"Error %@\n", error);
self.characteristic = [characteristics firstObject];
[self.peripheral setNotifyValue:YES forCharacteristic:self.characteristic];
这里我们可以使用readValueForCharacteristic:来读取数据。如果数据是不断更新的,则可以使用setNotifyValue:forCharacteristic:来实现只要有新数据,就获取。
4.7 Step 7 处理数据
读到数据后会调用delegate方法:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
NSData *data = characteristic.
// Parse data ...
4.8 Step 8 向设备写数据
这个很简单,只要使用:
[self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
data是NSData类型。
使用小米手环实验,得到如下结果:
2015-06-10 16:52:31.607 KetherDemo[13786:1792995] scaning device
2015-06-10 16:52:33.474 KetherDemo[13786:1793032] name:&CBPeripheral: 0x, identifier = 6FF833E3-93C1-28C6-CBC0-74A706AAAE31, name = LS_SCA16, state = disconnected&
2015-06-10 16:52:33.475 KetherDemo[13786:1793032] connect peripheral
2015-06-10 16:52:37.538 KetherDemo[13786:1793031] peripheral did connect
2015-06-10 16:52:37.984 KetherDemo[13786:1793031] service:FEE7
2015-06-10 16:52:37.985 KetherDemo[13786:1793031] service:Device Information
2015-06-10 16:52:38.099 KetherDemo[13786:1793032] characteristics:(
"&CBCharacteristic: 0x, UUID = FEC8, properties = 0x20, value = (null), notifying = NO&",
"&CBCharacteristic: 0x, UUID = FEC7, properties = 0x8, value = (null), notifying = NO&"
2015-06-10 16:52:38.100 KetherDemo[13786:1793032] Kether did connect
2015-06-10 16:52:38.101 KetherDemo[13786:1793032] Kether did connect
2015-06-10 16:52:38.280 KetherDemo[13786:1793031] characteristics:(
"&CBCharacteristic: 0x, UUID = Manufacturer Name String, properties = 0x2, value = (null), notifying = NO&",
"&CBCharacteristic: 0x, UUID = Model Number String, properties = 0x2, value = (null), notifying = NO&",
"&CBCharacteristic: 0x, UUID = Serial Number String, properties = 0x2, value = (null), notifying = NO&",
"&CBCharacteristic: 0x17009eb90, UUID = Hardware Revision String, properties = 0x2, value = (null), notifying = NO&",
"&CBCharacteristic: 0x, UUID = Firmware Revision String, properties = 0x2, value = (null), notifyi``
通过上面的方法,我们就可以轻松的对BLE进行开发。实际上比想象的要简单。
【本文为原创文章,转载请注明出处:blog.csdn.net/songrotek】
相关搜索:
相关阅读:
相关频道:
Android教程最近更新您正在使用IE低版浏览器,为了您的雷锋网账号安全和更好的产品体验,强烈建议使用更快更安全的浏览器
发私信给Longye
导语:按:“蓝牙”派智能硬件,从2011年苹果iPhone 4S发布开始,几年间已经发展成业内公认的智能硬件|物联网连接标准之一。Google迟到了两年,在2013年才推出支持蓝牙4.0 BLE特性的Android 4.3。由于Android生态天然的开放性,Google一直无力推进4.3的普及,以至于Android对蓝牙4
同步到新浪微博
当月热门文章
为了您的账户安全,请
您的邮箱还未验证,完成可获20积分哟!
您的账号已经绑定,现在您可以以方便用邮箱登录分享Android 蓝牙4.0(ble)开发的解决方案
作者:请叫我小东子
字体:[ ] 类型:转载 时间:
这篇文章主要为大家分享了Android 蓝牙4.0(ble)开发的解决方案,感兴趣的小伙伴们可以参考一下
最近,随着智能穿戴式设备、智能医疗以及智能家居的普及,蓝牙开发在移动开中显得非常的重要。由于公司需要,研究了一下,蓝牙4.0在Android中的应用。
以下是我的一些总结。
1.先介绍一下关于蓝牙4.0中的一些名词吧:&&&
(1)、GATT(Gneric Attibute& Profile)
通过ble连接,读写属性类小数据Profile通用的规范。现在所有的ble应用Profile& 都是基于GATT
(2)、ATT(Attribute Protocal)
GATT是基于ATT Potocal的ATT针对BLE设备专门做的具体就是传输过程中使用尽量少的数据,每个属性都有个唯一的UUID,属性chartcteristics and Service的形式传输。
(3)、Service是Characteristic的集合。
(4)、Characteristic 特征类型。
比如,有个蓝牙ble的血压计。他可能包括多个Servvice,每个Service有包括多个Characteristic
注意:蓝牙ble只能支持Android 4.3以上的系统 SDK&=18
2.以下是开发的步骤:
2.1首先获取BluetoothManager&
代码如下:BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);&
2.2获取BluetoothAdapter
代码如下:BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();&
2.3创建BluetoothAdapter.LeScanCallback
private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() {
public void onLeScan(final BluetoothDevice device, int rssi, final byte[] scanRecord) {
runOnUiThread(new Runnable() {
public void run() {
String struuid = NumberUtils.bytes2HexString(NumberUtils.reverseBytes(scanRecord)).replace("-", "").toLowerCase();
if (device!=null && struuid.contains(DEVICE_UUID_PREFIX.toLowerCase())) {
mBluetoothDevices.add(device);
} catch (Exception e) {
e.printStackTrace();
2.4.开始搜索设备。
代码如下:mBluetoothAdapter.startLeScan(mLeScanCallback);&
2.5.BluetoothDevice& 描述了一个蓝牙设备 提供了getAddress()设备Mac地址,getName()设备的名称。
2.6开始连接设备
* 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)}
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
// 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()) {
mConnectionState = STATE_CONNECTING;
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
// We want to directly connect to the device, so we are setting the
// autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress =
mConnectionState = STATE_CONNECTING;
2.7连接到设备之后获取设备的服务(Service)和服务对应的Characteristic。
// Demonstrates how to iterate through the supported GATT
// Services/Characteristics.
// In this sample, we populate the data structure that is bound to the
// ExpandableListView
// on the UI.
private void displayGattServices(List&BluetoothGattService& gattServices) {
if (gattServices == null)
String uuid =
ArrayList&HashMap&String, String&& gattServiceData = new ArrayList&&();
ArrayList&ArrayList&HashMap&String, String&&& gattCharacteristicData = new ArrayList&&();
mGattCharacteristics = new ArrayList&&();
// Loops through available GATT Services.
for (BluetoothGattService gattService : gattServices) {
HashMap&String, String& currentServiceData = new HashMap&&();
uuid = gattService.getUuid().toString();
if (uuid.contains("ba11f08c-5f14-0b0d-1080")) {//服务的uuid
//System.out.println("this gattService UUID is:" + gattService.getUuid().toString());
currentServiceData.put(LIST_NAME, "Service_OX100");
currentServiceData.put(LIST_UUID, uuid);
gattServiceData.add(currentServiceData);
ArrayList&HashMap&String, String&& gattCharacteristicGroupData = new ArrayList&&();
List&BluetoothGattCharacteristic& gattCharacteristics = gattService.getCharacteristics();
ArrayList&BluetoothGattCharacteristic& charas = new ArrayList&&();
// Loops through available Characteristics.
for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
charas.add(gattCharacteristic);
HashMap&String, String& currentCharaData = new HashMap&&();
uuid = gattCharacteristic.getUuid().toString();
if (uuid.toLowerCase().contains("cd01")) {
currentCharaData.put(LIST_NAME, "cd01");
} else if (uuid.toLowerCase().contains("cd02")) {
currentCharaData.put(LIST_NAME, "cd02");
} else if (uuid.toLowerCase().contains("cd03")) {
currentCharaData.put(LIST_NAME, "cd03");
} else if (uuid.toLowerCase().contains("cd04")) {
currentCharaData.put(LIST_NAME, "cd04");
currentCharaData.put(LIST_NAME, "write");
currentCharaData.put(LIST_UUID, uuid);
gattCharacteristicGroupData.add(currentCharaData);
mGattCharacteristics.add(charas);
gattCharacteristicData.add(gattCharacteristicGroupData);
mCharacteristicCD01 = gattService.getCharacteristic(UUID.fromString("0-805f9b34fb"));
mCharacteristicCD02 = gattService.getCharacteristic(UUID.fromString("0-805f9b34fb"));
mCharacteristicCD03 = gattService.getCharacteristic(UUID.fromString("0-805f9b34fb"));
mCharacteristicCD04 = gattService.getCharacteristic(UUID.fromString("0-805f9b34fb"));
mCharacteristicWrite = gattService.getCharacteristic(UUID.fromString("0-805f9b34fb"));
//System.out.println("=======================Set Notification==========================");
// 开始顺序监听,第一个:CD01
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD01, true);
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD02, true);
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD03, true);
mBluetoothLeService.setCharacteristicNotification(mCharacteristicCD04, true);
2.8获取到特征之后,找到服务中可以向下位机写指令的特征,向该特征写入指令。
public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
mBluetoothGatt.writeCharacteristic(characteristic);
2.9写入成功之后,开始读取设备返回来的数据。
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentA
//System.out.println("=======status:" + status);
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
Log.w(TAG, "onServicesDiscovered received: " + status);
//从特征中读取数据
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//System.out.println("onCharacteristicRead");
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
//向特征中写入数据
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//System.out.println("--------write success----- status:" + status);
* when connected successfully will callback this method this method can
* dealwith send password or data analyze
*当连接成功将回调该方法
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
if (characteristic.getValue() != null) {
//System.out.println(characteristic.getStringValue(0));
//System.out.println("--------onCharacteristicChanged-----");
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
//System.out.println("onDescriptorWriteonDescriptorWrite = " + status + ", descriptor =" + descriptor.getUuid().toString());
UUID uuid = descriptor.getCharacteristic().getUuid();
if (uuid.equals(UUID.fromString("0-805f9b34fb"))) {
broadcastUpdate(ACTION_CD01NOTIDIED);
} else if (uuid.equals(UUID.fromString("0-805f9b34fb"))) {
broadcastUpdate(ACTION_CD02NOTIDIED);
} else if (uuid.equals(UUID.fromString("0-805f9b34fb"))) {
broadcastUpdate(ACTION_CD03NOTIDIED);
} else if (uuid.equals(UUID.fromString("0-805f9b34fb"))) {
broadcastUpdate(ACTION_CD04NOTIDIED);
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
//System.out.println("rssi = " + rssi);
----------------------------------------------
//从特征中读取数据
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
//System.out.println("onCharacteristicRead");
if (status == BluetoothGatt.GATT_SUCCESS) {
broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
2.10、断开连接
* Disconnects an existing connection or cancel a pending connection. The
* disconnection result is reported asynchronously through the
* {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
* callback.
public void disconnect() {
if (mBluetoothAdapter == null || mBluetoothGatt == null) {
Log.w(TAG, "BluetoothAdapter not initialized");
mBluetoothGatt.disconnect();
2.11、数据的转换方法
// byte转十六进制字符串
public static String bytes2HexString(byte[] bytes) {
String ret = "";
for (byte aByte : bytes) {
String hex = Integer.toHexString(aByte & 0xFF);
if (hex.length() == 1) {
hex = '0' +
ret += hex.toUpperCase(Locale.CHINA);
* 将16进制的字符串转换为字节数组
* @param message
* @return 字节数组
public static byte[] getHexBytes(String message) {
int len = message.length() / 2;
char[] chars = message.toCharArray();
String[] hexStr = new String[len];
byte[] bytes = new byte[len];
for (int i = 0, j = 0; j & i += 2, j++) {
hexStr[j] = "" + chars[i] + chars[i + 1];
bytes[j] = (byte) Integer.parseInt(hexStr[j], 16);
大概整体就是如上的步骤,但是也是要具体根据厂家的协议来实现通信的过程。
就拿一个我们项目中的demo说一下。
一个蓝牙ble的血压计。 上位机---手机& 下位机 -- 血压计
1.血压计与手机连接蓝牙之后。
2.上位机主动向下位机发送一个身份验证指令,下位机收到指令后开始给上位做应答,
3.应答成功,下位机会将测量的血压数据传送到上位机。
4.最后断开连接。
希望本文对大家学习Android蓝牙技术有所帮助。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具}

我要回帖

更多关于 蓝牙4.0支持几个设备 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信