このエントリーをはてなブックマークに追加

EdisonでgolangからBLEを扱う

Intel Edisonが人気です。特に、WiFiとBLEが両方とも使えるのは非常にIoT向きといえるでしょう。

Edisonには標準でNodeJSを使った開発環境が搭載されていますが、やはりここはgolangで扱いたいところです。

paypal/gatt

GolangでBLEを扱うには、github.com/paypal/gattが最適です。このライブラリはBLEのperipheralの動作などからすべてgolangで実装しており、pure golangで動作します。

以下にサンプルプログラムを記載します。この例では、 mainでgatt.NewDeviceでdeviceを作り、onStateChangedonPeriphDiscoveredという二つの関数をハンドラに登録するだけで、BLE機器の探索が行えます。

func onStateChanged(d gatt.Device, s gatt.State) {
     fmt.Println("State:", s)
     switch s {
     case gatt.StatePoweredOn:
             fmt.Println("scanning...")
             d.Scan([]gatt.UUID{}, false)
             return
     default:
             d.StopScanning()
     }
}
func onPeriphDiscovered(p gatt.Peripheral, a *gatt.Advertisement, rssi int) {
     fmt.Printf("\nPeripheral ID:%s, NAME:(%s)\n", p.ID(), p.Name())
     fmt.Println("  Local Name        =", a.LocalName)
     fmt.Println("  TX Power Level    =", a.TxPowerLevel)
     fmt.Println("  Manufacturer Data =", a.ManufacturerData)
     fmt.Println("  Service Data      =", a.ServiceData)
}
func main() {
     d, err := gatt.NewDevice(option.DefaultClientOptions...)
     if err != nil {
             log.Fatalf("Failed to open device, err: %s\n", err)
     }
     // Register handlers.
     d.Handle(gatt.PeripheralDiscovered(onPeriphDiscovered))
     d.Init(onStateChanged)
     select {}
}

paypal/gattを使うことで、golangから簡単にBLEを扱えるのですが、一つ困ったことがあります。

paypal/gattは、HCI USER CHANNELを前提としており、これはLinux 3.14以降でのみ搭載されています。つまり、Linux 3.10で動いているEdisonでは、paypal/gattは動作しない、ということになります。

noble

しかし、 NodeJSで動作するnobleは動くよな、と思い調べていくとnobleは以下の二つの小さなヘルパープロセスをインストール時にbuildし、実行時に使っていることが分かりました。

nobleをインストールすると、以下の二つのバイナリができあがっています。

  • node_modules/noble/build/Release/hci-ble
  • node_modules/noble/build/Release/l2cap-ble

その名前の通り、hci-bleがHCIを、l2cap-bleがL2CAPを扱っています。この二つはBluezのライブラリを直接linkしているため、kernel 3.10でも動作します。

noblechild

ここまで調べたところで、思いつきます。

「nobleのヘルパープロセスを使えばPure golangでもkernel 3.10でBLE扱えるんじゃね」

ということで作ったのがnoblechildです。

noblechildは、nobleのヘルパープロセスを起動し、nobleと同じようにヘルパープロセスを扱うことで、Pure golangからkernel 3.10でもBLEを扱えるようになります。

使い方

  1. nobleをインストールします。
  2. NOBLE_TOPDIR環境変数を、nobleをインストールしたディレクトリのトップに設定します。

以上です。あとは、ほぼpaypal/gattと同じインタフェースを提供していますので、そのまま使えます。

func main() {
     d, err := noblechild.NewDevice(DefaultClientOptions...)
     if err != nil {
             log.Fatalf("Failed to open device, err: %s\n", err)
     }
     d.Handle(noblechild.PeripheralDiscovered(onPeriphDiscovered))
     d.Init(onStateChanged)
}

まとめ

Intel EdisonでgolangからBLEを扱えるようにするnoblechildというライブラリを作成しました。

ぶっちゃけハックなので、筋は良くありません。Edisonが3.14に上がれば直接paypal/gattを使えるので、それまでの間のつなぎ、という位置づけと考えています。

golangでBLEを扱えると便利ですね。弊社も関連しているMQTT ゲートウェイのfujiにも搭載し、問題なく動作していますので、そのうち公開したいと思います。

お仕事募集中

ツキノワ株式会社では、BLEやMQTT、Golangに関するお仕事を募集しております。お気軽にお問い合わせください。