一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第1天,点击查看活动详情。
最近在项目有使用到低功耗蓝牙相关的,所以在此写一下蓝牙的使用及使用中遇到的问题,如果文中有问题的话,欢迎各位掘友指正。
一般我们使用蓝牙的主要流程通常如下:
- 开始一个中心管理对象
- 发现并且连接广告中的设备
- 在连接设备之后扫描数据。
- 针对设备服务的特征发送读写请求
- 订阅支持notified(在数据更新时会主动上报)的特征。
我们常用的属性和方法如下:
CBCentralManager
CBCentralManager对象,就是所谓的中心管理对象,是本地中心设备的CoreBluetooth面向对象的象征。可以通过CBManagerState来获取当前CBCentralManager对象的状态。如下代码所示
public enum CBManagerState : Int {
case unknown = 0 //未知
case resetting = 1 //复位
case unsupported = 2 //该设备不支持蓝牙
case unauthorized = 3//该设备无权限使用蓝牙
case poweredOff = 4 //蓝牙关闭
case poweredOn = 5 //蓝牙打开
}
复制代码
初始化
CBCentralManager的初始化方法有两种
public convenience init(delegate: CBCentralManagerDelegate?, queue: DispatchQueue?)
@available(iOS 7.0, )
public init(delegate: CBCentralManagerDelegate?, queue: DispatchQueue?, options: [String : Any]? = nil)
复制代码
delegate:设置代理
queue:指明在哪个队列处理事件,为nil时表示在主线程处理
options:这个字典有俩个官方的key
CBCentralManagerOptionShowPowerAlertKey:提示蓝牙开关未打开时会弹出警告框
CBCentralManagerOptionRestoreIdentifierKey:系统使用此UID来识别特定的
CentralManager。 因此,为了继续执行应用程序,UID必须保持不变,以便CentralManager成功恢复。
常用的CBCentralManagerDelegate,CBPeripheralDelegate的代理方法比较多,以下只列取部分
连接状态的更新,可以通过此代理方法可以获取当前设备蓝牙是否可用
func centralManagerDidUpdateState(_ central: CBCentralManager)
复制代码
扫描发现设备
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber)
复制代码
注意⚠️:在扫描发现设备中,iOS端不能像安卓一样直接获取蓝牙的Mac地址,iOS端的蓝牙Mac地址是存储在advertisementData中,需要做进一步转化,可通过如下方法转化
let _tempData = advertisementData["kCBAdvDataManufacturerData"]
let macAddress = "\(String(describing: _tempData))".substring(from: "<").substring(to: ">").replacingOccurrences(of: " ", with: "").uppercased().reversed(preserveFormat: false).substring(to: 12).reversed(preserveFormat: false)
复制代码
蓝牙设备已连接
func centralManager( _ central: CBCentralManager, didConnect peripheral: CBPeripheral)
复制代码
蓝牙设备连接失败,可以通过打印错误信息来排查失败原因
func centralManager( _ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?)
复制代码
蓝牙设备已经断开连接
func centralManager( _ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?)
复制代码
指令的发送,是使用CBPeripheral下的 func writeValue( _ data: Data, for characteristic: CBCharacteristic, type: CBCharacteristicWriteType)
方法 其中CBCharacteristicWriteType有两个值分别为withResponse与withoutResponse,有些同学给蓝牙发送指令,但是蓝牙设备无响应,就是这个值弄错了,不清楚用哪个值的同学,可以和嵌软的同学确认下。
关于蓝牙数据的读取与解析在此就不多做阐述了,说到底只是数据包的解析,定义字段的读取等。