api ble ios
iOS BLe
2016-07-22 15:55:24 shb2058 阅读数 541

http://blog.csdn.net/vnanyesheshou/article/details/50572860

最近做的项目主要是iphone与平常的一些设备进行蓝牙连接,通信等功能。所以整理了一下蓝牙方面的一些知识。

iOS蓝牙开发主要有种方式。

1 GameKit.framework   iOS7之前的蓝牙通讯框架,从iOS7开始过期,但是目前多数应用还是基于此框架。只能用于iOS设备之间,多用于游戏。

2 MultipeerConnectivity.framework  iOS7开始引入的新的蓝牙通讯开发框架,用于取代GameKit。也只能用于iOS设备间,主要用于共享文件。

3 CoreBluetooth.framework  功能强大的蓝牙开发框架,要求设备必须支持蓝牙4.0,可与其他第三方设备进行通信。

4 ExternalAccessory.framework 也可于第三方蓝牙设备交互,但是蓝牙设备必须经过MFI认证,需要有苹果的协议,这就有一定的局限性。

对比明显可以看到CoreBluetooth这个比较好用,并且功能强大,不再局限于iOS设备之间进行传输数据,你可以通过iOS设备向Android、Windows Phone以及其他安装有蓝牙4.0芯片的智能设备传输,因此也是目前智能家居、无线支付等热门智能设备所推崇的技术。我这里介绍一下这个的使用。


CoreBluetooth.framework

从iOS6开始苹果推出了此框架,它专门用于与BLE4.0设备通信,不仅限于iOS设备。

CoreBluetooth框架的核心其实是两个东西,peripheral和central, 可以理解成外设和中心。类似于C/S设计(客户端和服务端),外围设备可以理解为客户端,中央设备可以当作服务端。

外围设备和中央设备在CoreBluetooth中使用CBPeripheralManager和CBCentralManager表示。

CBPeripheralManager:外围设备通常用于发布服务、生成数据、保存数据。外围设备发布并广播服务,告诉周围的中央设备它的可用服务和特征。

CBCentralManager:中央设备使用外围设备的数据。中央设备扫描到外围设备后会就会试图建立连接,一旦连接成功就可以使用这些服务和特征。

外围设备和中央设备之间交互的桥梁是服务(CBService)和特征(CBCharacteristic),二者都有一个唯一的标识UUID(CBUUID类型)来唯一确定一个服务或者特征,每个服务可以拥有多个特征。



左侧表示中央设备,右侧为外围设备。

CBCentralManager  中央设备管理,使用外围设备的数据。中央设备扫描到外围设备后会就会试图建立连接,一旦连接成功就可以使用这些服务和特征。

CBPeripheralManager  外围设备管理,通常用于发布服务、生成数据、保存数据。外围设备发布并广播服务,告诉周围的中央设备它的可用服务和特征。

CBPeripheral  外围设备。

CBCentral      中央设备。

CBServiceCBMutableServic    服务,其中CBMutableServic CBService的子类,只多了一个初始化的方法和两个变量。

CBCharacteristicCBMutableCharacteristic  特征。其中CBMutableCharacteristicCBCharacteristic的子类,多了一个初始化的方法和几个变量。
CBUUID         uuid帮助类。

CBATTRequest      中央发出的读或者写的请求。  


主要说一下中央设备的使用。

iOS 中蓝牙操作主要放在BluetoothManager/GABluetoothManager类中。
该类遵循<CBCentralManagerDelegate,CBPeripheralDelegate>协议。

CBCentralManagerDelegate 中的方法主要有中央的可用性,扫描到的外围设备,与外围设备连接状态。

CBPeripheralDelegate  中主要是发现服务、特征、描述,读写特征和描述。

初始化中央管理器

[objc] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. self.cbCM = [[CBCentralManager alloc] init];  
  2. self.cbCM.delegate = self;  

扫描外围设备

[objc] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],CBCentralManagerScanOptionAllowDuplicatesKey, nil nil];  
  2. self.cbCM scanForPeripheralsWithServices:nil options:dic];  

scanForPeripheralsWithServices方法

第一个参数为想要扫描指定uuid service的外围设备,nil是扫描所有。

第二个参数 扫描选项,

CBCentralManagerScanOptionAllowDuplicatesKey 当指定其为YES时,说明过滤功能是不启用的,也就是说centra每次都能接受到来自peripherals的广播包数据,这样的话对电池的寿命会有很大的影响。当设定为NO是每次寻找都会合并相同的peripheral。


/**

 *  发现外围设备

 *  @param central           中心管理

 *  @param peripheral        外围设备

 *  @param advertisementData 广播数据

 *  @param RSSI              信号质量(信号强度)

 */

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

测试参数peripheral中的name不能保证是最新的名字(当一个外围设备改变蓝牙名后),所以我们用广播中的数据

advertismentData,广播中的数据是最新的,可以通过广播蓝牙名和service 的uuid。


[self.cbCM stopScan];//停止扫描

连接外围设备

[objc] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. [self.cbCM connectPeripheral:device.peripheral  
  2.     options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];  

options中可以设置一些连接设备的初始属性键值如下

NSString *const CBConnectPeripheralOptionNotifyOnConnectionKey;

APP被挂起时,这时如果APP连接到peripheral时,是否要给APP一个提示框,当然是在APP支持后台运行的前期下。

NSString *const CBConnectPeripheralOptionNotifyOnDisconnectionKey;

APP处于挂起状态时,恰好在这个时候断开连接,要不要给APP一个断开提示。这种情况只有指定了该APP指定在后台能够运行时才显示。

NSString *const CBConnectPeripheralOptionNotifyOnNotificationKey;

