65
71

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Swift][初心者]BLE接続するための情報まとめ

Posted at

Objective-Cをまだよく理解できてない初心者の私が、SwiftでBLE接続するまでの情報をまとめてみました。
個人メモに近いので間違いがあればご容赦くださいませ。

実行環境

  • Mac OS X Yosemite 10.7.5
  • Xcode version 6.0.1
  • iPhone6plus + iOS 8.1.2

前提知識

BLE(Bluetooth Low Energy)の仕組みについて基本だけでも理解する必要があります。
私はApple公式ドキュメント Core Bluetooth プログラミングガイド が非常にわかりやすかったです。
まずはひと通り目を通して以下のキーワードを理解するとよいです。

  • セントラルとペリフェラル
  • サービスとキャラクタリスティック
  • アドバタイズ

やりたかったこと

  →mbed HRM1017側はwrite用のサービス"FFF0"、キャラクタリスティック"FFF1"と仮定。mbed側のプログラムは対象外。

概要説明

iOSアプリのおおまかな流れは以下になります。

1-1. CentralManagerの起動
1-2. CentralManager状態の受信

2-1. Peripheral探索開始
2-2. Peripheral探索結果の受信(複数あれば複数回)

3-1. 指定したPeripheralへ接続開始
3-2. Peripheralへの接続結果の受信

4-1. 利用可能Serviceの探索開始
4-2. Service探索結果の受信

5-1. 利用可能Characteristicの探索開始
5-2. Characterristic探索結果の受信

----ここからは用途に応じて----
<Writeの場合>
6-1. 指定データの書き込み
6-2. 書き込み結果の受信

<Notifyの場合>
7-1. 指定データの書き込み
7-2. 書き込み結果の受信

ソースコード

  • StoryBoardで作成したためViewControllerのソースコードのみ記載します。
  • あくまで流れを理解するためのサンプルです、コピペはオススメしません。
  • 引数にnilを設定するなどApple非推奨の内容も含まれます、ご注意を。
swift
import UIKit
import CoreBluetooth

class ViewController: UIViewController, CBCentralManagerDelegate, CBPeripheralDelegate {

    var centralManager: CBCentralManager!
    private var peripheralArray = [CBPeripheral]()
    private var serviceArray = [CBService]()
    private var characteristicArray = [CBCharacteristic]()

    @IBOutlet weak var scanStatus: UILabel!
    @IBOutlet weak var scanStatusText: UITextView!
    @IBOutlet weak var connectStatus: UILabel!
    @IBOutlet weak var sendText: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // ボタン押下でCoreBluetoothを起動
    @IBAction func pushStartBtn(sender: AnyObject) {

        // 1-1. CentralManagerの起動
        self.centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)
    }

    // 1-2. CentralManager状態の受信
    func centralManagerDidUpdateState(central: CBCentralManager!) {

        switch (central.state) {
        case .PoweredOff:
            println("BLE PoweredOff")
        case .PoweredOn:
            println("BLE PoweredOn")
            // 2-1. Peripheral探索開始
            central.scanForPeripheralsWithServices(nil, options: nil)
            /* ↑の第1引数はnilは非推奨。
               該当サービスのCBUUIDオブジェクトの配列が望ましい */
        case .Resetting:
            println("BLE Resetting")
        case .Unauthorized:
            println("BLE Unauthorized")
        case .Unknown:
            println("BLE Unknown")
        case .Unsupported:
            println("BLE Unsupported")
        }
    }

    // 2-2. Peripheral探索結果の受信(複数あれば複数回)
    func centralManager(central: CBCentralManager!,
        didDiscoverPeripheral peripheral: CBPeripheral!,
        advertisementData: [NSObject : AnyObject]!,
        RSSI: NSNumber!){
            
            println("name: \(peripheral.name)")
            println("UUID: \(peripheral.identifier.UUIDString)")
            println("advertisementData: \(advertisementData)")
            println("RSSI: \(RSSI)")

            // 配列に追加
            self.peripheralArray.append(peripheral as CBPeripheral)
    }

    // リストから該当Peripheralを選択し接続を開始
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        // 省電力のためスキャンを停止
        self.centralManager.stopScan()
        
        // 3-1. 指定したPeripheralへ接続開始
        self.centralManager.connectPeripheral(peripheralArray[indexPath.row], options: nil)
    }

    // 3-2. Peripheralへの接続結果の受信(成功時)
    func centralManager(central: CBCentralManager!,
        didConnectPeripheral peripheral: CBPeripheral!)
    {
        println("connection success!")
        // デリゲートの設定
        peripheral.delegate = self
        
        // 今回はサービスを"FFF0"に指定
        let UUID = CBUUID(string: "FFF0")
        // 4-1. 利用可能Serviceの探索開始
        peripheral.discoverServices([UUID])
        /* ↑の引数はnilは非推奨。*/
    }

    // 3-2. Peripheralへの接続結果の受信(失敗時)
    func centralManager(central: CBCentralManager!,
        didFailToConnectPeripheral peripheral: CBPeripheral!,
        error: NSError!)
    {
        println("connection failed")
    }

    // 4-2. Service探索結果の受信
    func peripheral(peripheral: CBPeripheral!, didDiscoverServices error: NSError!) {
        
        if (error != nil) {
            println("error: \(error)")
            return
        }
        
        for service in peripheral.services
        {
            self.serviceArray.append(service as CBService)

            // 5-1. 利用可能Characteristicの探索開始
            peripheral.discoverCharacteristics(nil, forService:service as CBService)
            /* ↑の第1引数はnilは非推奨。*/
        }
    }

    // 5-2. Characterristic探索結果の受信
    func peripheral(peripheral: CBPeripheral!,
        didDiscoverCharacteristicsForService service: CBService!,
        error: NSError!)
    {
        if (error != nil) {
            println("error: \(error)")
            return
        }

        for characteristic in service.characteristics {
            self.characteristicArray.append(characteristic as CBCharacteristic)
        }
    }
    
    // ボタン押下で書き込み開始
    @IBAction func pushWriteBtn(sender: AnyObject) {
        
        // 書き込むデータを仮で設定
        var value: UInt = 0x0000FF80808080808000
        let data: NSData = NSData(bytes: &value, length: 10)

        // 6-1. 指定データの書き込み
        [peripheral .writeValue(data, forCharacteristic: characteristicArray[0], type: CBCharacteristicWriteType.WithResponse)]
    }

    // 6-2. 書き込み結果の受信
    func peripheral(peripheral: CBPeripheral!,
        didWriteValueForCharacteristic characteristic: CBCharacteristic!,
        error: NSError!)
    {
        if (error != nil) {
            println("Write...error: \(error)")
            return
        }
        
        println("Write success!")
    }
}

感想

  • サンプルは多数出回っていますが基本はどれも同じ流れです。
  • 自分が躓いたのは受信したPeripheralやサービスを保存しておく必要がある点です。これさえ抑えておけば後はどうにかなるかなと。
65
71
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
65
71

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?