gpt4 book ai didi

iOS蓝牙开发 蓝牙连接和数据读写

转载 作者:qq735679552 更新时间:2022-09-28 22:32:09 27 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章iOS蓝牙开发 蓝牙连接和数据读写由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

在做蓝牙开发之前,最好先了解一些概念: 服务(services):蓝牙外设对外广播的必定会有一个服务,可能也有多个,服务下面包含着一些特征,服务可以理解成一个模块的窗口; 特征(characteristic):存在于服务下面的,一个服务下面也可以存在多个特征,特征可以理解成具体实现功能的窗口,一般特征都会有value,也就是特征值,特征是与外界交互的最小单位; UUID:可以理解成蓝牙上的唯一标识符(硬件上肯定不是这个意思,但是这样理解便于我们开发),为了区分不同的服务和特征,或者给服务和特征取名字,我们就用UUID来代表服务和特征.

蓝牙连接可以大致分为以下几个步骤 。

1.建立一个Central Manager实例进行蓝牙管理 2.搜索外围设备 3.连接外围设备 4.获得外围设备的服务 5.获得服务的特征 6.从外围设备读数据 7.给外围设备发送数据 其他:提醒 。

首先我们先导入系统的BLE的框架 #import <CoreBluetooth/CoreBluetooth.h> 。

必须遵守2个协议 <CBCentralManagerDelegate, CBPeripheralDelegate> 。

/** 中心管理者 */ @property (nonatomic, strong) CBCentralManager *cMgr,

/** 连接到的外设 */ @property (nonatomic, strong) CBPeripheral *peripheral,

1.建立一个Central Manager实例进行蓝牙管理 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
-(CBCentralManager *)cmgr
{
   if (!_cmgr) {
     _cMgr = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
   }
   return _cMgr;
}
 
//只要中心管理者初始化 就会触发此代理方法 判断手机蓝牙状态
- ( void )centralManagerDidUpdateState:(CBCentralManager *)central
{
   switch (central.state) {
     case 0:
       NSLog(@ "CBCentralManagerStateUnknown" );
       break ;
     case 1:
       NSLog(@ "CBCentralManagerStateResetting" );
       break ;
     case 2:
       NSLog(@ "CBCentralManagerStateUnsupported" ); //不支持蓝牙
       break ;
     case 3:
       NSLog(@ "CBCentralManagerStateUnauthorized" );
       break ;
     case 4:
     {
       NSLog(@ "CBCentralManagerStatePoweredOff" ); //蓝牙未开启
     }
       break ;
     case 5:
     {
       NSLog(@ "CBCentralManagerStatePoweredOn" ); //蓝牙已开启
        // 在中心管理者成功开启后再进行一些操作
       // 搜索外设
       [self.cMgr scanForPeripheralsWithServices:nil // 通过某些服务筛选外设
                        options:nil]; // dict,条件
       // 搜索成功之后,会调用我们找到外设的代理方法
       // - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI; //找到外设
     }
       break ;
     default :
       break ;
   }
}

2.搜索外围设备 (我这里为了举例,采用了自己身边的一个手环) 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// 发现外设后调用的方法
- ( void )centralManager:(CBCentralManager *)central // 中心管理者
  didDiscoverPeripheral:(CBPeripheral *)peripheral // 外设
    advertisementData:(NSDictionary *)advertisementData // 外设携带的数据
          RSSI:(NSNumber *)RSSI // 外设发出的蓝牙信号强度
{
   //NSLog(@"%s, line = %d, cetral = %@,peripheral = %@, advertisementData = %@, RSSI = %@", __FUNCTION__, __LINE__, central, peripheral, advertisementData, RSSI);
  
   /*
    peripheral = <CBPeripheral: 0x166668f0 identifier = C69010E7-EB75-E078-FFB4-421B4B951341, Name = "OBand-75", state = disconnected>, advertisementData = {
    kCBAdvDataChannel = 38;
    kCBAdvDataIsConnectable = 1;
    kCBAdvDataLocalName = OBand;
    kCBAdvDataManufacturerData = <4c69616e 0e060678 a5043853 75>;
    kCBAdvDataServiceUUIDs =   (
    FEE7
    );
    kCBAdvDataTxPowerLevel = 0;
    }, RSSI = -55
    根据打印结果,我们可以得到运动手环它的名字叫 OBand-75
   
    */
  
   // 需要对连接到的外设进行过滤
   // 1.信号强度(40以上才连接, 80以上连接)
   // 2.通过设备名(设备字符串前缀是 OBand)
   // 在此时我们的过滤规则是:有OBand前缀并且信号强度大于35
   // 通过打印,我们知道RSSI一般是带-的
  
   if ([peripheral.name hasPrefix:@ "OBand" ]) {
     // 在此处对我们的 advertisementData(外设携带的广播数据) 进行一些处理
    
     // 通常通过过滤,我们会得到一些外设,然后将外设储存到我们的可变数组中,
     // 这里由于附近只有1个运动手环, 所以我们先按1个外设进行处理
    
     // 标记我们的外设,让他的生命周期 = vc
     self.peripheral = peripheral;
     // 发现完之后就是进行连接
     [self.cMgr connectPeripheral:self.peripheral options:nil];
     NSLog(@ "%s, line = %d" , __FUNCTION__, __LINE__);
   }
}

