分階段了解:
- 掃描
- 連接
- 發(fā)現(xiàn)服務(wù)和特征,寫入或讀取數(shù)據(jù)
掃描類
BTScanner
這個(gè)類是對(duì)CBCentralManager類中scanForPeripherals方法的封裝.而掃描到的外設(shè)會(huì)通過CBCentralManagerDelegate中的代理方法centralManager(_: didDiscover: advertisementData: rssi:)實(shí)時(shí)的回調(diào)出來
首先說一下這兩個(gè)方法的用途及參數(shù)介紹:
/*
* withServices
1.指定掃描外設(shè)的ServiceUUID,一般是和外設(shè)開發(fā)同事協(xié)商好的,所有設(shè)備都共用這一個(gè),是由外設(shè)在廣播時(shí)初始化傳入的,并告知中心設(shè)備
2.這里也可傳nil,表示掃描附近所有設(shè)備,不建議傳nil
* options:傳入字典類型
默認(rèn)值為false表示不會(huì)重復(fù)掃描已經(jīng)發(fā)現(xiàn)的設(shè)備
key:CBCentralManagerScanOptionAllowDuplicatesKey
value:true
你想掃描的目標(biāo)設(shè)備它所包含的serviceUUID數(shù)組
key:CBCentralManagerScanOptionSolicitedServiceUUIDsKey
value:[CBUUID]
*/
centralManager.scanForPeripherals(withServices: nil, options:nil)
可在CBCentralManagerDelegate的代理方法centralManagerDidUpdateState(_ central:)中調(diào)用此掃描方法,因?yàn)樵诔跏蓟疌BCentralManager后會(huì)自動(dòng)調(diào)用此代理方法,而后需手動(dòng)調(diào)用掃描方法開始掃描,做到效率最高,此代理方法在用戶改變藍(lán)牙狀態(tài)后,會(huì)被反復(fù)調(diào)用,為了避免重復(fù)操作,需要對(duì)掃描方法做一些處理.
- 添加一個(gè)定時(shí)器,用于在過了超時(shí)時(shí)間后,自動(dòng)停止掃描外設(shè),節(jié)約用戶的電量
- 添加一個(gè)標(biāo)志位busy表示此時(shí)正在掃描中
開始掃描外設(shè)
func scan(duration:TimeInterval) throws {
guard !busy else { throw BikeScannerError.busy }
guard centralManager != nil else { throw BikeScannerError.noCentralManagerSet }
busy = true
centralManager.scanForPeripherals(withServices: configuration.servicesUUIDs, options:[CBCentralManagerScanOptionAllowDuplicatesKey: true])
timer = Timer.scheduledTimer(timeInterval: duration, target: self, selector: #selector(timerElapsed), userInfo: nil, repeats: false)
}
結(jié)束掃描的方法
func endScan() -> Void {
centralManager.stopScan()
busy = false
if let timer = timer {
timer.invalidate()
//成員變量scanHandlers是一個(gè)閉包scanHandlers?.completionHandler(discoveries)
}
discoveries.removeAll()
}
調(diào)用掃描方法后,就會(huì)自動(dòng)調(diào)用下面這個(gè)代理方法
/*
* central:中心設(shè)備
* peripheral:發(fā)現(xiàn)的外設(shè)
* advertisementData:掃描到外設(shè)廣播的數(shù)據(jù)
* rssi:外設(shè)的信號(hào)強(qiáng)度
*/
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber)
如果外設(shè)是手機(jī)設(shè)備,那么這個(gè)外設(shè)僅可以通過advertisementData發(fā)送包含兩個(gè)字段的數(shù)據(jù),通過上面的回調(diào)方法,接收廣播數(shù)據(jù):
[
CBAdvertisementDataLocalNameKey:"我是外設(shè)的名字",
CBAdvertisementDataServiceUUIDsKey:[serviceUUID]
]
所以第一步需要新建個(gè)模型(BTDiscovery)將掃描回調(diào)的信息存起來
struct BTDiscovery {
var advertisementData: [String : Any]
var RSSI: NSNumber
var peripheral:CBPeripheral
//外設(shè)的名字
var localName:String? {
return advertisementData[CBAdvertisementDataLocalNameKey] as? String
}
//服務(wù)id
var uuid:Array<CBUUID>? {
return advertisementData[CBAdvertisementDataServiceUUIDsKey] as? Array<CBUUID>
}
//檢索目標(biāo)設(shè)備是否以約定字符串命名 比如: "Bluetooth1234"
func hasPrefix(_ peripheralName:String) -> Bool {
if let name = localName, name.hasPrefix(peripheralName) {
return true
}
else{
return false
}
}
}
extension BTDiscovery: Hashable, Equatable {
var hashValue: Int {
return peripheral.identifier.hashValue
}
}
func ==(lhs:BTDiscovery, rhs:BTDiscovery) -> Bool {
return lhs.peripheral == rhs.peripheral
}
接下來在回調(diào)方法中完成初始化,并存入成員變量discoveries數(shù)組中:
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
//用于避免重復(fù)掃描的標(biāo)志位,后面會(huì)說到用處
guard busy else { return }
let remotePeripheral = BikePeripheral(peripheral)
let discovery = BikeDiscovery(advertisementData: advertisementData, remotePeripheral: remotePeripheral, RSSI: Int(RSSI))
if discovery.hasPrefix("BT") {
discovery.peripheral.start(withConfiguration: configuration)
//通過信號(hào)強(qiáng)度來過濾掉一些設(shè)備
if discovery.RSSI < 1 && discovery.RSSI > -75 {
//成員變量scanHandlers是一個(gè)閉包
scanHandlers?.progressHandler?(self, discovery)
}
discoveries.insert(discovery)
}
}
BikePeripheral是對(duì)CBPeripheral的再次封裝,在發(fā)現(xiàn)服務(wù)和特征,寫入或讀取數(shù)據(jù)小節(jié)中會(huì)講到,此處可忽略
其中變量scanHandlers聲明如下:
private var scanHandlers:(progressHandler:ScanProgressHandler?, completionHandler:ScanCompletionHandler)?
下篇將介紹藍(lán)牙連接類,戳這里
具體代碼請(qǐng)參考GitHub鏈接