App处于挂起状态时,是否接受到所有的来自peripheral的包都要弹出提示框。当然这个key值也是以APP能够在后台运行为前期的。


//连接外围设备失败

- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error


// 连接到外围设备

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral


发现服务、特征、描述

连接成功后,发现services

设置peripheral的delegate为self非常重要,否则,didDiscoverServices无法回调

peripheral.delegate = self;

[peripheral discoverServices:nil];参数指定service uuid,nil时则不限制uuid。
//已搜索到services

- (void) peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
验证service uuid 是否是我们需要的uuid,如果正确则发现特征。

[peripheral discoverCharacteristics:nil forService:service];可以指定characteristic的uuid。
//已搜索到Characteristics

- (void) peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error

验证characteristic uuid是否正确,正确则发送数据,订阅特征。

通信

验证characteristic正确后,先订阅此characteristic
[peripheral setNotifyValue:YES forCharacteristic:c];这样就可以监听characteristic 值的改变了,改变时会回调下面方法:
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError*)error
然后发送数据给外围设备。
NSString *str = [NSString stringWithFormat:@"<%@>%@", (hasbond ? @"connect" : @"bind"), self.myUUID];
 NSData *data =[str dataUsingEncoding:NSUTF8StringEncoding];
[peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
参数CBCharacteristicWriteWithResponse,则需要外围设备回应write请求。

2017-05-25 15:33:50 Melissa_htt 阅读数 401

iOS BLE开发

Android BLE开发的原理是一样的.手机做中心设备,iOS开发BLE:

蓝牙权限

在info.polist中添加权限Privacy - Bluetooth Peripheral Usage Description

封装单例

@interface XBBleHelper ()<CBCentralManagerDelegate,CBPeripheralDelegate>
@property (nonatomic,copy) BTDiscoverCompletion discoverComplection;
@property (nonatomic,copy) BTDevConnectedCompletion devConnectedComplection;
@property (nonatomic,copy) BTDevDisConnectedCompletion devDisconnectedComplection;

//中心管理者
@property (nonatomic,strong) CBCentralManager *centralMgr;
//检测到的所有设备
@property (nonatomic,strong) NSMutableArray *allPeripherals;
//是否系统蓝牙打开
@property (nonatomic,assign) BOOL isLocalBleOpen;
//读数据的特征
@property (nonatomic,strong) CBCharacteristic *readCharacteristic;
//写数据的特征
@property (nonatomic,strong) CBCharacteristic *writeCharacteristic;

@end

@implementation XBBleHelper

//是否连接成功
static bool isConnected = false;

//单例
static XBBleHelper *bleHelper = nil;
+ (instancetype)shareBleHelper{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        bleHelper = [[XBBleHelper alloc]init];
    });
    return bleHelper;
}
- (instancetype)init
{
    self = [super init];
    if (self) {
        self.isLocalBleOpen = NO;
        self.centralMgr =[[CBCentralManager alloc]initWithDelegate:self queue:dispatch_get_main_queue() options:nil];
        self.peripheralArray = [NSMutableArray array];
    }
    return self;
}
//开始扫描
- (void)startSearch{
    if (!self.isLocalBleOpen) {
        return;
    }
    [self stopSearch];
    [self.centralMgr scanForPeripheralsWithServices:nil options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],CBCentralManagerScanOptionAllowDuplicatesKey, nil]];
}
//开始扫描
-(void)startSearchBTDevice:(BTDiscoverCompletion)discoverCompletion connectedCompletion:(BTDevConnectedCompletion)devConnected disconnectedCompletion:(BTDevDisConnectedCompletion)devDisconnect
{
    if (!self.isLocalBleOpen) {
        return;
    }
    //每次开始扫描之前先停止上一次的扫描,并将回调函数清空
    [self stopSearch];

    self.discoverComplection = discoverCompletion;
    self.devConnectedComplection = devConnected;
    self.devDisconnectedComplection = devDisconnect;

    [self.centralMgr scanForPeripheralsWithServices:nil options:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:NO],CBCentralManagerScanOptionAllowDuplicatesKey, nil]];
}

//停止扫描
- (void)stopSearch{
    [self.centralMgr stopScan];
    [self.peripheralArray removeAllObjects];

    self.discoverComplection = nil;
    self.devDisconnectedComplection = nil;
    self.devConnectedComplection = nil;
}
//是否连接成功
-(BOOL) isConnected
{
    return isConnected;
}
//是否本地蓝牙打开
- (BOOL)isLocalBleOpen{
    return _isLocalBleOpen;
}

