iOS藍芽4.0開發基礎教程

weixin_34293059發表於2016-12-27

一:簡介

目前藍芽開發越來越火,很多外部裝置都使用的是藍芽技術(如:智慧手環,智慧家居,可穿戴裝置等)網上的資料也很多。隨著藍芽低功耗技術BLE(Bluetooth Low Energy)的發展,藍芽技術正在一步步成熟,如今的大部分移動裝置都配備有藍芽4.0,相比之前的藍芽技術耗電量大大降低。本文基於藍芽4.0使用Apple自家的藍芽框架Core Bluetooth講解。如有不當之處,望各位朋友多多提醒!

二:基本概念

  • 中心模式和外設模式
    顧名思義,比如以App作為中心,連線其他外設的場景稱為中心模式,而使用手機作為外設被其他中心裝置操作的場景則被稱為外設模式。

    1176193-cc2931a1de4fef4e.png

    如圖在Core Bluetooth框架API中,左列為中心模式,右列為外設模式

  • Central和Peripheral是什麼?
    Core Bluetooth框架核心的兩個東西:中心Central和外圍裝置Peripheral

    1176193-c55a13fa3704650b.png

    如圖是以APP作為中心Central,連線其他的外設Peripheral的中心模式。在中心模式中本地Central表示為CBCentralManager,用來發現和連線外設Peripheral表示為CBPeripheral。

  • 服務Service和特徵Characteristic是什麼?
    服務Service:外設對外廣播必須要有服務,服務可以是多個,服務裡面又包含了特徵Characteristic
    特徵Characteristic:存在於服務裡面,服務裡面也可以存在多個特徵,特徵就是具體的鍵值對,提供資料的地方。

    1176193-af3145edd5aa2553.png

三:開始使用

這裡以APP為中心模式舉個例

import UIKit
import CoreBluetooth //匯入藍芽框架
//新增藍芽代理
class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {

@IBOutlet weak var tableView: UITableView!
var manager: CBCentralManager?//中心角色
var per: CBPeripheral?//服務
var readCharac: CBCharacteristic? // 讀取特徵
var writeCharac: CBCharacteristic? // 寫入特徵

var deviceArray: [CBPeripheral] = [] //外設資料來源

override func viewDidLoad() {
    super.viewDidLoad()
    //建立中心角色
    manager = CBCentralManager(delegate: self, queue: nil)
}

//判斷藍芽是否開啟,並開始掃描
func centralManagerDidUpdateState(_ central: CBCentralManager) {
    if let central = manager {
        switch central.state {
        case .poweredOn:
            print("藍芽已開啟,請掃描外設")
            manager?.scanForPeripherals(withServices: nil, options: nil)
        case .poweredOff:
            print("藍芽沒有開啟,請先開啟藍芽")
        default:
            break
        }
    }
}

//查詢外設的代理
func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
    //查詢到外設後新增到資料來源裡面,並重新整理tableView資料
    if !deviceArray.contains(peripheral) {
        deviceArray.append(peripheral)
    }
    tableView.reloadData()
}

//連線外設成功,啟動發現服務
func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
    print("連線成功:\(peripheral.name)")//列印外設name
    peripheral.delegate = self
    peripheral.discoverServices(nil)//開始發現服務
    per = peripheral
}

//連線外設失敗
func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
    print("連線失敗:\(peripheral.name)")
}

//發現服務
func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
    //遍歷服務,發現服務下的特徵
    for server in peripheral.services! {
        //也可以通過服務UUID來過濾服務
        //server.uuid
        peripheral.discoverCharacteristics(nil, for: server)
    }
}

//訊號檢測
func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: Error?) {
    let rssi = abs(RSSI .intValue)
    let str = "發現BLT4.0熱點:\(peripheral),強度:\(rssi)"
    print(str)
}

//搜尋到特徵Characteristics
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
    print("服務UUID:\(service.uuid)")
    //遍歷每個服務下的特徵
    for c in service.characteristics! {
        print("特徵UUID:\(c.uuid)")
        //根據外設所定製的特徵,分別處理
        //比如特徵"1111"為讀取,"2222"為寫入
        if (c.uuid.uuidString.range(of: "1111") != nil) {
            readCharac = c
            peripheral.readRSSI()//檢測外設訊號
            peripheral.readValue(for: c)//讀取一次特徵值
            peripheral.setNotifyValue(true, for: c)//當特徵值改變時通知
        }else if (c.uuid.uuidString.range(of: "2222") != nil) {
            //寫入的特徵
            writeCharac = c
        }
    }
}

//獲取外設發來的資料(無論是讀取還是通知,都在這個方法接收)
func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
    if characteristic.uuid == CBUUID(string: "1111") {
        let data = characteristic.value
        //data則是讀取過來的資料
    }
}

//檢測中心向外設寫資料是否成功
func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
    if (error != nil) {
        print("傳送失敗")
    }else {
        print("傳送成功")
    }
}

//模擬寫入資料
//func testWriteData() {
//    per?.writeValue(writeData, for: writeCharac!, type: CBCharacteristicWriteType.withResponse)
//}
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return deviceArray.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let identified = "cell"
    var cell = tableView.dequeueReusableCell(withIdentifier: identified)
    if cell == nil {
        cell = UITableViewCell(style: .default, reuseIdentifier: identified)
    }
    let per = deviceArray[indexPath.row]
    
    if let name = per.name {
        cell?.textLabel?.text = name
    }else {
        cell?.textLabel?.text = per.identifier.uuidString
    }
    
    return cell!
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    per = deviceArray[indexPath.row]
    manager?.connect(per!, options: nil)
}
}

總得來說藍芽連線分為以下幾個步驟
1.建立一個Central Manager例項進行藍芽管理
2.搜尋外圍裝置
3.連線外圍裝置
4.獲得外圍裝置的服務
5.獲得服務的特徵
6.從外圍裝置讀資料
7.給外圍裝置傳送資料

Demo地址:https://github.com/yueyeqi/CoreBluetooth_Demo

相關文章