> ## Documentation Index
> Fetch the complete documentation index at: https://docs.wuji.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# 设备信息

## 概述

本篇实践介绍如何读取设备静态信息和关节诊断状态。应用场景包括检查在线关节、排查温度异常和定位设备故障。

对应的 C 示例为 [2\_hand\_info.c](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/wuji_hand_2/2_hand_info.c)。 参数和诊断字段见 [设备身份与诊断](/docs/wuji-hand/latest/sdk-reference/device-operations#身份与诊断) 和 [关节诊断数据类型](/docs/wuji-hand/latest/sdk-reference/diagnostics#数据类型)。

<Info>
  Python 侧没有对应的独立示例，但相关能力都有：`hand.handedness()`、`hand.ip()`、`hand.online_joints_count()`、`hand.joints`、`hand.effort_limit()`，以及订阅 `joint_diagnostics` 取诊断快照。
</Info>

## 前置条件

### 硬件

| 项目 | 要求 |
| - | - |
| Wuji Hand 2 | 1 只 |
| 连接方式 | 以太网 |

### 软件

| 项目 | 要求 |
| - | - |
| 操作系统 | Ubuntu 22.04 LTS 及以上版本 |
| Wuji SDK | v2026.8.31 或更高版本 |
| C 工具链 | CMake 3.16 及以上版本，以及解压后的 SDK 包 |

## 数据流

```mermaid theme={null}
flowchart TD
    INIT["初始化 SDK<br/>C: wuji_init()"]
    SCAN["扫描并筛选 Wuji Hand 2<br/>C: wuji_scan()"]
    CONNECT["按序列号连接<br/>C: wuji_connect()"]
    INFO["读取手性、IP、在线关节数<br/>C: wuji_hand_2_get_handedness()<br/>wuji_hand_2_get_ip()、wuji_hand_2_online_joints_count()"]
    LIMIT["读取力矩上限与在线位图<br/>C: wuji_hand_2_get_all_effort_limit()"]
    DIAG["订阅 joint_diagnostics<br/>等待并复制一帧诊断快照"]
    CLEAN["关闭订阅并清理<br/>wuji_sub_close()、断开、释放、wuji_shutdown()"]

    INIT --> SCAN --> CONNECT --> INFO --> LIMIT --> DIAG --> CLEAN
```

在线位图是 32 位整数，第 N 位对应索引 N 的关节。20 关节全在线时为 `0x000FFFFF`。

## 关节的两套编号

这是读懂本示例输出、也是读懂 `joint_states` 的关键。

| 编号 | 取值 | 用途 |
| - | - | - |
| **数组索引** | 连续的 0 到 19 | `effort_limit`、`mit_params`、`joint_command` 等数组类接口的下标 |
| **`nid`** | 1–4、6–9、11–14、16–19、21–24 | 固件总线节点 ID，出现在 `joint_states` 与 `joint_diagnostics` 里 |

每根手指占用 5 个 nid 号段但只用前 4 个，所以 5、10、15、20 被跳过。两者的换算关系实测吻合全部 20 个关节：

```text theme={null}
nid = (索引 // 4) * 5 + (索引 % 4) + 1
```

| 索引 | 标签 | nid |
| - | - | - |
| 0 | `thumb_S1` | 1 |
| 3 | `thumb_S4` | 4 |
| 4 | `index_S1` | 6 |
| 7 | `index_S4` | 9 |
| 8 | `middle_S1` | 11 |
| 19 | `pinky_S4` | 24 |

**拿 `joint_states` 里的 `nid` 直接当数组下标会整体错位。**

## 集成步骤

### 1. 发现并连接设备

本篇对应 C 示例。先用 `wuji_init()` 初始化 SDK，通过 `wuji_scan()` 找到 Wuji Hand 2，再将目标序列号传给 `wuji_connect()`。连接调用返回后释放扫描结果，成功连接后继续读取信息。

```c theme={null}
WujiConnectTarget tgt = {
    .kind = WUJI_CONNECT_TARGET_KIND_SN,
    .value = list[idx].serial_number,
};
struct WujiDevice *dev = NULL;
WujiStatus st = wuji_connect(&tgt, "hand2", NULL, &dev);
wuji_discovered_free(list, n);
```

`idx` 是扫描结果中已确认的 Wuji Hand 2 下标。没有匹配设备或连接失败时直接进入清理路径。

### 2. 读取设备信息和关节上限

使用 `wuji_hand_2_get_handedness()` 读取手性，`wuji_hand_2_online_joints_count()` 读取在线数量。IP 字符串使用 `wuji_hand_2_get_ip()` 两次调用：先查询缓冲区长度，再分配并读取。

```c theme={null}
WujiHandedness side;
uint8_t count = 0;
wuji_hand_2_get_handedness(dev, &side);
wuji_hand_2_online_joints_count(dev, &count);
```

`wuji_hand_2_get_all_effort_limit()` 同时返回上限数组和在线位图。只有位图中标为在线的条目可供读取。

```c theme={null}
float limits[WUJI_HAND_2_JOINT_COUNT];
uint32_t online = 0;
if (wuji_hand_2_get_all_effort_limit(dev, limits, &online) == WUJI_STATUS_OK) {
    for (int i = 0; i < WUJI_HAND_2_JOINT_COUNT; i++) {
        if (WUJI_JOINT_ONLINE(online, i))
            printf("joint %d: %.3f A\n", i, limits[i]);
    }
}
```

### 3. 获取一帧诊断快照

注册 `joint_diagnostics` 回调，在回调中将条目复制到应用持有的快照，再用原子标志通知主线程。示例最多等待约 1 秒，随后关闭订阅，读取复制后的数据。

```c theme={null}
diag_snapshot_t snap = {0};
struct WujiSub *sub = NULL;
if (wuji_hand_2_subscribe_joint_diagnostics(dev, on_diag, &snap, &sub)
        == WUJI_STATUS_OK) {
    for (int i = 0; i < 100 && !atomic_load_explicit(&snap.got, memory_order_acquire); i++)
        usleep(10000);
    wuji_sub_close(sub);
}
```

`diag_snapshot_t` 和 `on_diag` 是示例定义的快照结构与回调，[C 示例](https://github.com/wuji-technology/wuji-sdk/blob/main/examples/c/wuji_hand_2/2_hand_info.c) 包含字段复制和跨线程同步。超时未收到帧时不读取快照条目。

### 4. 释放设备和 SDK

完成信息读取后断开连接、释放设备句柄，最后关闭 SDK。错误路径使用同一清理顺序。

```c theme={null}
wuji_dev_disconnect(dev);
wuji_dev_release(dev);
wuji_shutdown();
```

## 运行与输出

```bash theme={null}
./build/hand2/2_hand_info
```

### 实测输出

在 20 关节全在线的右手 Wuji Hand 2 上实跑：

```text theme={null}
Connecting to WH2KA00XXXXXXXXX (192.168.1.100:7447)
handedness: right
ip: 192.168.1.100
online joints (count): 20

online bitmap = 0x000FFFFF  (20 joints online)
  i   label     state      effort_lim
  0   thumb_S1  online        1.500A
  1   thumb_S2  online        1.500A
  2   thumb_S3  online        1.500A
  3   thumb_S4  online        1.500A
  4   index_S1  online        1.500A
  ...
  19  pinky_S4  online        1.500A

joint_diagnostics snapshot (20 joints):
  nid  status_word   current    vbus   temp err_code
  1    0x24620001    0.00A   12.3V  54.8C   0x0000
  2    0x24620001   -0.01A   12.4V  55.4C   0x0000
  ...
  24   0x24620001    0.01A   12.3V  55.8C   0x0000
```

| 指标 | 实测 |
| - | - |
| 在线位图 | `0x000FFFFF`，20 位全置 |
| 关节标签 | `thumb_S1` 到 `pinky_S4`，每指 4 个 |
| 力矩上限 | 全部 1.500 A |
| 状态字 | 全部 `0x24620001` |
| 母线电压 | 12.3 到 12.4 V |
| 温度 | 49.1 到 58.6 摄氏度 |
| 错误码 | 全部 `0x0000` |
| 静置电流 | −0.02 到 +0.01 A |

静置未使能时电流在零附近小幅波动，温度稳定在 50 摄氏度上下，这是正常状态。

## 注意事项

| 分支点 | 表现 | 处理 |
| - | - | - |
| 关节离线 | 位图对应位为 0，该关节标记 `offline` | 检查总线连接与供电 |
| 错误码非零 | `err_code` 栏非 `0x0000` | 对照故障码定位，必要时 `clear_fault()` |
| 温度偏高 | `temp` 栏数值偏大 | 实测静置状态约 49 到 59 摄氏度 |
| 多台设备 | 示例连扫到的第一台 | 共用网络要改成指定 SN |

## 扩展用法

### 判断关节是否在线

位图比逐个查询快。`(bitmap >> i) & 1` 为 1 表示索引 i 的关节在线。注意这里用的是**数组索引**，不是 nid。

### 温度与电压的参考范围

实测静置状态温度 49 到 59 摄氏度、母线电压 12.3 到 12.4 V。长时间大幅运动后温度会上升，持续偏高要检查散热与负载。

### 故障码排查

`err_code` 非零时对照故障码表定位。清除故障用 `clear_fault()`，清不掉说明故障仍然存在。

### 定位某个具体关节

已知标签想找 nid，用上面的换算公式。已知 nid 想找标签，反推索引 `i = (nid - 1) // 5 * 4 + (nid - 1) % 5`，注意 nid 为 5、10、15、20 时无对应关节。

## 相关内容

* [数据订阅：回调](/docs/wuji-hand/latest/sdk-practice/subscribe-callback)：`joint_states` 里 nid 的实际表现
* [发布控制指令](/docs/wuji-hand/latest/sdk-practice/publish-command)：数组下标与 nid 在控制接口里的用法
* [故障排查](/docs/wuji-sdk/troubleshooting/)：故障码与处理


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.