以前作過藍牙鏈接的功能,可是要麼是直接在別人的基礎上更改和新增功能,要麼就是囫圇吞棗直接按別人的文章一步步寫過去,寫完了本身也仍是沒有頭緒,僅僅是能用而已。此次借設計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。