【iOS官方文档翻译】iOS的蓝牙连接、数据接收及发送

说明:苹果官方开发文档中涉及一些名词:Central(中心设备)、Peripheral(外围设备)、advertising(广告)、Services(服务)、Characteristic(特征)等,请点击查看我的另一篇翻译


目录:

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

步骤2.搜索外围设备

步骤3.连接外围设备

步骤4.获得外围设备的服务

步骤5.获得服务的特征

步奏6.从外围设备读数据(直接读取和订阅两种方法)

步骤7.给外围设备发送数据


步骤一.开启Central Manager

CBCentralManager 是Core Bluetooth的一个对象,代表一个本地中心设备,在使用任何蓝牙传输前,你必须给CBCentralManager实例分配内存和初始化。可以通过CBCentralManager类的initWithDelegate:queue:options: 方法:

myCentralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil options:nil];

在这个例子中,self会被设置为接收所有中心设备角色的事件的代理,设置dispatch queue为nil后,central manager会通过主线程来处理这些事件。ViewController需要实现CBCentralManagerDelegate,CBPeripheralDelegate这两个代理


当创建了一个central manager,会回调代理的centralManagerDidUpdateState:方法,你必须实现这个代理方法来确定中心设备是否支持BLE以及是否可用


步骤二.搜索正在广告的外围设备


中心设备的第一个任务是搜索你的APP可以连接的外围设备,正如上一篇文章中提到的,广告(advertising)是外围设备使其被周围设备发现的主要方法,你可以通过CBCentralManager类的scanForPeripheralsWithServices:options: 方法,搜索任何正在广告的外围设备:

[myCentralManager scanForPeripheralsWithServices:nil options:nil];

你调用了scanForPeripheralsWithServices:options: 方法来搜索可连接的外围设备后,central manager 在每次搜索到一个外围设备都会回调其代理的centralManager:didDiscoverPeripheral:advertisementData:RSSI: 方法。任何被搜索到的外围设备都以CBPeripheral类的方式返回。像下面的代码,你可以实现这个代理方法来罗列出所有被搜索到的蓝牙设备:

- (void)centralManager:(CBCentralManager *)central

 didDiscoverPeripheral:(CBPeripheral *)peripheral

     advertisementData:(NSDictionary *)advertisementData

                  RSSI:(NSNumber *)RSSI {

 

    NSLog(@"Discovered %@", peripheral.name);

    ...

当你已经找到了一个你需要连接的外围设备,停止搜索其它设备来节省电量。

[myCentralManager stopScan];
NSLog(@"Scanning stopped”);

步骤三.连接一个你搜索到并希望连接的外围设备

  

在你搜索到一个外围设备,并且它广告了你需要的服务,你可以请求和这个外围设备连接,通过调用 CBCentralManager类的connectPeripheral:options:方法,简而言之,调用这个方法并且说明你需要连接的外围设备:

 [myCentralManager connectPeripheral:peripheral options:nil];

假设连接成功了,central manager 会回调其代理方法centralManager:didConnectPeripheral: ,你可以实现这个方法来打印“外围设备连接”:

- (void)centralManager:(CBCentralManager *)central

  didConnectPeripheral:(CBPeripheral *)peripheral {

 

    NSLog(@"Peripheral connected");

    ...
</pre><p></p><p style=""></p><p style="">在你开始和外围设备交互之前,你应该设置外围设备的代理以确保它能接收合适的回调,像这样</p><div><pre name="code" class="objc" style="color: rgb(102, 102, 102);">peripheral.delegate = self;

步骤四.搜索你已经连接的外围设备的服务

在你与外围设备建立连接之后,你可以开始勘察它的数据。第一步是勘察外围设备提供了什么服务,因为外围设备广告的数据有大小限制,你或许会发现外围设备提供比它广告的还有更多服务。你可以通过CBPeripheral类的discoverServices: 方法来发现一个外围设备提供的所有服务:

 [peripheral discoverServices:nil];


当发现了具体的服务,外围设备(已经连接的 CBPeripheral类)会回调其代理的peripheral:didDiscoverServices: 方法。Core Bluetooth 建立CBService 类的array数组——存储外围设备的每一个服务。像下面的代码,你可以实现这个代理方法来获得发现的服务列表:

- (void)peripheral:(CBPeripheral *)peripheral

didDiscoverServices:(NSError *)error {

 

    for (CBService *service in peripheral.services) {

        NSLog(@"Discovered service %@", service);

        ...

    }

    …

步骤五.搜索服务的特征

假定你已经找到了你需要的服务,下一步就是探索服务的所有“特征”(characteristics),搜索一个服务的所有特征只要调用 CBPeripheral类的discoverCharacteristics:forService:方法,参数为具体的服务:

    NSLog(@"Discovering characteristics for service %@", interestingService);

    [peripheral discoverCharacteristics:nil forService:interestingService];

当发现了指定服务的特征,外围设备会回调peripheral:didDiscoverCharacteristicsForService:error:代理方法。Core Bluetooth建立存储CBCharacteristic实例的array数组———每一个都代表一个发现了的特征。下面的示例就是实现这个代理方法来简单地打印每个发现了的特征:


- (void)peripheral:(CBPeripheral *)peripheral

didDiscoverCharacteristicsForService:(CBService *)service

             error:(NSError *)error {

 

    for (CBCharacteristic *characteristic in service.characteristics) {

        NSLog(@"Discovered characteristic %@", characteristic);

        ...

    }

    ...

步骤六.取得特征的值(就是从外围设备取数据)

一个特征包含一个代表外围设备服务的简单值,例如,有一个健康温度计服务,这个服务有一个温度测量特征,而这个特征有一个摄氏温度的值,你可以直接读取或者订阅这个特征来取得这个特征对应的值。

6.1直接读取特征的值

你得到你希望得到的服务的某个特征后,你可以通过调用CBPeripheral类的readValueForCharacteristic:方法来读取这个特征对应的值,参数为需要读取的特征:

  NSLog(@"Reading value for characteristic %@", interestingCharacteristic);

  [peripheral readValueForCharacteristic:interestingCharacteristic];

当你试图去读一个特征对应的值,外围设备会回调它的代理方法

peripheral:didUpdateValueForCharacteristic:error:去取值,如果值成功返回,你可以通过特征的value属性来获得它:

- (void)peripheral:(CBPeripheral *)peripheral

didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic

             error:(NSError *)error {

 

    NSData *data = characteristic.value;

    // parse the data as needed

    ...

6.2订阅一个特征的值

在某些使用情况下,通过 readValueForCharacteristic: 读取一个特征的值会很有效率,但是这不是获得值改变的最有效率方法,对于大部分特征值的改变——例如,你在给定时间的心率,你应该通过订阅来获得它。当你订阅了一个特征的值,你可以在值改变的时候接收到通知。你可以通过CBPeripheral类的setNotifyValue:forCharacteristic: 方法来订阅你需要的特征,参数为YES,以及需要订阅的特征:

[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];

当你试图去订阅(或取消订阅)一个特征时,外围设备会调用 它的代理的peripheral:didUpdateNotificationStateForCharacteristic:error:方法,如果订阅请求失败,你可以通过实现这个方法来获得错误原因:

- (void)peripheral:(CBPeripheral *)peripheral

didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic

             error:(NSError *)error {

 

    if (error) {

        NSLog(@"Error changing notification state: %@",

           [error localizedDescription]);

    }

    ...

当你成功订阅了某个特征,在特征的值改变时,外围设备会通知你的app,每次值改变,外围设备会调用 其代理的peripheral:didUpdateValueForCharacteristic:error:方法。你可以通过实现这个方法来获得改变的值,这个方法和上面直接读取时回调的方法一样。


步骤七.写值到特征中(就是发数据给外围设备)

在某些使用情况下,需要写数据到特征中,这是可行的。例如,你的app与一个BLE电子温度调节器交互,你或许需要提供给调节器一个值来设定房间的温度,如果特征的值可以被写,你可以通过CBPeripheral类的writeValue:forCharacteristic:type:方法把数据(NSData的实例)写到特征的值里:

NSLog(@"Writing value for characteristic %@", interestingCharacteristic);

    [peripheral writeValue:dataToWrite forCharacteristic:interestingCharacteristic

        type:CBCharacteristicWriteWithResponse];

当你试图去写特征的值时,你需要说明你需要用哪种类型的写的方法。上面的例子中,写的方法为CBCharacteristicWriteWithResponse,用这个方法,外围设备会让你的app知道写操作是否成功(就是)。更多写的方法请看CBPeripheral Class Reference里面的CBCharacteristicWriteType枚举。


使用CBCharacteristicWriteWithResponse方法给外围设备写数据时,会回调 其代理的peripheral:didWriteValueForCharacteristic:error:方法。如果写数据失败,可以通过这个方法找到失败的原因。像这样:


- (void)peripheral:(CBPeripheral *)peripheral

didWriteValueForCharacteristic:(CBCharacteristic *)characteristic

             error:(NSError *)error {

 

    if (error) {

        NSLog(@"Error writing characteristic value: %@",

            [error localizedDescription]);

    }

    ...

  简单写了个测试demo,见下图,输入框为待发送的文本,Label为接收到的文本,我的蓝牙测试模块是返回我发送的数据。

  这个demo只连接指定蓝牙名字的蓝牙设备,测试时,请将第十行的HMSoft改为自己的外围设备名称,这个demo比较水,每次viewdidload后就去搜索蓝牙设备并连接,不便于测试,自己可以加断点调试。

  另外由于我的测试的蓝牙设备不支持CBCharacteristicWriteWithResponse,发送数据时都返回没有权限的错误,所以我用的CBCharacteristicWriteWithoutResponse。成功后不会回调didWriteValueForCharacteristic方法

下载demo :https://github.com/dolacmeng/Bluetooth













  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 以下是一个简单的iOS蓝牙连接发送消息的代码示例: 1. 导入CoreBluetooth库 ```Swift import CoreBluetooth ``` 2. 声明并初始化CentralManager和Peripheral对象 ```Swift var centralManager: CBCentralManager! var peripheral: CBPeripheral! ``` 3. 初始化CBCentralManager ```Swift centralManager = CBCentralManager(delegate: self, queue: nil) ``` 4. 扫描周围的蓝牙设备 ```Swift centralManager.scanForPeripherals(withServices: nil, options: nil) ``` 5. 处理扫描到的蓝牙设备 ```Swift func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { if peripheral.name == "Your Bluetooth Device Name" { self.peripheral = peripheral self.peripheral.delegate = self centralManager.connect(peripheral, options: nil) } } ``` 6. 处理连接成功的回调函数 ```Swift func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { print("Connected to: \(peripheral.name ?? "Unknown Device")") peripheral.discoverServices(nil) } ``` 7. 处理发现服务的回调函数 ```Swift func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { guard let services = peripheral.services else { return } for service in services { print("Service found with UUID: \(service.uuid)") peripheral.discoverCharacteristics(nil, for: service) } } ``` 8. 处理发现特征的回调函数 ```Swift func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { return } for characteristic in characteristics { print("Characteristic found with UUID: \(characteristic.uuid)") } } ``` 9. 发送消息 ```Swift func sendMessage() { let message = "Hello, World!" guard let data = message.data(using: .utf8) else { return } if let characteristic = peripheral.services?.first?.characteristics?.first { peripheral.writeValue(data, for: characteristic, type: .withResponse) } } ``` 以上是基本的蓝牙连接发送消息的代码示例,具体实现可以根据实际需求进行修改。 ### 回答2: iOS蓝牙连接发送消息的代码如下: 1. 首先,需要导入CoreBluetooth框架。在代码中导入`CoreBluetooth`库。 ```swift import CoreBluetooth ``` 2. 创建一个蓝牙中心管理器对象来扫描并连接蓝牙外设。 ```swift class BluetoothManager: NSObject, CBCentralManagerDelegate { var centralManager: CBCentralManager! override init() { super.init() centralManager = CBCentralManager(delegate: self, queue: nil) } func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == .poweredOn { // 蓝牙已打开,可以开始扫描和连接外设 central.scanForPeripherals(withServices: nil, options: nil) } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { // 发现外设,可以根据名称或其他信息过滤 if peripheral.name == "YourPeripheralName" { // 停止扫描并连接外设 central.stopScan() central.connect(peripheral, options: nil) } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { // 已成功连接外设,可以开始进行数据通信 peripheral.delegate = self peripheral.discoverServices(nil) } } ``` 3. 创建一个外设代理类来处理外设的操作。 ```swift extension BluetoothManager: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { guard let services = peripheral.services else { return } for service in services { peripheral.discoverCharacteristics(nil, for: service) } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { return } for characteristic in characteristics { if characteristic.properties.contains(.write) { // 发送消息的特征 let message = "你好,蓝牙设备!" let data = message.data(using: .utf8) peripheral.writeValue(data!, for: characteristic, type: .withoutResponse) } } } } ``` 4. 在你的ViewController或AppDelegate中实例化蓝牙管理器类。 ```swift let bluetoothManager = BluetoothManager() ``` 上述代码可以实现以下功能: 1. 初始化蓝牙中心管理器; 2. 扫描并过滤外设; 3. 连接外设,并发现外设的服务和特征; 4. 发送消息给外设。 请根据实际情况进行相应更改,例如替换`"YourPeripheralName"`为要连接的外设名称,以及根据需要使用其他特征的属性和值。 ### 回答3: 在iOS端,蓝牙通信主要通过CoreBluetooth框架来实现。下面是一个简单的示例代码,用于实现蓝牙连接发送消息: 首先,需要在项目中导入CoreBluetooth框架,并在需要使用蓝牙功能的地方引入`import CoreBluetooth`。 然后,创建一个蓝牙管理器和一个蓝牙特征的全局变量: ```swift var centralManager: CBCentralManager! var peripheralDevice: CBPeripheral! var characteristic: CBCharacteristic! ``` 接下来,在需要进行蓝牙通信的地方初始化蓝牙管理器: ```swift centralManager = CBCentralManager(delegate: self, queue: nil) ``` 然后,实现CBCentralManagerDelegate代理方法,用于处理蓝牙状态的变化以及扫描到的外设: ```swift extension ViewController: CBCentralManagerDelegate { func centralManagerDidUpdateState(_ central: CBCentralManager) { switch central.state { case .poweredOn: central.scanForPeripherals(withServices: nil, options: nil) default: print("蓝牙不可用") } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { // 扫描到外设后的处理逻辑 if peripheral.name == "设备名" { // 根据设备名过滤外设 peripheralDevice = peripheral peripheralDevice.delegate = self centralManager.connect(peripheralDevice, options: nil) } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { peripheralDevice.discoverServices(nil) } } ``` 然后,实现CBPeripheralDelegate代理方法,用于处理服务和特征的发现以及数据发送: ```swift extension ViewController: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { if let services = peripheral.services { for service in services { peripheralDevice.discoverCharacteristics(nil, for: service) } } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let characteristics = service.characteristics { for characteristic in characteristics { if characteristic.uuid == CBUUID(string: "特征UUID") { self.characteristic = characteristic break } } } } func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if error != nil { print("发送消息失败") } else { print("发送消息成功") } } } ``` 最后,调用发送消息的方法来发送数据: ```swift func sendMessage(message: String) { if let data = message.data(using: .utf8) { peripheralDevice.writeValue(data, for: characteristic, type: .withResponse) } } ``` 以上是一个简单的iOS蓝牙连接发送消息的代码示例,具体的逻辑根据项目的需求来进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值