
VSS形式の車両データをやり取りするためのAPI仕様であるVISSのリファレンス実装を触ってみた
VISS(Vehicle Information Service Specification)は、VSS(Vehicle Signal Specification)で定義された車両データを取得、操作するためのAPI仕様です。今回は、VISSの基本的な仕組みを理解するために、公式のリファレンス実装であるVISSR(VISS Reference Implementation)のHello World exampleを試してみます。 ネイティブビルドベースとDockerベースの2種類の例がありますが、今回はネイティブビルドベースを試します。
VISS(Vehicle Information Service Specification)
VISSは、車両のさまざまなデータやセンサー情報へ標準化された方法でアクセスするためのAPI仕様です。VISSはVSS(Vehicle Signal Specification)で定義されたツリー構造のデータモデルに基づき、JSON形式で情報をやり取りします。
VISSの標準化活動は、当初W3C(World Wide Web Consortium)でGENIVI(現在のCOVESA)と協力して始まりました。W3CのAutomotive Working Groupが中心となって仕様策定が進められていましたが、2024年2月に同ワーキンググループがクローズしたことにより、現在はCOVESAがその活動を引き継ぎ、VISSの仕様策定やメンテナンスを主導しています。
VISS v2では、WebSocketだけでなくHTTPやMQTTなど複数のプロトコルに対応し、より柔軟な運用が可能になりました。主な操作として、データの取得(get)、更新(set)、サブスクリプション(subscribe/unsubscribe)などが用意されています。リリース候補版のVISS v3では、ファイル転送やデータ圧縮、ペイロードエンコーディングなどの機能が追加されています。
VISSはAUTOSAR Adaptive Platformの「Automotive API Gateway」でも利用されており、車両内外のアプリケーションから標準化された方法で車両データへアクセスするためのインターフェイスとなっています。
VISSR(VISS Reference Implementation)
VISSのリファレンス実装は、主に以下のソフトウェアコンポーネントで構成されています。
- Server: VISSに従ったサーバー
- Clients: VISSと接続するクライアント
- Data Storage: ServerとFeedersの間に位置し、両者のデータアクセス操作を分離(デカップリング)する
- Feeders:
- 車両インターフェイスからデータを読み書きし、Data StorageやServerとやり取りする
- VSSドメインと車両ドメインのデータ変換を行う
- Tools: ServerやFeedersなど「オンライン」コンポーネントで使用するためのアーティファクト(設定ファイルやコード生成物など)を「オフライン」で作成するソフトウェア
※ 図内のWAIIはW3C Automotive Interface Implementationの略のようです
試してみる
環境
- macOS
- Redis: v=7.2.7
- go: go1.24.2 darwin/arm64
セットアップ
まずは、VISSRのリポジトリをクローンします。
git clone https://github.com/COVESA/vissr.git
Data StorageとしてRedisを使用します。
RedisのUnix Domain Socketが配置されるディレクトリを作成します。
※ feederv3.go
やredisNative.conf
、uds-registration.json
などでSocketのパスが指定されています。
sudo mkdir -p /var/tmp/vissv2 && sudo chmod 777 /var/tmp/vissv2
redis-serverを起動します。
redis-server redis/redisNative.conf
feederをビルドし、起動します。
feederにはいくつか種類がありますが、今回はfeeder-template/feederv3を使います。各feederの説明はフォルダごとのREADMEファイルやドキュメントに記載されています。
cd vissr/feeder/feeder-template/feederv3/
go build
./feederv3
次のようなログが流れます。
{"file":"feederv3.go:580","level":"info","msg":"Redis state storage initialised.","time":"2025-04-24T16:53:24+09:00"}
{"file":"feederv3.go:605","level":"info","msg":"Initializing the feeder for mapping file VssVehicle.cvt.","time":"2025-04-24T16:53:24+09:00"}
...
次に別のターミナルでserverをビルドし、起動します。
cd vissr/server/vissv2server/
go build
./vissv2server
次のようなログが流れます。
Total number of nodes in VSS tree = 1413
Max depth of VSS tree = 9
Total number of nodes in VSS tree = 37
Max depth of VSS tree = 6
{"file":"vissv2server.go:852","level":"info","msg":"main():starting loop for channel receptions...","time":"2025-04-24T16:58:51+09:00"}
...
いくつかのクライアントが用意されていますが、今回はサーバーとWebSocketで接続するクライアントを使います。
vissr/client/client-1.0/Javascript/wsclient.html
をブラウザで開きます。
host ipのところにlocalhost
を入力し、Server IP
を押して、serverと接続します。
クライアントから色々試す
クライアントからいくつかの操作を試してみます。
まずは、チュートリアルに従い、次のようなJSONを投げます。
{"action":"get","path":"Vehicle.Cabin.Door.Row1.DriverSide.IsOpen","requestId":"232"}
そうすると、つぎのようにサーバーからのレスポンスが表示されます。
valueはvisserr:Data-not-available
となっています。feederv3はVssVehicle.cvt
に指定されているシグナルのシミュレーション値を作成します。
VssVehicle.cvt
はDomain Conversion Tool(DCT)で作成されたファイルです。このファイルには、「vehicle domain」と「VSS domain」間でシグナルがどのようにマッピングおよびスケーリングされるかの指示が含まれています。cvtファイルには、tools/DomainConversionTool/Map-VSSv0.1-CANv0.1.yaml
ファイルに記載されている5つのシグナルのみが含まれています。したがって、サーバーから値を取得したい場合は、Map-VSSv0.1-CANv0.1.yaml
に記載されているシグナルを指定する必要があります。もしくは、新しいcvtファイルを作成することで、より多くのシグナルを取得できます。詳細については、DomainConversionToolのREADMEを参照してください。
Server: {"action":"get","data":{"dp":{"ts":"2025-04-24T17:10:47.780Z","value":"visserr:Data-not-available"},"path":"Vehicle.Cabin.Door.Row1.DriverSide.IsOpen"},"requestId":"232","ts":"2025-04-24T17:10:47.778Z"}
次は、シグナルが定義されているVehicle.Speed
を取得してみます。
{"action":"get","path":"Vehicle.Speed","requestId":"232"}
レスポンスのvalueに、値が設定されています!
Server: {"action":"get","data":{"dp":{"ts":"2025-04-24T17:43:34.411Z","value":"1145.8529"},"path":"Vehicle.Speed"},"requestId":"232","ts":"2025-04-24T17:43:34.770Z"}
次はsubscribeを試します。
filterには、variant
とparameter
を指定します。10秒ごとに値を取得するという条件のようです。
その他の条件の指定方法については、VISSの仕様を参照してください。
{"action":"subscribe","path":"Vehicle.Speed","filter":{"variant":"timebased","parameter":{"period":"10000"}},"requestId":"246"}
subscribe時のレスポンスは次のとおりです。値は返さず、subscriptionIdが返ってきます。subscriptionIdは、subscriptionを解除する時に使います。
Server: {"action":"subscribe","requestId":"246","subscriptionId":"1","ts":"2025-04-24T17:45:25.355Z"}
その後10秒ごとに次のような値が送られてきました。
Server: {"action":"subscription","data":{"dp":{"ts":"2025-04-24T17:45:07.442Z","value":"69.20179"},"path":"Vehicle.Speed"},"subscriptionId":"1","ts":"2025-04-24T17:45:35.358Z"}
Server: {"action":"subscription","data":{"dp":{"ts":"2025-04-24T17:45:07.442Z","value":"69.20179"},"path":"Vehicle.Speed"},"subscriptionId":"1","ts":"2025-04-24T17:45:45.357Z"}
Server: {"action":"subscription","data":{"dp":{"ts":"2025-04-24T17:45:52.462Z","value":"548.7863"},"path":"Vehicle.Speed"},"subscriptionId":"1","ts":"2025-04-24T17:45:55.358Z"}
subscribeを解除します。
{"action":"unsubscribe","subscriptionId":"1","requestId":"240"}
解除時のレスポンスは次のとおりです。
Server: {"action":"unsubscribe","requestId":"240","ts":"2025-04-24T17:46:02.953Z"}
以上で終わろうと思いますが、client/client-1.0/Javascript/appclient_commands.txt にさまざまなリクエストの例が記載されているようです。色々試してみることで、より理解が深まりそうです。
試し終えたら、ctrl+cでfeederv3とserverを終了します。
redisは以下のコマンドで終了します。
redis-cli -s /var/tmp/vissv2/redisDB.sock shutdown
さいごに
今回は、VISSのリファレンス実装であるVISSRのHello World exampleを実際に動かしながら、VISSで定められてる基本的な操作について学びました。
車両ドメインとVSSドメインとの変換を行うためのfeederといったコンポーネントもVISSRに用意されています。また、車両ドメインのシグナルをどのようにエンコード/デコードし、VSSドメインにマッピングするのかといった情報を定義したファイルを作るための各ツールもVISSRに用意されています。VISSRのサーバー部分がVISSに規定されている箇所にはなりますが、それだけでは機能しません。feederや各ツール、サーバーを検証するためのクライアントなどそれぞれ用意されているのは非常にありがたいですね。