00. 设备清单
通过 REST HTTP API 探索所有已连接的Haply 设备——无需 WebSocket。这是一个基础测试,用于验证运行环境是否正常工作并能检测到硬件。
您将学到:
- 审问
GET /devices查看Inverse3 、VerseGrip 和 VerseGrip 无线版等设备列表 - 在 JSON 响应中读取按设备类型分组的设备标识符
- 使用会话选择器在设备的原始坐标与会话的应用空间视图之间切换
流程
- 发送
GET http://localhost:10001/devices. - 分析 JSON 响应——三个顶级数组:
inverse3,verse_grip,wireless_verse_grip. - 按类型显示已分组的设备标识符。若表格为空,则表示未检测到该类型的设备。
- 如果一个 会话选择器 以以下形式添加:
?session=<selector>,响应会根据本次会话中的设备进行过滤,坐标会被转换到其应用空间(应用的基础空间、装载空间和工作空间)中。Python 示例以 CLI 参数的形式展示了这一点--session SELECTOR(接受:profile:instance,#id,:-1,:0, …) — 与在 教程 08(HTTP:远程配置),因此在这里找到的选择器可以直接粘贴到那里。C++示例中未使用选择器进行查询。
参数
| 参数 | 默认 | 角色 |
|---|---|---|
| 服务网址 | http://localhost:10001 | HTTP 基础 URL |
| 终点 | /devices | 设备发现端点 |
| 会话选择器 | (无) | ?session=:0, ?session=:-1, ?session=:my_profile:0, ?session=co.haply.hub::*:0 (支持通配符)——参见 选择器. 以……的形式呈现 --session SELECTOR 在 Python 示例中(与 教程 08). |
密钥
- Python
- C++ (nlohmann)
- C++ (Glaze)
该 Python 示例将会话选择器作为 argparse 参数进行展示 --session SELECTOR. 如果不使用该参数,设备将被转换回设备坐标系中的原始坐标;如果使用该参数,则会根据所选会话对坐标进行过滤,并转换为应用坐标系。帮助文本与 教程 08(HTTP:远程配置),因此在这里找到的选项可以直接粘贴到那里。
def parse_args():
parser = argparse.ArgumentParser(
description="List connected Haply Inverse devices via the HTTP API.")
parser.add_argument(
"--session", type=str, default="",
help=(
"Session selector. Formats:\n"
" :profile:instance by profile name (e.g. ':my_profile:0')\n"
" pattern:instance glob wildcard in profile (e.g. 'co.haply.hub::*:0')\n"
" '*' matches any sequence, '?' one character\n"
" #session_id by numeric id (e.g. '#42' — quote in shells to escape '#')\n"
" :-1 the last active session\n"
" :0 the first session"
))
return parser.parse_args()
def main():
args = parse_args()
session = args.session or 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 参数——请添加 ?session=<selector> 如需获取应用空间的联系方式,请访问该网址。
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());
}
包含在 SDK 安装程序中
教程 00 也随 SDK 一起安装在本地——请参阅 tutorials/00-haply-inverse-device-list/ 在服务安装目录中。