zoukankan      html  css  js  c++  java
  • IOS蓝牙连接 初步简单封装使用

    最近写一个蓝牙项目 初步实现一下蓝牙设备连接交互,后期继续完善。。。。

    1、连接蓝牙相关操作

    BlueToothManger.h

    //
    //  BlueToothManger.h
    //  SmartRobot
    //
    //  Created by 杜文杰 on 2017/8/2.
    //  Copyright © 2017年 appleLJ. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @interface BlueToothManger : CBCentralManager
    // connectSeccuss YES 连接成功 NO 连接失败
    @property (nonatomic, copy) void(^cbperipheral)(CBPeripheral *peripheral,BOOL connectSeccuss);
    @property (nonatomic, copy) void(^cbCharacteristic)(CBCharacteristic *characteristic);
    - (instancetype)ShareBlueToothManger;
    - (CBCentralManager *)centralManager;
    
    @end

    BlueToothManger.m

    //
    //  BlueToothManger.m
    //  SmartRobot
    //
    //  Created by 杜文杰 on 2017/8/2.
    //  Copyright © 2017年 appleLJ. All rights reserved.
    //
    
    #import "BlueToothManger.h"
    #import <CoreBluetooth/CoreBluetooth.h>
    
    @interface BlueToothManger ()<CBCentralManagerDelegate,CBPeripheralDelegate>
    /// 中央管理者 -->管理设备的扫描 --连接
    @property (nonatomic, strong) CBCentralManager *centralManager;
    // 存储的设备
    @property (nonatomic, strong) NSMutableArray *peripherals;
    // 扫描到的设备
    @property (nonatomic, strong) CBPeripheral *cbPeripheral;
    // 文本
    //@property (weak, nonatomic) IBOutlet UITextView *peripheralText;
    // 蓝牙状态
    @property (nonatomic, assign) CBManagerState peripheralState;
    
    @property (nonatomic, copy) NSString *sendServerValue;
    
    @property (nonatomic, copy) BlueToothManger *blueToothManger;
    @end
    
    // 蓝牙4.0设备名
    static NSString * const kBlePeripheralName = @"JDY-08";
    // 通知服务
    static NSString * const kNotifyServerUUID = @"FFE0";
    // 写服务
    static NSString * const kWriteServerUUID = @"FFE1";
    // 通知特征值
    static NSString * const kNotifyCharacteristicUUID = @"FFE1";
    // 写特征值
    static NSString * const kWriteCharacteristicUUID = @"FFE1";
    
    @implementation BlueToothManger
    
    - (instancetype)ShareBlueToothManger
    {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _blueToothManger = [[BlueToothManger alloc]init];
        });
        return _blueToothManger;
        
    }
    - (NSMutableArray *)peripherals
    {
        if (!_peripherals) {
            _peripherals = [NSMutableArray array];
        }
        return _peripherals;
    }
    
    - (CBCentralManager *)centralManager
    {
        if (!_centralManager)
        {
            _centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
        }
        return _centralManager;
    }
    
    // 222  扫描设备
    - (void)scanForPeripherals
    {
        [self.centralManager stopScan];
        NSLog(@"扫描设备");
        //    [self showMessage:@"扫描设备"];
        if (self.peripheralState ==  CBManagerStatePoweredOn)
        {
            [self.centralManager scanForPeripheralsWithServices:nil options:nil];
        }
    }
    
    // 连接设备
    - (void)connectToPeripheral
    {
        if (self.cbPeripheral != nil)
        {
            NSLog(@"连接设备");
            //        [self showMessage:@"连接设备"];
            [self.centralManager connectPeripheral:self.cbPeripheral options:nil];
        }
        else
        {
            //        [self showMessage:@"无设备可连接"];
        }
    }
    
    // 清空设备
    - (void)clearPeripherals
    {
        NSLog(@"清空设备");
        [self.peripherals removeAllObjects];
        //    self.peripheralText.text = @"";
        //    [self showMessage:@"清空设备"];
        
        if (self.cbPeripheral != nil)
        {
            // 取消连接
            NSLog(@"取消连接");
            //        [self showMessage:@"取消连接"];
            [self.centralManager cancelPeripheralConnection:self.cbPeripheral];
        }
    }
    ////000
    //- (void)viewDidLoad {
    //    [super viewDidLoad];
    //    [self centralManager];
    //}
    ///111
    //只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态   状态更新时调用
    - (void)centralManagerDidUpdateState:(CBCentralManager *)central
    {
        switch (central.state) {
            case CBManagerStateUnknown:{
                NSLog(@"为知状态");
                self.peripheralState = central.state;
            }
                break;
            case CBManagerStateResetting:
            {
                NSLog(@"重置状态");
                self.peripheralState = central.state;
            }
                break;
            case CBManagerStateUnsupported:
            {
                NSLog(@"不支持的状态");
                self.peripheralState = central.state;
            }
                break;
            case CBManagerStateUnauthorized:
            {
                NSLog(@"未授权的状态");
                self.peripheralState = central.state;
            }
                break;
            case CBManagerStatePoweredOff:
            {
                NSLog(@"关闭状态");
                self.peripheralState = central.state;
            }
                break;
            case CBManagerStatePoweredOn:
            {
                NSLog(@"开启状态-可用状态");
                self.peripheralState = central.state;
                // 链接成功开始扫描设备
                [self scanForPeripherals];
                NSLog(@"%ld",(long)self.peripheralState);
            }
                break;
            default:
                break;
        }
    }
    /**
     333扫描到设备  发现设备是开启状态后调用方法
     
     @param central 中心管理者
     @param peripheral 扫描到的设备
     @param advertisementData 广告信息
     @param RSSI 信号强度
     */
    - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *,id> *)advertisementData RSSI:(NSNumber *)RSSI
    {
        //    [self showMessage:[NSString stringWithFormat:@"发现设备,设备名:%@",peripheral.name]];
        // 设备数组中是否存在 该设备
        if (![self.peripherals containsObject:peripheral])
        {
            [self.peripherals addObject:peripheral];
            NSLog(@"%@",peripheral);
            
            //最常用的场景是查找某一个前缀开头的设备 mogu
            if ([peripheral.name hasPrefix:@"JDY"] ) {
                //            [self showMessage:@"开始连接"];
                [self.centralManager connectPeripheral:peripheral options:nil];
            }
        }
    }
    
    /**
     连接失败
     
     @param central 中心管理者
     @param peripheral 连接失败的设备
     @param error 错误信息
     */
    
    - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
        //    [self showMessage:@"连接失败"];
        if ([peripheral.name isEqualToString:kBlePeripheralName])
        {
            [self.centralManager connectPeripheral:peripheral options:nil];
        }
    }
    
    /**
     连接断开
     
     @param central 中心管理者
     @param peripheral 连接断开的设备
     @param error 错误信息
     */
    
    - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
    {
        //    [self showMessage:@"断开连接"];
        if ([peripheral.name isEqualToString:kBlePeripheralName])
        {
            [self.centralManager connectPeripheral:peripheral options:nil];
        }
    }
    
    /**
     444连接成功
     
     @param central 中心管理者
     @param peripheral 连接成功的设备
     */
    - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
    {
        NSLog(@"连接设备:%@成功",peripheral.name);
        //    self.peripheralText.text = [NSString stringWithFormat:@"连接设备:%@成功",peripheral.name];
    //    [self showMessage:[NSString stringWithFormat:@"连接设备:%@成功",peripheral.name]];
        // 设备
        self.cbPeripheral = peripheral;
        self.cbperipheral(peripheral, YES);
        
        // 设置设备的代理
        peripheral.delegate = self;
        // services:传入nil  代表扫描所有服务
        [peripheral discoverServices:nil];
    }
    
    /**
     555扫描到服务
     
     @param peripheral 服务对应的设备
     @param error 扫描错误信息
     */
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
    {
        // 遍历所有的服务
        for (CBService *service in peripheral.services)
        {
            NSLog(@"服务:%@",service.UUID.UUIDString);
            // 获取对应的服务
            if ([service.UUID.UUIDString isEqualToString:kWriteServerUUID] || [service.UUID.UUIDString isEqualToString:kNotifyServerUUID])
            {
                // 根据服务去扫描特征
                [peripheral discoverCharacteristics:nil forService:service];
            }
        }
    }
    
    /**
     666扫描到对应的特征
     
     @param peripheral 设备
     @param service 特征对应的服务
     @param error 错误信息
     */
    - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
    {
        // 遍历所有的特征
        for (CBCharacteristic *characteristic in service.characteristics)
        {
            
            NSLog(@"特征值:%@",characteristic.UUID.UUIDString);
            if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
            {
                self.cbCharacteristic(characteristic);
            }
            if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
            {
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            }
        }
    }
    
    - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error;
    {
        //这个方法比较好,这个是你发数据到外设的某一个特征值上面,并且响应的类型是 CBCharacteristicWriteWithResponse ,上面的官方文档也有,如果确定发送到外设了,就会给你一个回应,当然,这个也是要看外设那边的特征值UUID的属性是怎么设置的,看官方文档,人家已经说了,条件是,特征值UUID的属性:CBCharacteristicWriteWithResponse
        if (!error) {
            NSLog(@"说明发送成功,characteristic.uuid为:%@ 发送为%@",[characteristic.UUID UUIDString],characteristic.value);
            Byte byte2[] = {0xf0, 0x3d, 0x3d, 0x5d,0x02,0xf7};
            NSData* data2 = [[NSData alloc] initWithBytes:byte2 length:3];
            if ([characteristic.value isEqualToData:data2]) {
                NSLog(@"说明发送成功,characteristic.uuid为:%@ 发送为%@",[characteristic.UUID UUIDString],characteristic.value);
            }
        }else{
            NSLog(@"发送失败了啊!characteristic.uuid为:%@  原因:%@",[characteristic.UUID UUIDString],error);
            
        }
        //调用下面的方法后 会调用到代理的- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
        [peripheral readValueForCharacteristic:characteristic];
    }
    
    ///**
    // 根据特征读到数据
    // 
    // @param peripheral 读取到数据对应的设备
    // @param characteristic 特征
    // @param error 错误信息
    // */
    - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error
    {
        if ([characteristic.UUID.UUIDString isEqualToString:kNotifyCharacteristicUUID])
        {
            NSData *data = characteristic.value;
            NSLog(@"%@",data);
        }
    }
    
    @end

    2、一般在登录后的主窗口 初始化下面这个类 连接蓝牙和保存蓝牙相关数据 保存蓝牙设备值和特征值  发送数据会用到

    SaveValueForBlueThooth.h

    //
    //  SaveValueForBlueThooth.h
    //  SmartRobot
    //
    //  Created by 杜文杰 on 2017/8/10.
    //  Copyright © 2017年 appleLJ. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import <CoreBluetooth/CoreBluetooth.h>
    #import "BlueToothManger.h"
    
    @interface SaveValueForBlueThooth : NSObject
    
    @property (nonatomic, strong) BlueToothManger *blueToothManager;
    // 设备
    @property (nonatomic, strong) CBPeripheral *peripheral;
    // 特征值
    @property (nonatomic, strong) CBCharacteristic *characteristic;
    // 连接成功标识
    @property (nonatomic, assign) BOOL connectSeccess;
    
    + (instancetype)allocWithZone:(struct _NSZone *)zone;
    // 重新连接
    - (void)bluetoothConnect;
    // 发送数据
    - (void)postValueForBlueThoothWithString:(NSString *)valueWithStr;
    
    @end

    SaveValueForBlueThooth.m

    //
    //  SaveValueForBlueThooth.m
    //  SmartRobot
    //
    //  Created by 杜文杰 on 2017/8/10.
    //  Copyright © 2017年 appleLJ. All rights reserved.
    //
    
    #import "SaveValueForBlueThooth.h"
    
    // 通知特征值
    static NSString * const kNotifyCharacteristicUUID = @"FFE1";
    
    
    @implementation SaveValueForBlueThooth
    
    static SaveValueForBlueThooth *_instance;
    + (instancetype)allocWithZone:(struct _NSZone *)zone
    {
        // 也可以使用一次性代码
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            if (_instance == nil) {
                _instance = [super allocWithZone:zone];
            }
        });
        return _instance;
    }
    
    // 连接蓝牙设备
    - (void)bluetoothConnect
    {
        [self.blueToothManager connectPeripheral:self.peripheral options:nil];
        
    }
    
    // 发送数据
    - (void)postValueForBlueThoothWithString:(NSString *)valueWithStr
    {
        
        NSLog(@"设备名:%@     特征值 %@",self.peripheral.name,self.characteristic);
        // 特征值
        NSString *tzName = self.characteristic.UUID.UUIDString;
        // 设备名
        NSString *peripheraName = self.peripheral.name;
        if (tzName.length > 0 && peripheraName.length > 0) {
            // 写入数据 M_1_1000_
    
            NSData *data = [valueWithStr dataUsingEncoding: NSUTF8StringEncoding];
            [self.peripheral writeValue:data forCharacteristic:self.characteristic type:CBCharacteristicWriteWithoutResponse];
            NSLog(@"%@",self.characteristic.UUID.UUIDString);
            
            NSLog(@"发送成功");
        }else {
            [self bluetoothConnect];
            NSLog(@"重新连接蓝牙");
        }
        
    }
    
    @end

    3、在跟控制器 主窗口中声明属性

    (1)

    @property (nonatomic, strong) BlueToothManger *blueToothManager;
    // 设备
    @property (nonatomic, strong) CBPeripheral *peripheral;
    // 特征值
    @property (nonatomic, strong) CBCharacteristic *characteristic;
    // 连接成功标识
    @property (nonatomic, assign) BOOL connectSeccess;
    
    @property (nonatomic, strong) SaveValueForBlueThooth *saveValueForBlueThooth;

    (2)在 viewDidLoad中调用连接蓝牙 并保存相关 发送需要的数据

    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 连接蓝牙
        [self connectPeripheral];
       
    }

    (3)

    #pragma  mark - 蓝牙连接
    - (void)connectPeripheral
    {
        // 单例记录发送数据 需要用的 设备值和特征值
        _saveValueForBlueThooth = [[SaveValueForBlueThooth alloc]init];
        // 初始化blueToothManager类连接蓝牙设备
        self.blueToothManager = [[[BlueToothManger alloc]init]ShareBlueToothManger];
        [self.blueToothManager centralManager];
        __block
        __block typeof(SaveValueForBlueThooth *)saveValueForBlue = _saveValueForBlueThooth;
        // 连接蓝牙设备成功回调
        // 存储设备值
        self.blueToothManager.cbperipheral = ^(CBPeripheral *peripheral, BOOL connectSeccuss) {
            saveValueForBlue.peripheral = peripheral;
            saveValueForBlue.connectSeccess = connectSeccuss;
        };
        // 存储特征值
        self.blueToothManager.cbCharacteristic = ^(CBCharacteristic *characteristic) {
            saveValueForBlue.characteristic = characteristic;
        };
    }

    4、在需要发送数据的界面

    (1)在 viewDidLoad中初始化类

     self.blueThoothPostValue = [[SaveValueForBlueThooth alloc]init];

    (2)发送按钮点击事件

    //
    - (void)topBtnEvent{
        NSLog(@"up");
        [self.blueThoothPostValue postValueForBlueThoothWithString:@"E 1
    "];
    }
  • 相关阅读:
    ORACLE不常用但实用的技巧- 树查询 level用法
    oracle的start with connect by prior如何使用
    Oracle SQL日期及日期格式获取命令
    2019年起一般纳税人和小规模纳税人的区别
    10.pandas的替换和部分替换(replace)
    pandas中.value_counts()的用法
    Python模块/包/库安装几种方法(转载)
    预处理数据的方法总结(使用sklearn-preprocessing)
    python时间序列分析之_用pandas中的rolling函数计算时间窗口数据
    BZOJ2007 [Noi2010]海拔
  • 原文地址:https://www.cnblogs.com/dujiahong/p/7358441.html
Copyright © 2011-2022 走看看