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实例进行蓝牙管理

-(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.搜索外围设备 (我这里为了举例,采用了自己身边的一个手环)

// 发现外设后调用的方法
- (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.连接外围设备

// 中心管理者连接外设成功
- (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.获得服务的特征

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

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

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

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

[self.peripherale writeValue:_batteryData forCharacteristic:self.characteristic type:CBCharacteristicWriteWithResponse];
//第一个参数是已连接的蓝牙设备 ;第二个参数是要写入到哪个特征; 第三个参数是通过此响应记录是否成功写入
// 需要注意的是特征的属性是否支持写数据
- (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,所以一个枚举可能对应多个类型,所以判断不能用 = ,而应该用包含&
}

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

(0)

相关推荐

  • IOS Ble蓝牙开发实现方法

    本篇博文阐述如何开发Ble蓝牙.在蓝牙中的一些常见服务,扫描,以及链接: 主蓝牙类文件.h 主蓝牙类文件.m UUID文件 蓝牙列表展示的文件 一:引入Ble蓝牙的框架<CoreBluetooth/CoreBluetooth.h> BuleHelp.h #import <Foundation/Foundation.h> //导入蓝牙框架 #import <CoreBluetooth/CoreBluetooth.h> #import "DeviceModel.h

  • iOS蓝牙开发数据实时传输

    随着iOS项目开发  很多app需要通过蓝牙与设备连接 蓝牙开发注意: 先定义中心设备和外围设备以及遵守蓝牙协议 @interface ViewController()<CBCentralManagerDelegate,CBPeripheralDelegate> @property (strong, nonatomic) CBCentralManager *manager; @property (nonatomic, strong) CBPeripheral *peripheral; @pro

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

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

  • 详解iOS应用开发中Core Data数据存储的使用

    1.如果想创建一个带有coreData的程序,要在项目初始化的时候勾选中   2.创建完成之后,会发现在AppDelegate里多出了几个属性,和2个方法 复制代码 代码如下: <span style="font-size:18px;">    @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;  @property (readonly, strong,

  • Android BLE 蓝牙开发之实现扫码枪基于BLESSED开发

    目录 一.蓝牙模式HID与BLE 二.BLE协议白话 三.第三方库 BLESSED for Android的使用 一.蓝牙模式HID与BLE 当扫码枪与手机连接时,通常采用的是蓝牙HID(Human Interface Device)模式.本质上是一个把扫码枪作为一个硬件键盘,按照键盘协议把扫码后的结果逐个输入到对应的控件上. 优点:无需开发集成,配对就可以立即作为键盘输入使用.可以使用输入框等组件直接接收扫码结果. 缺点:对非数字支持不佳,与输入法相关,在某些时候会触发英文联想-_-||,与虚

  • Android 蓝牙开发实例解析

    在使用手机时,蓝牙通信给我们带来很多方便.那么在Android手机中怎样进行蓝牙开发呢?本文以实例的方式讲解Android蓝牙开发的知识.        1.使用蓝牙的响应权限 XML/HTML代码 <uses-permission android:name="android.permission.BLUETOOTH"/> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN&qu

  • iOS开发系列--详细介绍数据存取

    概览 在iOS开发中数据存储的方式可以归纳为两类:一类是存储为文件,另一类是存储到数据库.例如前面IOS开发系列-Objective-C之Foundation框架的文章中提到归档.plist文件存储,包括偏好设置其本质都是存储为文件,只是说归档或者plist文件存储可以选择保存到沙盒中,而偏好设置系统已经规定只能保存到沙盒的Library/Preferences目录.当然,文件存储并不作为本文的重点内容.本文重点还是说数据库存储,做过数据库开发的朋友应该知道,可以通过SQL直接访问数据库,也可以

  • 大数据开发phoenix连接hbase流程详解

    目录 一.安装phoennix添加配置 二.启动phoenix服务 三.phoenix常用语法 四.java代码集成phoenix 一.安装phoennix添加配置 1.将phoenix-server-hbase-2.4-5.1.2.jar拷贝至hbase的的lib下 cp  phoenix-server-hbase-2.4-5.1.2.jar ../hbase/lib/ 2.配置phoenix可以访问hbase的系统表 (1)将以下配置添加至hbase-site.xml中 <property>

  • java使用jdbc连接数据库工具类和jdbc连接mysql数据示例

    这个工具类使用简单,实例化直接调用就可以了,大家还可以方便的根据自己的需要在里面增加自己的功能 复制代码 代码如下: package com.lanp.ajax.db; import java.sql.Connection;import java.sql.DriverManager;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException; /** * 连接数据库的工具类,被定

  • iOS用两行代码完美解决数据持久化

    前言 在实际的iOS开发中,有些时候涉及到将程序的状态保存下来,以便下一次恢复,或者是记录用户的一些喜好和用户的登录信息等等. 这就需要涉及到数据的持久化了,所谓数据持久化就是数据的本地保存,将数据从内存中迁入到存储器上.网上有很多种数据持久化的方法,如实现自己实现I/O.数据库.云或则走第三方接口等等.但是有时候可能只是进行一些简单的数据存储,如用户的偏好设置.用户的sessionID等等,这时候使用上述方法便显得有点兴师动众了,现在需要一种更加轻量化的操作方式. 一.认识 NSUserDef

随机推荐