HumansXDocumentation Center 日本語Website ↗
Knowledge Base › Software › Wuji SDK

Device Discovery & Connection

Developer Guide

Connecting takes three steps: scan the local network and local USB bus for a device list, locate the target by serial number, address, or handedness, and let the SDK hold the connection until you close it explicitly. Python and C share the same semantics. They differ in error reporting and handle lifetime.

Device Discovery

Scan for Wuji devices connected via Ethernet on the local network or over USB:

  • Python

  • C

from wuji_sdk import SdkManager

manager = SdkManager.instance()
devices = manager.scan()

for dev in devices:
    print(f"SN: {dev.sn}, Type: {dev.device_type}, Address: {dev.address}")
#include "wuji_sdk.h"

wuji_init(NULL);

WujiDiscovered *devs = NULL;
size_t count = 0;
wuji_scan(&devs, &count);

for (size_t i = 0; i < count; i++) {
    printf("SN: %s, Type: %s, Address: %s\n",
           devs[i].serial_number, devs[i].model, devs[i].address);
}
wuji_discovered_free(devs, count);

Each discovered record carries the serial number, address, and device type, so you can tell what a device is before connecting. In Python, DiscoveredDevice.device_type is a DeviceType enum (WujiGlove / WujiHand2 / WujiHand). In C, WujiDiscovered.device_id is a WujiDeviceType enum (WUJI_DEVICE_TYPE_WUJI_GLOVE / _WUJI_HAND_2 / _WUJI_HAND). Unknown and WUJI_DEVICE_TYPE_UNKNOWN mean the type was not available at scan time or isn’t recognized by this SDK build.

Network prerequisite: Ethernet devices use static IPs, not DHCP. Before scanning or connecting, set your host NIC to the same subnet (for example 192.168.1.50, avoiding the device default addresses), or the devices can’t be discovered or reached.

When running the SDK on macOS, allow the terminal or IDE to access the device’s local network if prompted for local network permission. If the system firewall is enabled and prompts you to allow incoming connections for the application, select Allow.

On macOS 15 or later, if you denied local network access, enable it for the terminal or IDE in System Settings › Privacy & Security › Local Network.

Connecting to a Device

device_name in all connect APIs is a local alias, used only to look up the device later and to namespace resource paths. It does not select a device and does not determine the returned handle type. The returned type is determined by the actual connected device. The name must be non-empty and must not contain / or ..

Choose a Connection Method

Pick by how many devices are currently discovered. See Auto Connect, Connect by SN, Connect by Address, Connect by USB, and Connect by Handedness:

How many devices does scan() currently find?
│
├─ exactly one ──▶ auto_connect() — works for USB and Ethernet alike
│
└─ multiple ▶ connect() with an explicit locator — sn / address / handedness are mutually exclusive
     ├─ sn=... — any device, most precise (filter USB devices by TransportType.Usb first)
     ├─ address=... — direct connect when you know the IP
     └─ handedness=... — by hand side (Wuji Hand 2 / Wuji Glove)
          └─ multiple same-side devices ▶ AmbiguousHandedness ▶ use sn

Any method can take Connection Options to configure timeout, retries, and device sharing.

Auto Connect

auto_connect() connects to the single device currently discovered. If multiple devices are present, the call fails because the target is ambiguous. Use connect() to disambiguate in that case:

glove = manager.auto_connect(device_name="glove")
print(f"Connected: {glove.serial_number}")

C has no equivalent. Call wuji_scan(), confirm the list holds exactly one record, then take its serial_number and follow Connect by SN.

Connect by SN

Connect to a specific device by serial number:

  • Python

  • C

glove = manager.connect(sn="WG1JA00XXXXXXXXX", device_name="glove")
WujiConnectTarget target = {
    .kind = WUJI_CONNECT_TARGET_KIND_SN,
    .value = "WG1JA00XXXXXXXXX",
};

WujiDevice *glove = NULL;
if (wuji_connect(&target, "glove", NULL, &glove) != WUJI_STATUS_OK) {
    fprintf(stderr, "connect failed: %s\n", wuji_last_error());
    return 1;
}

Connect by Address

Manually connect using IP address and port:

  • Python

  • C