//连接外设
- (void)connectPeripheralAtIndex:(NSUInteger)aIndex{
    if(self.peripheralArray.count < aIndex+1)
        return;
    CBPeripheral * peripheral = [self.peripheralArray objectAtIndex:aIndex];
    self.currentPeripheral = peripheral;
    if (peripheral.state == CBPeripheralStateConnected) {
        [self.centralMgr cancelPeripheralConnection:peripheral];
    }else{
        [self.centralMgr connectPeripheral:peripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
         [[NSNotificationCenter defaultCenter] postNotificationName:KNOTIFICATION_START_BTCONNECT object:nil];//蓝牙开始连接
    }
}
//断开蓝牙外设
- (void)disconnectCurrentBTDevice{
    if (self.currentPeripheral.state == CBPeripheralStateConnected ) {
        [self.centralMgr cancelPeripheralConnection:self.currentPeripheral];
    }
}
//设置通知
- (void)setCharacteristic:(CBCharacteristic *)characteristic toNotifyValue:(BOOL)enabled {
    [self.currentPeripheral setNotifyValue:enabled forCharacteristic:characteristic];
}
- (void)sendData:(NSData *)data{
    [self.currentPeripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithoutResponse];
}
#pragma mark --- CBCentralManagerDelegate
//centralMgr状态改变,只有设备打开后才会能扫描设备
- (void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBCentralManagerStateUnknown:
            HT_LLog(@">>>>>>>CBCentralManagerStateUnknown");
            //break;
        case CBCentralManagerStateResetting:
            HT_LLog(@">>>>>>>CBCentralManagerStateResetting");
            //break;
        case CBCentralManagerStateUnsupported:
            HT_LLog(@">>>>>>>CBCentralManagerStateUnsupported");
            //break;
        case CBCentralManagerStateUnauthorized:
            HT_LLog(@">>>>>>>CBCentralManagerStateUnauthorized");
            //break;
        case CBCentralManagerStatePoweredOff:
            HT_LLog(@">>>>>>>CBCentralManagerStatePoweredOff");
            self.isLocalBleOpen = NO;
            break;
        case CBCentralManagerStatePoweredOn:
            HT_LLog(@">>>>>>>CBCentralManagerStatePoweredOn");
            self.isLocalBleOpen = YES;
            //在此时开始扫描设备
            break;
        default:
            break;
    }

}
//当扫描到外设的时候,会进入到该方法
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI{

    if([self.peripheralArray containsObject:peripheral] || ![peripheral.name containsString:@"--"])
    {
        return;
    }
    [self.peripheralArray addObject:peripheral];
    if (self.discoverComplection){
        self.discoverComplection();//扫描到外设
    }
}

//外设连接成功
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    if (self.devConnectedComplection){
        self.devConnectedComplection();
    }
    self.currentPeripheral = peripheral;
    if (self.delegate) {
        [self.delegate bleDidConnect];
    }
    isConnected = true;
    peripheral.delegate = self;
    [peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]];

}

//外设连接失败
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
    self.currentPeripheral = nil;
    isConnected = false;

}

//外设断开连接
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
    self.currentPeripheral = nil;
    isConnected = false;
    if (self.devDisconnectedComplection) {
        self.devDisconnectedComplection();
    }
    if (self.delegate) {
        [self.delegate bleDidDisconnect];
    }
}
#pragma mark --- CBPeripheralDelegate

//扫描外设的所有服务
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error{
    if (error){
        HT_LLog(@"error:%@",[error localizedDescription]);
        return;
    }

    for (CBService *service in peripheral.services) {
        if ([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]) {
            [peripheral discoverCharacteristics:nil forService:service];
        }
    }
}

//
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(nullable NSError *)error{

}

//扫描特定服务的所有特征
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{
    if (error)
    {
        HT_LLog(@"error Discovered characteristics for %@ with error: %@", service.UUID, [error localizedDescription]);
        return;
    }

    //搜索第一个服务
    if([service.UUID isEqual:[CBUUID UUIDWithString:kServiceUUID]]){
        for (CBCharacteristic *characteristic  in service.characteristics) {
            HT_LLog(@"service:%@ characteristic:%@",service.UUID,characteristic);
            if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:kCharacteristerUUID]]) {
                if (characteristic.properties & 2) {
                    self.readCharacteristic = characteristic;
                    //通知的方式,读取这个特征的value
                    [self setCharacteristic:characteristic toNotifyValue:YES];
                }
                if (characteristic.properties & 4) {
                    self.writeCharacteristic = characteristic;
                }
            }
        }
    }
}
//读取特征的值,或者通知的方式读取特征的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{
    //接收到数据
    if(self.delegate){
      [self.delegate bleDidReceivedData:characteristic.value];
    }
}

//向特征写入值后的反馈
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{


}

- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{

}

//扫描特定特征的描述
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error{

}

//读取描述的值
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error{

}

//向描述中写入值后的反馈
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error{

}


- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral NS_AVAILABLE(NA, 6_0){

}

- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices NS_AVAILABLE(NA, 7_0){

}

- (void)peripheralDidUpdateRSSI:(CBPeripheral *)peripheral error:(nullable NSError *)error NS_DEPRECATED(NA, NA, 5_0, 8_0){

}
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error NS_AVAILABLE(NA, 8_0){

}
@end
2018-10-22 17:11:00 weixin_34247155 阅读数 21

一.关键词

  • 中央设备:中央设备用于管理外设,一个中央设备可以同时连接管理多个外设。
  • 中心设备管理(CBCentralManager):管理外设的工具,提供扫描连接外设等方法。
  • 外设(CBPeripheral):如蓝牙耳机,音响,打印机等,外设主动广播数据(advertisementData)描述其设备的基本信息,如此设备是什么,叫什么,提供什么样的服务(CBService)(类似于电台广播,不管是否有用户,都会广播信号以描述其电台信息)。
  • 外设管理(CBPeripheralManager):管理外设,给外设添加服务
  • 服务(CBService):一个外设至少有一个服务,一个服务包含多个特征,每个服务由唯一的一个UUID确定。
  • 特征(CBCharacteristic):设备间通讯的最小单元或者说是一个通讯通道,每个特征由唯一的一个UUID确定。
  • 特征值:特征存储的数据。
  • 特征属性:用于描述特征的权限,如读,写等,以下是oc特征属性的枚举:
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
    CBCharacteristicPropertyBroadcast                                               = 0x01,
    CBCharacteristicPropertyRead                                                    = 0x02,
    CBCharacteristicPropertyWriteWithoutResponse                                    = 0x04,
    CBCharacteristicPropertyWrite                                                   = 0x08,
    CBCharacteristicPropertyNotify                                                  = 0x10,
    CBCharacteristicPropertyIndicate                                                = 0x20,
    CBCharacteristicPropertyAuthenticatedSignedWrites                               = 0x40,
    CBCharacteristicPropertyExtendedProperties                                      = 0x80,
    CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)     = 0x100,
    CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)   = 0x200
};
  • 广播数据(advertisementData):用于描述外设基本信息

二.工作流程

外设工作流程

  1. 建立外设管理(CBPeripheralManager):需要实现CBPeripheralManagerDelegate协议。
  2. 新建添加服务(CBMutableService)设置服务特征(CBCharacteristic),后续通过特征通讯。
  3. 广播服务。

中心设备工作流程

  1. 建立中心设备管理(CBCentralManager):需实现CBCentralManagerDelegate,CBPeripheralDelegate协议
  2. 扫描外设。
  3. 连接外设。
  4. 扫描外设服务。
  5. 选择使用外设服务。
  6. 获取服务特征(即获取了通讯通道)。
  7. 选择使用特征进行通讯。

通讯流程

三.上代码

外设

//
//  BLECBPeripheral.h
//  BLE
//
//  Created by chenguibang on 2017/3/15.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
@interface BLECBPeripheral : NSObject<CBPeripheralManagerDelegate>
@property(nonatomic,strong) CBPeripheralManager *peripheralManager;

+(id)shared;

-(void)setup;

-(void)addSe;
-(void)adv;
@end

//
//  BLECBPeripheral.m
//  BLE
//
//  Created by chenguibang on 2017/3/15.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import "BLECBPeripheral.h"
#define kPeripheralName @"Kenshin Cui's Device" //外围设备名称
#define kServiceUUID @"C4FB2349-72FE-4CA2-94D6-1F3CB16331EE" //服务的UUID
#define kCharacteristicUUID @"6A3E4B28-522D-4B3B-82A9-D5E2004534FC" //特征的
@implementation BLECBPeripheral

+(id)shared{
    static dispatch_once_t onceToken;
    static BLECBPeripheral *per = nil;
    dispatch_once(&onceToken, ^{
        per = [[BLECBPeripheral alloc]init];
    });
    return per;
    
}

-(void)setup{
    self.peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];
}


-(void)addSe{
    CBUUID *characteristicUUID=[CBUUID UUIDWithString:kCharacteristicUUID];
    CBMutableCharacteristic *characteristicM=[[CBMutableCharacteristic alloc]initWithType:characteristicUUID properties:CBCharacteristicPropertyNotify|CBCharacteristicPropertyWriteWithoutResponse|CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable|CBAttributePermissionsWriteable|CBAttributePermissionsReadEncryptionRequired|CBAttributePermissionsWriteEncryptionRequired];
    CBUUID *serviceUUID=[CBUUID UUIDWithString:kServiceUUID];
    //创建服务
    CBMutableService *serviceM=[[CBMutableService alloc]initWithType:serviceUUID primary:YES];
    //设置服务的特征
    [serviceM setCharacteristics:@[characteristicM]];
    
    /*将服务添加到外围设备*/
    [self.peripheralManager addService:serviceM];
}


-(void)adv{
    //添加服务后开始广播
    NSDictionary *dic=@{CBAdvertisementDataLocalNameKey:kPeripheralName};//广播设置
    [self.peripheralManager startAdvertising:dic];//开始广播
}

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    
    switch (peripheral.state) {
        case CBManagerStatePoweredOn:
            NSLog(@"BLE已打开.");
        
            break;
            
        default:
            NSLog(@"BLE已打开.异常");
            break;
    }
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{
    NSLog(@"添加服务成功");
}

-(void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error{
    NSLog(@"广播成功");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{
    NSLog(@"有服务订阅特征值");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic{
    NSLog(@"有服务取消订阅特征值");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{
    NSLog(@"收到读请求");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests{
    NSLog(@"收到写请求");
    
}

@end


中央设备

//
//  BLETool.h
//  BLEOCChat
//
//  Created by chenguibang on 2017/3/14.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>

typedef void(^ErrorBlcok)(NSError* error);

@interface BLETool : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)CBCentralManager *centerManager;
@property(nonatomic,strong)NSMutableArray<CBPeripheral*> *peripherals;
@property(nonatomic,strong)NSMutableArray<CBService*> *sevices;
@property(nonatomic,strong)NSMutableArray<CBCharacteristic *>*characters;
@property(nonatomic,copy)ErrorBlcok errorBlcok;
+(id)shared;
-(void)setup;
-(void)scanfPer:(NSUInteger)timeout;
-(void)stopScanf;
-(void)connectTo:(CBPeripheral*)peripheral reuslt:(void(^)())result;
-(void)disconnect:(CBPeripheral*)peripheral;
-(void)discoverServicesFor:(CBPeripheral*)peripheral;
-(void)discoverCharactersFor:(CBService *)service In:(CBPeripheral*)peripheral;


-(void)write:(CBPeripheral*)peripheral forCharacteristic:(CBCharacteristic *)characteristic value:(NSData *)data;
@end


//
//  BLETool.m
//  BLEOCChat
//
//  Created by chenguibang on 2017/3/14.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import "BLETool.h"


#define findMeServiceUUID             [CBUUID UUIDWithString:@"1802"]
#define genericAccessServiceUUID      [CBUUID UUIDWithString:@"1800"]
#define linkLossServiceUUID           [CBUUID UUIDWithString:@"1803"]
#define deviceNameCharacteristicUUID  [CBUUID UUIDWithString:@"2A00"]
#define alertLevelCharacteristicUUID  [CBUUID UUIDWithString:@"2A06"]
#define BT_ALERT_LEVEL_NONE 0
#define BT_LEVEL_MILD 1
#define BT_ALERT_LEVEL_HIGH 2
#define BT_ALERT_LEVEL_RESERVED(LVL) LVL

@interface BLETool(){
//    CBCentralManager *centerManager;
    
}

@end

@implementation BLETool


+(id)shared{
    static dispatch_once_t onceToken;
    static BLETool *tool;
    dispatch_once(&onceToken, ^{
        tool = [[BLETool alloc]init];
        [tool setup];
    });
    return tool;
}
-(void)setup{
    
//    1.建立中心管理
    self.centerManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
    self.centerManager.delegate  = self;//设置代理
    self.peripherals = [NSMutableArray array];
    self.sevices = [NSMutableArray array];
    self.characters = [NSMutableArray array];


}

-(void)scanfPer:(NSUInteger)timeout{
    

    if (self.centerManager.isScanning) {
        [[self mutableArrayValueForKey:@"peripherals"]removeAllObjects];
        [self.centerManager stopScan];
    }
//    2.扫描外设
    [self.centerManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithInt:1],CBCentralManagerOptionShowPowerAlertKey:[NSNumber numberWithInt:1]}];
}
-(void)stopScanf{
    [self.centerManager stopScan];
}

-(void)connectTo:(CBPeripheral*)peripheral reuslt:(void(^)())result{
    if (self.centerManager.isScanning) {
        [self.centerManager stopScan];
    }
    //    3.连接外设
    if (peripheral.state != CBPeripheralStateDisconnected) {
        NSLog(@"该设备暂时不能连接");
        
        self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:1 userInfo:@{@"msg":@"外设暂时状态不可连接"}]);
    
    }else{
        [self.centerManager connectPeripheral:peripheral options:nil];
    }
    
    
}
-(void)disconnect:(CBPeripheral *)peripheral{
    [self.centerManager cancelPeripheralConnection:peripheral];
}

