00. デバイス一覧
HTTP REST API を通じて、接続されているすべてのHaply 検出します。WebSocket は不要です。ランタイムが起動しており、ハードウェアを検出できているかを確認するための簡単な動作確認テストです。
学習内容:
- クエリの実行
GET /devicesInverse3、VerseGrip、およびWireless VerseGripデバイスを一覧表示する - JSONレスポンスからデバイスIDを読み取り、デバイスタイプごとにグループ化する
- セッションセレクタを使用して、デバイスの生座標とセッションのアプリケーション空間ビューを切り替える
ワークフロー
- 送信
GET http://localhost:10001/devices. - JSONレスポンスを解析する — 3つの最上位の配列:
inverse3,verse_grip,wireless_verse_grip. - デバイスIDをタイプごとにグループ分けして出力します。配列が空の場合は、そのタイプのデバイスが検出されていないことを意味します。
- もし……なら セッションセレクタ は次のように付加されます
?session=<selector>、応答はそのセッションのデバイスにフィルタリングされ、座標はそのアプリケーション空間に変換されます(基底、マウント、ワークスペースが適用されます)。Pythonのサンプルでは、これをCLI引数として公開しています。一方、C++のサンプルでは、セレクタを指定せずにクエリを実行します。
パラメータ
| パラメータ | デフォルト | 目的 |
|---|---|---|
| サービスのURL | http://localhost:10001 | HTTPのベースURL |
| エンドポイント | /devices | デバイス検出エンドポイント |
| セッションセレクタ | (なし) | ?session=:0, ?session=:-1, ?session=:my_profile:0 — 参照 セレクタ. PythonのサンプルではCLI引数として公開されています。 |
キーコード
- Python
- C++ (nlohmann)
- C++ (Glaze)
このPythonサンプルでは、セッションセレクタをCLI引数として指定できるようにしています。これを指定しない場合、デバイスは生のデバイス空間座標で返されますが、指定すると、選択されたセッションにフィルタリングされ、アプリケーション空間に変換されます。
def main():
session = sys.argv[1] if len(sys.argv) > 1 else None
url = f"{BASE_URL}/devices"
if session:
url += f"?session={session}"
print(f"Querying devices for session '{session}' (application space)\n")
else:
print("Querying all detected devices (device space)\n")
r = requests.get(url, timeout=3)
r.raise_for_status()
data = r.json()
print_devices("Inverse3", data.get("inverse3"))
print_devices("Wired Verse Grip", data.get("verse_grip"))
print_devices("Wireless Verse Grip", data.get("wireless_verse_grip"))
C++版では libhv HTTP用と、パース用にnlohmann/jsonを使用しています。これは、各トップレベルキーを contains() かつ、配列が空でない場合はそれを反復処理します。C++のサンプルでは、セッションセレクタのCLI引数は公開されていません — append ?session=<selector> アプリケーション空間の座標が必要な場合は、URLにアクセスしてください。
HttpResponsePtr resp = requests::get("localhost:10001/devices");
if (resp == nullptr) { /* ... error ... */ return 1; }
json data = json::parse(resp->body);
if (data.contains("inverse3") && !data["inverse3"].empty()) {
printf("Inverse3 found:\n");
for (auto &element : data["inverse3"]) {
printf(" (id: %s)\n", element["device_id"].get<std::string>().c_str());
}
}
// ... same pattern for verse_grip and wireless_verse_grip
Glazeのバリアントは、JSONの構造を反映したプレーンな構造体を宣言します。Glazeはコンパイル時のリフレクションを通じてこれらを埋めます。いいえ contains() 確認事項:欠落している配列は空として返される std::vector<>.
static constexpr glz::opts glz_settings{.error_on_unknown_keys = false};
struct device_entry { std::string device_id; };
struct devices_response {
std::vector<device_entry> inverse3;
std::vector<device_entry> verse_grip;
std::vector<device_entry> wireless_verse_grip;
};
// In main():
HttpResponsePtr resp = requests::get("localhost:10001/devices");
devices_response data;
if (auto err = glz::read<glz_settings>(data, resp->body)) {
printf("JSON parse error: %s\n", glz::format_error(err, resp->body).c_str());
return 1;
}
for (const auto &dev : data.inverse3) {
printf(" (id: %s)\n", dev.device_id.c_str());
}