Raspbian「stretch」上にGO言語をインストール」でGo言語をインストールしましたが、今回はSensorTagから温度情報を入力します。アプリはWindows10上のVisual Studio Codeで開発し、Raspberry Pi上で動作させます。なお、使用するSensorTagについては「Bluez を使用したSensorTagへのアクセス」を参照してください。

開発環境

  • Raspbian:buster
  • go言語のバージョン:go1.13.4
  • コーディング環境:Visual Studio Code 1.44.2

SensorTagの仕様説明

CC2541 SensorTagのデバイス名は、「SensorTag」で、温度データの取得するためのUUIDは、次のようになっています。

  • サービスUUID : F000AA00-0451-4000-B000-000000000000
  • データUUID : F000AA01-0451-4000-B000-000000000000
  • 通知UUID : F000AA02-0451-4000-B000-000000000000

Go言語パッケージのインストール

次のコマンドでBLE用のパッケージ「gatt」をインストールします。
4.BLE paypal/gatt のインストール

$ go get github.com/paypal/gatt

パッケージ「gatt」

BLE機能を持つパッケージで、詳細については「package gatt」に示します。

アプリの作成

作業フォルダ「goble」に次に示す「blemain.go」を作成します。

  • 27行目のonPeriphDiscoveredはBEL機器を検出すると、制御が移ります。BLE機器がSensorTagかを調べます。
  • 35行目のonPeriphConnectedはSensorTagと接続すると制御が移ります。
  • 74行目のonPeriphDisconnectedはSensorTagと切断したときに制御が移ります。
  • 15行目でBEL機器をスキャンします。
  • 76行目でチャンネル「done」をcloseすることにより、97行目のチェンネルにデータが送信されてプログラムが終了します。
  • 66行目で通知を「ON」にします。
  • 57行目で通知されてきたデータを受け取ります。

blemain.go

package main

import (
	"log"

	"github.com/paypal/gatt"
)

var done = make(chan struct{})

var uartServiceId = gatt.MustParseUUID("f000aa00-0451-4000-b000-000000000000")
var uartServiceRXCharId = gatt.MustParseUUID("f000aa02-0451-4000-b000-000000000000")
var uartServiceTXCharId = gatt.MustParseUUID("f000aa01-0451-4000-b000-000000000000")

func onStateChanged(d gatt.Device, s gatt.State) {
	log.Println("State:", s)
	switch s {
	case gatt.StatePoweredOn:
		log.Println("scanning...")
		d.Scan([]gatt.UUID{}, false)
		return
	default:
		d.StopScanning()
	}
}

func onPeriphDiscovered(p gatt.Peripheral, a *gatt.Advertisement, rssi int) {
	if a.LocalName == "SensorTag" {
		log.Printf("Preipheral Discovered: %s \n", p.Name())
		p.Device().StopScanning()
		p.Device().Connect(p)
	}
}

func onPeriphConnected(p gatt.Peripheral, err error) {
	log.Printf("Peripheral connected\n")

	services, err := p.DiscoverServices(nil)
	if err != nil {
		log.Printf("Failed to discover services, err: %s\n", err)
		return
	}

	for _, service := range services {

		if service.UUID().Equal(uartServiceId) {
			log.Printf("Service Found %s\n", service.Name())

			cs, _ := p.DiscoverCharacteristics(nil, service)

			for _, c := range cs {
				if c.UUID().Equal(uartServiceTXCharId) {
					log.Println("TX Characteristic Found")

					p.DiscoverDescriptors(nil, c)

					p.SetNotifyValue(c, func(c *gatt.Characteristic, b []byte, e error) {
						log.Printf("UUID: %s notified: % X | %q\n", c.UUID().String(), b, b)
						//log.Printf("Got back %s\n", string(b))
					})
				}
			}
			for _, c := range cs {
				if c.UUID().Equal(uartServiceRXCharId) {
					log.Println("RX Characteristic Found")
					p.WriteCharacteristic(c, []byte{0x01}, true)
					log.Printf("UUID: %s Wrote %s\n", c.UUID().String(), string([]byte{0x01}))
				}
			}
		}
	}
}

func onPeriphDisconnected(p gatt.Peripheral, err error) {
	log.Println("Disconnected")
	close(done)
}

func main() {
	var DefaultClientOptions = []gatt.Option{
		gatt.LnxMaxConnections(1),
		gatt.LnxDeviceID(-1, false),
	}

	d, err := gatt.NewDevice(DefaultClientOptions...)
	if err != nil {
		log.Fatalf("Failed to open device, err: %s\n", err)
		return
	}

	d.Handle(
		gatt.PeripheralDiscovered(onPeriphDiscovered),
		gatt.PeripheralConnected(onPeriphConnected),
		gatt.PeripheralDisconnected(onPeriphDisconnected),
	)
	d.Init(onStateChanged)
	<-done
	log.Println("Done")
}

アプリの実行

次のコマンドで作成したアプリをコンパイルして実行します。SensorTagのボタンを押すと、SensorTagとRaspberry Piが接続され、Notify転送により1秒周期で温度データがSensorTagから転送されます。もう一度SensorTagのボタンを押すと、切断されてプログラムが終了します。

$ go build
$ sudo ./goble
2020/05/09 14:43:36 dev: hci0 up
2020/05/09 14:43:36 dev: hci0 down
2020/05/09 14:43:36 dev: hci0 opened
2020/05/09 14:43:37 State: PoweredOn
2020/05/09 14:43:37 scanning...
2020/05/09 14:43:39 DATA: [ 50 00 20 03 ]
2020/05/09 14:43:39 Preipheral Discovered: SensorTag
2020/05/09 14:43:39 Peripheral connected
2020/05/09 14:43:40 Service Found
2020/05/09 14:43:40 TX Characteristic Found
2020/05/09 14:43:40 RX Characteristic Found
2020/05/09 14:43:40 UUID: f000aa0204514000b000000000000000 Wrote
2020/05/09 14:43:40 UUID: f000aa0104514000b000000000000000 notified: 43 FF 94 0B | "C\xff\x94\v"
2020/05/09 14:43:41 UUID: f000aa0104514000b000000000000000 notified: C4 FF 94 0B | "\xc4\xff\x94\v"
2020/05/09 14:43:42 UUID: f000aa0104514000b000000000000000 notified: 68 00 98 0B | "h\x00\x98\v"
2020/05/09 14:43:43 UUID: f000aa0104514000b000000000000000 notified: B3 FF 98 0B | "\xb3\xff\x98\v"
2020/05/09 14:43:44 UUID: f000aa0104514000b000000000000000 notified: E6 FE 94 0B | "\xe6\xfe\x94\v"
2020/05/09 14:43:45 UUID: f000aa0104514000b000000000000000 notified: F3 FF 98 0B | "\xf3\xff\x98\v"
2020/05/09 14:43:45 Disconnected
2020/05/09 14:43:45 Done