-(void)discoverServicesFor:(CBPeripheral*)peripheral{
    NSMutableArray *sevices = [self mutableArrayValueForKeyPath:@"sevices"];
    [sevices removeAllObjects];
    peripheral.delegate = self;
    [peripheral discoverServices:nil];
}



-(void)write:(CBPeripheral*)peripheral forCharacteristic:(CBCharacteristic *)characteristic value:(NSData *)data{
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    [peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}

-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
    
    switch (central.state) {
        case CBManagerStateUnknown:
            
            break;
        case CBManagerStateResetting:
            
            break;
            
        case CBManagerStateUnsupported:
            
            break;
            
        case CBManagerStateUnauthorized:
            
            break;
            
        case CBManagerStatePoweredOff:
            
            break;
            
        case CBManagerStatePoweredOn:
//            [central scanForPeripheralsWithServices:nil options:nil];
            break;
        default:
            break;
    }
    
    
    NSLog(@"scanState  :  %ld \n" , (long)central.state);
}

-(void)discoverCharactersFor:(CBService *)service In:(CBPeripheral*)peripheral;{
    NSMutableArray *characters = [self mutableArrayValueForKeyPath:@"characters"];
    [characters removeAllObjects];
    [peripheral discoverCharacteristics:nil forService:service];
}



//advertisementData 外设主动发送的广播数据  RSSI 信号强度单位是dbm
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    
    NSMutableArray *peripherals = [self mutableArrayValueForKeyPath:@"peripherals"];
    if (![self.peripherals containsObject:peripheral]) {
        
        [peripherals addObject:peripheral];
//        [[self mutableArrayValueForKeyPath:@"peripherals"] addObject:peripheral];
        
    }else{
      NSUInteger index =  [peripherals indexOfObject:peripheral];
        [peripherals replaceObjectAtIndex:index withObject:peripheral];
        
//        [[self mutableArrayValueForKeyPath:@"peripherals"] replaceObjectAtIndex:[self.peripherals indexOfObject:peripheral] withObject:peripheral];
        
    }
    NSLog(@"scan DisconnectPeripherals:  %@ \n",self.peripherals);
//  NSLog(@"uuid : %@\n",peripheral.identifier.UUIDString);


}

-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"连接成功");
    self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:9999 userInfo:@{@"msg":@"连接成功"}]);

}
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
    self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:9999 userInfo:@{@"msg":@"连接失败"}]);
}


-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    
}

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
     NSLog(@"发现服务");

    if (!error) {
        NSMutableArray *sevices = [self mutableArrayValueForKeyPath:@"sevices"];
        [sevices addObjectsFromArray:peripheral.services];
        for (CBService *service in peripheral.services) {
            NSLog(@"%@",service.UUID);
            [peripheral discoverCharacteristics:nil forService:service];
        }
    }else{
        self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:9999 userInfo:@{@"msg":@"查找失败"}]);
    }
    
    
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{
    NSMutableArray *characters = [self mutableArrayValueForKeyPath:@"characters"];
    [characters addObjectsFromArray:service.characteristics];
}


-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
    
}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
}

@end


2018-03-11 21:56:00 weixin_33744141 阅读数 18

今天我所记录的是CoreBlueTooth

简介:

*可用于第三方蓝牙设备交互,设备必须支持蓝牙4.0

*iPhone的设备必须是4S或者更新

*iPad设备必须是iPad mini或者更新

*iOS的系统必须是iOS 6或者更新

*蓝牙4.0以`低功耗`著称,所以一般被称为BLE(bluetooth low energy)

核心:

*CBCentralManager:中心设备(用来连接到外部设备的管家)

*CBPeripheralManager:外部设备(第三方的蓝牙4.0设备)

开发步骤:

*建立中心管家

```

// 1. 创建中心管家,并且设置代理

self.cmgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];

```

*扫描外设(discover)

```

// 2. 在代理方法中扫描外部设备

 /**

  *  scanForPeripheralsWithServices :如果传入指定的数组,那么就只会扫描数组中对应ID的设备

  *                                  如果传入nil,那么就是扫描所有可以发现的设备

  *  扫描完外部设备就会通知CBCentralManager的代理

  */

 - (void)centralManagerDidUpdateState:(CBCentralManager *)central

{

    if ([central state] == CBCentralManagerStatePoweredOn) {

        [self.cmgr scanForPeripheralsWithServices:nil options:nil];

    }

}

```