3.连接外围设备 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 中心管理者连接外设成功
- ( void )centralManager:(CBCentralManager *)central // 中心管理者
  didConnectPeripheral:(CBPeripheral *)peripheral // 外设
{
   NSLog(@ "%s, line = %d, %@=连接成功" , __FUNCTION__, __LINE__, peripheral.name);
   // 连接成功之后,可以进行服务和特征的发现
  
   // 设置外设的代理
   self.peripheral.delegate = self;
  
   // 外设发现服务,传nil代表不过滤
   // 这里会触发外设的代理方法 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
   [self.peripheral discoverServices:nil];
}
// 外设连接失败
- ( void )centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
   NSLog(@ "%s, line = %d, %@=连接失败" , __FUNCTION__, __LINE__, peripheral.name);
}
 
// 丢失连接
- ( void )centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
   NSLog(@ "%s, line = %d, %@=断开连接" , __FUNCTION__, __LINE__, peripheral.name);
}

4.获得外围设备的服务 & 5.获得服务的特征 。

?
1
2
3
4
5
6
7
8
9
10
// 发现外设服务里的特征的时候调用的代理方法(这个是比较重要的方法,你在这里可以通过事先知道UUID找到你需要的特征,订阅特征,或者这里写入数据给特征也可以)
- ( void )peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
   NSLog(@ "%s, line = %d" , __FUNCTION__, __LINE__);
  
   for (CBCharacteristic *cha in service.characteristics) {
     //NSLog(@"%s, line = %d, char = %@", __FUNCTION__, __LINE__, cha);
    
   }
}

5.从外围设备读数据 。

?
1
2
3
4
5
6
7
8
// 更新特征的value的时候会调用 (凡是从蓝牙传过来的数据都要经过这个回调,简单的说这个方法就是你拿数据的唯一方法) 你可以判断是否
- ( void )peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
   NSLog(@ "%s, line = %d" , __FUNCTION__, __LINE__);
   if (characteristic == @ "你要的特征的UUID或者是你已经找到的特征" ) {
   //characteristic.value就是你要的数据
   }
}

6.给外围设备发送数据(也就是写入数据到蓝牙) 。

这个方法你可以放在button的响应里面,也可以在找到特征的时候就写入,具体看你业务需求怎么用啦 。

?
1
2
[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
//第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 需要注意的是特征的属性是否支持写数据
- ( void )yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic
{
   /*
    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
    };
   
    打印出特征的权限(characteristic.properties),可以看到有很多种,这是一个NS_OPTIONS的枚举,可以是多个值
    常见的又read,write,noitfy,indicate.知道这几个基本够用了,前俩是读写权限,后俩都是通知,俩不同的通知方式
    */
//  NSLog(@"%s, line = %d, char.pro = %d", __FUNCTION__, __LINE__, characteristic.properties);
   // 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:https://blog.csdn.net/Mr_tangIT/article/details/80620969 。

最后此篇关于iOS蓝牙开发 蓝牙连接和数据读写的文章就讲到这里了,如果你想了解更多关于iOS蓝牙开发 蓝牙连接和数据读写的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com