iOS蓝牙开发4.0总结学习Demo

--- .h文件 ---

#import <Foundation/Foundation.h>

//BLIE4.0 蓝牙库

#import <CoreBluetooth/CoreBluetooth.h>

/**

蓝牙链接状态

@param state 状态

*/

typedef void (^BLELinkBlock)(NSString *state);

/**

蓝牙返回数据

@param array 返回数据

*/

typedef void (^BLEDataBlock)(NSMutableArray *array);

typedef enum BLEState_NOW{

    

    BLEState_Successful = 0,//连接成功

    BLEState_Disconnect = 1, // 失败

    BLEState_Normal,         // 未知

    

}BLEState_NOW;

/**

蓝牙连接成功 或者断开

*/

typedef void(^BLEStateBlcok)(int number);

@interface BLEModel : NSObject

/**

外设名称 外设UUID 外设读取数据 UUID 外设写入UUID

*/

@property (nonatomic,strong) NSString *BLEName; //蓝牙硬设名称

@property (nonatomic,strong) NSString *BLEServiceID; //蓝牙硬设设备ID

@property (nonatomic,strong) NSString *BLEServiceReadID;//蓝牙硬设读取权限ID

@property (nonatomic,strong) NSString *BLEServiceWriteID;//蓝牙硬设写入信息ID

@property (nonatomic,copy) NSString *connectState;//蓝牙连接状态

@property (nonatomic,copy) BLELinkBlock linkBlcok; //蓝牙状态回调

@property (nonatomic,copy) BLEDataBlock dataBlock; //蓝牙硬设返回数据

@property (nonatomic,copy) BLEStateBlcok stateBlock; //蓝牙连接成功失败

/**

*  开始扫描

*/

-(void)startScan;

/**

主动断开链接

*/

-(void)cancelPeripheralConnection;

/**

发送命令

*/

- (void) sendData:(NSData *)data;

@end

--- .h文件 ---

--- .m文件 ---

#import "BLEModel.h"

//#import "BLEIToll.h"

@interface BLEModel ()<CBCentralManagerDelegate,CBPeripheralDelegate>

/**

*  蓝牙连接必要对象

*/

@property (nonatomic, strong) CBCentralManager *centralMgr; //蓝牙操作对象

@property (nonatomic, strong) CBPeripheral *discoveredPeripheral; //获取蓝牙设备信息

@property (strong, nonatomic) CBCharacteristic* writeCharacteristic;  //蓝牙设备读写服务操作对象

@property (nonatomic,assign) BOOL isInitiativeDisconnect;//主动断开连接

@end

@implementation BLEModel

- (instancetype)init

{

    self = [super init];

    if (self) {

        _centralMgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];

    }

    return self;

}

/**

*  开始扫描

*/

- (void)startScan{

    _centralMgr = [[CBCentralManager alloc]initWithDelegate:self queue:nil];

}

/**

*  停止扫描

*/

-(void)stopScan

{

    [_centralMgr stopScan];

}

#pragma mark - 蓝牙的状态

/**

*  --  初始化成功自动调用

*  --  必须实现的代理,用来返回创建的centralManager的状态。

*  --  注意:必须确认当前是CBCentralManagerStatePoweredOn状态才可以调用扫描外设的方法:

scanForPeripheralsWithServices

*/

// 2. 搜索扫描外围设备

// CBCentralManagerDelegate 必须实现的代理函数