```

/**

 *  发现外部设备,每发现一个就会调用这个方法

 *  所以可以使用一个数组来存储每次扫描完成的数组

 */

- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI

{

    // 有可能会导致重复添加扫描到的外设

    // 所以需要先判断数组中是否包含这个外设

    if(![self.peripherals containsObject:peripheral]){

        [self.peripherals addObject:peripheral];

    }

}

```

*连接外设

```

/**

 *  模拟开始连接方法

 */

- (void)start

{

    // 3. 连接外设

    for (CBPeripheral *ppl in self.peripherals) {

        // 扫描外设的服务

        // 这个操作应该交给外设的代理方法来做

        // 设置代理

        ppl.delegate = self;

        [self.cmgr connectPeripheral:ppl options:nil];

    }

}

```

*扫描外设中的服务和特征

-服务和特征的关系

`每个蓝牙4.0的设备都是通过服务和特征来展示自己的,一个设备必然包含一个或多个服务,每个服务下面又包含若干个特征。`

```

/**

 *  连接外设成功调用

 */

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral

{

    // 查找外设服务

    [peripheral discoverServices:nil];

}

```

```

/**

 *  发现服务就会调用代理方法

 *

 *  @param peripheral 外设

 */

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error

{

    // 扫描到设备的所有服务

    NSArray *services = peripheral.services;

    // 根据服务再次扫描每个服务对应的特征

    for (CBService *ses in services) {

        [peripheral discoverCharacteristics:nil forService:ses];

    }

}

```

*与外设做数据交互

-在指定的特征下做相应的操作

```

/**

 *  发现服务对应的特征

 */

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error

{

    // 服务对应的特征

    NSArray *ctcs = service.characteristics;

    // 遍历所有的特征

    for (CBCharacteristic *character in ctcs) {

        // 根据特征的唯一标示过滤

        if ([character.UUID.UUIDString isEqualToString:@"根据通讯协议里面选择具备读写权限的UUID"]) {

        //进行写入数据到蓝牙设备

         Bytedata[] = {0xF0,0xE0,0x06,0x00};//一般是16进制数据写入

         NSData * dataD = [[NSData alloc] initWithBytes:data length:4];//NSData 是 <f0e00600>

         [peripheralwriteValue:dataD forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];//这个是写入数据到蓝牙设备的方法

        }

    }

}

```

*获取蓝牙返回数据

/**

 *  获取蓝牙返回数据

 */

- (void)peripheral:(CBPeripheral*)peripheral didUpdateValueForCharacteristic:(CBCharacteristic*)characteristic error:(NSError*)error

{

    if(error) {

        NSLog(@"-- error -- ");

    }

    @synchronized(self) {

        NSLog(@"didUpdateValueForCharacteristic: %@",characteristic.value);

        if(characteristic.value.length==0){

            return;}

    }

//下面这个是测试接受数据解析操作,具体看各自的蓝牙协议。

    Byte *testByte = (Byte *)[characteristic.value bytes];

    if (testByte[2] == 0x02) {

        if (testByte[3] == 0x01) {

            testdata = testByte[4];

            NSLog(@"返回数据 === %d ===",testdata);

        }

    }

}

*断开连接

```

/**

 *  断开连接

 */

- (void)stop

{

    // 断开所有连接上的外设

    for (CBPeripheral *per in self.peripherals) {

        [self.cmgr cancelPeripheralConnection:per];

    }

  //注意断开蓝牙的时候一定要设备连接上蓝牙再才断,我有过未连接上直接断开会崩溃,闪退的经历。

}

```

2018-10-22 17:11:00 weixin_34191845 阅读数 3

一.关键词

  • 中央设备:中央设备用于管理外设,一个中央设备可以同时连接管理多个外设。
  • 中心设备管理(CBCentralManager):管理外设的工具,提供扫描连接外设等方法。
  • 外设(CBPeripheral):如蓝牙耳机,音响,打印机等,外设主动广播数据(advertisementData)描述其设备的基本信息,如此设备是什么,叫什么,提供什么样的服务(CBService)(类似于电台广播,不管是否有用户,都会广播信号以描述其电台信息)。
  • 外设管理(CBPeripheralManager):管理外设,给外设添加服务
  • 服务(CBService):一个外设至少有一个服务,一个服务包含多个特征,每个服务由唯一的一个UUID确定。
  • 特征(CBCharacteristic):设备间通讯的最小单元或者说是一个通讯通道,每个特征由唯一的一个UUID确定。
  • 特征值:特征存储的数据。
  • 特征属性:用于描述特征的权限,如读,写等,以下是oc特征属性的枚举:
typedef NS_OPTIONS(NSUInteger, CBCharacteristicProperties) {
    CBCharacteristicPropertyBroadcast                                               = 0x01,
    CBCharacteristicPropertyRead                                                    = 0x02,
    CBCharacteristicPropertyWriteWithoutResponse                                    = 0x04,
    CBCharacteristicPropertyWrite                                                   = 0x08,
    CBCharacteristicPropertyNotify                                                  = 0x10,
    CBCharacteristicPropertyIndicate                                                = 0x20,
    CBCharacteristicPropertyAuthenticatedSignedWrites                               = 0x40,
    CBCharacteristicPropertyExtendedProperties                                      = 0x80,
    CBCharacteristicPropertyNotifyEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)     = 0x100,
    CBCharacteristicPropertyIndicateEncryptionRequired NS_ENUM_AVAILABLE(NA, 6_0)   = 0x200
};
  • 广播数据(advertisementData):用于描述外设基本信息

