iOS-蓝牙简介及CoreBluetooth.framework的使用

1.BLE
最新的蓝牙4.0以其低功耗著称,所以一般也叫BLE(Bluetooth Low Energy)。iOS 有两个框架支持蓝牙与外设连接。一个是 ExternalAccessory,从ios3.0就开始支持,也是在iphone4s出来之前用的比较多的一种模式,但是它有个不好的地方,External Accessory需要拿到苹果公司的MFI认证。另一个框架则是本文要介绍的CoreBluetooth,在iphone4s开始支持,专门用于与BLE设备通讯(因为它的API都是基于BLE的)。这个不需要MFI,并且现在很多蓝牙设备都支持4.0,所以也是在IOS比较推荐的一种开发方法。蓝牙4.0协议从iPhone 4s 以上开始支持, iPad 3.0以上 iPad Mini 及以上版本支持.
Core Bluetooth framework可以让你的iOS和Mac apps与Bluetooth Low Energy 设备(简写BLE)交流。这些设备包括心率监测器,数字体温计,等等。Core Bluetooth framework是一个对Bluetooth4.0 specification的抽象,并定义了一系列容易使用的协议来和BLE设备通信。

2.Central和Peripheral
Central:就像一个老板,它想要从一群它的员工中得到信息来完成特定的任务。它能搜索设备发出的广播packets,
peripheral:就像员工,它收集并发布数据给需要这些数据的设备。广播是peripheral基本的体现其存在的方式,广播包含数据的packets,例如peripheral的名字,或者peripheral收集的一些其他数据。若是一个心率监测器则它的packet中也提供心跳/分钟(BPM)这样的数据。
关系如图:
这里写图片描述

3.设备数据结构:
advertising packets是非常小的不会包括大量的信息.所以一个Central需要连接到设备来获得更多的可用信息.
所以,central一连接到一个设备,就需要选择它感兴趣的数据.在BLE数据是封装在services和characteristics中.
service是一个描述一个设备具体功能和特征的数据集合.一个service的例子是心率监测器从心率传感器发出心律数据.一个设备可以不止一个service.
characteristic提供一个peripheral的service的更具体的内容.
下面的图示描述了service和characteristic的关系:
这里写图片描述
一旦central与设备建立了连接,central就能自由获取所有的service和characteristic的值或读写一些service的characteristic的value.

4.CBPeripheral,CBService and CBCharacteristic
在CoreBluetooth framework,一个CBPeripheral对象代表一个设备.一个设备的service用CBService对象来表示.
NOTE:有关蓝牙标准可以参考https://developer.bluetooth.org/Pages/default.aspx.
Centrals由CBCentralManager对象表示用来搜索和连接peripheral设备.
CBPeripheral,CBService,CBCharacteristic关系如图:
这里写图片描述
每一个service和characteristic都有一个唯一的标识符UUID.UUID是16或128位的值,但若你创建的是client-server(central-peripheral)应用,那么你就需要创建你自己的128位UUID.你也需要保证不要和其他的services的UUID冲突.
service的UUID参考链接:https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx

5.实际应用中如何写代码:

NSArray *services = @[[CBUUID UUIDWithString:POLARH7_HRM_HEART_RATE_SERVICE_UUID],[CBUUID UUIDWithString:POLARH7_HRM_DEVICE_INFO_SERVICE_UUID]];
//1>建立一个中心.第二个参数为nil表示将要运行于主线程上.
    _centralManage = [[CBCentralManager alloc]initWithDelegate:self queue:nil options:nil];
