
車両データをやりとりするAPI仕様、COVESA Vehicle Information Service Specification 3.0がリリースされました!
COVESA Vehicle Signal Specification(VSS)形式の車両データを扱うためのAPI仕様であるCOVESA Vehicle Information Service Specification(VISS)のバージョン3.0がリリースされました。
本記事では、このVISSv3.0でどのような機能が追加され、VISSv2.0から何が変わったのかについて紹介します。また、gRPCサポートについて、リファレンス実装を用いて試してみます。
COVESA Vehicle Information Service Specification(VISS) 3.0
VISSv3.0の仕様はCore、Payload Encoding、Transportの3つで構成されています。
リリース内容を元に新しい機能とVISSv2.0からの非互換な変更点を紹介します。
新しい機能
新しい機能について、概要と関連する仕様を紹介します。
- サーバー機能の可視化: クライアントがサーバーの対応機能(どんなデータにアクセスできるか、どんな通信方式をサポートしているか等)をツリー構造で把握できるようになりました。
- ファイル転送: ファイルのアップロードやダウンロードが可能になりました。(例: ログファイル取得、設定ファイル更新など)
- データ圧縮: 通信データの各値等を圧縮することが可能になりました。圧縮によってネットワーク帯域幅の削減やパフォーマンス向上が期待できます。
- ペイロードエンコーディング: Protobufなど、より効率的なデータ形式で通信できるようになりました。
- gRPCサポート: 高パフォーマンスな通信プロトコルであるgRPCに対応しました。
- JSONスキーマ: 主要な通信データの形式がJSONスキーマで定義され、データの検証や開発が容易になりました。
- エラーメッセージ改善: エラー情報の構造が変更されました。
- インラインエラー報告: 複数の処理を一度にリクエストした際、個々の処理のエラーを具体的に報告できるようになりました。
VISSv2.0からの非互換な変更点
- フィルタのキー名が
type
からvariant
に変更されました。 - フィルタの種別(variant)である
static-metadata
とdynamic-metadata
がmetadata
に統合されました。 unsubscribe
(購読解除)の応答メッセージからsubscriptionId
パラメータが削除されました。- エラー情報内のキーワードが
message
からdescription
に変更されました。 - エラーの
description
(説明文)の内容は、仕様で厳密に規定されなくなりました(実装者がより柔軟に設定可能)。 - エラーメッセージを構成する3つの要素(番号、理由、説明)がすべて必須項目となりました。
ためしてみる
VISSのリファレンス実装であるVISS Reference Implementation(VISSR)を用いて、gRPCでのVISSサーバーとのやりとりを試してみます。
※ VISSRのサーバーはVISSv2.0を示唆するような名前(vissv2server)ですが、gRPCでの通信もサポートしており、データの形式などからVISSv3.0に準拠していると考えられます。また、VISSのTransportにおけるgRPCの定義箇所でも、処理の実装例としてVISSRのgRPCの処理を挙げています。
サーバーのセットアップ
VSS形式の車両データをやり取りするためのAPI仕様であるVISSのリファレンス実装を触ってみた で紹介した内容と同様に、VISSRをクローンした上で、Redisとfeederv3、vissv2serverを起動します。
リポジトリルートで以下のコマンドを実行し、Unix Domain Socketを配置するディレクトリを作った上で、Redisを起動します。
sudo mkdir -p /var/tmp/vissv2 && sudo chmod 777 /var/tmp/vissv2
redis-server redis/redisNative.conf
feederをビルドし、起動します。
cd vissr/feeder/feeder-template/feederv3/
go build
./feederv3
サーバーをビルドし、起動します。
cd vissr/server/vissv2server/
go build
./vissv2server
gRPC用クライアントを試す
Goで実装された、gRPC用クライアントを利用します。
grpc_client.goのinitCommandListで、VISSサーバーに対する実行可能なコマンドが次のように定義されています。
commandList[0] = `{"action":"get","path":"Vehicle/Speed","requestId":"232"}`
commandList[1] = `{"action":"set", "path":"Vehicle/Body/Lights/IsLeftIndicatorOn", "value":"true", "requestId":"245"}`
commandList[2] = `{"action":"subscribe","path":"Vehicle.CurrentLocation","filter":[{"variant":"paths","parameter":["Latitude", "Longitude"]}, {"variant":"timebased","parameter":{"period":"3000"}}], "dc":"2+1","requestId":"286"}`
commandList[3] = `{"action":"unsubscribe","subscriptionId":"X","requestId":"240"}` // X is replaced according to input, e.g. 23 sets X=2
gRPC用クライアントは、grpc_pbを参照しています。protocol buffer compiler(protoc)でVISSv3.0.protoを元に生成されたコードです。VISSv3.0.protoにはメッセージとサービスが定義されています。これらはMQTTなどでprotocol bufferを用いる際にも参考、活用できそうです。
では、gRPC用クライアントを利用するために、ビルドします。
cd client/client-1.0/grpc_client
go build
gRPC用クライアントを起動します。
cd client/client-1.0/grpc_client
go build
./grpc_client
次のようなメッセージが表示されます。transportSec.jsonがないというエラーが表示されていますが、TLSでの通信を行う必要がなければ問題ありません。
エラーメッセージの下には、Commandの説明が表示されます。GET、SET、SUBSCRIBE、UNSUBSCRIBEの4つのコマンドが用意されており、コマンドに対応する数字を入力することで実行されます。
ReadTransportSecConfig():/client/client-1.0/grpc_client/transport_sec/transportSec.json error=open {パス}/vissr/client/client-1.0/grpc_client//client/client-1.0/grpc_client/transport_sec/transportSec.json: no such file or directory{"file":"grpc_client.go:173","level":"info","msg":"secConfig.TransportSec=no","time":"2025-05-07T16:10:35+09:00"}
Command indicies: 0->GET, 1->SET, 2->SUBSCRIBE, X%!=(MISSING)3->UNSUBSCRIBE, any other value terminates.
For UNSUBSCRIBE X/10 is the subscriptionId.
Command index:
まずは、0を入力して、getを試してみます。
次のように、選択したコマンドと接続中のメッセージに続いて、getのレスポンスが表示されました。Vehicle.Speedの値が返ってきています。
Command index:0
Selected request:{"action":"get","path":"Vehicle/Speed","requestId":"232"}
{"file":"grpc_client.go:75","level":"info","msg":"connecting to port = 8887","time":"2025-05-07T16:43:05+09:00"}
Received response:{"action":"get","data":{"path":"Vehicle.Speed","dp":{"value":"1292.3032","ts":"2025-05-07T16:42:52.220Z"}},"ts":"2025-05-07T16:43:05.392Z","requestId":"232"}
1を入力して、setを試してみます。
どうやら入力したパスにfeederが対応していないようで、エラーが返ってきます。いったん、今回はsetが動くパターンはスキップします。
※ feederv3がデフォルトで対応しているのはマッピングを指定したVssVehicle.cvtやスケーリングを指定したVssVehicle.jsonに記載されているデータです。Domain Conversion Toolでこれらのファイルを作成し、feeder起動時に指定することで対応するデータを変更することが可能です。
Command index:1
Selected request:{"action":"set", "path":"Vehicle/Body/Lights/IsLeftIndicatorOn", "value":"true", "requestId":"245"}
{"file":"grpc_client.go:75","level":"info","msg":"connecting to port = 8887","time":"2025-05-07T16:43:19+09:00"}
Received response:{"action":"set","error":{"number":"404","reason":"unavailable_data","description":"The requested data was not found."},"ts":"2025-05-07T16:43:19.974Z","requestId":"245"}
次は、2を入力して、subscribeを試します。filterの条件として、パスを緯度と経度に絞り込み、3秒間隔でデータを送信するという条件が指定されています。条件の種類を指定するキーは、VISSv2.0ではtypeが使われていましたが、VISSv3.0ではvariantになります。レスポンスとして、subscriptionIdが返ってきています。subscriptionIdは、unsubscribeの際に必要になります。
Command index:2
Selected request:{"action":"subscribe","path":"Vehicle.CurrentLocation","filter":[{"variant":"paths","parameter":["Latitude", "Longitude"]}, {"variant":"timebased","parameter":{"period":"3000"}}], "dc":"2+1","requestId":"286"}
Received response:{"action":"subscribe","ts":"2025-05-07T16:43:32.469Z","subscriptionId":"1","requestId":"286"}
コマンド実行後3秒ごとに次のようにsubscribeしたデータが送られてきます。
Command index:Received response:{"action":"subscription","data":[{"path":"Vehicle.CurrentLocation.Latitude","dp":{"value":"visserr:Data-not-available","ts":"2025-05-07T16:43:35.472Z"}},{"path":"Vehicle.CurrentLocation.Longitude","dp":{"value":"62","ts":"2025-05-07T16:43:13.227Z"}}],"ts":"2025-05-07T16:43:35.470Z","subscriptionId":"1"}
unsubscribeするには、subscriptionId * 10 + 3を入力します。今回はsubscriptionIdが1なので、13を入力します。
13
Selected request:{"action":"unsubscribe","subscriptionId":"X","requestId":"240"}
{"file":"grpc_client.go:75","level":"info","msg":"connecting to port = 8887","time":"2025-05-07T16:45:13+09:00"}
Unsubscribe request=:{"action":"unsubscribe","subscriptionId":"1","requestId":"240"}
Received response:{"action":"unsubscribe","ts":"2025-05-07T16:45:13.950Z","requestId":"240"}
VISSRにおけるgRPC用クライアントは、以上の4種類のリクエストに対応していますが、grpc_client.goを書き換えることで任意のリクエストを投げることが可能です。
試し終えたら、Ctrl+C でfeederv3とserverを終了します。redisは以下のコマンドで終了します。
redis-cli -s /var/tmp/vissv2/redisDB.sock shutdown
さいごに
VISSv3.0での変更内容を紹介し、リファレンス実装を用いてgRPCでのVISSサーバーとのやり取りを試してみました。ペイロードエンコーディングの追加によって、今回試したgRPC以外にもWebSocketやMQTTのペイロードとしてprotobufを用いることも可能になります。他にもサーバー機能の可視化、ファイル転送、データ圧縮など多くの機能強化がなされています。
VISS自体は車両データをやり取りするAPI仕様になります。今回の進化によって、VISS準拠サーバーの可能性を大きく広げ、車両データ活用の幅も広がっていきそうです!