二.工作流程

外设工作流程

  1. 建立外设管理(CBPeripheralManager):需要实现CBPeripheralManagerDelegate协议。
  2. 新建添加服务(CBMutableService)设置服务特征(CBCharacteristic),后续通过特征通讯。
  3. 广播服务。

中心设备工作流程

  1. 建立中心设备管理(CBCentralManager):需实现CBCentralManagerDelegate,CBPeripheralDelegate协议
  2. 扫描外设。
  3. 连接外设。
  4. 扫描外设服务。
  5. 选择使用外设服务。
  6. 获取服务特征(即获取了通讯通道)。
  7. 选择使用特征进行通讯。

通讯流程

三.上代码

外设

//
//  BLECBPeripheral.h
//  BLE
//
//  Created by chenguibang on 2017/3/15.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
@interface BLECBPeripheral : NSObject<CBPeripheralManagerDelegate>
@property(nonatomic,strong) CBPeripheralManager *peripheralManager;

+(id)shared;

-(void)setup;

-(void)addSe;
-(void)adv;
@end

//
//  BLECBPeripheral.m
//  BLE
//
//  Created by chenguibang on 2017/3/15.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import "BLECBPeripheral.h"
#define kPeripheralName @"Kenshin Cui's Device" //外围设备名称
#define kServiceUUID @"C4FB2349-72FE-4CA2-94D6-1F3CB16331EE" //服务的UUID
#define kCharacteristicUUID @"6A3E4B28-522D-4B3B-82A9-D5E2004534FC" //特征的
@implementation BLECBPeripheral

+(id)shared{
    static dispatch_once_t onceToken;
    static BLECBPeripheral *per = nil;
    dispatch_once(&onceToken, ^{
        per = [[BLECBPeripheral alloc]init];
    });
    return per;
    
}

-(void)setup{
    self.peripheralManager = [[CBPeripheralManager alloc]initWithDelegate:self queue:nil];
}


-(void)addSe{
    CBUUID *characteristicUUID=[CBUUID UUIDWithString:kCharacteristicUUID];
    CBMutableCharacteristic *characteristicM=[[CBMutableCharacteristic alloc]initWithType:characteristicUUID properties:CBCharacteristicPropertyNotify|CBCharacteristicPropertyWriteWithoutResponse|CBCharacteristicPropertyRead value:nil permissions:CBAttributePermissionsReadable|CBAttributePermissionsWriteable|CBAttributePermissionsReadEncryptionRequired|CBAttributePermissionsWriteEncryptionRequired];
    CBUUID *serviceUUID=[CBUUID UUIDWithString:kServiceUUID];
    //创建服务
    CBMutableService *serviceM=[[CBMutableService alloc]initWithType:serviceUUID primary:YES];
    //设置服务的特征
    [serviceM setCharacteristics:@[characteristicM]];
    
    /*将服务添加到外围设备*/
    [self.peripheralManager addService:serviceM];
}


-(void)adv{
    //添加服务后开始广播
    NSDictionary *dic=@{CBAdvertisementDataLocalNameKey:kPeripheralName};//广播设置
    [self.peripheralManager startAdvertising:dic];//开始广播
}

-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    
    switch (peripheral.state) {
        case CBManagerStatePoweredOn:
            NSLog(@"BLE已打开.");
        
            break;
            
        default:
            NSLog(@"BLE已打开.异常");
            break;
    }
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error{
    NSLog(@"添加服务成功");
}

