本文档主要讲述iOS苹果手机通过蓝牙4.0与智能硬件之间的交互。也就是苹果设备对智能硬件进行扫描、连接、发命令、以及接收反馈等操作:
CoreBluetooth.framework 是苹果给开发者提供的蓝牙4.0开发框架。其中包含了玉智能硬件交互的相关API。其中主要包含:
不管是什么框架初始化是最基本的,初始化如下:
#import
@implementation BluetoothManager
-(id)init
{
self = [super init];
if(self != null)
{
self.centralManager = [[CBCentralManager alloc] initWithDelegate:nil queue:nil];
self.centralManager.delegate = self;
//扫描到的设备集合
self.foundPeripheralsArray = [NSMutableArray array];
//连接到的设备集合
self.connectPeripheralsArray = [NSMutableArray array];
...
}
return self;
}
@end
首先,要想与设备连接,第一件事情就是要先判断目前蓝牙开关是否开启。当然如果是关着的,并且程序内已有蓝牙权限的情况下系统也会提醒的。
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) {
case CBCentralManagerStatePoweredOn:
//蓝牙设备已开启
break;
case CBManagerStatePoweredOff:
//蓝牙设备已关闭
break;
case CBManagerStateUnsupported:
//设备不支持的状态
break;
case CBManagerStateResetting:
//设备正在重置
break;
default:
break;
}
}
确认好蓝牙设备已经开启,下面进行扫描周围的蓝牙设备。
注:开启扫描之前清空掉之前扫描过的设备数组
- (void)ScanDevice
{
if(self.foundPeripheralsArray.length > 0){
[self.foundPeripheralsArray removeAllObjects];
}
//扫描外围设备
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
有开启扫描,自然也有停止扫描
-(void)StopScanDevice
{
//停止扫描
[self.centralManager stopScan];
}
扫描回调的delegate函数
如centralManager的delegate已开启。扫描到的设备都会进入下面的函数
/**
* 发现了设备。
*
* @param central 中央设备
* @param peripheral 外围设备
* @param advertisementData 广播数据
* @param RSSI 信号强度
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
//一般进行过滤掉无关设备的操作
//过滤完无关的设备之后,过滤掉重复的设备并加入到数组里
//如果只连接特定的设备,找到之后直接连接
[self ConnectPeripheral:peripheral];
}
找到了要连接的设备之后
- (void)ConnectPeripheral:(CBPeripheral *)peripheral
{
for(int i = 0; i < 5; i++)
{
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
注:为什么要发5次之多,这是为了能更加稳定的与设备进行连接。因为发一次的话,有些时候是收不到的。体会会很差。所以这里面要尝试发很多条保证让设备收到这个命令。
连接设备的delegate函数
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
//设备已经连接成功了,不需要再连接其他设备就停止扫描
[self StopScanDevice];
peripheral.delegate = self;
//扫描设备的服务
[peripheral discoverServices:nil];
}
与连接设备相反也有失去连接的时候也有对应的函数
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
//失去了与外围设备的的连接,所以在这里要重新开启扫描来找连接过的设备
[self ScanDevice];
/*
能进入此函数说明有两种情况
1.是因为信号不好与设备断开了连接
2.用户主动去断开连接
*/
}
扫描设备的服务delegate函数
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
BOOL found = NO;
for (CBService *s in peripheral.services)
{
if ([s.UUID isEqual:[CBUUID UUIDWithString:@"XXXX"]])
{
found = YES;
break;
}
}
//如果找到了服务,继续扫描服务下的特征值,没有找到就断开与设备的连接
if(found)
{
for (CBService *s in peripheral.services)
{
[peripheral discoverCharacteristics:nil forService:s];
}
}
else
{
[self.centralManager cancelPeripheralConnection:peripheral];
}
}
扫描特征的delegate函数
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if([service.UUID isEqual:[CBUUID UUIDWithString:@"XXXX"]])
{
//发送命令
}
else if([service.UUID isEqual:[CBUUID UUIDWithString:@"180A"]])
{
//iOS可以通过这个特征值来获取设备的MAC地址
for(CBCharacteristic * characteristic in service.characteristics)
{
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A23"]])
{
[peripheral readValueForCharacteristic:characteristic];
}
}
}
}
注:与Android不一样iOS是无法从广播上直接获取设备的MAC地址所以通过设备的某个特殊服务下面的特征值来获取MAC地址。
特征值发生变化时的delegate
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
//接收到的特征值
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"XXXX"]])
{
//通过UUID来区分它的具体功能。
}
else if([characteristic.UUID isEqual:[CBUUID UUIDWithString:@"2A23"]])
{
//在这里获取到了设备的MAC地址,不过并不是按照顺序来的。所以要再对数据进行处理
NSString *value = [NSString stringWithFormat:@"%@",characteristic.value];
NSMutableString *macString = [[NSMutableString alloc] init];
[macString appendString:[[value substringWithRange:NSMakeRange(16, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(14, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(12, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(5, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(3, 2)] uppercaseString]];
[macString appendString:@":"];
[macString appendString:[[value substringWithRange:NSMakeRange(1, 2)] uppercaseString]];
}
}
- Write(写入)
- Read(读取)
- Notification(通知)
Write(写入)
- (void)writeValue:(NSData *)data forCharacteristic:(CBCharacteristic *)characteristic type:(CBCharacteristicWriteType)type;
Read(读取)
- (void)readValueForCharacteristic:(CBCharacteristic *)characteristic;
Notification(通知)
- (void)setNotifyValue:(BOOL)enabled forCharacteristic:(CBCharacteristic *)characteristic;