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 인수로 노출됩니다. |
키 코드
- 파이썬
- 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());
}