glove = manager.connect(address="192.168.1.100:50000", device_name="glove")
WujiConnectTarget target = {
    .kind = WUJI_CONNECT_TARGET_KIND_ADDR,
    .value = "192.168.1.100:50000",
};

WujiDevice *glove = NULL;
wuji_connect(&target, "glove", NULL, &glove);

Include the port in the address. Use IP:port for IPv4. IPv6 addresses aren’t supported. A bare IP address returns a missing-port error instead of being treated as a USB path. Serial port paths aren’t supported either — scan first, then connect by SN.

Connect by USB

Wuji Hand attaches over USB. Filter the scan results by transport type, then connect by serial number:

  • Python

  • C

from wuji_sdk import SdkManager, TransportType

manager = SdkManager.instance()
usb_devices = [d for d in manager.scan() if d.transport_type == TransportType.Usb]

hand = manager.connect(sn=usb_devices[0].sn, device_name="wuji_hand")
print(f"Connected: {hand.serial_number} ({hand.handedness_name()})")
WujiDiscovered *devs = NULL;
size_t count = 0;
wuji_scan(&devs, &count);

WujiDevice *hand = NULL;
for (size_t i = 0; i < count; i++) {
    if (devs[i].transport == WUJI_TRANSPORT_TYPE_USB) {
        if (wuji_hand_connect_sn(devs[i].serial_number, "wuji_hand", &hand) != WUJI_STATUS_OK) {
            fprintf(stderr, "connect failed: %s\n", wuji_last_error());
            hand = NULL;
        }
        break;
    }
}
wuji_discovered_free(devs, count);

wuji_hand_connect_sn() is shorthand for wuji_connect() with SN targeting. Both return the same kind of device handle.

If a matching-handedness tactile glove is plugged in alongside the hand, the SDK auto-pairs it on connect. Check with hand.is_tactile_attached() in Python or wuji_hand_is_tactile_attached() in C. The value reflects the current attachment and turns false after the glove is unplugged at runtime. Once unplugged, the tactile status stream’s state becomes 0 (not present), other tactile reads and subscriptions fail with a tactile_not_present error, and the hand itself keeps working. Re-attaching the glove requires reconnecting the hand.

On a Mac with Apple silicon, Wuji Hand and its tactile glove need no extra USB driver. Unplugging the Wuji Hand USB cable reports USB I/O error: device disconnected. After plugging it back in, reconnect the device and recreate subscriptions.

Connect by Handedness

Connect to a two-handed device (such as Wuji Hand 2 or Wuji Glove) by left or right hand, without looking up a serial number first. The SDK scans the local network and selects the unique device by the fourth character of its serial number (J for left, K for right):

from wuji_sdk import Handedness

# Connect the right-hand device
hand = manager.connect(handedness=Handedness.Right, device_name="wuji_hand_2")

# Connect the left-hand glove
glove = manager.connect(handedness=Handedness.Left, device_name="wuji_glove")

handedness is mutually exclusive with sn and address—specify only one.

C has no equivalent. In the wuji_scan() results, match serial_number[3] against 'J' or 'K' to isolate the target, then follow Connect by SN.

In Python, if no device matches the handedness, DeviceNotFound is raised. If multiple devices share the handedness, AmbiguousHandedness is raised with all candidate serial numbers. Specify sn explicitly instead.

Connection Options

Configure timeout, retries, and device sharing:

  • Python

  • C

from wuji_sdk import ConnectOptions

options = ConnectOptions(
    timeout_ms=1000,   # Connection timeout (milliseconds)
    retry_count=3      # Number of retries
)

glove = manager.connect(
    sn="WG1JA00XXXXXXXXX",
    device_name="glove",
    options=options
)
WujiConnectOptions options = wuji_connect_options_default();
options.timeout_ms = 1000;   // Connection timeout (milliseconds)
options.retry_count = 3;     // Number of retries

WujiConnectTarget target = {
    .kind = WUJI_CONNECT_TARGET_KIND_SN,
    .value = "WG1JA00XXXXXXXXX",
};

WujiDevice *glove = NULL;
wuji_connect(&target, "glove", &options, &glove);

enable_bridge (on by default) controls whether multiple SDK instances (including processes on other hosts) can connect to the same device. When enabled, this process shares the connected device. Turn it off for exclusive access — other instances can’t reach the device through this process.

