Peripherail実装してみた

CoreBluetoohでシンプルなPeripheralを実装してみました。
CoreBluetoothでは直接的にPeripheralのインスタンスを作成することができない為、テストしたい際にIOTデバイスに模したPeripheralを実装しておくと便利です。

サンプルコード

CBPeripheralManagerのインスタンスを生成すると以下のメソッドが呼ばれます。

func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) 

このメソッドの引数であるperipheral.stateの値が.poweredOn出ない場合BLE通信が不可能な為何かしらの判定が必要です。

今回のサンプルコードではここでserviceとcharactaristicを追加していますが、まずはこの時点でadvertiseを行ってみるといいかもしれません。

コード一覧

Central側から7777のキャラクタリスティックに値を書き込むと画面の背景色が変化します。

import UIKit
import CoreBluetooth

class ViewController: UIViewController {
    var manager: CBPeripheralManager!
    var service: CBMutableService!
    var characteristic: CBMutableCharacteristic!
    var characteristic2: CBMutableCharacteristic!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.manager = CBPeripheralManager(delegate : self, queue : nil, options: nil)
    }
}


extension ViewController: CBPeripheralManagerDelegate {
    //デバイスの状態判定
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        switch peripheral.state {
        case .poweredOn:
            //サービス,キャラクタリスティックの追加
            service = CBMutableService(type: CBUUID(string: "1234"), primary: true)
            let properties: CBCharacteristicProperties = [.notify, .read, .write]
            let permissions: CBAttributePermissions = [.readable, .writeable]
            
            characteristic = CBMutableCharacteristic(type: CBUUID(string: "7777"),properties: properties, value: nil, permissions: permissions)
            
            characteristic2 = CBMutableCharacteristic(type: CBUUID(string: "0987"), properties: properties, value: nil, permissions: permissions)
            
            self.service.characteristics = [self.characteristic, characteristic2]
            self.manager.add(self.service)
        case .unknown:
            print("bluetooth error")
        case .resetting:
            print("bluetooth error")
        case .unsupported:
            print("bluetooth error")
        case .unauthorized:
            print("bluetooth error")
        case .poweredOff:
            print("bluetooth error")
        @unknown default:
            print("bluetooth error")
        }
    }
    //サービス追加の成功・失敗レスポンス
    func peripheralManager(_ peripheral: CBPeripheralManager, didAdd service: CBService, error: Error?) {
        if error != nil {
            print("Service Add Failed...")
            return
        }
        print("Service Add Success!")

        if (self.manager.isAdvertising == false) {
            //アドバタイズ開始
            let advertisementData = [CBAdvertisementDataLocalNameKey: "TestPeripheralDevice"]
            manager.startAdvertising(advertisementData)
        }
    }

    //アドバタイズの成功・失敗レスポンス
    func peripheralManagerDidStartAdvertising(_ peripheral: CBPeripheralManager, error: Error?) {
        if let error = error {
            print("Failed... error: \(error)")
            return
        }
        print("Succeeded!")
    }
    
    //セントラルから書き込まれた値が飛んでくる
    func peripheralManager(_ peripheral: CBPeripheralManager, didReceiveWrite requests: [CBATTRequest]) {
        
        for request in requests where request.characteristic.uuid == CBUUID(string: "7777") {
            let col:[UIColor] = [.blue, .red, .yellow, .green, .orange, .purple]
            self.view.backgroundColor = col.randomElement()
        }
    }
}

検証用Central

アドバタイズを確認するためのCentralはLightBlue® Explorerを使うのが簡単でおすすめです。

注意点

iPhoneは一度connectを行うとペアリングされてしまい、アドバタイズ時に設定した名前ではなく端末名が表示されてしまいます!!
面倒ですが毎回ここから消す以外表示名を直す方法はわかりませんでした。