章节连接

iOS Core Bluetooth_1 概述
iOS Core Bluetooth_2 基础知识
iOS Core Bluetooth_3 用作中央设备的常用方法(1/2)[swift实现]
iOS Core Bluetooth_4 用作中央设备的常用方法(2/2)[swift实现]

写在前面

在上一节中主要介绍了CoreBluetooth中中央设备的实例化、扫描与连接。这一节继续介绍,在连接设备后的查询服务与特征字段,读取、写入、订阅等操作。

  • 实例化中央管理器对象
  • 发现并连接到正在广播的外围设备
  • 在连接到外围设备后浏览其数据
  • 发送读写请求到外围服务的特征值
  • 订阅特征值以在更新时被通知

在本文中找到的代码示例是简单抽象的。您可能需要进行适当的更改以将其合并到您的真实应用中。

1 发现您所连接的外围设备的服务

建立与外围设备的连接后,您可以浏览其数据。与外围设备进行数据交互的第一步是发现其可用的服务。由于外围设备可以广播的数据量受到大小限制,因此您可能会发现外围设备提供的服务多于其广播的内容(在其广播包中)。您可以通过调用(进行连接后的)外围设备的discoverServices:方法来发现外围设备提供的所有服务,如下所示:

peripheral.discoverServices([TransferService.serviceUUID])

注意: 在实际应用中,通常不传入nil参数,因为这样做会返回外围设备上所有可用的服务。由于外围设备可能包含比您所需要的更多的服务,因此发现所有这些外围设备可能会浪费电池寿命并不必要的浪费时间。取而代之的是,通常指定您已经知道有兴趣发现的服务的UUID,如本例中:[TransferService.serviceUUID]

发现指定的服务后,外围设备(CBPeripheral您连接到的对象)将调用peripheral:didDiscoverServices:其代理方法。核心蓝牙创建一个CBService对象数组保存每个在外围设备上发现的服务并遍历指定字段。如下所示,您可以实现此代理方法来访问发现的服务数组(通常通过extension实现):

func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {if let error = error {os_log("Error discovering services: %s", error.localizedDescription)cleanup()return}// Discover the characteristic we want...// Loop through the newly filled peripheral.services array, just in case there's more than one.guard let peripheralServices = peripheral.services else { return }for service in peripheralServices {peripheral.discoverCharacteristics([TransferService.characteristicUUID], for: service)}
}

2 发现服务的特征字段

当您找到自己感兴趣的服务时,探索外围设备必须提供的下一步就是发现该服务的所有特征。发现服务的所有特征就像发现外围设备的所有服务或指定发现某一种服务一样简单,通过调用discoverCharacteristics:forService:方法,如下所示:(下文中订阅了指定的字段)

func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {// Deal with errors (if any).if let error = error {os_log("Error discovering characteristics: %s", error.localizedDescription)cleanup()return}// Again, we loop through the array, just in case and check if it's the right oneguard let serviceCharacteristics = service.characteristics else { return }for characteristic in serviceCharacteristics where characteristic.uuid == TransferService.characteristicUUID {// If it is, subscribe to ittransferCharacteristic = characteristicperipheral.setNotifyValue(true, for: characteristic)}// Once this is complete, we just need to wait for the data to come in.}

3 检索特征值(读取和订阅)

特征包含单个值,该值表示有关外围设备服务的信息。例如,健康温度计服务的温度测量特性可以具有指示摄氏温度的值。您可以通过直接阅读或订阅来检索特征的值。

3-1 读取特征值

找到感兴趣的服务的特征后,可以通过调用外围设备的readValue(for characteristic: CBCharacteristic)或readValue(for descriptor: CBDescriptor)方法并指定适当的特征来读取特征的值,如下所示:

peripheral.readValue(for characteristic: CBCharacteristic)

当您调用此方法以读取特征值时,外围设备将调用其委托对象的方法。如果外设成功读取特征值,则可以通过特征的属性对其进行访问。peripheral(_:didUpdateValueFor:error:)value

并非所有特征都具有可读的值。您可以通过访问枚举的相关属性来确定特征值是否可读。

具体代理方法实现如下:
注意,所有的,不管是 read , notify 的特征的值都是在这里读取

   func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)-> (){if(error != nil){return}switch characteristic.uuid.uuidString {case "***************":print("接收到了设备的温度特征的值的变化")default:print("收到了其他数据特征数据: \(characteristic.uuid.uuidString)")}}

