クイックスタート
このページは、はじめから終わりまでの流れをひととおり示します。その背景にある考え 方は、先に拡張機能をつくるを読んでください。
1. SDK と非同期ランタイムに依存する
Section titled “1. SDK と非同期ランタイムに依存する”拡張機能に必要なものは 2 つです。SDK のクレートと、非同期のコードを動かす何か。そ れ以外はありません。
[dependencies]vros-ext = "2.0"tokio = { version = "1", features = ["rt-multi-thread", "macros"] }クレートのバージョンは vrOS 自身のバージョンで、プロトコルのバージョンではありませ
ん。通信のバージョンは別の定数 vxp::VXP_VERSION で、現在は 1.7 です。ホストは
現行の VXP メジャーバージョンと、その 1 つ前を受け付け、1.x のマイナーは追加しかし
ません。古い SDK で作った拡張機能も新しい vrOS で動き続け、それ以降に加わったもの
が見えないだけです。
2. 接続し、hello を送る
Section titled “2. 接続し、hello を送る”vrOS は、エンドポイント、起動ごとのトークン、拡張機能の id を環境変数に入れてバイ
ナリを起動します。connect_from_env はそれらを読んで接続し、起動時の競合をしのぐ
ために数秒のあいだ再試行します。
そのうえで hello を送ります。猶予は起動から 5 秒で、それまで他には何も応答されませ ん。先に hello、初期化はそのあとです。
use vros_ext::conn::{Client, SocketConnection};use vros_ext::event::VxpEvent;use vros_ext::hello::{HelloReply, HelloRequest};use vros_ext::vxp;
#[tokio::main]async fn main() -> Result<(), Box<dyn std::error::Error>> { let conn = SocketConnection::connect_from_env().await?; let client = Client::new(conn);
let reply = client .hello(&HelloRequest { id: std::env::var(vxp::ENV_EXT_ID)?, vxp_version: vxp::VXP_VERSION.into(), token: std::env::var(vxp::ENV_TOKEN).ok(), }) .await?;
// The welcome carries what the user actually granted, and their locale. let (granted, locale) = match reply { HelloReply::Welcome { granted, locale, .. } => (granted, locale), HelloReply::Rejected { code, message } => { return Err(format!("hello rejected ({code:?}): {message}").into()); } other => return Err(format!("unknown hello reply: {other:?}").into()), };
// Do your setup here — read KV, subscribe to what you were granted, // push your panel's words. Then park on the event stream. let mut events = client.take_events().ok_or("no event stream")?; while let Some(event) = events.recv().await { match event { VxpEvent::ShuttingDown => break, _ => {} } } Ok(())}ケーパビリティを使う前に、マニフェストがまるごと受け入れられたと決めてかからず、
granted を確認してください。利用者の同意はケーパビリティごとで、許可されなかった
ものはそのセッションのあいだ変わりません。
3. マニフェストを書く
Section titled “3. マニフェストを書く”vros-ext.toml はバイナリの隣に置かれ、その拡張機能を説明します。同意画面が読むの
はこれで、読まれるのは拡張機能が停止しているあいだです。
[extension]id = "com.example.hello"name = "Hello"version = "0.1.0"author = "Your name"entry = "hello.exe" # the binary name; drop the .exe on Linuxrestart = "on-crash"
[capabilities]bus = ["vr.lifecycle"]
[panels]overlay = "ui/hello.slint"id は [a-z0-9.-] から取った小文字の逆引き DNS 形式で、慣例は tld.author.name
です。これはインストール先のフォルダー名でもあり、KV の名前空間でもあり、バスのプ
レフィックス(ext.<id>.*)でもあります。一度決めたら、そのまま使い続けてくださ
い。
4. フォルダーとして置く
Section titled “4. フォルダーとして置く”インストールとは、マニフェストと、そこに名前の書かれたバイナリと、パネルのソース を入れたフォルダーのことです。
%LOCALAPPDATA%\vrOS\extensions\com.example.hello\ (Windows)~/.local/share/vros/extensions/com.example.hello/ (Linux) ├─ vros-ext.toml ├─ hello.exe └─ ui/hello.slint5. 有効にする
Section titled “5. 有効にする”設定 → 拡張機能を開き、「更新」を押します。その拡張機能が、要求したケーパビリティ を並べた状態で、無効として現れます。有効にして同意すると、vrOS がそれを起動しま す。同じページに状態、再起動の回数、直近のエラーが出ます。あとで削除するのもここ です。
6. その先へ
Section titled “6. その先へ”プロトコルリファレンスは、通信上のすべての名前空間 — KV とシークレット、バス、パネルのプロパティと画像、コマンド、設定、文字列、オーディ オ、メディア、フェイストラッキング — を、上限とエラーコードとともに扱います。
つまずきやすいところ
Section titled “つまずきやすいところ”- hello は形式ではなく締め切りです。 5 秒を過ぎるとホストはプロセスを終了さ せ、指定された再起動ポリシーを適用します。
- パネルのパスはパース時に検査されます。 相対パス、区切りはスラッシュ、各要素
は英字・数字・ドット・アンダースコア・ハイフンのみ、末尾は
.slint。ディレクト リの遡り、絶対パス、ドライブレター、バックスラッシュは、ディスクを読む前に拒否 されます。 - マニフェストのフィールドはホストのバージョンを前提にします。 未知のマニフェ
ストのフィールドは、受け流されるのではなくエラーになります。
[[settings]]を含む マニフェストは VXP 1.1 より古いホストで、numberやselectの設定は VXP 1.3 よ り古いホストで、rail_labelやiconはそのフィールドを知らないホストでパースに 失敗します。例外はオーバーレイのwidth_mmだけで、古いホストはこれを無視し、既 定の幅でパネルを表示します。 - 1 行につき JSON オブジェクトは 1 つです。 バッチの配列は拒否され、3 MiB を超 えるフレームは破損として扱われます。
- 話すバージョンを正直に伝えてください。 hello には決め打ちの文字列ではなく
vxp::VXP_VERSIONを送ります。フェイスの更新は 1.5 以上、メディアの状態イベン トは 1.4 以上で hello を送った拡張機能にだけ届きます。 - 永続する状態は KV だけです。 何をしている最中でも再起動されうると考え、残りは 組み立て直してください。
まだ公開されていません
Section titled “まだ公開されていません”SDK のクレートは crates.io になく、それを収めたリポジトリ — クレート、リファレンス
の hello 拡張機能、@vros/theme.slint モジュール、オーサリング契約 — は現時点では
非公開です。コードは MIT または Apache-2.0 の選択制でライセンスされており、公開さ
れた瞬間に、このページからクレートとサンプルへリンクします。それより前にこれを相
手に開発したい場合は、Discord で声をかけてくださ
い。