-(void)centralManagerDidUpdateState:(CBCentralManager *)central{

    switch (central.state) {

        case CBManagerStateUnknown:

        {

            //NSLog(@"无法获取设备的蓝牙状态");

            self.connectState = kCONNECTED_UNKNOWN_STATE;

        }

            break;

        case CBManagerStateResetting:

        {

            //NSLog(@"蓝牙重置");

            self.connectState = kCONNECTED_RESET;

        }

            break;

        case CBManagerStateUnsupported:

        {

            //NSLog(@"该设备不支持蓝牙");

            self.connectState = kCONNECTED_UNSUPPORTED;

        }

            break;

        case CBManagerStateUnauthorized:

        {

            //NSLog(@"未授权蓝牙权限");

            self.connectState = kCONNECTED_UNAUTHORIZED;

        }

            break;

        case CBManagerStatePoweredOff:

        {

            //NSLog(@"蓝牙已关闭");

            self.connectState = kCONNECTED_POWERED_OFF;

        }

            break;

        case CBManagerStatePoweredOn:

        {

            //NSLog(@"蓝牙已打开");

            self.connectState = kCONNECTED_POWERD_ON;

            [_centralMgr scanForPeripheralsWithServices:nil options:nil];

        }

            break;

            

        default:

        {

            //NSLog(@"未知的蓝牙错误");

            self.connectState = kCONNECTED_ERROR;

        }

            break;

    }

    self.linkBlcok(self.connectState);

    //[self getConnectState];

    

}

#pragma mark -- CBCentralManagerDelegate

#pragma mark- 发现设备 扫描设备,连接

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

{

    NSLog(@"name:%@",peripheral);

    /**

     当扫描到蓝牙数据为空时,停止扫描

     */

    if (!peripheral || !peripheral.name || ([peripheral.name isEqualToString:@""])) {

        return;

    }

    

    /**

     当扫描到服务UUID与设备UUID相等时,进行蓝牙与设备链接

     */

    

    if ((!self.discoveredPeripheral || (self.discoveredPeripheral.state == CBPeripheralStateDisconnected))&&([peripheral.name isEqualToString:_BLEName])) {

        self.discoveredPeripheral = [peripheral copy];

        //self.peripheral.delegate = self;

        NSLog(@"connect peripheral:  %@",peripheral);

        // 3.连接外围设备

        // 连接设备(.h中声明出去的接口, 一般在点击设备列表连接时调用)

        [self.centralMgr connectPeripheral:peripheral options:nil];

    }

}

#pragma park- 连接外设--成功,扫描services

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

{

    if (!peripheral) {

        return;

    }

    //连接成功后停止扫描,节省内存

    [self.centralMgr stopScan];

    

    self.stateBlock(BLEState_Successful);

    

    NSLog(@"peripheral did connect:  %@",peripheral);

    // 是 peripheral.delegate = self; 还是 self.discoveredPeripheral有待考察

    //4.扫描外设的服务

    /**

     --     外设的服务、特征、描述等方法是CBPeripheralDelegate的内容,所以要先设置代理peripheral.delegate = self

     --     参数表示你关心的服务的UUID,比如我关心的是"FFE0",参数就可以为@[[CBUUID UUIDWithString:@"FFE0"]].那么didDiscoverServices方法回调内容就只有这两个UUID的服务,不会有其他多余的内容,提高效率。nil表示扫描所有服务

     --     成功发现服务,回调didDiscoverServices

     */

    [self.discoveredPeripheral setDelegate:self];

    [self.discoveredPeripheral discoverServices:@[[CBUUID UUIDWithString:@"你要用的服务UUID"]]];

}

#pragma mark 连接外设——失败

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

    NSLog(@"%@", error);

}

#pragma mark 取消与外设的连接回调 外设断开连接

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

    NSLog(@"外设断开连接 %@: %@\n", [peripheral name], [error localizedDescription]);

    self.stateBlock(BLEState_Disconnect);

    //重连外设

    if (!self.isInitiativeDisconnect) {

        [self.centralMgr connectPeripheral:peripheral options:nil];

    }

}

// 4. 获得外围设备的服务

#pragma mark - 扫描service

#pragma mark 发现服务回调

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

    NSArray *services = nil;

    

    if (peripheral != self.discoveredPeripheral) {

        NSLog(@"Wrong Peripheral.\n");

        return ;

    }

    

    if (error != nil) {

        NSLog(@"Error %@\n", error);

        return ;

    }

    

    services = [peripheral services];

    NSLog(@"%@",services);

    if (!services || ![services count]) {

        NSLog(@"No Services");

        return ;

    }

    // 遍历服务

    for (CBService *service in services) {

        NSLog(@"该设备的service:%@",service);

        // [[service UUID] isEqual:[CBUUID UUIDWithString:@"你要用的服务UUID"]]

        if ([[service.UUID UUIDString] isEqualToString:_BLEServiceID]) {

            [peripheral discoverCharacteristics:nil forService:service];

            return ;

        }

    }

}

