天天看点

iOS蓝牙4.0开发流程iOS 蓝牙4.0与智能硬件之间的交互

iOS 蓝牙4.0与智能硬件之间的交互

本文档主要讲述iOS苹果手机通过蓝牙4.0与智能硬件之间的交互。也就是苹果设备对智能硬件进行扫描、连接、发命令、以及接收反馈等操作:

  • coreBluetooth框架
  • 具体使用方法

CoreBluetooth.framework

CoreBluetooth.framework 是苹果给开发者提供的蓝牙4.0开发框架。其中包含了玉智能硬件交互的相关API。其中主要包含:

  • CBCentralManager (中心设备) 也就是iPhone、iPad等设备。
  • CBPeripheral (外围设备) 智能硬件设备,如:智能手环、智能电子秤、智能体温计等等市场上的智能硬件。

    利用以上的两个类来完成iOS设备与智能硬件之间的操作。

初始化CBCentral

不管是什么框架初始化是最基本的,初始化如下:

#import<CoreBluetooth/CoreBluetooth.h>
@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
           

使用方法

1、检查设备是否已开启蓝牙

首先,要想与设备连接,第一件事情就是要先判断目前蓝牙开关是否开启。当然如果是关着的,并且程序内已有蓝牙权限的情况下系统也会提醒的。

- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
    switch (central.state) {
        case CBCentralManagerStatePoweredOn:
            //蓝牙设备已开启
            break;
        case CBManagerStatePoweredOff:
            //蓝牙设备已关闭
            break;
        case CBManagerStateUnsupported:
            //设备不支持的状态
            break;
        case CBManagerStateResetting:
            //设备正在重置
            break;
        default:
            break;
    }
}
           

2、扫描与停止扫描(CBPeripheral)

确认好蓝牙设备已经开启,下面进行扫描周围的蓝牙设备。

注:开启扫描之前清空掉之前扫描过的设备数组
- (void)ScanDevice
{
    if(self.foundPeripheralsArray.length > ){
        [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];
}
           

3、连接与断开

找到了要连接的设备之后

- (void)ConnectPeripheral:(CBPeripheral *)peripheral
{
    for(int i = ; i < ; 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.用户主动去断开连接
    */
}
           

4、扫描服务

扫描设备的服务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];
    }
}
           

5、扫描特征

扫描特征的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地址。

6、数据交互

特征值发生变化时的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(, )] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[value substringWithRange:NSMakeRange(, )] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[value substringWithRange:NSMakeRange(, )] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[value substringWithRange:NSMakeRange(, )] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[value substringWithRange:NSMakeRange(, )] uppercaseString]];
        [macString appendString:@":"];
        [macString appendString:[[value substringWithRange:NSMakeRange(, )] uppercaseString]];        
    }
}
           

常用的命令格式

  • Write(写入)
  • Read(读取)
  • Notification(通知)

Write(写入)

Read(读取)

Notification(通知)