おはようございます。長男は自分に似て忘れ物多く、先日奥さんが学校に一緒に宿題のノートを忘れて下校後にとりに行った際、机の中からなくなってしまった数々の アイテムが発見されるなど順調なw小学校生活となってきました。@kjunichiです。
背景
こどもたちにRaspberry Piを占有(おもにRaspberry Pi版のマインクラフト)されがちで、リモートからアクセスすることが多くなった。 どんどん暑くなる季節。これまでの記事にもあるように、Raspberry Pi3は温度が高くなりがち そんな中、Raspberry PiのCPUの温度が気になる。
デスクトップマスコットのgopheronにRaspberry Piの温度をしゃべらせよう
黒い画面も味気ないので、ふとデスクトップマスコットのGopheronの機能追加も兼ねて gRPCの勉強がてら取り組んでみようという流れに。
Node.jsのgRPCは静的な実装も選べるが、動的だとprotoファイルのコンパイル的な物が不要
システム構成図のようなもの
すでにWebSocketというかSocket.ioで通信しているが、今回はgRPCを使う事も目的の一つなので、 Raspberry Piとの通信はgRPCで実装を進めた。
以下の様なイメージ
工夫したところなど
もともと、Gopheronでは Gopher君のセリフをCanvasに描画してそれをThree.jsでテクスチャとして ポリゴンに表示するという大変回りくどい実装を行っていた。
今回はさらにこれに悪ノリして、絵文字や、セリフの文字を多くしたかったので、既存のセリフを直接Canvasに フォント描画するところを、HTMLをレンダリングしてSVGを経由してCanvasイメージにするという 実装を行い、本人としてはいい感じになったし、客観的にもインスタ映えしたので、海外から非常に高い評価を 頂いた。
gRPCまわり
公式のHelloworldをそのまま流用して、PCからサブコマンドを受け取り、Raspberry Pi側でそれを実行し、 実行結果を返すというとてもシンプルな実装。関数名もそのまま流用というw。
Raspberry Pi側
func (s *server) SayHelloAgain(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) { out, err := exec.Command("vcgencmd", in.Name).Output() if err != nil { log.Fatalf("Exec fail: %v", err) } return &pb.HelloReply{Message: string(out)}, nil }
クライアント側(PC)
const client = new hello_proto.Greeter('raspberrypi.local:50051', grpc.credentials.createInsecure()) client.sayHelloAgain({ name: argv }, (err, response) => { //console.log('Greeting:', response.message) const tmp = response.message const msg = `${tmp}<span style="font-size:larger;font-family: 'Segoe UI Emoji';">${getEmoji(tmp)}</span>` const html = `<div style="display: flex;flex-wrap:no-wrap;"><div style="width: 132px;padding-right: 2px"><img src="${icon}"></div><div style="font-size: 27px;wrap">${msg}</div></div>` socket.emit('gopher sendHtml', html) })
response受け取り後の文字列編集こそ、ごちゃごちゃしているが、基本公式のHelloWorldと同様。
成果物
使い方
Go言語が動く状態のRaspberry Piであれば、以下の様にgRPCサーバーを動かす
go get -u github.com/kjunichi/gopheron-raspberrypi cd $GOPATH/src/github.com/kjunichi/gopheron-raspberrypi go run server/main.go
Go言語が入っていないRaspberry Piの場合、Go言語が動くPCでクロスコンパイル可能です。
go get -u github.com/kjunichi/gopheron-raspberrypi cd $GOPATH/src/github.com/kjunichi/gopheron-raspberrypi GOOS=linux GOARCH=arm go build server/main.go
作成されたバイナリ(main)を
scp main pi@raspberrypi.local:/home/pi/
などでRaspberry piに配置して、これを実行します。
子供たちに占領されていないPC側でGopheronを動かし、
go get -u github.com/kjunichi/gopheron cd $GOPATH/src/github.com/kjunichi/gopheron npm install go build gopheron.go ./gopheron
おもむろに以下を実行
node rpiClient.js measure_temp
実行結果
学べたこと
goでもcgoを使うとクロスビルドで依存ライブラリを用意したり大変になる。 ピュアGoだとこの心配が不要ということも今回の作業で分かった。
そして、クロスコンパイルしてRaspberry Piで動いたことで、 gRPCがピュアGo実装だったのだと実感した。
Node.jsのgRPCだと定義ファイルを変更してもビルド不要で動かせる 動的モード?があるので、便利だった。
参考資料
関連記事
- ElectronでWebGL(three.js)使ってデスクトップマスコット作った際に分かったこと
- Goオールスターズ2に行くので、gopheronをGo言語で動かせるようにした #websocket
- macOSのCPU温度をgRPCを使ってElectronで作ったデスクトップマスコットに表示させた
- DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition insteadの警告を消すには
- Arduinoで測った室温をデスクトップマスコットのgopheronに表示させた
14年前の記事
4年前の記事
RSコンポーネントRaspberry Pi 3 B +マザーボード
- 出版社/メーカー: Raspberry Pi
- メディア: 付属品
- この商品を含むブログを見る