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

2025-05-29 0 29

在做蓝牙开发之前,最好先了解一些概念:
服务(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,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&

}

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

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 iOS蓝牙开发 蓝牙连接和数据读写 https://www.kuaiidc.com/89171.html

相关文章

发表评论
暂无评论