2015年12月25日

BLE NanoでiOSアプリとBluetooth通信(iOSアプリ編)

BLE Nanoのセットアップが完了したので、iOSアプリでBLE Nanoに接続してBluetooth通信したいと思います。

BLE Nanoを準備

セットアップが完了したBLE NanoをMK20を使ってパソコンと接続します。これで、BLE Nanoがアドバタイジングを発信、iOSアプリからBLE Nanoに接続してBleutooth通信する準備が完了しました。



Core BluetoothでBLE Nanoをスキャンする

CoreBluetoothとBLEの仕組みについてはネットや書籍で調べてみてください。一番最初は「Core Bluetoothプログラミングガイド」を読むのがおすすめです。また、「Core Bluetooth with Swift(ObjCのおまけ付き)」はソースコードがわかりやすくまとまっています。


● ViewController.swift

まずはCore Bluetoothを使ってiOSアプリからBLE Nanoをスキャンします。XcodeでCoreBluetoothフレームワークを追加することを忘れないようにしてください。

import UIKit
import CoreBluetooth

class ViewController: UIViewController,CBCentralManagerDelegate
{
    var centralManager:CBCentralManager!
    var BLEPeripheral:CBPeripheral!

    //===========================================================================
    // MARK: -- 初期化 & ビューライフサイクル --
    //===========================================================================
    override func viewDidLoad()
    {
        super.viewDidLoad()
        
        //CBCentralManagerを初期化
        //centralManagerDidUpdateStateで状態変化が取得できます
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    //===========================================================================
    // MARK: -- BLE --
    //===========================================================================
    //セントラルマネージャーの状態変化を取得
    func centralManagerDidUpdateState(central: CBCentralManager)
    {
        switch (central.state) {
            
        case .PoweredOff:
            print("Bluetoothの電源がOff")
        case .PoweredOn:
            print("Bluetoothの電源はOn")

            //ペリフェラルのスキャン開始
            centralManager.scanForPeripheralsWithServices(nil, options:nil)

        case .Resetting:
            print("レスティング状態")
        case .Unauthorized:
            print("非認証状態")
        case .Unknown:
            print("不明")
        case .Unsupported:
            print("非対応")
        }
    }
    
    //スキャン結果を受け取る
    func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber)
    {
        //スキャンが完了しない場合は、peripheral.nameが違っているかもしれません。
        //ここでperipheral.nameを確認してください。
        //print("\(peripheral.name)")
        
        if(peripheral.name == "BLE Nanoで設定したローカルネーム"){
            BLEPeripheral = peripheral
            centralManager.stopScan()

            print("\(peripheral.name)をスキャン完了!")
        }
    }
}

BLE Nanoに接続、データを送信

● ViewController.swift

BLE Nanoのスキャンが成功したら、接続してデータを送信します。サービスのキャラクタリスティックに値を書き込むことができたら、データの送信成功です。

import UIKit
import CoreBluetooth

class ViewController: UIViewController,CBCentralManagerDelegate,CBPeripheralDelegate
{
    var centralManager:CBCentralManager!
    var BLEPeripheral:CBPeripheral!

    //===========================================================================
    // MARK: -- 初期化 & ビューライフサイクル --
    //===========================================================================
    override func viewDidLoad()
    {
        super.viewDidLoad()
        centralManager = CBCentralManager(delegate: self, queue: nil)
    }

    //===========================================================================
    // MARK: -- BLE --
    //===========================================================================
    //セントラルマネージャーの状態変化を取得
    func centralManagerDidUpdateState(central: CBCentralManager)
    {
        switch (central.state) {
            
        case .PoweredOff:
            print("Bluetoothの電源がOff")
        case .PoweredOn:
            print("Bluetoothの電源はOn")
            centralManager.scanForPeripheralsWithServices(nil, options:nil)
        case .Resetting:
            print("レスティング状態")
        case .Unauthorized:
            print("非認証状態")
        case .Unknown:
            print("不明")
        case .Unsupported:
            print("非対応")
        }
    }
    
    //スキャン結果を受け取る
    func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral, advertisementData: [String : AnyObject], RSSI: NSNumber)
    {
        if(peripheral.name == "BLE Nanoで設定したローカルネーム"){
            BLEPeripheral = peripheral

            //BLE Nanoのスキャンに成功したら接続
            centralManager.connectPeripheral(BLEPeripheral, options: nil)
            centralManager.stopScan()
        }
    }

    //ペリフェラルに接続完了
    func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral)
    {
        BLEPeripheral.delegate = self
        //接続できたらサービスを探索
        BLEPeripheral.discoverServices(nil)
    }
    
    //ペリフェラルに接続失敗
    func centralManager(central: CBCentralManager, didFailToConnectPeripheral peripheral: CBPeripheral, error: NSError?)
    {
        print("接続失敗")
    }
    
    //サービスの探索結果を受け取る
    func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?)
    {
        if(error != nil){
            print("エラー:\(error)")
            return
        }
        
        if !(peripheral.services?.count > 0){
           print("サービスがありません")
        }
        
        let services = peripheral.services!
        print("\(services) サービスが見つかりました")

        //サービスが見つかったら、キャラクタリスティックを探索
        peripheral.discoverCharacteristics(nil, forService: services[0])
    }
    
    //キャラクリスティックの探索結果を受け取る
    func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?)
    {
        if(error != nil){
            print("エラー:\(error)")
            return
        }
        
        if !(service.characteristics?.count > 0){
            print("キャラクタリスティックがありません")
            return
        }
        
        let characteristics = service.characteristics!
        let characteristic = characteristics[0]
        print("\(characteristics) キャラクタリスティックが見つかりました")

        //キャラクタリスティックに値の書き込む
        let value = "T"
        let data: NSData! = value.dataUsingEncoding(NSUTF8StringEncoding,allowLossyConversion:true)
        BLEPeripheral.writeValue(data, forCharacteristic: characteristic, type: CBCharacteristicWriteType.WithResponse)
     }
    
    //書き込み結果の取得
    func peripheral(peripheral: CBPeripheral, didWriteValueForCharacteristic characteristic: CBCharacteristic, error: NSError?)
    {
        if(error != nil){
            print("エラー:\(error)")
            return
        }
        print("書き込み成功")
    }
}

BLE Nanoでデータが受信できたかどうかの確認

● BLEPeripheral.ino

BLE Nanoに書き込んだペリフェラルのプログラムで下記変更すれば、Arduinoのシリアルモニタでデータが受信できたどうかの確認ができます。

//データの送信処理
void writtenHandle(const GattWriteCallbackParams *Handler)
{
    uint8_t buf[TXRX_BUF_LEN];
    uint16_t bytesRead, index;

    if (Handler->handle == characteristic1.getValueAttribute().getHandle())
    {
        ble.readCharacteristicValue(characteristic1.getValueAttribute().getHandle(), buf, &bytesRead);
        for(byte index=0; index<bytesRead; index++)
        {
            //ここでprintすることで、シリアルモニタでiOSアプリからBluetooth通信で送信されたデータを確認できます。
            Serial1.print(buf[index], HEX);
            //Serial1.write(buf[index]);
        }
    }
}
  • このエントリーをはてなブックマークに追加
前の記事へ

BLE NanoでiOSアプリとBluetooth通信(BLE Nano編)

次の記事へ

BLE NanoでiOSアプリとBluetooth通信(Arduino編)