HumansXドキュメントセンター English公式サイトへ ↗
ナレッジベース › Wuji Hand 2 › マニュアル

Exporting Device Logs

SDK Practice

このページは現在英語版のみです。日本語でのご説明が必要な場合は HumansX までお問い合わせください。

Overview

The Wuji Hand 2 keeps a log ring buffer in flash. export_flash_logs() pulls the whole ring, decodes it frame by frame, and writes a JSONL file with one log entry per line.

When something goes wrong on the device, this is the primary evidence. It records events from the firmware’s point of view, which sits closer to the fault than host-side SDK logs.

Matching examples: examples/python/wuji_hand_2/5.export_flash_logs.py and examples/c/wuji_hand_2/5_export_flash_logs.c.

For API and field definitions, see Diagnostics and Logs.

This example only reads. It doesn’t enable the motors, and the fingers don’t move.

Prerequisites

Hardware

ItemRequirement
Wuji Hand 21
ConnectionEthernet

Software

ItemRequirement
Operating systemLinux or a Mac with Apple silicon, meeting the system requirements
Wuji SDKv2026.8.31 or later
Python3.10 or later
C toolchainCMake 3.16 or later, plus the extracted SDK package

Data Flow

Every call exports everything and writes a new file. There’s no API to ask how many entries exist first, and no incremental export.

Where Output Goes

out_dir defaults to None, writing to the SDK’s default directory ~/.wuji/logs alongside the SDK’s own logs, with a flash_ prefix on the filename:

~/.wuji/logs/flash_<SN>_<date>_<time>.jsonl

Pass out_dir to write elsewhere.

Fields per Line

FieldMeaning
timestamp_msDevice timestamp in milliseconds
levelLog level, such as Info or Warn
targetThe firmware module that produced the entry
messageThe log text

Integration Steps

1. Discover and Connect to the Target Device

In Python, filter scan() results for DeviceType.WujiHand2, confirm that a match exists, then call connect(sn=...). In C, initialize the SDK, filter wuji_scan() results for WUJI_DEVICE_TYPE_WUJI_HAND_2, then connect by serial number with wuji_connect(). Export doesn’t require enabling the motors.

manager = SdkManager.instance()
hands = [d for d in manager.scan() if d.device_type == DeviceType.WujiHand2]
if not hands:
    raise RuntimeError("No Wuji Hand 2 found")
hand = manager.connect(sn=hands[0].sn, device_name="wuji_hand_2")

2. Export Logs and Get the Result

One call exports all logs and returns the file path and frame count. Pass None in Python or NULL in C to use the SDK’s default directory.

  • Python

  • C

result = hand.export_flash_logs(out_dir=None)
print(result["path"], result["frames"])
WujiFlashLogExport result;
WujiStatus st = wuji_hand_2_export_flash_logs(dev, NULL, &result);
if (st == WUJI_STATUS_OK) {
    printf("%s: %u frames\n", result.path, result.frame_count);
    wuji_hand_2_flash_log_export_free(&result);
}

In C, read and free result only after a successful export. On failure, the output isn’t populated. Read the error and enter device cleanup.

3. Check the File and Disconnect

When the frame count is nonzero, the Python example reads and parses the first JSONL line. The C example prints the path and frame count. Use that path to read the file in the application.

if result["frames"]:
    with open(result["path"], encoding="utf-8") as stream:
        first = json.loads(stream.readline())
    print(first["level"], first["target"], first["message"])

Python calls manager.disconnect_all() in finally. C calls wuji_dev_disconnect(dev), wuji_dev_release(dev), and wuji_shutdown() in order.

Running It

  • Python

  • C

python examples/python/wuji_hand_2/5.export_flash_logs.py
python examples/python/wuji_hand_2/5.export_flash_logs.py --out /tmp/hand2-logs
./build/hand2/5_export_flash_logs

Measurements

On a right-hand Wuji Hand 2:

Connected: WH2KA00XXXXXXXXX
Decoded 1180 frames into ~/.wuji/logs/flash_WH2KA00XXXXXXXXX_<date>_<time>.jsonl
First entry: [Info] sboard_app: [B2] T:25 R:20 g:0 bc:0/0 rel:0/0 mgmt:25/20 to:5 crc:0% oe:0 ne:0 fe:5 dma:0/0
MetricMeasured
Entries exported1180
Duration2.89 seconds
Lines in the file1180, matching frames
Returned fieldspath, frames

What the export contained:

LevelCount
Info1169
Warn11
targetCount
sboard_app1117
sboard_app::bus_manager40
sboard_app::wuji_server12
sboard_app::zenoh_server6
sboard_app::wall_clock_persist2

Most of it is periodic status lines from sboard_app shaped like [B2] T:25 R:20 g:0 bc:0/0 ..., plus node heartbeats such as nodes 4/5: [1:hb=0 2:hb=0 ...]. When investigating, filter by level for Warn and above first, then narrow by target to a module.

Notes

Branch pointBehaviorWhat to do
Empty ring bufferframes is 0 and a file is still writtenThe example uses that to skip reading the first line
Target directory doesn’t existHandled on the SDK sidePassing an existing directory is safer
Several devicesThe example uses the first it findsOn a shared network, name a serial number
Export durationScales with entry count, measured at 2.9 seconds for 1180 entriesDon’t call it inside a real-time loop

Adapting It

Filter for What You Care About

Each JSONL line stands alone, so jq filters directly:

jq -c 'select(.level != "Info")' flash_*.jsonl
jq -c 'select(.target | startswith("sboard_app::bus_manager"))' flash_*.jsonl

Export to a Specific Directory

python examples/python/wuji_hand_2/5.export_flash_logs.py --out /tmp/hand2-logs

Pass the out_dir argument. The default lands in ~/.wuji/logs mixed in with the SDK’s own logs, distinguished by the flash_ prefix.

How This Relates to Host-Side SDK Logs

The two have different vantage points. Flash logs are the firmware’s view, recording the bus, node heartbeats, and server state. SDK logs sit in the same directory and record host-side connect, subscribe, and publish activity. For connection problems, compare timestamps across both.

Don’t Call It in a Real-Time Loop

A full export pulls the entire ring buffer, measured at about 3 seconds for a thousand-odd entries. This is an investigation tool, not a monitoring mechanism. For continuous monitoring, subscribe to joint_diagnostics.