Swift – CoreBluetooth 藍牙開發

iOS 的藍牙開發主要是透過 CoreBluetooth 框架來實現的。

iOS 藍牙開發的關鍵概念

  • Centrals and Peripherals

    • Centrals 中心設備 : 用來掃描周圍藍牙硬體的裝置, 比如使用手機的藍牙來掃描並連接智能手環, 這時候手機就是中心設備 。
    • Peripherals 外部設備 : 被掃瞄的裝置。 以上面的例子智能手環就是外部設備。
  • Advertising Packets

    • 外部設備會廣播藍牙訊號 (advertising packets) , 而中心設備的工作為掃描這些訊號, 並辨別出任何相關的外部設備, 可以與個別的裝置連結來取得更多的資訊。
  • Services and Characteristics

    • services 服務: 外部設備廣播和運行時會有服務, 可以理解為一個功能模組, 中心設備可以讀取服務。 外部設備可以有多個服務。
    • Characteristics 特徵: 在服務中的一個單位, 一個服務 service可以有多個特徵, 特徵會有一個值, 一般來說讀寫的數據就是這個值。

注意事項: Simulator不支援藍牙功能。

注意事項: 外部設備與中心設備版本, 需要兩隻蘋果裝置, 各一隻。

CoreBluetooth的外部設備版本

專案設置 : Swift4 + Xcode9

Step1. 導入 CoreBluetooth

import CoreBluetooth

Step2. 實現 CBPeripheralManagerDelegate

需要實現功能  peripheralManagerDidUpdateState , 並將對應的功能填入對應狀態變化的時候。

extension ViewController: CBPeripheralManagerDelegate {

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {

        switch peripheral.state {
        case .unknown:
            print("未知的")
        case .resetting:
            print("重置中"
        case .unsupported:
            print("未支持")
        case .unauthorized:
            print("未驗證")
        case .poweredOff:
            print("關閉")
        case .poweredOn:

            print("啟動")

            // 在此創建服務 、 廣播

            setupServiceAndCharacteristics()

self.peripheralManager?.startAdvertising([CBAdvertisementDataServiceUUIDsKey : [CBUUID.init(string: Service_UUID)]])

        }

    }

}

Step3.  創建服務 、 廣播

private func setupServiceAndCharacteristics() {

        let serviceID = CBUUID.init(string: Service_UUID)
        let service = CBMutableService.init(type: serviceID, primary: true)

        let characteristicID = CBUUID.init(string: Characteristic_UUID)
        let characteristic = CBMutableCharacteristic.init(type: characteristicID,
                                                          properties: [.read, .write, .notify],

                                                          value: nil,

                                                          permissions: [.readable, .writeable])

        service.characteristics = [characteristic]
        self.peripheralManager?.add(service)
        self.characteristic = characteristic

    }

Step4. 實現外部設備對應的Callback

    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveRead request: CBATTRequest) {

   // 當中心設備讀取數據時的callback

}

      func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {

  // 中心設備發送數據時, 接收數據並寫入textField

   }

   這樣就完成最基本的外部設備的藍牙傳送、接收的功能了。


CoreBluetooth的中心裝置版本

步驟幾乎相同, 不同的是實現 CBCentralManagerDelegate 的協議, 如果需要也有廣播的功能, 可以在實現 CBPeripheralDelegate 協議。

extension ViewController: CBCentralManagerDelegate, CBPeripheralDelegate {}

實現下列的函式

/** 找到符合要求的外部設備 */

    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {

        self.peripheral = peripheral
        central.connect(peripheral, options: nil)

    }

    
    /** didConnect Success */
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {

        self.centralManager?.stopScan()
        peripheral.delegate = self
        peripheral.discoverServices([CBUUID.init(string: Service_UUID)])
        print("didConnect Success")

    }


當連接成功的時候會呼叫上面的函式。   

func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral)

為了省電, 當連接上外部設備後, 就讓中心設備停止掃描。

 

  /** Find Characteristic */

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {

        for characteristic: CBCharacteristic in service.characteristics! {
            print("外部設備中的特徵有:\(characteristic)")
        }

     
        self.characteristic = service.characteristics?.last
        // Read characteristic
        peripheral.readValue(for: self.characteristic!)
        // 訂閱
        peripheral.setNotifyValue(true, for: self.characteristic!)

    }
    // 外部設備發送數據時, 接收數據並寫入textField

    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {

        let data = characteristic.value

        self.textField.text = String.init(data: data!, encoding: String.Encoding.utf8)

    }

這樣便完成藍芽中心裝置的基本設定了。

有些細節寫在專案裡, 就不一一寫入文章中了, 請大家下載專案自行玩看看, 就會更了解藍牙的運作模式。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *