版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rigel_xu/article/details/87890641
基于CoreBluetooth与蓝牙4.0设备通讯非常方便,一句话总结就是中心-设备-服务-特征,对应的关键API为CBCentralManager-CBPeripheral-CBService-CBCharacteristic。
可以通过LightBlue查看你的蓝牙设备相关信息,也可以发送简单指令。
CBCentralManager scanForPeripherals时需要注意两点:
- APP需要后台扫描withServices必须指定要扫描的服务的UUID,不传系统会忽略不执行后台扫描;
- 指定服务UUID无法找到设备,可能是芯片不支持在没有连接的情况下扫描服务。如果确实需要就找芯片开发沟通,非必要就扫描所有设备再通过设备名称等过滤连接后再找到服务。
设定特征uuid为:
private let Characteristic_UUID: String = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"
一、使用中心对象查找设备
centralManager = CBCentralManager.init(delegate: self, queue: .main)
func centralManagerDidUpdateState(_ central: CBCentralManager) {
switch central.state {
case .unknown:
print("unknown")
case .resetting:
print("resetting")
case .unsupported:
print("unsupported")
case .unauthorized:
print("unauthorized")
case .poweredOff:
print("poweredOff")
case .poweredOn:
print("ok")
central.scanForPeripherals(withServices: [], options: nil)
}
}
二、连接设备并查找服务
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
self.peripheral = peripheral
// 根据设备名称来过滤
if ((peripheral.name != nil) && (peripheral.name?.hasPrefix("XXX"))!) {
central.connect(peripheral, options: nil)
central.stopScan();
}
}
三、获取指定服务,查询指定特征
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
for service: CBService in peripheral.services! {
print("设备中的服务有:\(service)")
}
//假设外设中只有一个服务
let service = peripheral.services?.last
//根据UUID寻找服务中的特征
peripheral.discoverCharacteristics([CBUUID.init(string: Characteristic_UUID)], for: service!)
}
四、发现指定特征
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic: CBCharacteristic in service.characteristics! {
print("外设中的特征有:\(characteristic)")
}
self.characteristic = service.characteristics?.last
}
五、向特征发送十六进制指令
此特征必须是约定的可写入特征(是否可写入与设备的通讯协议一般都会定好,也可以通过LightBlue查看),指令通讯一般是十六进制指令,假设指令为打开(0x2601),为方便操作封装一个十六进制字符串转data的方法:
func dataWithHexString(hex: String) -> Data {
var hex = hex
var data = Data()
while(hex.count > 0) {
let subIndex = hex.index(hex.startIndex, offsetBy: 2)
let c = String(hex[..<subIndex])
hex = String(hex[subIndex...])
var ch: UInt32 = 0
Scanner(string: c).scanHexInt32(&ch)
var char = UInt8(ch)
data.append(&char, count: 1)
}
return data
}
调用此方法:
if peripheral == nil || characteristic == nil {
print("no peripheral connected")
return;
}
let data = dataWithHexString(hex: "2601")
peripheral?.writeValue(data, for: characteristic!, type: CBCharacteristicWriteType.withoutResponse)
这里需要注意,一般的写入操作CBCharacteristicWriteType的类型是withResponse需要设备有响应,但是具体设备要看芯片设计,如果发现没有成功尝试使用withoutResponse。
写入有响应会回调:
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
print("写入数据")
}
简单的基于CoreBluetooth发送指令就介绍这些,如果涉及与蓝牙设备大数据传输代码和通讯协议相对较复杂,另外还需要注意发送数据的间隔,因为限于载波大小如果单次数据较大可能会没有响应,间隔参考值: