HaLake Magazine

コワーキングスペースHaLakeの技術情報発信サイト!IoT,AR,VRなど最新技術情報をお届け!

Raspberry Pi Zero WをGo言語で触ってみる

※この記事は、IoTLTAdvent Calendar 2019の22日目の記事として書いています。

qiita.com

こんにちは、ニャンパス株式会社の登尾です。今回、手元に転がっていたRaspberry Pi Zero WをGo言語で触ってみようと思い、その模様をまとめてみました。

なぜGo言語をRaspberry Piで触ってみようとしたのかというと、下記の記事を読んで確かにJavaScriptRaspberry Pi上でもサクッとかけて便利だけれどちょっとメンテナンスしなくなると古いランタイムでしか動かない状況になるなと思い、Go言語であればバイナリとして配布できて、安定性があると感じているため、今回Raspberry Piで試して見ました。

techblog.kayac.com

Rasberry Piのセットアップ

SDカードにRaspbianを入れました。今回GUI等は必要としないので、 Raspbian Buster Lite を選んでいます。

www.raspberrypi.org

解凍したimgファイルを、Macから書き込みました。(/dev/disk2にマウントされていることを確認して以下のコマンドを打っています。)

# diskutil unMountDisk /dev/disk2
Unmount of all volumes on disk2 was successful
# sudo dd if=/Users/<user name>/Downloads/2019-09-26-raspbian-buster-lite.img  of=/dev/rdisk2 bs=1m

しばらく待って書き込まれたSDカードをRaspberry Piに指し、HDMIとキーボードをつなぎます。

f:id:t_noborio:20191221132236j:plain

以下のような画面が表示され、piユーザでログインします。ログイン後に、Wifiの有効化(raspi-configでサクッと設定)とsshdの立ち上げを行っています。

f:id:t_noborio:20191221132211j:plain

Go言語で記述したプログラムを送り込んで見る

ここからは、手元のMac環境でプログラムを書いて見ます。

IoT用のフレームワークとして、Gobotというものがあり、Raspberry Piや様々なプラットフォームに対応しているというものなので今回始めて触ってみます。

gobot.io

まずはインストールを行います。

go get -d -u gobot.io/x/gobot/...

しばらくまつと、以下のようにインストールされたことが確認できます。

ls ~/go/src/gobot.io/x/gobot/
CHANGELOG.md           appveyor.yml           drivers                helpers_test.go        sysfs
CODE_OF_CONDUCT.md     ci                     event.go               master.go              travis_build_opencv.sh
CONTRIBUTING.md        cli                    eventer.go             master_test.go         utils.go
LICENSE.txt            commander.go           eventer_test.go        platforms              utils_test.go
Makefile               commander_test.go      examples               robot.go               version.go
README.md              connection.go          examples_test.go       robot_test.go
ROADMAP.md             device.go              go.mod                 robot_work.go
adaptor.go             doc.go                 go.sum                 robot_work_test.go
api                    driver.go              gobottest       

まずはサンプルのLチカを試してみます。16番ピンを制御する以下のプログラムを記述します。

package main

import (
    "time"

    "gobot.io/x/gobot"
    "gobot.io/x/gobot/drivers/gpio"
    "gobot.io/x/gobot/platforms/raspi"
)

func main() {
    r := raspi.NewAdaptor()
    
    led := gpio.NewLedDriver(r, "16")

    work := func() {
        gobot.Every(1*time.Second, func() {
            led.Toggle()
        })
    }

    robot := gobot.NewRobot("blinkBot",
        []gobot.Connection{r},
        []gobot.Device{led},
        work,
    )

    robot.Start()
}

手元の環境でビルドして転送するということをするので、以下のようなMakefileを用意しました。

build:
    GOARM=6 GOARCH=arm GOOS=linux go build main.go

deploy:
    scp main pi@raspberrypi.local:./

こうしておくとmakeによってビルドだけ行ったり、make build deployのようにビルドとデプロイを同時に行えるので便利です。(ただ、プロジェクトとして開発するのであれば、ディレクトリ構成やビルドの依存関係を記述するべきだとは思います。)

ともあれ、Lチカが実現で来ました。

f:id:t_noborio:20191221145710j:plain

GobotでAPIサーバを立てよう

Gobotのドキュメントを読んでいるとAPIサーバとしても立ち上がってくれて、かつブラウザ上で動くAPIクライアントも同梱されていることが分かりました。 最後にこの機能を使ってみようと思います。さきほどのLEDをAPI用のコマンドとして定義してます。

package main

import (
    "gobot.io/x/gobot"
    "gobot.io/x/gobot/api"
    "gobot.io/x/gobot/drivers/gpio"
    "gobot.io/x/gobot/platforms/raspi"
)

func main() {
    master := gobot.NewMaster()
    api.NewAPI(master).Start()

    r := raspi.NewAdaptor()
    
    led := gpio.NewLedDriver(r, "16")

    robot := gobot.NewRobot("blinkBot",
        []gobot.Connection{r},
        []gobot.Device{led},
    )

    robot.AddCommand("toggleLed", func(params map[string]interface{}) interface{} {
        led.Toggle()
        return "ok"
    })

    master.AddRobot(robot)

    master.Start()
}

toggleLedというコマンドが増え、このコマンドが呼ばれるとLEDの点灯が切り替わるという意図です。cURLをターミナルから実行し、実行のたびにLEDの点灯消灯が切り替わることが確認できます。

> curl 'http://raspberrypi.local:3000/api/robots/blinkBot/commands/toggleLed'

また、 http://raspberry.local:3000/ にアクセスすると、以下のように先程定義したコマンドが表示されてブラウザからも叩けるようになっています。

f:id:t_noborio:20191221153156p:plain

まとめ

軽い気持ちでRaspberry PiでGo言語のプログラムを実行してみたいということで書き始めましたが、最後にGobotのAPIサーバとしての出来に感動しました。

IoTにおいて、PoC等の用途でさくっとAPIサーバが立ち上がり、デバイスの状態を取得したりあるいは更新できるというのは大変便利な機能だと思いますので、Go言語 + Gobotの組み合わせは今後も試してみたいと思います。