文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2022-05-26 08:54

关注

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

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

建立一个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;

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


-(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;
  }
}

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


// 发现外设后调用的方法
- (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);
  
  
  
  // 需要对连接到的外设进行过滤
  // 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__);
  }
}

连接外围设备


// 中心管理者连接外设成功
- (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);
}

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


// 发现外设服务里的特征的时候调用的代理方法(这个是比较重要的方法,你在这里可以通过事先知道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);
    
  }
}

从外围设备读数据


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

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

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


[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
//第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入

// 需要注意的是特征的属性是否支持写数据
- (void)yf_peripheral:(CBPeripheral *)peripheral didWriteData:(NSData *)data forCharacteristic:(nonnull CBCharacteristic *)characteristic
{
  
//  NSLog(@"%s, line = %d, char.pro = %d", __FUNCTION__, __LINE__, characteristic.properties);
  // 此时由于枚举属性是NS_OPTIONS,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&
}

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

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