-(void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error{
    NSLog(@"广播成功");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic{
    NSLog(@"有服务订阅特征值");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic{
    NSLog(@"有服务取消订阅特征值");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request{
    NSLog(@"收到读请求");
}

-(void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray<CBATTRequest *> *)requests{
    NSLog(@"收到写请求");
    
}

@end


中央设备

//
//  BLETool.h
//  BLEOCChat
//
//  Created by chenguibang on 2017/3/14.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>

typedef void(^ErrorBlcok)(NSError* error);

@interface BLETool : NSObject<CBCentralManagerDelegate,CBPeripheralDelegate>
@property(nonatomic,strong)CBCentralManager *centerManager;
@property(nonatomic,strong)NSMutableArray<CBPeripheral*> *peripherals;
@property(nonatomic,strong)NSMutableArray<CBService*> *sevices;
@property(nonatomic,strong)NSMutableArray<CBCharacteristic *>*characters;
@property(nonatomic,copy)ErrorBlcok errorBlcok;
+(id)shared;
-(void)setup;
-(void)scanfPer:(NSUInteger)timeout;
-(void)stopScanf;
-(void)connectTo:(CBPeripheral*)peripheral reuslt:(void(^)())result;
-(void)disconnect:(CBPeripheral*)peripheral;
-(void)discoverServicesFor:(CBPeripheral*)peripheral;
-(void)discoverCharactersFor:(CBService *)service In:(CBPeripheral*)peripheral;


-(void)write:(CBPeripheral*)peripheral forCharacteristic:(CBCharacteristic *)characteristic value:(NSData *)data;
@end


//
//  BLETool.m
//  BLEOCChat
//
//  Created by chenguibang on 2017/3/14.
//  Copyright © 2017年 chenguibang. All rights reserved.
//

#import "BLETool.h"


#define findMeServiceUUID             [CBUUID UUIDWithString:@"1802"]
#define genericAccessServiceUUID      [CBUUID UUIDWithString:@"1800"]
#define linkLossServiceUUID           [CBUUID UUIDWithString:@"1803"]
#define deviceNameCharacteristicUUID  [CBUUID UUIDWithString:@"2A00"]
#define alertLevelCharacteristicUUID  [CBUUID UUIDWithString:@"2A06"]
#define BT_ALERT_LEVEL_NONE 0
#define BT_LEVEL_MILD 1
#define BT_ALERT_LEVEL_HIGH 2
#define BT_ALERT_LEVEL_RESERVED(LVL) LVL

@interface BLETool(){
//    CBCentralManager *centerManager;
    
}

@end

@implementation BLETool


+(id)shared{
    static dispatch_once_t onceToken;
    static BLETool *tool;
    dispatch_once(&onceToken, ^{
        tool = [[BLETool alloc]init];
        [tool setup];
    });
    return tool;
}
-(void)setup{
    
//    1.建立中心管理
    self.centerManager = [[CBCentralManager alloc]initWithDelegate:self queue:nil];
    self.centerManager.delegate  = self;//设置代理
    self.peripherals = [NSMutableArray array];
    self.sevices = [NSMutableArray array];
    self.characters = [NSMutableArray array];


}

-(void)scanfPer:(NSUInteger)timeout{
    

    if (self.centerManager.isScanning) {
        [[self mutableArrayValueForKey:@"peripherals"]removeAllObjects];
        [self.centerManager stopScan];
    }
//    2.扫描外设
    [self.centerManager scanForPeripheralsWithServices:nil options:@{CBCentralManagerScanOptionAllowDuplicatesKey:[NSNumber numberWithInt:1],CBCentralManagerOptionShowPowerAlertKey:[NSNumber numberWithInt:1]}];
}
-(void)stopScanf{
    [self.centerManager stopScan];
}

-(void)connectTo:(CBPeripheral*)peripheral reuslt:(void(^)())result{
    if (self.centerManager.isScanning) {
        [self.centerManager stopScan];
    }
    //    3.连接外设
    if (peripheral.state != CBPeripheralStateDisconnected) {
        NSLog(@"该设备暂时不能连接");
        
        self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:1 userInfo:@{@"msg":@"外设暂时状态不可连接"}]);
    
    }else{
        [self.centerManager connectPeripheral:peripheral options:nil];
    }
    
    
}
-(void)disconnect:(CBPeripheral *)peripheral{
    [self.centerManager cancelPeripheralConnection:peripheral];
}

-(void)discoverServicesFor:(CBPeripheral*)peripheral{
    NSMutableArray *sevices = [self mutableArrayValueForKeyPath:@"sevices"];
    [sevices removeAllObjects];
    peripheral.delegate = self;
    [peripheral discoverServices:nil];
}



-(void)write:(CBPeripheral*)peripheral forCharacteristic:(CBCharacteristic *)characteristic value:(NSData *)data{
    [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    [peripheral writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];
}

-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
    
    switch (central.state) {
        case CBManagerStateUnknown:
            
            break;
        case CBManagerStateResetting:
            
            break;
            
        case CBManagerStateUnsupported:
            
            break;
            
        case CBManagerStateUnauthorized:
            
            break;
            
        case CBManagerStatePoweredOff:
            
            break;
            
        case CBManagerStatePoweredOn:
//            [central scanForPeripheralsWithServices:nil options:nil];
            break;
        default:
            break;
    }
    
    
    NSLog(@"scanState  :  %ld \n" , (long)central.state);
}

-(void)discoverCharactersFor:(CBService *)service In:(CBPeripheral*)peripheral;{
    NSMutableArray *characters = [self mutableArrayValueForKeyPath:@"characters"];
    [characters removeAllObjects];
    [peripheral discoverCharacteristics:nil forService:service];
}



//advertisementData 外设主动发送的广播数据  RSSI 信号强度单位是dbm
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI{
    
    NSMutableArray *peripherals = [self mutableArrayValueForKeyPath:@"peripherals"];
    if (![self.peripherals containsObject:peripheral]) {
        
        [peripherals addObject:peripheral];
//        [[self mutableArrayValueForKeyPath:@"peripherals"] addObject:peripheral];
        
    }else{
      NSUInteger index =  [peripherals indexOfObject:peripheral];
        [peripherals replaceObjectAtIndex:index withObject:peripheral];
        
//        [[self mutableArrayValueForKeyPath:@"peripherals"] replaceObjectAtIndex:[self.peripherals indexOfObject:peripheral] withObject:peripheral];
        
    }
    NSLog(@"scan DisconnectPeripherals:  %@ \n",self.peripherals);
//  NSLog(@"uuid : %@\n",peripheral.identifier.UUIDString);


}

-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    NSLog(@"连接成功");
    self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:9999 userInfo:@{@"msg":@"连接成功"}]);

}
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error{
    self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:9999 userInfo:@{@"msg":@"连接失败"}]);
}


-(void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    
}

-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
     NSLog(@"发现服务");

    if (!error) {
        NSMutableArray *sevices = [self mutableArrayValueForKeyPath:@"sevices"];
        [sevices addObjectsFromArray:peripheral.services];
        for (CBService *service in peripheral.services) {
            NSLog(@"%@",service.UUID);
            [peripheral discoverCharacteristics:nil forService:service];
        }
    }else{
        self.errorBlcok([NSError errorWithDomain:NSURLErrorDomain code:9999 userInfo:@{@"msg":@"查找失败"}]);
    }
    
    
}

- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error{
    NSMutableArray *characters = [self mutableArrayValueForKeyPath:@"characters"];
    [characters addObjectsFromArray:service.characteristics];
}


-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(NSError *)error{
    
}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
}

-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
}

@end


转载于:https://www.jianshu.com/p/244668e2c959

iOS BLE开发

阅读数 15

ios ble 参考

阅读数 15

iOS BLE开发

阅读数 13

iOS 蓝牙 BLE

阅读数 19

没有更多推荐了,返回首页