38
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

ズンドコキヨシ with Bluetooth Low Energy

既に 多くの言語・技術でズンドコキヨシ が試みられていますが、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バイトの値を送る、という仕様にしてます。 

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
38
Help us understand the problem. What are the problem?