1.はじめに
前回の記事では、Elixirからカチャカへの通信を確立させて、カチャカのステータスを取得するまでを試行しました。
次のステップとして、カチャカに対して指示を送って、動かすまでを試行しました。
結論
結論としては、「未解決」です。
- Elixir→カチャカへの運転指令は出せた
- カチャカは受理するも、コマンドを解釈できない
ここからは現時点の考察です。
- kachaka-api.protoから生成する、Elixir側のrpcクライアントのコードに不具合がありそう
- 具体的には、
protoファイルの
oneof
構文の解釈がうまくできていない - Elixir側でマップ
Command
にkeyとなるatomを渡しても、oneofで定義されているもののうち、意図する型のメンバーを引いてこられない - protoファイルを直接いじってElixir側で上記を解決(2パターン試行)するも、protoの構造が変わってるので、カチャカでコマンドを受け取れない
といったところで、以下に今回の顛末を整理します。
2.試行おぼえ
(1)環境構築
Elixirのバージョン
$ elixir -v Erlang/OTP 26 [erts-14.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns] Elixir 1.15.7 (compiled with Erlang/OTP 24)
protobuf関連のツールをインストール
# protocコンパイラ他 sudo apt install protobuf-compiler -y # protocのElixirプラグイン mix escript.install hex protobuf
プロジェクトを作る
# 作業ディレクトリ $ mkdir -p ~/gitwork/kachaka/ # 新規プロジェクト $ cd !$ $ mix new kachakex $ cd !$
(2)カチャカのprotoファイルからrpcクライアントを生成
# カチャカのprotoファイルを入手 $ wget https://raw.githubusercontent.com/pf-robotics/kachaka-api/main/protos/kachaka-api.proto # protoファイル生成のElixirプラグインのパスを通す(Elixirのバージョンによって変わるのでパス名に注意) PATH=${HOME}/.asdf/installs/elixir/1.15.7/.mix/escripts/:$PATH # protoファイルから生成 protoc --elixir_out=plugins=grpc:./lib/ kachaka-api.proto
(3)まずは基本の形から
結論:NG
(4)試行1:生のprotoファイルで生成したkachaka-api.pb.ex
のうち、oneofが効かないところを手直し
結論:通信は届くけど、カチャカがコマンドの解釈ができないエラーを返してきてNG
修正前
kachakex/lib/kachaka-api.pb.ex
ファイル、375行目付近
protobufの、いわゆるunion型に相当する記述を展開した場所
defmodule KachakaApi.Command do @moduledoc false use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" oneof(:command, 0) field(:move_shelf_command, 1, type: KachakaApi.MoveShelfCommand, json_name: "moveShelfCommand", oneof: 0 ) field(:return_shelf_command, 2, type: KachakaApi.ReturnShelfCommand, json_name: "returnShelfCommand", oneof: 0 ) … field(:lock_command, 9, type: KachakaApi.LockCommand, json_name: "lockCommand", oneof: 0) end
修正後
上記の関数KachakaApi.Command
をまるっと書き換え。
とりあえず今回の試行で使うmove_to_location_command
フィールドだけを書いた関数とした。
defmodule KachakaApi.Command do @moduledoc false use Protobuf, syntax: :proto3, protoc_gen_elixir_version: "0.12.0" field(:move_to_location_command, 1, type: KachakaApi.MoveToLocationCommand, json_name: "moveToLocationCommand" ) end
(5)試行2:他のprotoファイルの書き方をまねる
結論:NG
3.まとめ
protoファイルのoneof構文の書き方を気を付ければできそう。。。 なのですが、カチャカ本体にまでは修正の手が出せないので、今回はここでいったん終了です。
おそらくコレに関するissueは出ていて、解消の可能性も・・・?
Inconsistent behaviour when encoding oneof · Issue #362 · elixir-protobuf/protobuf · GitHub
おとなしく、Pythonほかを使った実装で作ってみようと思います。