CoreBluetooth的API是基于BLE4.0的标准的,从iphone4s往后的设备支持,还有iPhone iOS6的模拟器也支持。
一,外设(Peripheral)和中央(Central)
CoreBluetooth框架的核心就是peripheral(外设)和central(中心)。
比如,通过手机和智能手表通信,那么手机就是Central,手表就是Peripheral。可以认为外设是一个广播数据的设备,他广播到外部世界说他这儿有数据,并且也说明了能提供的服务。另一边,中央开始扫描附近有没有服务,如果中央发现了想要的服务,就会请求连接该外设,一旦连接建立成功,两个设备之间就开始交换传输数据了。
在具体的使用场景下,每一个外设都通过唯一的设备UUID来彼此区分,也可以保存下来作为重连的凭据,在第四部分具体说明。
二,服务(Service)和特征值(Characteristic)
每个BLE4.0设备必然包含一个或多个服务,每个服务下面又包含若干个特征。特征是与外界交互的最小单位。比如说一只智能手表,用特征值A来描述自己的出厂信息,用特征值B来收发数据等。
服务和特征值都是用UUID来唯一标识的,UUID是一个16bit或者128bit的值。国际蓝牙组织为一些很典型的设备(比如测量心跳和血压的设备)规定了标准的service UUID,当然还有很多设备并不在这个标准列表里,比如我在开发中用到的智能手表,“6e400001-b5a3-f393-e0a9-e50e24dcca9e”用来读写手表信息,“00001530-1212-efde-1523-785feabcd123”用来进行ota升级。
三,BLE通信实现流程
1,建立中心角色
1
2
3
4
5
|
#import
CBCentralManager *manager;
manager = [[CBCentralManager alloc] initWithDelegate:
self
queue:
nil
];
|
2,扫描外设(discover)
[manager scanForPeripheralsWithServices:nil options:options];
3,连接外设(connect)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
- (
void
)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(
NSDictionary
*)advertisementData RSSI:(
NSNumber
*)RSSI
{
if
([peripheral.name isEqualToString:BLE_SERVICE_NAME]){
[
self
connect:peripheral];
}
}
-(
BOOL
)connect:(CBPeripheral *)peripheral
{
self
.manager.delegate =
self
;
[
self
.manager connectPeripheral:peripheral
options:[
NSDictionary
dictionaryWithObject:[
NSNumber
numberWithBool:
YES
] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
}
|
4,扫描外设中的服务和特征值(discover)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
- (
void
)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog
(@
"Did connect to peripheral: %@"
, peripheral);
_testPeripheral = peripheral;
[peripheral setDelegate:
self
];
//查×××
[peripheral discoverServices:
nil
];
}
- (
void
)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(
NSError
*)error
{
NSLog
(@
"didDiscoverServices"
);
if
(error)
{
NSLog
(@
"Discovered services for %@ with error: %@"
, peripheral.name, [error localizedDescription]);
if
([
self
.delegate respondsToSelector:
@selector
(DidNotifyFailConnectService:withPeripheral:error:)])
[
self
.delegate DidNotifyFailConnectService:
nil
withPeripheral:
nil
error:
nil
];
return
;
}
for
(CBService *service in peripheral.services)
{
//发现服务
if
([service.UUID isEqual:[CBUUID UUIDWithString:UUIDSTR_ISSC_PROPRIETARY_SERVICE]])
{
NSLog
(@
"Service found with UUID: %@"
, service.UUID);
//查找特征值
[peripheral discoverCharacteristics:
nil
forService:service];
break
;
}
}
}
- (
void
)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(
NSError
*)error
{
if
(error)
{
NSLog
(@
"Discovered characteristics for %@ with error: %@"
, service.UUID, [error localizedDescription]);
[
self
error];
return
;
}
NSLog
(@
"服务:%@"
,service.UUID);
for
(CBCharacteristic *characteristic in service.characteristics)
{
//发现特征
if
([characteristic.UUID isEqual:[CBUUID UUIDWithString:@
"xxxxxxx"
]]) {
NSLog
(@
"监听:%@"
,characteristic);
//监听特征值
[
self
.peripheral setNotifyValue:
YES
forCharacteristic:characteristic];
}
}
}
|
5,与外设做数据交互(读 与 写)
读
1
2
3
4
5
6
7
8
9
10
11
12
|
- (
void
)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(
NSError
*)error
{
if
(error)
{
NSLog
(@
"Error updating value for characteristic %@ error: %@"
, characteristic.UUID, [error localizedDescription]);
self
.error_b = BluetoothError_System;
[
self
error];
return
;
}
[
self
decodeData:characteristic.value];
}
|
写
1
2
3
4
5
|
NSInteger
time = [[
NSDate
date] timeIntervalSince1970];
//时间戳
NSMutableData
* data = [
NSMutableData
data];
[data appendBytes:&time length:4];
[
self
.peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
|
读写数据需要考虑具体的使用场景,比如Data,Byte,bit的转换,数据字节序的大小端,数据是否分包。以及对于外设的某些信息的判断:比如说,你要交互的特征,它的properties的值是0x10,表示你只能用订阅的方式来接收数据:
[_testPeripheral setNotifyValue:YES forCharacteristic:_readCharacteristic];
四,重连外设(Retrieve)
当外设已处于连接状态,或者与手机配对的状态下,是无法直接通过扫描发现外设的,CoreBluetooth提供了重连恢复的API,它有两种方式,返回值都是外设Peripheral数组:
1.retrievePeripheralsWithIdentifiers,参数是设备的UUID
2.retrieveConnectedPeripheralsWithServices,参数是特定服务的UUID
1
2
3
4
5
6
7
|
NSUUID
*
uuid
= [[
NSUUID
alloc] initWithUUIDString:uuidString1];
[uuidArray addObject:(
id
)
uuid
];
if
(uuidArray.count != 0)
{
NSArray
* arr = [_bleCentralManager retrievePeripheralsWithIdentifiers:uuidArray];
}
|
原文出处:http://www.cnblogs.com/clumsy1006/p/5251992.html