Application層
最後に、ここまでで説明した内容をふまえてアプリケーション開発者がApplication層を実装する必要があります。 スマートフォンアプリを作る場合、各OSごとに用意されているBLE開発のためのフレームワークを利用することになります。2016年5月現在、iOS/Androidではセントラルとペリフェラル、Windows 8ではセントラル側の実装が可能のようです。
ここからはプラットフォームごとに内容が異なるため、本稿では詳細について説明しませんが、ここまでで開設したBLEの概念が理解できていれば、実装はさほど難しくはないはずです。雰囲気をつかむために、iOS用のフレームワーク「Code Bluetooth」を使ったSwiftのコードを見てみましょう。ここではiPhoneアプリ(セントラル)が周辺機器(ペリフェラル)とやりとりすることを想定しています。
import UIKit
import Foundation
import CoreBluetooth
class ViewController: UIViewController, CBCentralManagerDelegate,
CBPeripheralDelegate {
var manager : CBCentralManager!
var peripherals : [String: CBPeripheral] = [:]
override func viewDidLoad() {
super.viewDidLoad()
self.manager = CBCentralManager(delegate: self, queue: nil)
}
// Centralの状態が変わったときに呼ばれる
func centralManagerDidUpdateState(central: CBCentralManager) {
if central.state == CBCentralManagerState.PoweredOn {
// Peripheralのスキャンを開始する(全てのPeripheralを対象にする)
print("Start scanning peripherals...")
self.manager.scanForPeripheralsWithServices(nil, options: nil)
} else if central.state == CBCentralManagerState.Unsupported {
print("Unsupported")
}
}
// CentralがPeripheralを発見したときに呼ばれる
func centralManager(central: CBCentralManager, didDiscoverPeripheral peripheral: CBPeripheral,
advertisementData: [String : AnyObject], RSSI: NSNumber) {
print("found peripheral[" + peripheral.identifier.UUIDString + "]")
peripheral.delegate = self
// Peripheralに接続する
manager.connectPeripheral(peripheral, options: nil)
peripherals[peripheral.identifier.UUIDString] = peripheral
}
// CentralがPeripheralと接続したときに呼ばれる
func centralManager(central: CBCentralManager, didConnectPeripheral peripheral: CBPeripheral) {
print("connected to peripheral[" + peripheral.identifier.UUIDString + "]")
// PeripheralのServiceを検索する
peripheral.discoverServices(nil)
}
// CentralがPeripheralと切断したときに呼ばれる
func centralManager(central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: NSError?) {
print("disconnected from peripheral[" + peripheral.identifier.UUIDString + "]")
self.peripherals[peripheral.identifier.UUIDString] = nil
}
// PeripheralのServiceを発見したときに呼ばれる
func peripheral(peripheral: CBPeripheral, didDiscoverServices error: NSError?) {
peripheral.services?.forEach { service in
// Serviceに含まれるCharacteristicを検索する
print("found service[" + service.UUID.UUIDString + "] of peripheral[" + peripheral.identifier.UUIDString + "]")
peripheral.discoverCharacteristics(nil, forService: service)
}
}
// Serviceに含まれるCharacteristicを発見したときに呼ばれる
func peripheral(peripheral: CBPeripheral, didDiscoverCharacteristicsForService service: CBService, error: NSError?) {
service.characteristics?.forEach { characteristic in
print("found characteristic[" + characteristic.UUID.UUIDString + "] of service[" + service.UUID.UUIDString + "]")
if (!characteristic.properties.intersect(CBCharacteristicProperties.Read).isEmpty) {
// Characteristicの値を取得する
peripheral.readValueForCharacteristic(characteristic)
}
}
}
// Characteristicの値を取得したときに呼ばれる
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?) {
if let value = characteristic.value {
let str : String = NSString(data : value, encoding : NSUTF8StringEncoding) as! String
print("found value[" + str + "] of characteristic[" + characteristic.UUID.UUIDString + "]")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
非同期処理が多いためとっつきにくそうですが、慣れてしまえばそれほど大したことはありません。
電池寿命を考慮する
長期運用を考えると電池寿命を考慮した設計が必須になります。ここで、改めて電池寿命を左右するパラメータを洗い出してみましょう。
- advInterval(Advertisingの周期)
- scanInterval(Scanningの周期)
- connInterval(接続確立後のポーリングの周期)
- connSlaveLatency(Peripheral側にデータがない場合に受信を無視できる回数)
- Push通知するか否か
実は、これらの値はプラットフォームによって設定できる範囲はまちまちです。例えば、iOSではconnIntervalは20ms以上などとガイドラインに明記されています。気になるところは、あらかじめ確認しておくとよいでしょう。
上位フレームワークの利用を検討する
アプリケーションによっては、BLEの全機能を利用するのではなくビーコン信号を受信する程度で事足りる場合があります。 スマートデバイスの位置測定やプッシュ型広告がその一例です。 その場合、以下のような上位フレームワーク(プロトコル)を利用することで、開発を迅速に進められます。ぜひ検討してみてください。
- iBeacon
- Appleの開発した技術で、iOS上でビーコン信号を送受信し内容とおおまかな距離を知ることができます。独自のプロトコルでラップしていますが、他のデバイスでも解析することは可能なようです。
- Eddystone
- Googleの開発した技術で、同じくビーコンを扱います。アドバタイズにURLを含めることができるという特徴があります。こちらはApache 2.0ライセンスでGitHubにソースが公開されています。
このような「ビーコン」の内部実装は、BLEの機能のうちAdvertisingパケットのみを使ったブロードキャスト通信となっています。
まとめ
以上、少々長めではありましたがBLEの仕様を一通り眺めました。説明の都合上、ここでは紹介しきれなかった概念もいくつかあるので必要に応じてキャッチアップしてください。
今回はBluetoothに限定した話でしたが、代替の通信手段としてはWi-Fiなどもありますし、IoTはハードウェアやクラウドなど様々な技術やサービスの組み合わせによって実現可能です。 柔軟で素晴らしいアイデアを生み出すきっかけのひとつとして、本記事がお役に立てば幸いです。