In C, always start from wuji_connect_options_default() and override only the fields you need. Zero-initializing the whole struct also clears enable_bridge and background time sync, which changes connection behavior. Pass NULL to wuji_connect() when the defaults are fine.

Multi-device Management

The SDK supports connecting multiple devices simultaneously, each identified by a unique device_name:

  • Python

  • C

left = manager.connect(handedness=Handedness.Left, device_name="left_hand")
right = manager.connect(handedness=Handedness.Right, device_name="right_hand")

# Get all connected devices
all_devices = manager.get_connected_devices()
for name, device in all_devices:
    print(f"{name}: {device.serial_number}")

# Get a device by name
left = manager.get_device(device_name="left_hand")
WujiConnectTarget left_target = {
    .kind = WUJI_CONNECT_TARGET_KIND_SN,
    .value = "WG1JA00XXXXXXXXX",
};
WujiConnectTarget right_target = {
    .kind = WUJI_CONNECT_TARGET_KIND_SN,
    .value = "WG1KA00XXXXXXXXX",
};

WujiDevice *left = NULL, *right = NULL;
wuji_connect(&left_target, "left_hand", NULL, &left);
wuji_connect(&right_target, "right_hand", NULL, &right);

// C has no alias registry — keep the handles yourself
char name[64];
wuji_dev_device_name(left, name, sizeof(name));
printf("%s: connected=%u\n", name, wuji_dev_is_connected(left));

Use different device_name values to keep the left and right hand in the same process. Reconnecting to an already-active device raises SessionAlreadyExists in Python and returns a failure status in C. Neither drops the existing connection — keep using the existing handle.

Disconnecting

  • Python

  • C

# Disconnect a specific device
manager.disconnect(device_name="glove")

# Or disconnect via the device object
glove.disconnect()

# Disconnect all devices managed by this manager
manager.disconnect_all()
// Disconnect first, then release the handle — both calls are required
wuji_dev_disconnect(glove);
wuji_dev_release(glove);

When a device is disconnected, all subscriptions on that device are automatically closed. You’ll need to re-establish subscriptions after reconnecting.

The SDK owns the connection, and dropping a device object or handle variable doesn’t close it. In Python, deleting or replacing a device object leaves the connection active until you call disconnect() or disconnect_all(), or until the process exits, so long-running programs should disconnect explicitly in a finally block. In C, wuji_dev_release() only returns the handle, so call wuji_dev_disconnect() before releasing it. With an exclusive connection, leaving the connection open also prevents other clients from connecting to the device.

Interface List

OperationPythonC
Initialize and shut down the SDKSdkManager.instance()wuji_init(), wuji_shutdown()
Scan for devicesmanager.scan()wuji_scan(), wuji_discovered_free()
Connect the only discovered devicemanager.auto_connect(device_name=...)No equivalent — scan first, then call wuji_connect() with the serial number
Connect by serial numbermanager.connect(sn=...)wuji_connect() with target.kind set to WUJI_CONNECT_TARGET_KIND_SN
Connect by addressmanager.connect(address=...)wuji_connect() with target.kind set to WUJI_CONNECT_TARGET_KIND_ADDR
Connect a Wuji Hand over USBFilter by TransportType.Usb, then manager.connect(sn=...)wuji_hand_connect_sn()
Connect by handednessmanager.connect(handedness=...)No equivalent — filter scan results on the fourth serial-number character, then call wuji_connect()
Configure connection parametersConnectOptions(...)wuji_connect_options_default(), then override WujiConnectOptions fields
Read serial number and aliasdevice.serial_number, device.device_namewuji_dev_serial_number(), wuji_dev_device_name()
Check connection statedevice.is_connectedwuji_dev_is_connected()
Look up a device by aliasmanager.get_device(device_name=...), manager.get_connected_devices()No equivalent — keep the device handles yourself
Disconnect one devicedevice.disconnect(), manager.disconnect(device_name=...)wuji_dev_disconnect(), wuji_dev_release()
Disconnect every devicemanager.disconnect_all()No equivalent — call wuji_dev_disconnect() on each handle

Python reports failures as exceptions. C reports them as WujiStatus return codes, with the reason available from wuji_last_error(). For build flags, linking, memory ownership, and the full status code list, see the C Interface Reference.