//5、获得服务的特征;

#pragma mark 发现特征回调

/**

--  发现特征后,可以根据特征的properties进行:读readValueForCharacteristic、写writeValue、订阅通知setNotifyValue、扫描特征的描述discoverDescriptorsForCharacteristic。

**/

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

    if (error) {

        NSLog(@"didDiscoverCharacteristicsForService error : %@", [error localizedDescription]);

        return;

    }

    // 遍历服务的特征

    for (CBCharacteristic *characteristic in service.characteristics) {

        NSLog(@"\n>>>\t特征UUID FOUND(in 服务UUID:%@): %@ (data:%@)",service.UUID.description,characteristic.UUID,characteristic.UUID.data);

        /**

         >>> 特征UUID FOUND(in 服务UUID:FFE0): FFE1 (data:<ffe1>)

         >>> 特征UUID FOUND(in 服务UUID:FFE0): FFE2 (data:<ffe2>)

         */

        /*

         根据特征不同属性去读取或者写

         if (c.properties==CBCharacteristicPropertyRead) {

         }

         if (c.properties==CBCharacteristicPropertyWrite) {

         }

         if (c.properties==CBCharacteristicPropertyNotify) {

         }

         */

        /*

         设备读取UUID 这里根据UUID判断 不一定对根据项目需求

        */

        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:_BLEServiceReadID]]) {

            self.writeCharacteristic = characteristic;

            // 订阅, 实时接收

            [_discoveredPeripheral setNotifyValue:YES forCharacteristic:self.writeCharacteristic];

        }

        

        /**

         设备写入UUID 这里根据UUID判断 不一定对根据项目需求

         */

        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:_BLEServiceWriteID]]) {

            self.writeCharacteristic = characteristic;

            NSData *data = [@"硬件工程师给我的指令, 发送给蓝牙该指令, 蓝牙会给我返回一条数据" dataUsingEncoding:NSUTF8StringEncoding];

            // 将指令写入蓝牙

            [_discoveredPeripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithResponse];

        }

        /**

         -- 当发现characteristic有descriptor,回调didDiscoverDescriptorsForCharacteristic

         */

        [peripheral discoverDescriptorsForCharacteristic:characteristic];

    }

}

// 已经发现特征的描述

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

    NSLog(@"didDiscoverDescriptorsForCharacteristic:%@",characteristic);

    for (CBDescriptor *d in characteristic.descriptors) {

        NSLog(@"Descriptor UUID:%@",d.UUID);

    }

}

// 6.从外围设备读取数据

#pragma mark - 读取数据 获取值

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

    if (error) {

        NSLog(@"didUpdateValueForCharacteristic error : %@", error.localizedDescription);

        return;

    }

    // characteristic.value就是蓝牙给我们的值(我这里是json格式字符串)

    NSData *data = characteristic.value;

    // 通过工具做处理

    // 或者NSDictionary *dataDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil];传出去即可

//    NSMutableArray *dataArr = [BLEIToll convertDataToHexStr:data];

    // 通过工具类处理 得到的Array 传出去

    NSMutableArray *dataArr = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];

    self.dataBlock(dataArr);

}

#pragma mark - 中心读取外设实时数据

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

    if (characteristic.isNotifying) {

        [peripheral readValueForCharacteristic:characteristic];

    } else {

        NSLog(@"Notification stopped on %@.  Disconnecting", characteristic);

        NSLog(@"%@", characteristic);

        [_centralMgr cancelPeripheralConnection:peripheral];

    }

}

#pragma mark - 主动断开连接

-(void)cancelPeripheralConnection{

    

    self.isInitiativeDisconnect = YES;

    if (self.discoveredPeripheral) {//已经连接外设,则断开

        [self.centralMgr cancelPeripheralConnection:self.discoveredPeripheral];

    }else{//未连接,则停止搜索外设

        [self.centralMgr stopScan];

    }

}

/**

发送命令

*/

