以前作过蓝牙链接的功能,可是要么是直接在别人的基础上更改和新增功能,要么就是囫囵吞枣直接按别人的文章一步步写过去,写完了本身也仍是没有头绪,仅仅是能用而已。此次借设计YModem升级工具及蓝牙多设备同时升级功能的机会,从头梳理一遍蓝牙链接的功能,并记之以文字。
更详细信息能够查看官方蓝牙框架文档: 《Core Bluetooth Programming Guide》文章连接:蓝牙链接(swift版)html
蓝牙2.0是传统蓝牙,也叫作经典蓝牙。git
蓝牙2.0如要上架需进行MFI认证,使用ExternalAccessory框架。github
蓝牙4.0由于耗电低,也叫作低功耗蓝牙(BLE)。它将三种规格集于一体,包括传统蓝牙技术、高速技术和低耗能技术。swift
蓝牙4.0使用CoreBluetooth框架。数组
一个外设包含多个服务,而每个服务中又包含多个特征,特征包括特征的值和特征的描述.每一个服务包含多个字段,字段的权限有read(读)、write(写)、notify(通知/订阅)。闭包
正常多使用write和notify。并发
蓝牙开发分为两种模式,中心模式(central),和外设模式(peripheral)。通常来说,咱们须要在软件内链接硬件,经过链接硬件给硬件发送指令以完成一些动做的蓝牙开发都是基于中心模式(central)模式的开发,也就是说咱们开发的app是中心,咱们要链接的硬件是外设。若是须要其余设备链接手机蓝牙,并对手机进行一些操做,那就是基于外设模式(peripheral)的开发。app
swift版:框架
oc版:ide
链接外设 connectPeripheral
扫描外设中的服务 discoverServices
扫描外设对应服务的特征 discoverCharacteristics
订阅特征的通知 setNotifyValue:forCharacteristic:
经常使用方法记录用到的方法, 代码是具体运用
import CoreBluetooth
private let BLE_WRITE_UUID = "xxxx" private let BLE_NOTIFY_UUID = "xxxx" var centralManager:CBCentralManager? ///扫描到的全部设备 var aPeArray:[CBPeripheral] = [] //当前链接的设备 var pe:CBPeripheral? var writeCh: CBCharacteristic? var notifyCh: CBCharacteristic?
实例化
var centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)
开始扫描
centralManager.scanForPeripherals(withServices: serviceUUIDS, options: nil)
链接设备
centralManager.connect(peripheral, options: nil)
断开链接
centralManager.cancelPeripheralConnection(peripheral)
中止扫描
centralManager.stopScan()
发现服务
peripheral.discoverServices(nil)
peripheral.delegate = self
发现特征
peripheral.discoverCharacteristics(nil, for: service)
peripheral.services
对应搜索特征设置通知
peripheral.setNotifyValue(true, for: characteristic)
将CBCenteralManager实例化:
centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey:false])
实例化完成后的回调:
func centralManagerDidUpdateState(_ central: CBCentralManager) { if central.state == CBManagerState.poweredOn { print("powered on") } else { if central.state == CBManagerState.poweredOff { print("BLE powered off") } else if central.state == CBManagerState.unauthorized { print("BLE unauthorized") } else if central.state == CBManagerState.unknown { print("BLE unknown") } else if central.state == CBManagerState.resetting { print("BLE ressetting") } } }
CBPeripheral
扫描设备:
centralManager.scanForPeripherals(withServices: serviceUUIDS, options: nil)
发现设备:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { guard !aPeArray.contains(peripheral), let deviceName = peripheral.name, deviceName.count > 0 else { return } }
链接设备:
centralManager.connect(peripheral, options: nil)
设备链接完成后的回调:
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { print("\(#function)链接外设成功。\ncentral:\(central),peripheral:\(peripheral)\n") // 设置代理 peripheral.delegate = self // 开始发现服务 peripheral.discoverServices(nil) }
Service
设备链接失败的回调:
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { print("\(#function)链接外设失败\n\(String(describing: peripheral.name))链接失败:\(String(describing: error))\n") // 这里能够发通知出去告诉设备链接界面链接失败 }
链接丢失的回调:
func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) { print("\(#function)链接丢失\n外设:\(String(describing: peripheral.name))\n错误:\(String(describing: error))\n") // 这里能够发通知出去告诉设备链接界面链接丢失 }
搜索服务(设备链接成功的回调处执行):
peripheral.discoverServices(nil)
发现服务:
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { if let error = error { print("\(#function)搜索到服务-出错\n设备(peripheral):\(String(describing: peripheral.name)) 搜索服务(Services)失败:\(error)\n") return } else { print("\(#function)搜索到服务\n设备(peripheral):\(String(describing: peripheral.name))\n") } for service in peripheral.services ?? [] { peripheral.discoverCharacteristics(nil, for: service) } }
搜索特征(当发现服务以后即执行搜索):
peripheral.discoverCharacteristics(nil, for: service)
发现特征
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { if let _ = error { print("\(#function)发现特征\n设备(peripheral):\(String(describing: peripheral.name))\n服务(service):\(String(describing: service))\n扫描特征(Characteristics)失败:\(String(describing: error))\n") return } else { print("\(#function)发现特征\n设备(peripheral):\(String(describing: peripheral.name))\n服务(service):\(String(describing: service))\n服务下的特征:\(service.characteristics ?? [])\n") } for characteristic in service.characteristics ?? [] { if characteristic.uuid.uuidString.lowercased().isEqual(BLE_WRITE_UUID) { pe = peripheral writeCh = characteristic } else if characteristic.uuid.uuidString.lowercased().isEqual(BLE_NOTIFY_UUID) { notifyCh = characteristic peripheral.setNotifyValue(true, for: characteristic) } //此处表明链接成功 } }
peripheral
和特征characteristic
,后续发送接收数据时使用获取设备发送的数据:
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) { if let _ = error { return } //拿到设备发送过来的值,可传出去并进行处理 }
发送数据:
peripheral.writeValue(data, for: characteristic, type: .withResponse)
characteristic
须要是写入的特征,不能用其余的特征检测发送数据是否成功:
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) { if let error = error { print("\(#function)\n发送数据失败!错误信息:\(error)") } }
github代码:BleDemo
欢迎相互学习交流,也欢迎去github点个star。