40
39

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.

Bluetooth Low EnergyAdvent Calendar 2016

Day 3

ズンドコキヨシ with Bluetooth Low Energy

Last updated at Posted at 2016-04-01

既に 多くの言語・技術でズンドコキヨシ が試みられていますが、Bluetooth Low Energy (以下BLE) 版はまだないみたいなので、やってみました。

ズンドコキヨシカルチャーの発祥ツイート:

ちなみに iOS / Core Bluetooth です。 Swift バージョンは 2.2

##GATT

ズンドコキヨシGATTを以下のように定義しました。(各UUID はuuidgen で生成)

###Services

####ズンドコキヨシService

  • UUID: B8A18F4F-2A2B-4084-AC2D-1ABC289EF05D
  • Characteristics
    • ズンドコCharacteristic
    • キヨシCharacteristic
GATT.swift
enum Service : Int {
    case ズンドコキヨシ
    
    func UUID() -> CBUUID {
        switch self {
        case .ズンドコキヨシ:
            return CBUUID(string: "B8A18F4F-2A2B-4084-AC2D-1ABC289EF05D")
        }
    }
    
    func mutableService() -> CBMutableService {
        return CBMutableService(type: UUID(), primary: true)
    }
}

###Characteristics

####ズンドコCharacteristic

  • UUID: C2F0882D-2440-40F4-A4A9-95BE43B89EAE
  • Properties: Read, Notify
  • value: ズン or ドコ

####キヨシCharacteristic

  • UUID: C2F0882E-2440-40F4-A4A9-95BE43B89EAE
  • Properties: Write
  • value: 0x00 1
GATT.swift
enum Characteristic : Int {
    case ズンドコ
    case キヨシ
    
    func UUID() -> CBUUID {
        switch self {
        case .ズンドコ:
            return CBUUID(string: "C2F0882D-2440-40F4-A4A9-95BE43B89EAE")
        case .キヨシ:
            return CBUUID(string: "C2F0882E-2440-40F4-A4A9-95BE43B89EAE")
        }
    }
    
    private func properties() -> CBCharacteristicProperties {
        switch self {
        case .ズンドコ:
            return [CBCharacteristicProperties.Notify, CBCharacteristicProperties.Read]
        case .キヨシ:
            return [CBCharacteristicProperties.Write]
        }
    }
    
    private func permissions() -> CBAttributePermissions {
        switch self {
        case .ズンドコ:
            return [CBAttributePermissions.Readable]
        case .キヨシ:
            return [CBAttributePermissions.Writeable]
        }
    }
    
    func mutableCharacteristic() -> CBMutableCharacteristic {
        return CBMutableCharacteristic(
            type: UUID(),
            properties: properties(),
            value: nil,
            permissions: permissions())
    }
}

##ズンドコ

ズンドコCharacteristicでやり取りする値。実体は UInt8 (1バイト)

Zundoko.swift
enum ズンドコ: UInt8 {
    case ズン
    case ドコ

    private func data() -> NSData {
        return NSData(bytes: [self], length: 1)
    }
    
    static func randomData() -> NSData {
        return ズンドコ(rawValue: UInt8(arc4random_uniform(2)))!.data()
    }
    
    init?(data: NSData) {
        var bytes = [UInt8](count: data.length, repeatedValue: 0)
        data.getBytes(&bytes, length: data.length)
        guard let value = bytes.first, zundoko = ズンドコ(rawValue: value) else { return nil }
        self = zundoko
    }
}

##ズンドコPeripheral

ボタンを押すと、 ズン or ドコ をランダムに生成してBLEで送信 します。具体的には、Zundoko Characteristic の値を ズン or ドコ で更新します。

Peripheral.swift
func publishservice () {
    // キャラクタリスティックを作成
    ズンドコCharacteristic = Characteristic.ズンドコ.mutableCharacteristic()
    キヨシCharacteristic   = Characteristic.キヨシ.mutableCharacteristic()
    
    // サービスを作成
    let service = Service.ズンドコキヨシ.mutableService()
    service.characteristics = [ズンドコCharacteristic, キヨシCharacteristic]
    
    // サービスを Peripheral Managerに追加
    peripheralManager.addService(service)
}
Peripoheral.swift
@IBAction func zundokoBtnTapped(sender: UIButton) {
    let data = ズンドコ.randomData()
    ズンドコCharacteristic.value = data

    // 更新を通知
    peripheralManager.updateValue(
        data,
        forCharacteristic: ズンドコCharacteristic,
        onSubscribedCentrals: nil)
}
IMG_3743.PNG

##キヨシCentral

BLEで送信されてきた ズン or ドコ を受け取り、画面に表示 します。具体的には、Peripheral側からのズンドコCharacteristicの更新通知を受け取り、画面を更新します。

Central.swift
func peripheral(peripheral: CBPeripheral, didUpdateValueForCharacteristic characteristic: CBCharacteristic, error: NSError?)
{
    guard let data = characteristic.value, zundoko = ズンドコ(data: data) else { return }
    zundokos.append(zundoko)

    let recents = zundokos.suffix(5)
    zundokoLabel.showZundokos(recents)
    
    if recents == [.ズン, .ズン, .ズン, .ズン, .ドコ] {
        sayKiyoshi()
    }
}
IMG_5899.PNG

直近5件が [ズン, ズン, ズン, ズン, ドコ] になると 「キ・ヨ・シ!」をBLEで送信 します。具体的には、Peripheral側のキヨシCharacteristicに値を書き込みます。

Central.swift
private func sayKiyoshi() {
    guard let peripheral = peripheral, kiyoshiCharacteristic = kiyoshiCharacteristic else { return }

    var value = 0x00
    let data = NSData(bytes: &value, length: 1)
    
    peripheral.writeValue(
        data,
        forCharacteristic: kiyoshiCharacteristic,
        type: CBCharacteristicWriteType.WithResponse)
}

##改めてズンドコPeripheral側

Peripheral側ではキヨシCharacteristicへの書き込み要求を受けたら、画面に「キ・ヨ・シ!」を表示 します。

Peripheral.swift
func peripheralManager(peripheral: CBPeripheralManager, didReceiveWriteRequests requests: [CBATTRequest])
{
    for request in requests where request.characteristic.UUID == キヨシCharacteristic.UUID {
        キヨシCharacteristic.value = request.value
        kiyoshiLabel.hidden = false
    }
    peripheralManager.respondToRequest(requests[0] , withResult: CBATTError.Success)
}
IMG_3742.PNG

##デモ

2台のiPhoneを用意し、それぞれにCentral, Peripheralをインストールします。

やってみた動画:

##参考書籍

下記書籍のサンプルを流用しました。

iOS×BLE Core Bluetoothプログラミング
堤 修一 松村 礼央
ソシム
売り上げランキング: 48,410

今回は「スキャン」や「アドバタイズ」等の話は割愛しましたが、本書4章以降にかなりわかりやすく書いてあります。以下に紹介記事を書いたので興味があればご参照ください。

##関連記事

  1. 「キ・ヨ・シ!」と文字列を送るのはBLEの思想的にマッチしないのでとりあえず1バイトの値を送る、という仕様にしてます。

40
39
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
40
39

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?