//我们需要实现CBCentralManagerDelegate协议来允许代理监测发现,连接,检索设备.
//2>CBCentralManager对象初始化完毕后自动调用此方法;
- (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBCentralManagerStatePoweredOff:
            //表示苹果设备的蓝牙没有手动打开
            break;
        case CBCentralManagerStatePoweredOn:
            //表示苹果设备的蓝牙已经打开并可以使用
            //此时我们开始搜索那些广播包括某些services的周围设备,若第二个参数为nil则返回所有的发现的peripherals.@seealso - (void)stopScan;
            [central scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_UUID]] options:nil];
            break;
        case CBCentralManagerStateResetting:
            NSLog(@"CBCentralManagerStateResetting");
            break;
        case CBCentralManagerStateUnauthorized:
            NSLog(@"CBCentralManagerStateUnauthorized");
            break;
        case CBCentralManagerStateUnknown:
            NSLog(@"CBCentralManagerStateUnknown");
            break;
        case CBCentralManagerStateUnsupported:
            NSLog(@"CBCentralManagerStateUnsupported");
            break;
        default:
            break;
    }
}
//3>这个方法在搜索的过程中,每发现一个peripheral就调用此方法一次
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
    [peripherals addObject:peripheral];//保存搜索到的设备;
    NSString *str = [NSString stringWithFormat:@"DiscoveredPeripheral[%u]:%@",(peripherals.count-1), peripheral.name];
    NSLog(@"%@",str);//peripheral的名字
    //获取advertisementData中的值.
    NSString *localName = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
    NSLog(@"%@", advertisementData);
    NSLog(@"%@", RSSI);//Received Signal Strength Indication接收的信号强度指示,可以用来测定信号点与接收点的距离.值的单位是:dBm,当值为127时表示不可用.在此前提下我们可以设定当离peripheral足够近的时候,激发某些操作.
}
//4>连接特定的peripheral;@seealso - (void)cancelPeripheralConnection:(CBPeripheral *)peripheral;
[_centralManage connectPeripheral:[peripherals lastObject] options:nil];
//4.1>若连接成功了
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    //设置代理
    peripheral.delegate = self;
    //发现某些服务,若参数为nil则发现所有服务.
    [peripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
}
//4.2>若连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;
//4.3>若连接断开成功.
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error;
//我们需要实现CBPeripheralDelegate协议来监测发现,搜索与远程设备service的交互.
//5>成功发现服务,当每发现一个服务时,调用下面方法一次.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    //发现某peripheral的所有服务的所有特征.
    for (NSInteger i = 0; i < peripheral.services.count; i++) {
        NSString *str = [NSString stringWithFormat:@"DiscoveredService[%lu]:%@", (long)i, [peripheral.services objectAtIndex:i]];
        NSLog(@"%@", str);
        [peripheral discoverCharacteristics:nil forService:[peripheral.services objectAtIndex:i]];
    }
}
//6>成功发现特征,对于每个服务的每个特征被发现时都调用此方法一次.
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {    
    for (NSInteger i = 0; i < service.characteristics.count; i++) {
        CBCharacteristic *characteristic = [service.characteristics objectAtIndex:i];
        NSLog(@"这是第--%u--个特征", i);

        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:Characteristic1_UUID]]) {
            NSLog(@"properties=%u", characteristic.properties);

            NSData *data = [characteristic value];//1
            if (data.length > 0) {
            //注意此处是如何将characteristic的value的值转换为字符串.显示出来.
                const uint8_t *reportData1 = (const uint8_t *)data.bytes;
                uint32_t bpm = 0;
                bpm = CFSwapInt32LittleToHost(*(uint32_t *)(&reportData1[0]));
                NSString* text = [NSString stringWithFormat:@"%x", bpm];
                NSLog(@"Value=%@---对应的Tag:%@",characteristic.value, text);
            }
            else {
                NSLog(@"value=%@",characteristic.value);
            }

            NSLog(@"descriptors=%@",characteristic.descriptors);
            NSLog(@"isBroadcasted=%hhd",characteristic.isBroadcasted);
            NSLog(@"isNotifying=%hhd",characteristic.isNotifying);
        }

        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:Characteristic2_UUID]]) {
            NSLog(@"properties=%u", characteristic.properties);

            if (characteristic.value.length > 0) {
                NSData *data = [characteristic value];//1
                const uint8_t *reportData1 = (const uint8_t *)data.bytes;
                uint32_t bpm = 0;
                bpm = CFSwapInt32LittleToHost(*(uint32_t *)(&reportData1[0]));
                NSString* text = [NSString stringWithFormat:@"%x", bpm];
                NSLog(@"Value=%@---对应的Tag:%@",characteristic.value, text);
            }
            else {M
                NSLog(@"value=%@",characteristic.value);
            }

            NSLog(@"descriptors=%@",characteristic.descriptors);
            NSLog(@"isBroadcasted=%hhd",characteristic.isBroadcasted);
            NSLog(@"isNotifying=%hhd",characteristic.isNotifying);
        }

        //设置通知;当参数2中的characteristic的值发生改变时或读characteristic的值时([peripheral readValueForCharacteristic:characteristic])调用- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;当停止对应的通知时调用- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];

        NSString *str = [NSString stringWithFormat:@"DiscoveredCharacteristic[%u]:%@", i, characteristic];
        NSLog(@"%@", str);
    }
}

There is an example :here

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值