- (void) sendData:(NSData *)data{

    

     /**

      通过CBPeripheral 类 将数据写入蓝牙外设中,蓝牙外设所识别的数据为十六进制数据,在ios系统代理方法中将十六进制数据改为 NSData 类型 ,但是该数据形式必须为十六进制数 0*ff 0*ff格式 在iToll中有将 字符串转化为 十六进制 再转化为 NSData的方法

      

      */

    [self.discoveredPeripheral writeValue:data forCharacteristic:self.writeCharacteristic type:CBCharacteristicWriteWithoutResponse];

}

//向peripheral中写入数据后的回调函数

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

    //该方法可以监听到写入外设数据后的状态

    if (error) {

        NSLog(@"didWriteValueForCharacteristic error : %@", error.localizedDescription);

        return;

        

    }

    

    NSLog(@"write value success : %@", characteristic);

}

@end

--- .m文件 ---

--- ViewControll 使用 ---

#import "ViewController.h"

#import "BLEModel.h"

#import "BLEIToll.h"

@interface ViewController ()

@property (nonatomic,strong) BLEModel *manager;

@end

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.

    

    self.view.backgroundColor = [UIColor lightGrayColor];

    

    [self initNavTitle];

    [self BluetoothConnection];

    

}

/**

设计导航

*/

- (void)initNavTitle{

    self.navigationItem.title = @"空气质量";

    //蓝牙图标

    

    UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 50, 20)];

    titleLabel.textColor = [BLEIToll  colorWithHexString:@"#6ccc8f"];

    titleLabel.text = @"未连接";

    titleLabel.font = [UIFont systemFontOfSize:12];

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:titleLabel];

}

/**

蓝牙初始化

*/

- (void)BluetoothConnection{

    WeakSelf;

    _manager = [[BLEModel alloc]init];

    _manager.BLEName = PMServiceName; //蓝牙硬设名称

    _manager.BLEServiceID = PMServiceUUID; //蓝牙硬设设备ID

    _manager.BLEServiceReadID = PMServiceUUID_Receive;

    _manager.BLEServiceWriteID = PMServiceUUID_Send;

    _manager.linkBlcok = ^(NSString *state){

        

        NSLog(@"++++++++:%@",state);

    };

    _manager.dataBlock = ^(NSMutableArray *array){

        //   NSLog(@"%@",array);

        if (array.count >= 20) {

            BLEIToll *itool = [[BLEIToll alloc]init];

            if ([array[0] isEqualToString:@"42"] && [array[1] isEqualToString:@"4d"]) {

                NSLog(@"-----------:%@",[itool handleTheBLEFirstData:array]);

            }else{

                NSLog(@"}}}}}}}}}}}:%@",[itool handleTheBLEFirstData:array]);

            }

        }

    };

    _manager.stateBlock = ^(int number){

        NSLog(@"%d",number);

        [weakSelf BLEStateInt:number];

    };

    /*

     发送一个  0xFA 0xE4 Ox33 的命令

     

     */

    /*

     NSData *data = [[BLEIToll alloc] stringToByte:@"FAE433"];

     NSLog(@"写入数据%@",data);

     [_manager sendData:data];

     */

}

- (void)BLEStateInt:(int) state{

    switch (state) {

        case BLEState_Successful:

        {

            //连接成功

            UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 50, 20)];

            titleLabel.textColor = [BLEIToll  colorWithHexString:@"#6ccc8f"];

            titleLabel.text = @"已连接";

            titleLabel.font = [UIFont systemFontOfSize:12];

            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:titleLabel];

        }

            break;

        case BLEState_Disconnect:

        {

            //外设断开连接

            UILabel *titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 50, 20)];

            titleLabel.textColor = [BLEIToll  colorWithHexString:@"#6ccc8f"];

            titleLabel.text = @"未连接";

            titleLabel.font = [UIFont systemFontOfSize:12];

            self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:titleLabel];

        }

            break;

            

        default:

            break;

    }

    

    

}

@end

--- ViewControll 使用 ---

下载链接

https://download.csdn.net/my/uploads/1/1

或者搜索 XJP蓝牙4.0封装

发布了49 篇原创文章 · 获赞 7 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_29680975/article/details/95329776