3-2 订阅特征值

尽管使用该readValueForCharacteristic:方法读取特征值对于静态值是有效的,但它并不是检索动态值的最有效方法。订阅随时间变化的特征值,例如您的心率。订阅特征值时,当值更改时,您会收到来自外围设备的通知。

通过调用外设的setNotifyValue:forCharacteristic:方法,将第一个参数指定为true,可以订阅您感兴趣的特征的值,如下所示:

peripheral.setNotifyValue(true, for: characteristic)

当您订阅(或取消订阅)特征值时,外围设备将调用peripheral:didUpdateNotificationStateForCharacteristic:error:其委托对象的方法。如果订阅请求由于任何原因失败,则可以实现此委托方法以访问错误原因,如以下示例所示:

func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {// Deal with errors (if any)if let error = error {os_log("Error changing notification state: %s", error.localizedDescription)return}// Exit if it's not the transfer characteristicguard characteristic.uuid == TransferService.characteristicUUID else { return }if characteristic.isNotifying {// Notification has startedos_log("Notification began on %@", characteristic)} else {// Notification has stopped, so disconnect from the peripheralos_log("Notification stopped on %@. Disconnecting", characteristic)cleanup()}}

注意: 并非所有特征都提供订阅。您可以通过检查特征的properties属性是否包含CBCharacteristicPropertyNotify或CBCharacteristicPropertyIndicate常量来确定特征是否提供订阅。

成功订阅特征值后,外围设备在值更改后会通知您的应用。每次更改值时,外围设备都会调用peripheral:didUpdateValueForCharacteristic:error:其委托对象的方法。要检索更新后的值,可以采用与上述读取特性值中所述相同的方法来实现此方法。

4 写特征值

有时写一个特征的值很有意义。例如,如果您的应用程序与蓝牙低功耗数字恒温器交互,则可能需要为恒温器提供一个设置房间温度的值。如果某个特征的值是可写的,则可以NSData通过调用外围设备的writeValue:forCharacteristic:type:方法将其值与数据(的一个实例)一起写入,如下所示:

写入特征值时,可以指定要执行的写入类型。在上面的示例中,写入类型可以为CBCharacteristicWriteWithResponse,它指示外围设备通过调用peripheral:didWriteValueForCharacteristic:error:其代理对象的方法来让您的应用知道写入是否成功。您可以实现此代理方法来处理错误情况,如以下示例所示:

//MARK: - 检测中心向外设写数据是否成功func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {if(error != nil){print("发送数据失败!error信息:\(String(describing: error))")}}

相反,如果您将写入类型指定为CBCharacteristicWriteWithoutResponse,则写入操作将尽力而为,并且不能保证也不报告传送。外设不调用任何代理方法。

注意: 特征可能仅支持某些类型的写入,或完全不支持。您可以通过检查properties特征的常量CBCharacteristicPropertyWriteWithoutResponse或CBCharacteristicPropertyWrite常量之一来确定特征支持的写入类型(如果有)。

iOS Core Bluetooth_4 用作中央设备的常用方法(2/2)[swift实现]相关推荐

  1. iOS Core Bluetooth_3 用作中央设备的常用方法(1/2)[swift实现]

    章节连接 iOS Core Bluetooth_1 概述 iOS Core Bluetooth_2 基础知识 iOS Core Bluetooth_3 用作中央设备的常用方法(1/2)[swift实现 ...

  2. iOS 蓝牙 Bluetooth 外围设备 中央设备

    今天项目中的蓝牙功能已经开发完毕,总结一下. CoreBluetooth.framework:功能强大的蓝牙框架,只要该设备支持蓝牙4.0,就可以进行蓝牙传输,只要该设备支持蓝牙4.0. CoreBl ...

  3. iOS Core Bluetooth_1 概述

    章节连接 iOS Core Bluetooth_1 概述 iOS Core Bluetooth_2 基础知识 iOS Core Bluetooth_3 用作中央设备的常用方法(1/2)[swift实现 ...

  4. iOS Core Bluetooth_2 基础知识

    章节连接 iOS Core Bluetooth_1 概述 iOS Core Bluetooth_2 基础知识 iOS Core Bluetooth_3 用作中央设备的常用方法(1/2)[swift实现 ...

  5. 图层几何学 -- iOS Core Animation 系列二

    <图层树和寄宿图 -- iOS Core Animation 系列一>介绍了图层的基础知识和一些属性方法.这篇主要内容是学习下图层在父图层上怎么控制位置和尺寸的. 1.布局 首先看一张例图 ...

  6. 国内用户ios android比例,国内iOS、Android系统的设备总量已达到了2亿

    首先,在2012年第三季度时,国内iOS.Android系统的设备总量已达到了2亿.在今年3月的时候,这一指标只有8700万,也就是说设备在半年内增长了125%.而在设备量大增的同时,用户也变得依赖移 ...

  7. IOS Core Image之二

    在上篇博客IOS Core Image之一中了解了下CIImage.CIFilter.CIContext三个类的使用,这篇了解下滤镜链(多滤镜)和人脸检测(不是人脸识别). 一.多滤镜 1.有些效果不 ...

  8. iOS - Core Animation 核心动画

    1.UIView 动画 具体讲解见 iOS - UIView 动画 2.UIImageView 动画 具体讲解见 iOS - UIImageView 动画 3.CADisplayLink 定时器 具体 ...

  9. iOS Core ML与Vision初识

    代码地址如下: http://www.demodashi.com/demo/11715.html 教之道 贵以专 昔孟母 择邻处 子不学 断机杼 随着苹果新品iPhone x的发布,正式版iOS 11 ...

最新文章

  1. Java基础 ----常用时间类
  2. Package CJK Error: Invalid character code. 问题解决方法--xelatex和pdflatex编译的转换
  3. python网站框架下载_Python搭建网站框架
  4. nssl1469-W【dp】
  5. 特性和混入不是面向对象的
  6. 【有返回值的回溯法】剑指offer——面试题66:矩阵中的路径(回溯法)
  7. mysql一般要配置的几个小节及选项是_MySQL - 必知必会(下)
  8. 一文了解 Serverless 2021 大事件
  9. conda环境下更新pip失败
  10. 工业企业能源管理系统
  11. DHCP中继配置(思科)
  12. 计算机用户名,账户名更改
  13. 消息中间件MQ与RabbitMQ
  14. 支付宝支付原理以及测试接口获取支付url
  15. OpenStack实战
  16. 二维特征分类的基础_带你搞懂朴素贝叶斯分类算法
  17. 用思维导图和孩子们一起了解“什么是春节”
  18. COM:根系微生物组研究中的合成群落还原法
  19. 山西宗教文化漫谈(四)——云冈:东方艺术宝库
  20. 态度篇·与其混不如滚

热门文章

  1. 第10课:生活中的迭代模式——下一个就是你了
  2. java任务系统设计_任务调度系统-任务依赖的设计
  3. CSDN豪华盲盒, 一发入魂直接获得iPhone13, 请叫我欧皇 !
  4. cas87345-22-0/5-(羟苯基)-10,15,20-苯基卟啉/分子式:C44H30N4O/分子量:630.7352/货期一周
  5. C语言杨辉三角的程序分析,C语言:打印杨辉三角
  6. 聚苯乙烯/聚4-乙烯基吡啶功能微球/CF3-PPFPA-PS聚苯胺/聚苯乙烯微球的制备
  7. 人工智能数学基础:利用导数判断函数单调性、凹凸性、极值、最值和描绘函数图形
  8. 阿里云Kuberneters微服务部署案例
  9. 思岚科技激光雷达在室外使用效果如何?
  10. 蓝牙相关学习:4.1.BLE空口包结构