Skip to content

获取 SDK

SDK 概述

灵巧手 SDK(Software Development Kit)为 BrainCo Revo 1 和 Revo 2 设备提供 Python 与 C++ 接口,包含设备连接、状态读取、电机控制、触觉数据读取和固件升级示例。

系统要求

  • Python: 3.9 ~ 3.12
  • Linux: Ubuntu 20.04/22.04 LTS (x86_64/aarch64), glibc ≥ 2.31
  • macOS: 10.15+
  • Windows: 10/11

支持的通信协议

设备RS-485ProtobufCANCANFDEtherCAT
Revo 1
Revo 2

下载与安装

SDK 仓库

GitHub - brainco-hand-sdk

Python SDK 安装

bash
# 从 PyPI 安装
pip3 install bc-stark-sdk==2.0.2

# 国内镜像(阿里云 OSS)
bash install_whl.sh 2.0.2

示例代码


示例运行说明 (Running Demos)

在成功克隆仓库并安装 Python 或 C++ SDK 依赖后,您可以按照以下步骤直接运行 Revo 1/2 的演示示例。

⚠️ Linux 系统权限与延迟配置

在 Linux 宿主机上使用 CAN FD 或 RS-485 串口时,请确认设备权限与延迟配置:

  • CAN 接口使能权限:请确保 SocketCAN 接口已配置为 1M 或 2M 波特率:
    bash
    sudo ip link set can0 up type can bitrate 1000000 dbitrate 2000000 fd on
  • FTDI 串口延迟设置:若使用 RS485 串口,并且需要较短查询周期,请启用 low_latency
    bash
    sudo setserial /dev/ttyUSB0 low_latency

1. Python 示例运行

进入仓库的 python/demo/ 目录运行基础控制与多传感器时序采集:

bash
cd python/demo

# 运行串口与协议自动扫频发现工具
python auto_detect.py

# 运行 Revo 1/2 综合控制演示
python hand_demo.py
python hand_demo.py -m /dev/ttyUSB0 115200 1           # Modbus
python hand_demo.py -p /dev/ttyUSB0 10                 # Protobuf
python hand_demo.py -c /dev/cu.usbmodem14201 1000000 1 # ZQWL CAN 2.0

# 运行实时数据监控
python hand_monitor.py

# 运行固件升级工具
python hand_dfu.py /path/to/firmware.bin
Python 输出节选

以下为 SDK 2.x 运行日志的脱敏节选,端口、ID、序列号、固件版本和传感器数值会随设备而变化:

text
$ python auto_detect.py
2026-05-29T20:25:46.134386Z [INFO] bc_stark_sdk version: 2.0.2
2026-05-29T20:25:46.699072Z [INFO] 🔍 Auto-detect: scan_all=false, port=None, protocol=None
2026-05-29T20:25:46.800163Z [INFO] 🔍 Trying Modbus on /dev/tty.usbserial-21101...
2026-05-29T20:25:47.688335Z [INFO] 🔍 Trying Modbus on /dev/tty.usbserial-21101 at Baud115200...
2026-05-29T20:25:47.918838Z [INFO] DeviceInfo: "{\"sku_type\":\"MediumLeft\",\"hand_type\":\"Left\",\"hardware_type\":\"Revo1Basic\",\"serial_number\":\"<device serial>\",\"firmware_version\":\"<firmware version>\",\"hardware_version\":\"\"}"
2026-05-29T20:25:47.919086Z [INFO] ✅ Found Modbus device: port=/dev/tty.usbserial-21101, ID=0x01, baudrate=Baud115200, hw=Revo1Basic
2026-05-29T20:25:48.423103Z [INFO] ✅ Auto-detect: Found 1 device(s)
2026-05-29T20:25:48.438205Z [INFO] Initialized context for Revo1Basic device (slave 0x01)

Found 1 device(s)
----------------------------------------------------------------------

[Device 1] Revo1 Basic
  Protocol:     Modbus
  Port:         /dev/tty.usbserial-21101
  Slave ID:     0x01 (1)
  Baudrate:     115200
  Serial:       <device serial>
  Firmware:     <firmware version>
  SKU:          MediumLeft
text
$ python hand_demo.py
[Init] Revo1Basic
  Protocol: StarkProtocolType.Modbus
  Port: /dev/tty.usbserial-21101
  Slave ID: 0x01 (1)
  Serial: <device serial>
  Firmware: <firmware version>

=== Demo 1: Position Control ===
Opening all fingers...
Closing Thumb...
Closing ThumbAux...
Closing Index...
Closing Middle...
Closing Ring...
Closing Pinky...
Making fist...
Opening all fingers...
Final positions: [0, 0, 0, 0, 0, 0]

2. C++ 示例编译与运行

c/ 目录下编译并运行跨平台 C++ 示例:

bash
cd c
make

# 运行自动探测连接设备
./demo/auto_detect.exe

# 运行 Revo 1/2 综合控制演示
./demo/hand_demo.exe
./demo/hand_demo.exe -m /dev/ttyUSB0 115200 1                 # Modbus
./demo/hand_demo.exe -p /dev/ttyUSB0 10                       # Protobuf
./demo/hand_demo.exe -c /dev/cu.usbmodem14201 1000000 1       # ZQWL CAN 2.0
./demo/hand_demo.exe -b can0 1                                # SocketCAN CAN 2.0 (Linux, SDK 内置)
C++ 输出节选

以下为 c/demo 示例源码对应的输出结构,端口、ID、序列号、固件版本和传感器数值会随设备而变化:

text
$ ./demo/auto_detect.exe
=== Stark Auto-Detect Example ===

[INFO] Auto-detecting devices...

[INFO] Found devices:

[1] Revo1Basic
    Protocol: Modbus
    Port: /dev/ttyUSB0
    Slave ID: 0x01 (1)
    Serial Number: <device serial>
    Firmware: <firmware version>

[INFO] Using the only available device
Slave[1] Serial Number: <device serial>, FW: <firmware version>
Hardware Type: Revo1Basic (1)
Slave[1] Baudrate: 115200

=== Testing Finger Control ===
Closing pinky...
Opening pinky...
Final positions: 0, 0, 0, 0, 0, 0

=== Example completed ===
text
$ ./demo/hand_demo.exe 1
=== Universal Motor Control - Complete Demo ===

[INFO] Auto-detecting devices...

[INFO] Found devices:

[1] Revo1Basic
    Protocol: Modbus
    Port: /dev/ttyUSB0
    Slave ID: 0x01 (1)

[INFO] Using the only available device
Slave[1] Serial Number: <device serial>, FW: <firmware version>
Hardware Type: Revo1Basic (1)

[INFO] Motor API: Revo1
[INFO] Touch type: None

=== Demo 1: Basic Position Control ===
[Demo] Performing fist gesture...
[Demo] Performing open hand...
[Demo] Moving single finger (middle)...
[Demo] Reading motor status...
  Positions: 0, 0, 0, 0, 0, 0
  Speeds: 0, 0, 0, 0, 0, 0
  Currents: 0, 0, 0, 0, 0, 0
  States: 0, 0, 0, 0, 0, 0

[INFO] Done!

进阶参考

接口定义文件

API 查阅与代码自动补全可参考以下接口定义文件,支持直接下载或在下方展开查看:

  • Python 类型存根 (.pyi): 下载 main_mod.pyi — 包含 bc_stark_sdk.main_mod 中的类、枚举、函数类型注解。
  • C/C++ 头文件 (.h): 下载 stark-sdk.h — SDK 2.x 发布包中的 C ABI 导出头文件。
展开查看 Python 类型存根 (main_mod.pyi)
python
# This file is automatically generated by pyo3_stub_gen
# ruff: noqa: E501, F401, F403, F405

import builtins
import enum
import typing
import typing_extensions
__all__ = [
    "ActionCmd",
    "ActionSequence",
    "ActionSequenceId",
    "ActionSequenceItem",
    "ActionStatus",
    "ArrayPressureStatus",
    "ArrayPressureTouchData",
    "ArrayPressureTouchDataBuffer",
    "Baudrate",
    "BaudrateCAN",
    "ButtonPressEvent",
    "CanChannel",
    "CanCmd",
    "CanFrameMultiRead",
    "CanParamAddress",
    "ContactState",
    "DataCollector",
    "DetectedDevice",
    "DeviceContext",
    "DeviceInfo",
    "DfuCommandType",
    "DfuExitReason",
    "DfuState",
    "EcModulusSdoSubIdx",
    "EcTashanSdoSubIdx",
    "EtherCATAddress",
    "EtherCATConfigIndex",
    "EtherCATCtrlAddress",
    "EtherCATCtrlSubAddressMulti",
    "EtherCATCtrlSubAddressSingle",
    "EtherCATFoeType",
    "FingerCtrlMode",
    "FingerId",
    "FingerUnitMode",
    "Force3DFingerData",
    "Force3DPoint",
    "Force3DTouchData",
    "Force3DTouchDataBuffer",
    "ForceLevel",
    "HandType",
    "LedColor",
    "LedInfo",
    "LedMode",
    "LogLevel",
    "ModulusTouchDataType",
    "MotorSettings",
    "MotorState",
    "MotorStatusBuffer",
    "MotorStatusData",
    "MsgType",
    "PressState",
    "PressureDetailedBuffer",
    "PressureDetailedItem",
    "PressureSummaryBuffer",
    "RegAddrArrayPressure",
    "RegAddrForce3D",
    "RegAddrRevo1",
    "RegAddrRevo2",
    "SerialPortCfg",
    "SkuType",
    "StarkError",
    "StarkHardwareType",
    "StarkModuleId",
    "StarkProtocolType",
    "TouchDataType",
    "TouchFingerData",
    "TouchFingerItem",
    "TouchRawData",
    "TouchSensorData",
    "TouchSensorItem",
    "TouchSensorStatus",
    "TouchStatusBuffer",
    "TouchVendor",
    "TurboConfig",
    "ZqwlDeviceInfo",
    "auto_detect",
    "auto_detect_device",
    "auto_detect_modbus_revo1",
    "auto_detect_modbus_revo2",
    "available_usb_ports",
    "close_device_handler",
    "close_socketcan",
    "close_zqwl",
    "get_sdk_version",
    "init_device_handler",
    "init_from_detected",
    "init_logging",
    "init_socketcan_can",
    "init_socketcan_canfd",
    "init_zqwl_can",
    "init_zqwl_canfd",
    "is_socketcan_available",
    "list_available_ports",
    "list_zqwl_devices",
    "modbus_close",
    "modbus_open",
    "protobuf_open",
    "scan_can_devices",
    "scan_canfd_devices",
    "set_can_rx_callback",
    "set_can_tx_callback",
    "set_modbus_read_holding_callback",
    "set_modbus_read_input_callback",
    "set_modbus_write_callback",
]

@typing.final
class ActionSequence:
    r"""
    Represents a full action sequence containing multiple items.
    """
    def __new__(cls, action_id: ActionSequenceId, data: typing.Sequence[ActionSequenceItem]) -> ActionSequence:
        r"""
        Create a new ActionSequence.
        
        Returns:
            ActionSequence: A new ActionSequence instance containing the given data items.
        """
    @property
    def action_id(self) -> ActionSequenceId: ...
    @property
    def data(self) -> builtins.list[ActionSequenceItem]: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    def new(self, action_id: ActionSequenceId, data: typing.Sequence[ActionSequenceItem]) -> ActionSequence: ...
@typing.final
class ActionSequenceItem:
    r"""
    Represents an item in an action sequence.
    """
    def __new__(cls, index: builtins.int, duration: builtins.int, mode: builtins.int, positions: typing.Sequence[builtins.int], durations: typing.Sequence[builtins.int], speeds: typing.Sequence[builtins.int], currents: typing.Sequence[builtins.int]) -> ActionSequenceItem:
        r"""
        Create a new ActionSequenceItem.
        
        Returns:
            ActionSequenceItem: A new ActionSequenceItem instance.
        """
    @property
    def currents(self) -> builtins.list[builtins.int]: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def duration(self) -> builtins.int: ...
    @property
    def durations(self) -> builtins.list[builtins.int]: ...
    @property
    def index(self) -> builtins.int: ...
    @property
    def mode(self) -> builtins.int: ...
    def new(self, index: builtins.int, duration: builtins.int, mode: builtins.int, positions: typing.Sequence[builtins.int], durations: typing.Sequence[builtins.int], speeds: typing.Sequence[builtins.int], currents: typing.Sequence[builtins.int]) -> ActionSequenceItem: ...
    @property
    def positions(self) -> builtins.list[builtins.int]: ...
    @property
    def speeds(self) -> builtins.list[builtins.int]: ...
@typing.final
class ArrayPressureStatus:
    r"""
    ArrayPressure touch sensor status
    """
    ...

@typing.final
class ArrayPressureTouchData:
    r"""
    ArrayPressure touch data
    """
    ...

@typing.final
class ArrayPressureTouchDataBuffer:
    r"""
    ArrayPressure touch data shared buffer.
    """
    def __new__(cls, max_size: builtins.int) -> ArrayPressureTouchDataBuffer: ...
    def clear(self) -> None: ...

    def is_empty(self) -> builtins.bool: ...
    def len(self) -> builtins.int: ...
    def peek_latest(self) -> typing.Optional[ArrayPressureTouchData]: ...
    def pop_all(self) -> builtins.list[ArrayPressureTouchData]: ...
@typing.final
class ButtonPressEvent:
    def __new__(cls, timestamp: builtins.int, button_id: builtins.int, press_state: PressState) -> ButtonPressEvent: ...
    @property
    def button_id(self) -> builtins.int: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    def new(self, timestamp: builtins.int, button_id: builtins.int, press_state: PressState) -> ButtonPressEvent: ...
    @property
    def press_state(self) -> PressState: ...
    @property
    def timestamp(self) -> builtins.int: ...
@typing.final
class DataCollector:
    r"""
    Python data collector wrapper
    """
    def get_motor_frequency(self) -> builtins.int:
        r"""
        Get current motor frequency
        
        Returns:
            int: Current motor frequency in Hz
        """

    def get_touch_frequency(self) -> builtins.int:
        r"""
        Get current touch frequency
        
        Returns:
            int: Current touch frequency in Hz
        """
    def is_running(self) -> builtins.bool:
        r"""
        Check if data collection is running
        """
    @staticmethod
    def new_array_pressure(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, touch_buffer: ArrayPressureTouchDataBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, touch_frequency: builtins.int = 10, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - ArrayPressure touch version (华立创: 5 fingers × Fx/Fy/Fz/Mx/My)
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            touch_buffer: ArrayPressureTouchDataBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            touch_frequency: Touch collection frequency in Hz (default 10)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            collector = DataCollector.new_array_pressure(ctx, motor_buffer, touch_buffer)
        """
    @staticmethod
    def new_basic(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - Basic version (motor data only)
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            # Basic version (no touch sensor)
            collector = PyDataCollector.new_basic(ctx, motor_buffer)
        """
    @staticmethod
    def new_capacitive(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, touch_buffer: TouchStatusBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, touch_frequency: builtins.int = 100, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - Capacitive touch version
        
        Touch sensor type is automatically detected from device info
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            touch_buffer: TouchStatusBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            touch_frequency: Touch collection frequency in Hz (default 100)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            # Capacitive touch version
            collector = PyDataCollector.new_capacitive(ctx, motor_buffer, touch_buffer)
        """
    @staticmethod
    def new_force3d(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, touch_buffer: Force3DTouchDataBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, touch_frequency: builtins.int = 10, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - Force3D touch version (帕西尼: 4 fingers × FxFyFz)
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            touch_buffer: Force3DTouchDataBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            touch_frequency: Touch collection frequency in Hz (default 10)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            collector = DataCollector.new_force3d(ctx, motor_buffer, touch_buffer)
        """
    @staticmethod
    def new_pressure_detailed(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, pressure_detailed_buffer: PressureDetailedBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, touch_frequency: builtins.int = 10, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - Pressure touch version (Detailed mode)
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            pressure_detailed_buffer: PressureDetailedBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            touch_frequency: Touch collection frequency in Hz (default 10)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            # Pressure touch Detailed mode
            collector = PyDataCollector.new_pressure_detailed(ctx, motor_buffer, pressure_detailed_buffer, touch_frequency=10)
        """
    @staticmethod
    def new_pressure_hybrid(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, pressure_summary_buffer: PressureSummaryBuffer, pressure_detailed_buffer: PressureDetailedBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, summary_frequency: builtins.int = 100, detailed_frequency: builtins.int = 10, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - Pressure touch version (Hybrid mode: Summary + Detailed)
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            pressure_summary_buffer: PressureSummaryBuffer
            pressure_detailed_buffer: PressureDetailedBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            summary_frequency: Summary collection frequency in Hz (default 100)
            detailed_frequency: Detailed collection frequency in Hz (default 10)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            # Pressure touch Hybrid mode: Summary 100Hz + Detailed 10Hz
            collector = PyDataCollector.new_pressure_hybrid(
                ctx, motor_buffer, pressure_summary_buffer, pressure_detailed_buffer,
                summary_frequency=100, detailed_frequency=10
            )
        """
    @staticmethod
    def new_pressure_summary(ctx: DeviceContext, motor_buffer: MotorStatusBuffer, pressure_summary_buffer: PressureSummaryBuffer, slave_id: builtins.int = 1, motor_frequency: builtins.int = 1000, touch_frequency: builtins.int = 100, enable_stats: builtins.bool = True) -> DataCollector:
        r"""
        Create a new data collector - Pressure touch version (Summary mode)
        
        Args:
            ctx: DeviceContext (from PyDeviceContext)
            motor_buffer: MotorStatusBuffer
            pressure_summary_buffer: PressureSummaryBuffer
            slave_id: Slave ID (default 1)
            motor_frequency: Motor collection frequency in Hz (default 1000)
            touch_frequency: Touch collection frequency in Hz (default 100)
            enable_stats: Whether to print statistics (default True)
        
        Examples:
            # Pressure touch Summary mode
            collector = PyDataCollector.new_pressure_summary(ctx, motor_buffer, pressure_summary_buffer)
        """
    def start(self) -> None:
        r"""
        Start data collection
        
        Runs in a separate SDK thread, does not block Python
        """
    def stop(self) -> None:
        r"""
        Stop data collection (non-blocking)
        
        Sends stop signal to the collection thread but returns immediately.
        The thread will finish its current operation and exit gracefully.
        Use wait() if you need to ensure the thread has finished.
        """
    def update_motor_frequency(self, frequency: builtins.int) -> None:
        r"""
        Update motor frequency at runtime (thread-safe)
        
        Args:
            frequency: New motor frequency in Hz (0 to disable)
        """
    def update_touch_frequency(self, frequency: builtins.int) -> None:
        r"""
        Update touch frequency at runtime (thread-safe)
        
        Args:
            frequency: New touch frequency in Hz (0 to disable)
        """
    def wait(self) -> None:
        r"""
        Wait for data collection thread to finish
        
        Blocks until the collection thread exits (with 500ms timeout).
        Should be called after stop() if you need to ensure cleanup is complete.
        """
@typing.final
class DetectedDevice:
    r"""
    Detected device information
    
    Contains information about a detected Stark device including protocol,
    port, slave ID, and optional device details.
    """
    @property
    def baudrate(self) -> Baudrate:
        r"""
        Baudrate (for Modbus/serial protocols, or CAN arbitration baudrate)
        """
    @property
    def data_baudrate(self) -> builtins.int:
        r"""
        Data baudrate (for CANFD only, 0 for other protocols)
        """
    @property
    def firmware_version(self) -> typing.Optional[builtins.str]:
        r"""
        Firmware version (if detected)
        """

    @property
    def hardware_type(self) -> typing.Optional[StarkHardwareType]:
        r"""
        Hardware type (if detected)
        """
    @property
    def port_name(self) -> builtins.str:
        r"""
        Port name (serial port or CAN adapter port)
        """
    @property
    def protocol_type(self) -> StarkProtocolType:
        r"""
        Protocol type
        """
    @property
    def serial_number(self) -> typing.Optional[builtins.str]:
        r"""
        Serial number (if detected)
        """
    @property
    def sku_type(self) -> typing.Optional[SkuType]:
        r"""
        SKU type (if detected)
        """
    @property
    def slave_id(self) -> builtins.int:
        r"""
        Slave ID on the bus
        """
@typing.final
class DeviceContext:
    r"""
    Device context for Python API.
    
    This class wraps the internal device context and provides async methods
    for communicating with Stark devices. Create instances using:
    - `modbus_open()` for Modbus/RS485 connections
    - `init_device_handler()` for CAN/CANFD connections
    - `init_from_detected()` after auto-detection
    
    All methods are async and should be awaited.
    """
    def __new__(cls) -> DeviceContext: ...
    def calibrate_position(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Trigger manual position calibration.
        
        Args:
            slave_id: The slave ID of the device
        """
    def clear_action_sequence(self, slave_id: builtins.int, action_id: ActionSequenceId) -> typing.Any:
        r"""
        Clear a stored action sequence.
        
        Args:
            slave_id: The slave ID of the device
            action_id: ActionSequenceId (Action1-Action6)
        """
    def close(self) -> typing.Any:
        r"""
        Close the device connection and release resources.
        
        For Modbus: closes the serial port.
        For CAN/CANFD: use `close_device_handler()` instead which also closes ZQWL.
        """
    def ec_reserve_master(self) -> typing.Any: ...
    def ec_setup_sdo(self, slave_id: builtins.int) -> typing.Any: ...
    def ec_start_dfu(self, slave_pos: builtins.int, dfu_type: EtherCATFoeType, file_path: builtins.str) -> typing.Any: ...
    def ec_start_loop(self, slave_positions: typing.Sequence[builtins.int], dc_assign_activate: builtins.int, sync0_cycle_time: builtins.int, sync0_shift_time: builtins.int, sync1_cycle_time: builtins.int, sync1_shift_time: builtins.int) -> typing.Any: ...
    def ec_stop_loop(self) -> typing.Any: ...
    def factory_backlash_self_check(self, slave_id: builtins.int, finger_id: builtins.int) -> typing.Any:
        r"""
        [Factory] Trigger finger backlash self-check.
        Requires factory key to be set first.
        
        Args:
            slave_id: Device slave ID
            finger_id: 0=thumb_tip, 1=thumb_root, 2=index, 3=middle, 4=ring, 5=pinky
        """
    def factory_get_backlash(self, slave_id: builtins.int) -> typing.Any:
        r"""
        [Factory] Get finger backlash compensation values.
        
        Returns:
            list: 6 values in unit °×10 [thumb_tip, thumb_root, index, middle, ring, pinky]
        """
    def factory_get_finger_pwms(self, slave_id: builtins.int, level: ForceLevel) -> typing.Any:
        r"""
        [Factory] Get finger PWM values for a force level.
        
        Args:
            slave_id: Device slave ID
            level: ForceLevel enum value
        
        Returns:
            list: PWM array (length 6)
        """
    def factory_get_stall_currents(self, slave_id: builtins.int, level: ForceLevel) -> typing.Any:
        r"""
        [Factory] Get stall detection currents for a force level.
        
        Args:
            slave_id: Device slave ID
            level: ForceLevel enum value
        
        Returns:
            list: Current array (length 6)
        """
    def factory_get_stall_durations(self, slave_id: builtins.int) -> typing.Any:
        r"""
        [Factory] Get stall detection durations.
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            list: Duration array (length 6)
        """
    def factory_set_backlash(self, slave_id: builtins.int, values: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        [Factory] Set finger backlash compensation values.
        Requires factory key to be set first.
        
        Args:
            slave_id: Device slave ID
            values: list of 6 values in unit °×10
        """
    def factory_set_device_sn(self, slave_id: builtins.int, sn: builtins.str) -> typing.Any:
        r"""
        [Factory] Set device serial number.
        
        Args:
            slave_id: Device slave ID
            sn: Serial number string
        """
    def factory_set_finger_pwms(self, slave_id: builtins.int, level: ForceLevel, pwms: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        [Factory] Set finger PWM values for a force level.
        
        Args:
            slave_id: Device slave ID
            level: ForceLevel enum value
            pwms: PWM array (length 6)
        """
    def factory_set_key(self, slave_id: builtins.int, key: builtins.str) -> typing.Any:
        r"""
        [Factory] Set factory key for unlocking factory functions.
        
        Args:
            slave_id: Device slave ID
            key: Factory key string
        """
    def factory_set_sku_type(self, slave_id: builtins.int, sku_type: SkuType) -> typing.Any:
        r"""
        [Factory] Set device SKU type.
        
        Args:
            slave_id: Device slave ID
            sku_type: SkuType enum value
        """
    def factory_set_stall_currents(self, slave_id: builtins.int, level: ForceLevel, currents: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        [Factory] Set stall detection currents for a force level.
        
        Args:
            slave_id: Device slave ID
            level: ForceLevel enum value
            currents: Current array (length 6)
        """
    def factory_set_stall_durations(self, slave_id: builtins.int, durations: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        [Factory] Set stall detection durations.
        
        Args:
            slave_id: Device slave ID
            durations: Duration array (length 6)
        """
    def get_action_sequence(self, slave_id: builtins.int, action_id: ActionSequenceId) -> typing.Any:
        r"""
        Get action sequence by ID.
        
        Args:
            slave_id: The slave ID of the device
            action_id: ActionSequenceId (Action1-Action6)
        
        Returns:
            ActionSequence: The stored action sequence
        """
    def get_all_finger_settings(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get motor settings for all fingers (Revo2 only).
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            list: MotorSettings for all fingers
        """
    def get_array_pressure_touch_data(self, slave_id: builtins.int) -> typing.Any:
        r"""
        [ArrayPressure] Get touch data (status + 25 registers).
        
        Returns:
            dict: {status: {sensor_status, warmup_complete}, data: list[int]}
        """
    def get_auto_calibration_enabled(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Check if auto calibration is enabled.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            bool: True if auto calibration is enabled
        """
    def get_button_event(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get button press event.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            ButtonPressEvent: Button press event data
        """
    def get_buzzer_enabled(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Check if buzzer is enabled.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            bool: True if buzzer is enabled
        """
    def get_canfd_baudrate(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get CANFD data baudrate.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            BaudrateCAN: CANFD data baudrate (1M, 2M, 4M, or 5M)
        """
    def get_device_fw_version(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get device firmware version.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            str: Firmware version string
        """
    def get_device_info(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get device information (serial number, firmware version, hardware type)
        
        IMPORTANT: This method should be called after connecting to the device.
        It automatically sets the hardware type (hw_type) internally based on the
        device's serial number. This is required for touch-related APIs to work
        correctly, especially for CAN/CANFD protocols.
        
        NOTE: If the SN is not recognized, hardware_type defaults to Revo2Basic.
        Use `set_hardware_type()` to manually override if needed.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            DeviceInfo object containing serial_number, firmware_version, hardware_type
        """
    def get_device_sn(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get device serial number.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            str: Device serial number
        """
    def get_finger_currents(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get finger currents
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            Current array (length 6), unified range **-1000~+1000** (all devices, all protocols)
        
        Note:
            SDK automatically converts internal values to unified external range.
        """
    def get_finger_max_current(self, slave_id: builtins.int, finger_id: FingerId) -> typing.Any:
        r"""
        Get maximum current limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
        
        Returns:
            int: Maximum current value
        """
    def get_finger_max_position(self, slave_id: builtins.int, finger_id: FingerId) -> typing.Any:
        r"""
        Get maximum position limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
        
        Returns:
            int: Maximum position value
        """
    def get_finger_max_speed(self, slave_id: builtins.int, finger_id: FingerId) -> typing.Any:
        r"""
        Get maximum speed limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
        
        Returns:
            int: Maximum speed value
        """
    def get_finger_min_position(self, slave_id: builtins.int, finger_id: FingerId) -> typing.Any:
        r"""
        Get minimum position limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
        
        Returns:
            int: Minimum position value
        """
    def get_finger_positions(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get finger positions
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            Position array (length 6), unified range **0~1000** (all devices, all protocols)
        
        Note:
            SDK automatically converts internal values to unified external range.
        """
    def get_finger_protected_current(self, slave_id: builtins.int, finger_id: FingerId) -> typing.Any:
        r"""
        Get protected current for a single finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
        
        Returns:
            int: Protected current value
        """
    def get_finger_protected_currents(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get protected currents for all fingers (Revo2 only).
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            list: Protected current array (length 6)
        """
    def get_finger_settings(self, slave_id: builtins.int, finger_id: FingerId) -> typing.Any:
        r"""
        Get motor settings for a single finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
        
        Returns:
            MotorSettings: Settings for the specified finger
        """
    def get_finger_speeds(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get finger speeds
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            Speed array (length 6), unified range **-1000~+1000** (all devices, all protocols)
        
        Note:
            SDK automatically converts internal values to unified external range.
        """
    def get_finger_unit_mode(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get finger unit mode (Revo2 only).
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            FingerUnitMode: Current finger unit mode
        """
    def get_force3d_finger_array(self, slave_id: builtins.int, finger: builtins.int) -> typing.Any:
        r"""
        [Force3D] Get finger array data (31 measurement points).
        
        Args:
            slave_id: Device slave ID
            finger: Finger index (0=index, 1=middle, 2=ring, 3=pinky)
        
        Returns:
            list[dict]: List of {fx, fy, fz} dicts (31 points)
        """
    def get_force3d_touch_summary(self, slave_id: builtins.int) -> typing.Any:
        r"""
        [Force3D] Get touch summary data (4 fingers, no thumb).
        
        Returns:
            dict: {index, middle, ring, pinky} each with {fx, fy, fz}
        """
    def get_force_level(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get force level (Revo1 Basic only).
        
        @deprecated Use get_motor_status() for current values instead.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            ForceLevel: Current force level
        """
    def get_hand_type(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get device hand type (simplified left/right).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            HandType enum (Left = 0, Right = 1)
        """
    def get_led_enabled(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Check if LED is enabled.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            bool: True if LED is enabled
        """
    def get_led_info(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get LED information (color, mode, brightness).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            LedInfo: LED configuration
        """
    def get_max_current(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get maximum current limit (Protobuf only).
        
        Note: This API is only available for Protobuf protocol.
        For Modbus/CAN protocols, use get_finger_max_current instead.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            int: Maximum current in mA (0-2000000)
        """
    def get_modulus_touch_data(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get modulus touch detailed data for all fingers (pressure sensors).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            list: Detailed pressure data for all fingers
        """
    def get_modulus_touch_data_type(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get modulus touch data type (pressure sensors).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            ModulusTouchDataType: Current data type setting
        """
    def get_modulus_touch_summary(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get modulus touch summary data for all fingers (pressure sensors).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            list: Summary data for all fingers
        """
    def get_motor_state(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get motor state (running, idle, stalled, etc.).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            list: Motor state array for each finger
        """
    def get_motor_status(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get motor status
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            MotorStatusData containing:
            - positions: Position array, unified range **0~1000** (all devices, all protocols)
            - speeds: Speed array, unified range **-1000~+1000** (all devices, all protocols)
            - currents: Current array, unified range **-1000~+1000** (all devices, all protocols)
            - states: Motor state array
        
        Note:
            SDK automatically converts internal values to unified external range.
        """
    def get_serialport_baudrate(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get RS485 serial baudrate.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            Baudrate: Serial baudrate
        """
    def get_serialport_cfg(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get serial port configuration.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            SerialPortCfg: Serial port configuration
        """
    def get_single_modulus_touch_data(self, slave_id: builtins.int, index: builtins.int) -> typing.Any:
        r"""
        Get modulus touch detailed data for a single finger (pressure sensors).
        
        Args:
            slave_id: The slave ID of the device
            index: Finger index (0-4)
        
        Returns:
            Detailed pressure data for the specified finger
        """
    def get_single_modulus_touch_summary(self, slave_id: builtins.int, index: builtins.int) -> typing.Any:
        r"""
        Get modulus touch summary data for a single finger (pressure sensors).
        
        Args:
            slave_id: The slave ID of the device
            index: Finger index (0-4)
        
        Returns:
            Summary data for the specified finger
        """
    def get_single_touch_sensor_status(self, slave_id: builtins.int, index: builtins.int) -> typing.Any:
        r"""
        Get touch sensor status for a single finger (capacitive sensors).
        
        Args:
            slave_id: The slave ID of the device
            index: Finger index (0-4)
        
        Returns:
            TouchFingerData: Touch status for the specified finger
        """
    def get_sku_type(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get device SKU type (hand side: left/right).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            SkuType: Device SKU type
        """
    def get_thumb_aux_lock_current(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get thumb auxiliary motor lock current (Revo2 only).
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            int: Lock current value
        """
    def get_touch_sensor_enabled(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get which touch sensors are enabled.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            int: Bitmask of enabled sensors (bit 0-4 for each finger)
        """
    def get_touch_sensor_fw_versions(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get touch sensor firmware versions.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            list: Firmware versions for each touch sensor
        """
    def get_touch_sensor_raw_data(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get touch sensor raw data (capacitive sensors).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            TouchRawData: Raw capacitive sensor data
        """
    def get_touch_sensor_status(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get touch sensor status for all fingers (capacitive sensors).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            list: TouchFingerData for all fingers
        """
    def get_turbo_config(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get turbo mode configuration (Revo1 Basic only).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            TurboConfig: Turbo mode configuration
        """
    def get_turbo_mode_enabled(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Check if turbo mode is enabled (Revo1 Basic only).
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            bool: True if turbo mode is enabled
        """
    def get_vibration_enabled(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Check if vibration motor is enabled.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            bool: True if vibration motor is enabled
        """
    def get_voltage(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Get device supply voltage in millivolts.
        
        Args:
            slave_id: The slave ID of the device
        
        Returns:
            int: Voltage in mV
        """
    def is_revo1_advanced_touch(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device is Revo1 Advanced Touch.
        """

    def is_touch_hand(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device has touch sensors.
        
        Args:
            slave_id: Device slave ID
        
        Returns:
            bool: True if device has touch sensors
        """
    def reboot(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Reboot the device.
        
        Args:
            slave_id: The slave ID of the device
        """
    def reset_default_gesture(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Reset action sequences to factory defaults.
        
        Args:
            slave_id: Device slave ID
        """
    def reset_default_settings(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Reset all settings to factory defaults.
        
        Args:
            slave_id: Device slave ID
        """
    def reset_dfu_state(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Reset DFU state to Idle (for recovery from stuck states).
        
        Use this if DFU gets stuck and you see "dfu is not available" error.
        
        Args:
            slave_id: Device slave ID
        """
    def reset_finger_positions(self, slave_id: builtins.int) -> typing.Any:
        r"""
        Reset finger positions to packing position (Protobuf only).
        
        Packing position is [60, 50, 2, 2, 2, 2] (thumb bent, other fingers open).
        
        Note: This API is only available for Protobuf protocol.
        
        Args:
            slave_id: The slave ID of the device
        """
    def run_action_sequence(self, slave_id: builtins.int, action_id: ActionSequenceId) -> typing.Any:
        r"""
        Run a stored action sequence.
        
        Args:
            slave_id: The slave ID of the device
            action_id: ActionSequenceId (Action1-Action6)
        """
    def save_action_sequence(self, slave_id: builtins.int, action_id: ActionSequenceId) -> typing.Any:
        r"""
        Save action sequence to device flash (Revo2 only).
        
        Note: Not supported on Revo1 devices.
        
        Args:
            slave_id: The slave ID of the device
            action_id: ActionSequenceId (Action1-Action6)
        """
    def set_array_pressure_sleep(self, slave_id: builtins.int, enable: builtins.bool) -> typing.Any:
        r"""
        [ArrayPressure] Set device sleep mode.
        
        Args:
            slave_id: Device slave ID
            enable: True to sleep, False to wake
        """
    def set_auto_calibration(self, slave_id: builtins.int, enabled: builtins.bool) -> typing.Any:
        r"""
        Enable or disable auto calibration.
        
        Args:
            slave_id: The slave ID of the device
            enabled: True to enable, False to disable
        """
    def set_buzzer_enabled(self, slave_id: builtins.int, enabled: builtins.bool) -> typing.Any:
        r"""
        Enable or disable buzzer.
        
        Args:
            slave_id: The slave ID of the device
            enabled: True to enable, False to disable
        """
    def set_canfd_baudrate(self, slave_id: builtins.int, baudrate: BaudrateCAN) -> typing.Any:
        r"""
        Set CANFD data baudrate.
        
        Args:
            slave_id: The slave ID of the device
            baudrate: BaudrateCAN enum value (1M, 2M, 4M, or 5M)
        """
    def set_finger_current(self, slave_id: builtins.int, finger_id: FingerId, current: builtins.int) -> typing.Any:
        r"""
        Set finger current
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            current: Current value, unified range **-1000~+1000** (all devices, all protocols)
                     Positive = close, Negative = open
        
        Note:
            SDK automatically converts to internal range based on device type and protocol.
        """
    def set_finger_currents(self, slave_id: builtins.int, currents: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set multiple finger currents
        
        Args:
            slave_id: Device slave ID
            currents: Current array (length 6), unified range **-1000~+1000** (all devices, all protocols)
        
        Note:
            SDK automatically converts to internal range based on device type and protocol.
        """
    def set_finger_max_current(self, slave_id: builtins.int, finger_id: FingerId, current: builtins.int) -> typing.Any:
        r"""
        Set maximum current limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            current: Maximum current value
        """
    def set_finger_max_position(self, slave_id: builtins.int, finger_id: FingerId, position: builtins.int) -> typing.Any:
        r"""
        Set maximum position limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            position: Maximum position value
        """
    def set_finger_max_speed(self, slave_id: builtins.int, finger_id: FingerId, speed: builtins.int) -> typing.Any:
        r"""
        Set maximum speed limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            speed: Maximum speed value
        """
    def set_finger_min_position(self, slave_id: builtins.int, finger_id: FingerId, position: builtins.int) -> typing.Any:
        r"""
        Set minimum position limit for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            position: Minimum position value
        """
    def set_finger_position(self, slave_id: builtins.int, finger_id: FingerId, position: builtins.int) -> typing.Any:
        r"""
        Set finger position
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            position: Position value, unified range **0~1000** (all devices, all protocols)
                      0 = fully open, 1000 = fully closed
        
        Note:
            SDK automatically converts to internal range based on device type and protocol.
        """
    def set_finger_position_with_millis(self, slave_id: builtins.int, finger_id: FingerId, position: builtins.int, milliseconds: builtins.int) -> typing.Any:
        r"""
        Set finger position with duration
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            position: Position value, unified range **0~1000** (all protocols)
            milliseconds: Duration in milliseconds (1~2000ms)
        
        Note:
            Only supported on Revo2 devices.
        """
    def set_finger_position_with_speed(self, slave_id: builtins.int, finger_id: FingerId, position: builtins.int, speed: builtins.int) -> typing.Any:
        r"""
        Set finger position with speed
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            position: Position value, unified range **0~1000** (all protocols)
            speed: Speed value (1~1000)
        
        Note:
            Only supported on Revo2 devices.
        """
    def set_finger_positions(self, slave_id: builtins.int, positions: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set multiple finger positions
        
        Args:
            slave_id: Device slave ID
            positions: Position array (length 6), unified range **0~1000** (all devices, all protocols)
        
        Note:
            SDK automatically converts to internal range based on device type and protocol.
        """
    def set_finger_positions_and_durations(self, slave_id: builtins.int, positions: typing.Sequence[builtins.int], durations: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set multiple finger positions with durations (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            positions: Position array (length 6), unified range 0~1000
            durations: Duration array (length 6), in milliseconds (1~2000ms)
        """
    def set_finger_positions_and_speeds(self, slave_id: builtins.int, positions: typing.Sequence[builtins.int], speeds: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set multiple finger positions with speeds (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            positions: Position array (length 6), unified range 0~1000
            speeds: Speed array (length 6), range 1~1000
        """
    def set_finger_protected_current(self, slave_id: builtins.int, finger_id: FingerId, current: builtins.int) -> typing.Any:
        r"""
        Set protected current for a single finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            current: Protected current value
        """
    def set_finger_protected_currents(self, slave_id: builtins.int, protected_currents: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set protected currents for all fingers (Revo2 only).
        
        Protected current is the threshold for stall detection.
        
        Args:
            slave_id: Device slave ID
            protected_currents: Current array (length 6)
        """
    def set_finger_pwm(self, slave_id: builtins.int, finger_id: FingerId, pwm: builtins.int) -> typing.Any:
        r"""
        Set finger PWM
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            pwm: PWM value, unified range **-1000~+1000** (all protocols)
                 Positive = close, Negative = open
        
        Note:
            Only supported on Revo2 devices.
        """
    def set_finger_pwms(self, slave_id: builtins.int, pwms: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set multiple finger PWM values (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            pwms: PWM array (length 6), unified range -1000~+1000
        """
    def set_finger_settings(self, slave_id: builtins.int, finger_id: FingerId, settings: MotorSettings) -> typing.Any:
        r"""
        Set motor settings for a finger (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            settings: MotorSettings object
        """
    def set_finger_speed(self, slave_id: builtins.int, finger_id: FingerId, speed: builtins.int) -> typing.Any:
        r"""
        Set finger speed
        
        Args:
            slave_id: Device slave ID
            finger_id: Finger ID
            speed: Speed value, unified range **-1000~+1000** (all devices, all protocols)
                   Positive = close, Negative = open, 0 = stop
        
        Note:
            SDK automatically converts to internal range based on device type and protocol.
        """
    def set_finger_speeds(self, slave_id: builtins.int, speeds: typing.Sequence[builtins.int]) -> typing.Any:
        r"""
        Set multiple finger speeds
        
        Args:
            slave_id: Device slave ID
            speeds: Speed array (length 6), unified range **-1000~+1000** (all devices, all protocols)
        
        Note:
            SDK automatically converts to internal range based on device type and protocol.
        """
    def set_finger_unit_mode(self, slave_id: builtins.int, mode: FingerUnitMode) -> typing.Any:
        r"""
        Set finger unit mode (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            mode: FingerUnitMode (FiveFingers or SixFingers)
        """
    def set_force_level(self, slave_id: builtins.int, force_level: ForceLevel) -> typing.Any:
        r"""
        Set force level (Revo1 Basic only).
        
        @deprecated Use set_finger_protected_currents() for Revo2 devices.
        
        Args:
            slave_id: The slave ID of the device
            force_level: ForceLevel enum value
        """
    def set_hardware_type(self, slave_id: builtins.int, hw_type: StarkHardwareType) -> typing.Any:
        r"""
        Set hardware type for a specific slave.
        
        Use this to manually override the hardware type when SN-based auto-detection
        in `get_device_info()` fails or returns an incorrect result
        (e.g. device SN not yet programmed, defaults to Revo2Basic).
        
        Call this after `get_device_info()` if the detected `hardware_type` is wrong.
        This is also needed for CAN protocol where hardware type may not be auto-detected.
        
        Args:
            slave_id: The slave ID
            hw_type: StarkHardwareType enum value
        
        Example:
            # Override hardware type after get_device_info
            info = await ctx.get_device_info(slave_id)
            if info.hardware_type != expected_type:
                await ctx.set_hardware_type(slave_id, StarkHardwareType.Revo2TouchPressure)
        """
    def set_led_enabled(self, slave_id: builtins.int, enabled: builtins.bool) -> typing.Any:
        r"""
        Enable or disable LED.
        
        Args:
            slave_id: The slave ID of the device
            enabled: True to enable, False to disable
        """
    def set_led_info(self, slave_id: builtins.int, led_info: LedInfo) -> typing.Any:
        r"""
        Set LED information (color, mode, brightness).
        
        Args:
            slave_id: The slave ID of the device
            led_info: LedInfo object
        """
    def set_max_current(self, slave_id: builtins.int, max_current: builtins.int) -> typing.Any:
        r"""
        Set maximum current limit (Protobuf only).
        
        Note: This API is only available for Protobuf protocol.
        For Modbus/CAN protocols, use set_finger_max_current instead.
        
        Args:
            slave_id: The slave ID of the device
            max_current: Maximum current in mA (0-2000000)
        """
    def set_modulus_touch_data_type(self, slave_id: builtins.int, data_type: ModulusTouchDataType) -> typing.Any:
        r"""
        Set modulus touch data type (pressure sensors).
        
        Args:
            slave_id: The slave ID of the device
            data_type: ModulusTouchDataType (Summary or Detailed)
        """
    def set_rs485_baudrate(self, slave_id: builtins.int, baudrate: Baudrate) -> typing.Any:
        r"""
        Alias for set_serialport_baudrate.
        """
    def set_serialport_baudrate(self, slave_id: builtins.int, baudrate: Baudrate) -> typing.Any:
        r"""
        Set RS485 serial baudrate.
        
        Args:
            slave_id: The slave ID of the device
            baudrate: Baudrate enum value
        """
    def set_slave_id(self, slave_id: builtins.int, new_id: builtins.int) -> typing.Any:
        r"""
        Set device slave ID.
        
        Args:
            slave_id: Current slave ID
            new_id: New slave ID to set
        """
    def set_thumb_aux_lock_current(self, slave_id: builtins.int, lock_current: builtins.int) -> typing.Any:
        r"""
        Set thumb auxiliary motor lock current (Revo2 only).
        
        Args:
            slave_id: Device slave ID
            lock_current: Lock current value
        """
    def set_turbo_config(self, slave_id: builtins.int, turbo_config: TurboConfig) -> typing.Any:
        r"""
        Set turbo mode configuration (Revo1 Basic only).
        
        Args:
            slave_id: The slave ID of the device
            turbo_config: TurboConfig object
        """
    def set_turbo_mode_enabled(self, slave_id: builtins.int, enabled: builtins.bool) -> typing.Any:
        r"""
        Enable or disable turbo mode (Revo1 Basic only).
        
        Args:
            slave_id: The slave ID of the device
            enabled: True to enable, False to disable
        """
    def set_vibration_enabled(self, slave_id: builtins.int, enabled: builtins.bool) -> typing.Any:
        r"""
        Enable or disable vibration motor.
        
        Args:
            slave_id: The slave ID of the device
            enabled: True to enable, False to disable
        """
    def start_dfu(self, slave_id: builtins.int, dfu_file_path: builtins.str, wait_secs: builtins.int, dfu_state_cb: typing.Any, dfu_progress_cb: typing.Any) -> typing.Any:
        r"""
        Start DFU (Device Firmware Update) process.
        
        Args:
            slave_id: Device slave ID
            dfu_file_path: Path to the firmware file
            wait_secs: Timeout in seconds to wait for DFU completion
            dfu_state_cb: Callback function for DFU state changes (slave_id, state)
            dfu_progress_cb: Callback function for DFU progress (slave_id, progress)
        
        Returns:
            bool: True if DFU completed successfully
        """
    def touch_sensor_calibrate(self, slave_id: builtins.int, bits: builtins.int) -> typing.Any:
        r"""
        Calibrate touch sensors.
        
        Args:
            slave_id: Device slave ID
            bits: Bitmask of sensors to calibrate (bit 0-4 for each finger)
        """
    def touch_sensor_reset(self, slave_id: builtins.int, bits: builtins.int) -> typing.Any:
        r"""
        Reset touch sensors.
        
        Args:
            slave_id: Device slave ID
            bits: Bitmask of sensors to reset (bit 0-4 for each finger)
        """
    def touch_sensor_setup(self, slave_id: builtins.int, bits: builtins.int) -> typing.Any:
        r"""
        Setup touch sensors (enable/disable specific fingers).
        
        Args:
            slave_id: Device slave ID
            bits: Bitmask of sensors to enable (bit 0-4 for each finger)
        """
    def transfer_action_sequence(self, slave_id: builtins.int, action_id: ActionSequenceId, sequences: typing.Sequence[typing.Sequence[builtins.int]]) -> typing.Any:
        r"""
        Transfer action sequence data to device.
        
        Args:
            slave_id: The slave ID of the device
            action_id: ActionSequenceId (Action1-Action6)
            sequences: List of position arrays, each array has 6 values (0-1000)
        """
    def uses_array_pressure_touch_api(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device uses ArrayPressure Touch API.
        """
    def uses_force3d_touch_api(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device uses Force3D Touch API.
        """
    def uses_pressure_touch_api(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device uses Pressure/Modulus Touch API.
        """
    def uses_revo1_motor_api(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device uses Revo1 Motor API.
        
        Revo1 Basic/Touch use Revo1 Motor API.
        Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
        
        Returns:
            True if uses Revo1 Motor API, False if uses Revo2 Motor API.
        """
    def uses_revo1_touch_api(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device uses Revo1 Touch API.
        
        Revo1Touch and Revo1AdvancedTouch use Revo1 Touch API.
        """
    def uses_revo2_motor_api(self, slave_id: builtins.int) -> builtins.bool:
        r"""
        Check if device uses Revo2 Motor API.
        
        Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
        Revo1 Basic/Touch use Revo1 Motor API.
        
        Returns:
            True if uses Revo2 Motor API, False if uses Revo1 Motor API.
        """
@typing.final
class DeviceInfo:
    def __new__(cls, sku_type: SkuType, hand_type: HandType, hardware_type: StarkHardwareType, serial_number: builtins.str, firmware_version: builtins.str, hardware_version: builtins.str) -> DeviceInfo: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def firmware_version(self) -> builtins.str:
        r"""
        Firmware version
        """
    def get_hardware_type(self) -> StarkHardwareType: ...
    @property
    def hand_type(self) -> HandType:
        r"""
        Hand type (Left/Right)
        """
    @property
    def hardware_type(self) -> StarkHardwareType:
        r"""
        Hardware type
        """
    @property
    def hardware_version(self) -> builtins.str:
        r"""
        Hardware version (reserved; empty for current legacy devices)
        """
    def is_touch(self) -> builtins.bool:
        r"""
        Check if device has any touch sensor.
        """
    def new(self, sku_type: SkuType, hand_type: HandType, hardware_type: StarkHardwareType, serial_number: builtins.str, firmware_version: builtins.str, hardware_version: builtins.str) -> DeviceInfo: ...
    @property
    def serial_number(self) -> builtins.str:
        r"""
        Serial number
        """
    @typing_extensions.deprecated("Use hand_type instead")
    @property
    def sku_type(self) -> SkuType:
        r"""
        Hand SKU (Deprecated, use hand_type instead)
        """
    def uses_revo1_motor_api(self) -> builtins.bool:
        r"""
        Check if device uses Revo1 Motor API.
        
        Revo1 Basic/Touch use Revo1 Motor API.
        Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
        """
    def uses_revo1_touch_api(self) -> builtins.bool:
        r"""
        Check if device uses Revo1 Touch API.
        
        Revo1 Touch API has different sensor counts per finger (4 sensors per finger).
        Includes Revo1Touch and Revo1AdvancedTouch.
        """
    def uses_revo2_motor_api(self) -> builtins.bool:
        r"""
        Check if device uses Revo2 Motor API.
        
        Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
        Revo1 Basic/Touch use Revo1 Motor API.
        """
    def uses_revo2_touch_api(self) -> builtins.bool:
        r"""
        Check if device uses Revo2 Touch API.
        
        Includes all Revo2 touch variants (Capacitive, Pressure, Force3D, ArrayPressure).
        """
@typing.final
class Force3DFingerData:
    r"""
    3D force data for a single finger
    """
    ...

@typing.final
class Force3DPoint:
    r"""
    3D force data for a single measurement point
    """
    ...

@typing.final
class Force3DTouchData:
    r"""
    Complete Force3D touch data (4 fingers, no thumb)
    """
    ...

@typing.final
class Force3DTouchDataBuffer:
    r"""
    Force3D touch data shared buffer.
    """
    def __new__(cls, max_size: builtins.int) -> Force3DTouchDataBuffer: ...
    def clear(self) -> None: ...

    def is_empty(self) -> builtins.bool: ...
    def len(self) -> builtins.int: ...
    def peek_latest(self) -> typing.Optional[Force3DTouchData]: ...
    def pop_all(self) -> builtins.list[Force3DTouchData]: ...
@typing.final
class LedInfo:
    def __new__(cls, color: LedColor, mode: LedMode) -> LedInfo: ...
    @property
    def color(self) -> LedColor: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def mode(self) -> LedMode: ...
    def new(self, color: LedColor, mode: LedMode) -> LedInfo: ...
@typing.final
class MotorSettings:
    def __new__(cls, min_position: builtins.int, max_position: builtins.int, max_speed: builtins.int, max_current: builtins.int) -> MotorSettings: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def max_current(self) -> builtins.int: ...
    @property
    def max_position(self) -> builtins.int: ...
    @property
    def max_speed(self) -> builtins.int: ...
    @property
    def min_position(self) -> builtins.int: ...
    def new(self, min_position: builtins.int, max_position: builtins.int, max_speed: builtins.int, max_current: builtins.int) -> MotorSettings: ...
@typing.final
class MotorStatusBuffer:
    r"""
    Motor status shared buffer
    
    Uses shared memory + polling mode to avoid GIL overhead from callbacks
    SDK side writes quickly, Python/C side reads on demand
    """
    def __new__(cls, max_size: builtins.int) -> MotorStatusBuffer: ...
    def clear(self) -> None:
        r"""
        Clear the buffer
        """

    def is_empty(self) -> builtins.bool:
        r"""
        Check if the buffer is empty
        """
    def len(self) -> builtins.int:
        r"""
        Check the number of items in the buffer
        """
    def peek_all(self) -> builtins.list[MotorStatusData]:
        r"""
        Peek at all data without removing it
        """
    def peek_latest(self) -> typing.Optional[MotorStatusData]:
        r"""
        Peek at the latest data without removing it
        """
    def pop_all(self) -> builtins.list[MotorStatusData]:
        r"""
        Get all pending motor status data
        """
    def pop_latest(self, count: builtins.int) -> builtins.list[MotorStatusData]:
        r"""
        Get the latest N motor status data items
        """
@typing.final
class MotorStatusData:
    def __new__(cls, positions: typing.Sequence[builtins.int], speeds: typing.Sequence[builtins.int], currents: typing.Sequence[builtins.int], states: typing.Sequence[builtins.int]) -> MotorStatusData: ...
    @property
    def currents(self) -> builtins.list[builtins.int]: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    def is_closed(self, uses_revo1_motor_api: builtins.bool) -> builtins.bool:
        r"""
        Check if hand is closed.
        
        Args:
            uses_revo1_motor_api: Whether device uses Revo1 Motor API
        """
    def is_idle(self) -> builtins.bool: ...
    def is_opened(self) -> builtins.bool: ...
    def new(self, positions: typing.Sequence[builtins.int], speeds: typing.Sequence[builtins.int], currents: typing.Sequence[builtins.int], states: typing.Sequence[builtins.int]) -> MotorStatusData: ...
    @property
    def positions(self) -> builtins.list[builtins.int]: ...
    @property
    def speeds(self) -> builtins.list[builtins.int]: ...
    @property
    def states(self) -> builtins.list[MotorState]: ...
@typing.final
class PressureDetailedBuffer:
    r"""
    Pressure detailed data buffer (Detailed mode)
    
    For Modulus pressure touch sensor detailed sensor point data
    One buffer per part, storing PressureDetailedItem
    """
    def __new__(cls, max_size: builtins.int) -> PressureDetailedBuffer: ...
    def clear(self) -> None: ...

    def is_empty(self) -> builtins.bool: ...
    def len_all(self) -> builtins.list[builtins.int]: ...
    def pop_all(self) -> builtins.list[builtins.list[PressureDetailedItem]]: ...
    def pop_finger(self, finger_index: builtins.int) -> builtins.list[PressureDetailedItem]: ...
    def pop_latest_all(self) -> builtins.list[typing.Optional[PressureDetailedItem]]: ...
@typing.final
class PressureDetailedItem:
    r"""
    Pressure sensor detailed data (Detailed mode)
    
    For Modulus pressure touch sensor detailed sensor point data
    - Fingers: 9 sensor points
    - Palm: 46 sensor points
    """
    @staticmethod
    def new_finger(sensors: typing.Sequence[builtins.int]) -> PressureDetailedItem:
        r"""
        Create finger data (9 sensor points)
        """
    @staticmethod
    def new_palm(sensors: typing.Sequence[builtins.int]) -> PressureDetailedItem:
        r"""
        Create palm data (46 sensor points)
        """

    @property
    def sensors(self) -> builtins.list[builtins.int]:
        r"""
        Get valid sensor point data (returns only valid sensors based on sensor_count)
        """
@typing.final
class PressureSummaryBuffer:
    r"""
    Pressure summary buffer (Summary mode)
    
    For Modulus pressure touch sensor summary data
    One buffer per part, storing u16 pressure values
    """
    def __new__(cls, max_size: builtins.int) -> PressureSummaryBuffer: ...
    def clear(self) -> None: ...

    def is_empty(self) -> builtins.bool: ...
    def len_all(self) -> builtins.list[builtins.int]: ...
    def pop_all(self) -> builtins.list[builtins.list[builtins.int]]: ...
    def pop_finger(self, finger_index: builtins.int) -> builtins.list[builtins.int]: ...
    def pop_latest_all(self) -> builtins.list[typing.Optional[builtins.int]]: ...
@typing.final
class SerialPortCfg:
    def __new__(cls, slave_id: builtins.int, baudrate: Baudrate) -> SerialPortCfg: ...
    @property
    def baudrate(self) -> Baudrate:
        r"""
        Baud rate for the serial communication
        """
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    def new(self, slave_id: builtins.int, baudrate: Baudrate) -> SerialPortCfg: ...
    @property
    def slave_id(self) -> builtins.int:
        r"""
        Slave ID for the protocol
        - For Protobuf protocol: range 10~254, default is 10, 254 is the broadcast address
        - For Modbus protocol: range 0~254, default is 1, 0 is the broadcast address (broadcast is only for control commands)
        """
@typing.final
class TouchFingerData:
    @property
    def items(self) -> builtins.list[TouchFingerItem]: ...

@typing.final
class TouchFingerItem:
    def __new__(cls, normal_force1: builtins.int, normal_force2: builtins.int, normal_force3: builtins.int, tangential_force1: builtins.int, tangential_force2: builtins.int, tangential_force3: builtins.int, tangential_direction1: builtins.int, tangential_direction2: builtins.int, tangential_direction3: builtins.int, self_proximity1: builtins.int, self_proximity2: builtins.int, mutual_proximity: builtins.int, status: builtins.int) -> TouchFingerItem: ...
    def desc(self) -> builtins.str:
        r"""
        Display description - shows all fields (Revo1 style with full sensor data)
        """

    @property
    def description(self) -> builtins.str: ...
    def is_abnormal(self) -> builtins.bool: ...
    def is_normal(self) -> builtins.bool: ...
    @property
    def mutual_proximity(self) -> builtins.int: ...
    def new(self, normal_force1: builtins.int, normal_force2: builtins.int, normal_force3: builtins.int, tangential_force1: builtins.int, tangential_force2: builtins.int, tangential_force3: builtins.int, tangential_direction1: builtins.int, tangential_direction2: builtins.int, tangential_direction3: builtins.int, self_proximity1: builtins.int, self_proximity2: builtins.int, mutual_proximity: builtins.int, status: builtins.int) -> TouchFingerItem: ...
    @property
    def normal_force1(self) -> builtins.int: ...
    @property
    def normal_force2(self) -> builtins.int: ...
    @property
    def normal_force3(self) -> builtins.int: ...
    @property
    def self_proximity1(self) -> builtins.int: ...
    @property
    def self_proximity2(self) -> builtins.int: ...
    @property
    def status(self) -> builtins.int: ...
    @property
    def tangential_direction1(self) -> builtins.int: ...
    @property
    def tangential_direction2(self) -> builtins.int: ...
    @property
    def tangential_direction3(self) -> builtins.int: ...
    @property
    def tangential_force1(self) -> builtins.int: ...
    @property
    def tangential_force2(self) -> builtins.int: ...
    @property
    def tangential_force3(self) -> builtins.int: ...
@typing.final
class TouchRawData:
    def __new__(cls, thumb: typing.Sequence[builtins.int], index: typing.Sequence[builtins.int], middle: typing.Sequence[builtins.int], ring: typing.Sequence[builtins.int], pinky: typing.Sequence[builtins.int]) -> TouchRawData: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def index(self) -> builtins.list[builtins.int]: ...
    @property
    def middle(self) -> builtins.list[builtins.int]: ...
    def new(self, thumb: typing.Sequence[builtins.int], index: typing.Sequence[builtins.int], middle: typing.Sequence[builtins.int], ring: typing.Sequence[builtins.int], pinky: typing.Sequence[builtins.int]) -> TouchRawData: ...
    @property
    def pinky(self) -> builtins.list[builtins.int]: ...
    @property
    def ring(self) -> builtins.list[builtins.int]: ...
    @property
    def thumb(self) -> builtins.list[builtins.int]: ...
@typing.final
class TouchSensorData:
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def items(self) -> builtins.list[TouchSensorItem]: ...
    @property
    def slave_id(self) -> builtins.int: ...
@typing.final
class TouchSensorItem:
    r"""
    ALGO OUTPUT
    """
    @property
    def force(self) -> builtins.float: ...
    @property
    def sliding_mag(self) -> builtins.float: ...

    @property
    def state(self) -> ContactState: ...
@typing.final
class TouchStatusBuffer:
    r"""
    Touch sensor status shared buffer
    
    Uses shared memory + polling mode to avoid GIL overhead from callbacks
    """
    def __new__(cls, max_size: builtins.int) -> TouchStatusBuffer: ...
    def clear(self) -> None:
        r"""
        Clear all buffers
        """

    def len_all(self) -> builtins.list[builtins.int]:
        r"""
        Check the number of items in each finger's buffer
        """
    def pop_all(self) -> builtins.list[builtins.list[TouchFingerItem]]:
        r"""
        Get touch data for all fingers
        """
    def pop_finger(self, finger_index: builtins.int) -> builtins.list[TouchFingerItem]:
        r"""
        Get touch data for a single finger
        """
    def pop_latest_all(self) -> builtins.list[typing.Optional[TouchFingerItem]]:
        r"""
        Get the latest data for all fingers
        """
@typing.final
class TurboConfig:
    def __new__(cls, interval: builtins.int, duration: builtins.int) -> TurboConfig: ...
    def desc(self) -> builtins.str: ...

    @property
    def description(self) -> builtins.str: ...
    @property
    def duration(self) -> builtins.int: ...
    @property
    def interval(self) -> builtins.int: ...
    def new(self, interval: builtins.int, duration: builtins.int) -> TurboConfig: ...
@typing.final
class ZqwlDeviceInfo:
    r"""
    ZQWL Device Information
    """
    @property
    def channel_count(self) -> builtins.int:
        r"""
        Number of channels
        """
    @property
    def description(self) -> builtins.str:
        r"""
        Device description
        """

    @property
    def pid(self) -> builtins.int:
        r"""
        USB PID
        """
    @property
    def port_name(self) -> builtins.str:
        r"""
        Serial port name
        """
    @property
    def supports_canfd(self) -> builtins.bool:
        r"""
        Whether CANFD is supported
        """
    @property
    def vid(self) -> builtins.int:
        r"""
        USB VID
        """
@typing.final
class ActionCmd(enum.Enum):
    SetStart = ...
    SetFinish = ...
    ReadStart = ...
    ReadFinish = ...
    Save = ...
    Run = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> ActionCmd: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class ActionSequenceId(enum.Enum):
    DefaultGestureOpen = ...
    DefaultGestureFist = ...
    DefaultGesturePinchTwo = ...
    DefaultGesturePinchThree = ...
    DefaultGesturePinchSide = ...
    DefaultGesturePoint = ...
    CustomGesture1 = ...
    CustomGesture2 = ...
    CustomGesture3 = ...
    CustomGesture4 = ...
    CustomGesture5 = ...
    CustomGesture6 = ...
    CustomGesture7 = ...
    CustomGesture8 = ...
    CustomGesture9 = ...
    CustomGesture10 = ...
    CustomGesture11 = ...
    CustomGesture12 = ...
    CustomGesture13 = ...
    CustomGesture14 = ...
    CustomGesture15 = ...
    CustomGesture16 = ...
    CustomGesture17 = ...
    CustomGesture18 = ...
    CustomGesture19 = ...
    CustomGesture20 = ...
    CustomGesture21 = ...
    CustomGesture22 = ...
    CustomGesture23 = ...
    CustomGesture24 = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> ActionSequenceId: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class ActionStatus(enum.Enum):
    Idle = ...
    Running = ...
    Completed = ...
    Error = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> ActionStatus: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class Baudrate(enum.Enum):
    Baud115200 = ...
    Baud57600 = ...
    Baud19200 = ...
    Baud460800 = ...
    Baud1Mbps = ...
    Baud2Mbps = ...
    Baud3Mbps = ...
    Baud5Mbps = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> Baudrate: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class BaudrateCAN(enum.Enum):
    Baud100Kbps = ...
    Baud125Kbps = ...
    Baud200Kbps = ...
    Baud250Kbps = ...
    Baud400Kbps = ...
    Baud500Kbps = ...
    Baud800Kbps = ...
    Baud1Mbps = ...
    Baud2Mbps = ...
    Baud4Mbps = ...
    Baud5Mbps = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> BaudrateCAN: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class CanChannel(enum.Enum):
    Thumb = ...
    ThumbAux = ...
    Index = ...
    Middle = ...
    Ring = ...
    Pinky = ...
    All = ...
    Reserved = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> CanChannel: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class CanCmd(enum.Enum):
    Position = ...
    Speed = ...
    Current = ...
    Pwm = ...
    PositionRead = ...
    SpeedRead = ...
    CurrentRead = ...
    StateRead = ...
    ParamConfig = ...
    ParamRead = ...
    MultiRead = ...
    PositionWithDuration = ...
    TouchSensorRead = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> CanCmd: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class CanFrameMultiRead(enum.Enum):
    FirmwareVersion = ...
    SerialNumber = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> CanFrameMultiRead: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class CanParamAddress(enum.Enum):
    Unknown = ...
    SkuType = ...
    DeviceId = ...
    TurboSwitch = ...
    TurboParam = ...
    AutoCalibration = ...
    ManualCalibration = ...
    StoreAndReboot = ...
    LedSwitch = ...
    BuzzerSwitch = ...
    VibrationSwitch = ...
    ResetSettings = ...
    LockCurrentThumbAux = ...
    UnitMode = ...
    EnterOta = ...
    ProtectedCurrentThumbBase = ...
    ProtectedCurrentThumbAux = ...
    ProtectedCurrentIndex = ...
    ProtectedCurrentMiddle = ...
    ProtectedCurrentRing = ...
    ProtectedCurrentPinky = ...
    DefaultGesture = ...
    TouchCalibration = ...
    TouchSwitch = ...
    TouchReset = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> CanParamAddress: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class ContactState(enum.Enum):
    NoContact = ...
    Contact = ...
    ContactSliding = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> ContactState: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class DfuCommandType(enum.Enum):
    RequestDeviceInfo = ...
    StartUpgrade = ...
    TransferData = ...
    TransferDone = ...
    ExitUpgrade = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> DfuCommandType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class DfuExitReason(enum.Enum):
    FirmwareVersionMismatch = ...
    HardwareVersionMismatch = ...
    FirmwareFileCorrupted = ...
    Unknown = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> DfuExitReason: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class DfuState(enum.Enum):
    Idle = ...
    Starting = ...
    Started = ...
    Transfer = ...
    Completed = ...
    Aborted = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> DfuState: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EcModulusSdoSubIdx(enum.Enum):
    CalibrationThumb = ...
    CalibrationIndex = ...
    CalibrationMiddle = ...
    CalibrationRing = ...
    CalibrationPinky = ...
    CalibrationPalm = ...
    SwitchThumb = ...
    SwitchIndex = ...
    SwitchMiddle = ...
    SwitchRing = ...
    SwitchPinky = ...
    SwitchPalm = ...
    Vendor = ...
    DataType = ...
    DeviceSnThumb = ...
    DeviceSnIndex = ...
    DeviceSnMiddle = ...
    DeviceSnRing = ...
    DeviceSnPinky = ...
    DeviceSnPalm = ...
    FwVersionThumb = ...
    FwVersionIndex = ...
    FwVersionMiddle = ...
    FwVersionRing = ...
    FwVersionPinky = ...
    FwVersionPalm = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EcModulusSdoSubIdx: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EcTashanSdoSubIdx(enum.Enum):
    ThumbCalibration = ...
    IndexCalibration = ...
    MidCalibration = ...
    RingCalibration = ...
    PinkyCalibration = ...
    TouchVendor = ...
    ThumbAcqParamUpdate = ...
    IndexAcqParamUpdate = ...
    MidAcqParamUpdate = ...
    RingAcqParamUpdate = ...
    PinkyAcqParamUpdate = ...
    Reserved1 = ...
    ThumbTouchFwVersion = ...
    IndexTouchFwVersion = ...
    MidTouchFwVersion = ...
    RingTouchFwVersion = ...
    PinkyTouchFwVersion = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EcTashanSdoSubIdx: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EtherCATAddress(enum.Enum):
    TX = ...
    RX = ...
    Config = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EtherCATAddress: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EtherCATConfigIndex(enum.Enum):
    SkuType = ...
    LedSwitch = ...
    BuzzerSwitch = ...
    VibrationSwitch = ...
    UnitMode = ...
    CalibratePosition = ...
    AutoCalibration = ...
    TurboMode = ...
    TurboParam = ...
    ProtectedCurrentThumbBase = ...
    ProtectedCurrentThumbAux = ...
    ProtectedCurrentIndex = ...
    ProtectedCurrentMiddle = ...
    ProtectedCurrentRing = ...
    ProtectedCurrentPinky = ...
    LockCurrentThumbAux = ...
    CtrlFirmwareVersion = ...
    CtrlSerialNumber = ...
    WristFirmwareVersion = ...
    WristSerialNumber = ...
    FoeFileType = ...
    FoeAuthCode = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EtherCATConfigIndex: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EtherCATCtrlAddress(enum.Enum):
    Multi = ...
    Single = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EtherCATCtrlAddress: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EtherCATCtrlSubAddressMulti(enum.Enum):
    Mode = ...
    Param1 = ...
    Param2 = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EtherCATCtrlSubAddressMulti: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EtherCATCtrlSubAddressSingle(enum.Enum):
    Mode = ...
    Id = ...
    Param1 = ...
    Param2 = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EtherCATCtrlSubAddressSingle: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class EtherCATFoeType(enum.Enum):
    Wrist = ...
    Control = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> EtherCATFoeType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class FingerCtrlMode(enum.Enum):
    PositionWithDuration = ...
    PositionWithSpeed = ...
    Speed = ...
    Current = ...
    Pwm = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> FingerCtrlMode: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class FingerId(enum.Enum):
    Thumb = ...
    ThumbAux = ...
    Index = ...
    Middle = ...
    Ring = ...
    Pinky = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> FingerId: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class FingerUnitMode(enum.Enum):
    Normalized = ...
    Physical = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> FingerUnitMode: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class ForceLevel(enum.Enum):
    Small = ...
    Normal = ...
    Full = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> ForceLevel: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class HandType(enum.Enum):
    Left = ...
    Right = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> HandType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class LedColor(enum.Enum):
    Unchanged = ...
    R = ...
    G = ...
    RG = ...
    B = ...
    RB = ...
    GB = ...
    RGB = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> LedColor: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class LedMode(enum.Enum):
    Unknown = ...
    Shutdown = ...
    Keep = ...
    Blink = ...
    OneShot = ...
    Blink0_5Hz = ...
    Blink2Hz = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> LedMode: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class LogLevel(enum.Enum):
    Error = ...
    Warn = ...
    Info = ...
    Debug = ...
    Trace = ...

@typing.final
class ModulusTouchDataType(enum.Enum):
    Raw = ...
    Calibrated = ...
    Force = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> ModulusTouchDataType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class MotorState(enum.Enum):
    Unknown = ...
    Idle = ...
    Running = ...
    Stall = ...
    Turbo = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> MotorState: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class MsgType(enum.Enum):
    Crimson = ...
    OxyZen = ...
    Mobius = ...
    MobiusV1_5 = ...
    Almond = ...
    AlmondV2 = ...
    Morpheus = ...
    Luna = ...
    REN = ...
    Breeze = ...
    Stark = ...
    EEGCap = ...
    Edu = ...
    Clear = ...
    Melody = ...
    Aura = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> MsgType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class PressState(enum.Enum):
    Unknown = ...
    Down = ...
    Up = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> PressState: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class RegAddrArrayPressure(enum.Enum):
    TouchSwitchAll = ...
    ZeroAll = ...
    ZeroThumb = ...
    ZeroIndex = ...
    ZeroMiddle = ...
    ZeroRing = ...
    ZeroPinky = ...
    DeviceSleep = ...
    SensorStatus = ...
    WarmupStatus = ...
    TouchDataBase = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> RegAddrArrayPressure: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class RegAddrForce3D(enum.Enum):
    TouchSwitchAll = ...
    TouchSwitchIndex = ...
    TouchSwitchMiddle = ...
    TouchSwitchRing = ...
    TouchSwitchPinky = ...
    CalibrationAll = ...
    CalibrationIndex = ...
    CalibrationMiddle = ...
    CalibrationRing = ...
    CalibrationPinky = ...
    SummaryIndexFxFy = ...
    SummaryIndexFz = ...
    SummaryMiddleFxFy = ...
    SummaryMiddleFz = ...
    SummaryRingFxFy = ...
    SummaryRingFz = ...
    SummaryPinkyFxFy = ...
    SummaryPinkyFz = ...
    ArrayIndexBase = ...
    ArrayMiddleBase = ...
    ArrayRingBase = ...
    ArrayPinkyBase = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> RegAddrForce3D: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class RegAddrRevo1(enum.Enum):
    EnterOta = ...
    SkuType = ...
    SetFactoryKey = ...
    SetSn = ...
    StallDuration = ...
    PwmSmall = ...
    PwmNormal = ...
    PwmFull = ...
    StallCurrentSmall = ...
    StallCurrentNormal = ...
    StallCurrentFull = ...
    SlaveId = ...
    Baudrate = ...
    Force = ...
    SetReboot = ...
    Position = ...
    Speed = ...
    Led = ...
    Current = ...
    Turbo = ...
    TurboInterval = ...
    TurboDuration = ...
    AutoCalibration = ...
    ManualCalibration = ...
    ActionCmd = ...
    ActionNum = ...
    ActionData = ...
    GetNowPosition = ...
    GetNowSpeed = ...
    GetNowCurrent = ...
    GetMotorState = ...
    GetVoltage = ...
    GetButtonStatus = ...
    GetFwVersion = ...
    GetSn = ...
    GetThumbNormalForce1 = ...
    GetThumbTangentialForce1 = ...
    GetThumbTangentialDirection1 = ...
    GetThumbNormalForce2 = ...
    GetThumbTangentialForce2 = ...
    GetThumbTangentialDirection2 = ...
    GetThumbSelfProximity1 = ...
    GetThumbStatus = ...
    GetIndexNormalForce1 = ...
    GetIndexTangentialForce1 = ...
    GetIndexTangentialDirection1 = ...
    GetIndexNormalForce2 = ...
    GetIndexTangentialForce2 = ...
    GetIndexTangentialDirection2 = ...
    GetIndexNormalForce3 = ...
    GetIndexTangentialForce3 = ...
    GetIndexTangentialDirection3 = ...
    GetIndexSelfProximity1 = ...
    GetIndexSelfProximity2 = ...
    GetIndexMutualProximity = ...
    GetIndexStatus = ...
    GetMiddleNormalForce1 = ...
    GetMiddleTangentialForce1 = ...
    GetMiddleTangentialDirection1 = ...
    GetMiddleNormalForce2 = ...
    GetMiddleTangentialForce2 = ...
    GetMiddleTangentialDirection2 = ...
    GetMiddleNormalForce3 = ...
    GetMiddleTangentialForce3 = ...
    GetMiddleTangentialDirection3 = ...
    GetMiddleSelfProximity1 = ...
    GetMiddleSelfProximity2 = ...
    GetMiddleMutualProximity = ...
    GetMiddleStatus = ...
    GetRingNormalForce1 = ...
    GetRingTangentialForce1 = ...
    GetRingTangentialDirection1 = ...
    GetRingNormalForce2 = ...
    GetRingTangentialForce2 = ...
    GetRingTangentialDirection2 = ...
    GetRingNormalForce3 = ...
    GetRingTangentialForce3 = ...
    GetRingTangentialDirection3 = ...
    GetRingSelfProximity1 = ...
    GetRingSelfProximity2 = ...
    GetRingMutualProximity = ...
    GetRingStatus = ...
    GetPinkyNormalForce1 = ...
    GetPinkyTangentialForce1 = ...
    GetPinkyTangentialDirection1 = ...
    GetPinkyNormalForce2 = ...
    GetPinkyTangentialForce2 = ...
    GetPinkyTangentialDirection2 = ...
    GetPinkySelfProximity1 = ...
    GetPinkyMutualProximity1 = ...
    GetPinkyStatus = ...
    SetThumbReset = ...
    SetIndexReset = ...
    SetMiddleReset = ...
    SetRingReset = ...
    SetPinkyReset = ...
    SetThumbCalibration = ...
    SetIndexCalibration = ...
    SetMiddleCalibration = ...
    SetRingCalibration = ...
    SetPinkyCalibration = ...
    TouchEnabledThumb = ...
    TouchEnabledIndex = ...
    TouchEnabledMiddle = ...
    TouchEnabledRing = ...
    TouchEnabledPinky = ...
    GetTouchFwVersion = ...
    GetTouchRawDataThumb = ...
    GetTouchRawDataIndex = ...
    GetTouchRawDataMiddle = ...
    GetTouchRawDataRing = ...
    GetTouchRawDataPinky = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> RegAddrRevo1: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class RegAddrRevo2(enum.Enum):
    EnterOta = ...
    SkuType = ...
    ResetGesture = ...
    ResetSettings = ...
    LEDSwitch = ...
    BuzzerSwitch = ...
    VibrationSwitch = ...
    SetFactoryKey = ...
    SetSn = ...
    ProtectedCurrentThumbBase = ...
    ProtectedCurrentThumbAux = ...
    ProtectedCurrentIndex = ...
    ProtectedCurrentMiddle = ...
    ProtectedCurrentRing = ...
    ProtectedCurrentPinky = ...
    LockCurrentThumbAux = ...
    UnitMode = ...
    SetFingerMinPosition = ...
    SetFingerMaxPosition = ...
    SetFingerMaxSpeed = ...
    SetFingerMaxCurrent = ...
    GetFingerMinPosition = ...
    GetFingerMaxPosition = ...
    GetFingerMaxSpeed = ...
    GetFingerMaxCurrent = ...
    TouchVendor = ...
    BacklashThumbTip = ...
    BacklashThumbRoot = ...
    BacklashIndex = ...
    BacklashMiddle = ...
    BacklashRing = ...
    BacklashPinky = ...
    BacklashSelfCheck = ...
    SlaveId = ...
    Baudrate = ...
    BaudrateCAN = ...
    CanFdAbitSamplingRate = ...
    SetReboot = ...
    PositionWithDuration = ...
    PositionWithSpeed = ...
    Speed = ...
    Current = ...
    Pwm = ...
    PositionWithDurationSingle = ...
    PositionWithSpeedSingle = ...
    SpeedSingle = ...
    CurrentSingle = ...
    PwmSingle = ...
    Led = ...
    Turbo = ...
    TurboInterval = ...
    AutoCalibration = ...
    ManualCalibration = ...
    PositionByPercent = ...
    ActionCmd = ...
    ActionNum = ...
    ActionData = ...
    GetNowPosition = ...
    GetNowSpeed = ...
    GetNowCurrent = ...
    GetMotorState = ...
    GetButtonStatus = ...
    GetFwVersion = ...
    GetSn = ...
    TouchEnabledThumb = ...
    TouchEnabledIndex = ...
    TouchEnabledMiddle = ...
    TouchEnabledRing = ...
    TouchEnabledPinky = ...
    SetThumbReset = ...
    SetIndexReset = ...
    SetMiddleReset = ...
    SetRingReset = ...
    SetPinkyReset = ...
    SetThumbCalibration = ...
    SetIndexCalibration = ...
    SetMiddleCalibration = ...
    SetRingCalibration = ...
    SetPinkyCalibration = ...
    GetTouchFwVersion = ...
    GetMultiFinger3DForce = ...
    GetMultiFingerProximity = ...
    GetMultiFingerTouchStatus = ...
    GetSingleFinger3DForce = ...
    GetTouchRawDataThumb = ...
    GetTouchRawDataIndex = ...
    GetTouchRawDataMiddle = ...
    GetTouchRawDataRing = ...
    GetTouchRawDataPinky = ...
    GetModulusSensorDataType = ...
    GetModulusTouchSummaryThumb = ...
    GetModulusTouchSummaryIndex = ...
    GetModulusTouchSummaryMiddle = ...
    GetModulusTouchSummaryRing = ...
    GetModulusTouchSummaryPinky = ...
    GetModulusTouchSummaryPalm = ...
    GetModulusTouchDataThumb = ...
    GetModulusTouchDataIndex = ...
    GetModulusTouchDataMiddle = ...
    GetModulusTouchDataRing = ...
    GetModulusTouchDataPinky = ...
    GetModulusTouchDataPalm = ...
    GetModulusFirmwareThumb = ...
    GetModulusFirmwareIndex = ...
    GetModulusFirmwareMiddle = ...
    GetModulusFirmwareRing = ...
    GetModulusFirmwarePinky = ...
    GetModulusFirmwarePalm = ...
    ModulusSwitchThumb = ...
    ModulusSwitchIndex = ...
    ModulusSwitchMiddle = ...
    ModulusSwitchRing = ...
    ModulusSwitchPinky = ...
    ModulusSwitchPalm = ...
    GetModulusSerialThumb = ...
    GetModulusSerialIndex = ...
    GetModulusSerialMiddle = ...
    GetModulusSerialRing = ...
    GetModulusSerialPinky = ...
    GetModulusSerialPalm = ...
    SetModulusCalibrationThumb = ...
    SetModulusCalibrationIndex = ...
    SetModulusCalibrationMiddle = ...
    SetModulusCalibrationRing = ...
    SetModulusCalibrationPinky = ...
    SetModulusCalibrationPalm = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> RegAddrRevo2: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class SkuType(enum.Enum):
    MediumRight = ...
    MediumLeft = ...
    SmallRight = ...
    SmallLeft = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> SkuType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class StarkError(enum.Enum):
    Success = ...
    Unknown = ...
    InvalidParams = ...
    InvalidData = ...
    ParseFailed = ...
    AllocFailed = ...
    ReadFailed = ...
    OperationFailed = ...
    SystemIsBusy = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> StarkError: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class StarkHardwareType(enum.Enum):
    Revo2Basic = ...
    Revo1Protobuf = ...
    Revo1Basic = ...
    Revo1Touch = ...
    Revo1Advanced = ...
    Revo1AdvancedTouch = ...
    Revo2Touch = ...
    Revo2TouchPressure = ...
    Revo2TouchForce3D = ...
    Revo2TouchArrayPressure = ...
    Revo2VisionTouch = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> StarkHardwareType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class StarkModuleId(enum.Enum):
    MCU = ...
    MTR = ...
    APP = ...
    SERIAL = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> StarkModuleId: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class StarkProtocolType(enum.Enum):
    Auto = ...
    Modbus = ...
    Can = ...
    CanFd = ...
    EtherCAT = ...
    Protobuf = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> StarkProtocolType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class TouchDataType(enum.Enum):
    Force = ...
    Proximity = ...
    Status = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> TouchDataType: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class TouchSensorStatus(enum.Enum):
    Unknown = ...
    Normal = ...
    Abnormal = ...
    SensorCommError = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> TouchSensorStatus: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
@typing.final
class TouchVendor(enum.Enum):
    Unknown = ...
    Capacitive = ...
    Pressure = ...
    ArrayPressure = ...
    Force3D = ...

    def __int__(self) -> builtins.int:
        r"""
        Support int(enum) conversion
        """

    def __new__(cls, value: builtins.int) -> TouchVendor: ...
    @property
    def int_value(self) -> builtins.int:
        r"""
        Get the integer value of the enum
        """
def auto_detect(scan_all: builtins.bool = False, port: typing.Optional[builtins.str] = None, protocol: typing.Optional[builtins.str] = None) -> typing.Any:
    r"""
    Auto-detect Stark devices
    
    Scans for devices across all supported protocols in priority order:
    1. ZQWL CANFD (Revo2: IDs 0x7E, 0x7F)
    2. ZQWL CAN 2.0 (Revo1/Revo2: IDs 1, 2)
    3. Modbus/RS485 (IDs 0x7E, 0x7F, 1, 2, 10)
    
    Args:
        scan_all: If True, scan for all devices. If False, stop at first found. Default False.
        port: Optional port name to scan. If None, scans all available ports.
        protocol: Optional protocol to use ("CanFd", "Can", "Modbus"). If None, tries all.
    
    Returns:
        List[DetectedDevice]: List of detected devices (empty if none found)
    
    Examples:
        # Auto-detect (simplest)
        devices = await sdk.auto_detect()
    
        # Scan all devices
        devices = await sdk.auto_detect(scan_all=False)
    
        # Scan specific port
        devices = await sdk.auto_detect(port="/dev/ttyUSB0")
    
        # Scan specific protocol
        devices = await sdk.auto_detect(protocol="CanFd")
    """

def auto_detect_device(port_name: typing.Optional[builtins.str] = None, quick: typing.Optional[builtins.bool] = True) -> typing.Any: ...

def auto_detect_modbus_revo1(port_name: typing.Optional[builtins.str] = None, quick: typing.Optional[builtins.bool] = True) -> typing.Any: ...

def auto_detect_modbus_revo2(port_name: typing.Optional[builtins.str] = None, quick: typing.Optional[builtins.bool] = True) -> typing.Any: ...

def available_usb_ports(vid: builtins.int, pid: builtins.int) -> typing.Any: ...

def close_device_handler(client: DeviceContext) -> typing.Any:
    r"""
    Close device handler and release resources.
    
    This is the counterpart to init_from_detected() and init_device_handler().
    It automatically handles cleanup based on the protocol type:
    - For CAN/CANFD: Closes ZQWL device
    - For Modbus: Closes serial port
    
    Args:
        client: PyDeviceContext to close
    
    Examples:
        ctx = await sdk.init_from_detected(device)
        # ... use ctx ...
        await sdk.close_device_handler(ctx)
    """

def close_socketcan() -> None:
    r"""
    Close SocketCAN device (Linux only)
    """

def close_zqwl() -> None:
    r"""
    Close ZQWL CAN/CANFD device
    """

def get_sdk_version() -> builtins.str: ...

def init_device_handler(protocol_type: StarkProtocolType, master_id: builtins.int = 0, slave_id: typing.Optional[builtins.int] = None, hw_type: typing.Optional[StarkHardwareType] = None) -> DeviceContext: ...

def init_from_detected(device: DetectedDevice) -> typing.Any:
    r"""
    Initialize device handler from detected device info.
    
    This function initializes the appropriate transport (Modbus, CAN, CANFD)
    based on the detected device's protocol and returns a ready-to-use handler.
    
    This is the recommended way to initialize after auto_detect() as it:
    - Automatically initializes the correct transport (BrainCo/ZQWL/SocketCAN or Modbus)
    - Sets hardware type from detected device info
    - Simplifies the initialization process
    
    Args:
        device: DetectedDevice from auto_detect()
    
    Returns:
        PyDeviceContext: Ready-to-use device context
    
    Raises:
        RuntimeError: If initialization fails
    
    Examples:
        devices = await sdk.auto_detect()
        if devices:
            ctx = await sdk.init_from_detected(devices[0])
            # ctx is ready to use, no need to call get_device_info
    """

def init_logging(level: typing.Optional[LogLevel] = LogLevel.Info) -> None: ...

def init_socketcan_can(iface: typing.Optional[builtins.str] = None) -> None:
    r"""
    Initialize SocketCAN CAN 2.0 device (Linux only)
    
    Args:
        iface: Interface name (e.g. "can0"). If None, uses STARK_SOCKETCAN_IFACE env var or "can0"
    
    Raises:
        RuntimeError: Initialization failed or not on Linux
    """

def init_socketcan_canfd(iface: typing.Optional[builtins.str] = None) -> None:
    r"""
    Initialize SocketCAN CANFD device (Linux only)
    
    Args:
        iface: Interface name (e.g. "can0"). If None, uses STARK_SOCKETCAN_IFACE env var or "can0"
    
    Raises:
        RuntimeError: Initialization failed or not on Linux
    """

def init_zqwl_can(port_name: builtins.str, arb_baudrate: builtins.int = 1000000) -> None:
    r"""
    Initialize ZQWL CAN device (CAN 2.0 mode)
    
    For Revo1 devices, baudrate is typically 1Mbps
    
    Args:
        port_name: Serial port name, e.g. "/dev/cu.usbmodem*" (macOS) or "COM3" (Windows)
        arb_baudrate: Arbitration baudrate (bps), default 1000000
    
    Raises:
        RuntimeError: Initialization failed
    """

def init_zqwl_canfd(port_name: builtins.str, arb_baudrate: builtins.int = 1000000, data_baudrate: builtins.int = 5000000) -> None:
    r"""
    Initialize ZQWL CANFD device
    
    For Revo2 devices, arbitration baudrate is typically 1Mbps, data baudrate is typically 5Mbps
    
    Args:
        port_name: Serial port name
        arb_baudrate: Arbitration baudrate (bps), default 1000000
        data_baudrate: Data baudrate (bps), default 5000000
    
    Raises:
        RuntimeError: Initialization failed
    """

def is_socketcan_available(iface: builtins.str) -> builtins.bool:
    r"""
    Check if SocketCAN interface is available (Linux only)
    
    Args:
        iface: Interface name (e.g. "can0")
    
    Returns:
        bool: True if interface exists and is up
    """

def list_available_ports() -> typing.Any: ...

def list_zqwl_devices() -> builtins.list[ZqwlDeviceInfo]:
    r"""
    List all ZQWL USB CAN/CANFD devices
    
    Returns:
        List[ZqwlDeviceInfo]: List of devices
    """

def modbus_close(client: DeviceContext) -> typing.Any: ...

def modbus_open(port_name: builtins.str, baudrate: Baudrate) -> typing.Any: ...

def protobuf_open(port_name: builtins.str, slave_id: builtins.int = 10, baudrate: builtins.int = 115200) -> typing.Any:
    r"""
    Open a Protobuf protocol connection
    
    Protobuf protocol uses default baudrate 115200 and default slave_id 10.
    Position range is 0-100 (not 0-1000 like Modbus/CAN).
    
    Args:
        port_name: Serial port name (e.g., "/dev/ttyUSB0" or "COM3")
        slave_id: Device slave ID (default is 10)
        baudrate: Baudrate (default is 115200)
    
    Returns:
        DeviceContext: Ready-to-use device context for Protobuf protocol
    
    Raises:
        RuntimeError: If opening the port fails
    
    Examples:
        ctx = await sdk.protobuf_open("/dev/ttyUSB0")
        # or with custom slave_id
        ctx = await sdk.protobuf_open("/dev/ttyUSB0", slave_id=10)
        # or with custom baudrate
        ctx = await sdk.protobuf_open("/dev/ttyUSB0", slave_id=10, baudrate=115200)
    """

def scan_can_devices(candidate_ids: typing.Optional[typing.Sequence[builtins.int]] = None, timeout_ms: builtins.int = 500) -> typing.Any:
    r"""
    Scan CAN bus for devices
    
    Uses get_can_params to read SkuType to detect devices
    
    Args:
        candidate_ids: Candidate device ID list, default [1, 2] (Revo1) or [0x7E, 0x7F] (Revo2)
        timeout_ms: Timeout in milliseconds, default 500
    
    Returns:
        Optional[int]: Found device ID, None if not found
    """

def scan_canfd_devices(ctx: DeviceContext, candidate_ids: typing.Optional[typing.Sequence[builtins.int]] = None, timeout_ms: builtins.int = 500) -> typing.Any:
    r"""
    Scan CANFD bus for devices
    
    Uses DeviceContext to read SkuType register to detect devices
    
    Args:
        ctx: PyDeviceContext
        candidate_ids: Candidate device ID list, default [0x7E, 0x7F] (Revo2)
        timeout_ms: Timeout in milliseconds, default 500
    
    Returns:
        Optional[int]: Found device ID, None if not found
    """

def set_can_rx_callback(func: typing.Any) -> None:
    r"""
    Set callback for receiving CAN FD frames.
    
    Args:
        func: Callback function to receive CAN FD frames.
    
    Returns:
        None
    """

def set_can_tx_callback(func: typing.Any) -> None:
    r"""
    Set callback for transmitting CAN FD frames.
    
    Args:
        func: Callback function to transmit CAN FD frames.
    
    Returns:
        None
    """

def set_modbus_read_holding_callback(func: typing.Any) -> None:
    r"""
    Set callback for reading Modbus holding registers (FC03).
    
    Args:
        func: Callback function for reading holding registers.
    
    Returns:
        None
    """

def set_modbus_read_input_callback(func: typing.Any) -> None:
    r"""
    Set callback for reading Modbus input registers (FC04).
    
    Args:
        func: Callback function for reading input registers.
    
    Returns:
        None
    """

def set_modbus_write_callback(func: typing.Any) -> None:
    r"""
    Set callback for writing Modbus holding registers (FC16).
    
    Args:
        func: Callback function for writing holding registers.
    
    Returns:
        None
    """
展开查看 C/C++ 头文件 (stark-sdk.h)
c
#ifndef STARK_SDK_H
#define STARK_SDK_H

/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */

#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>

/// Built‑in gestures 1~6: open hand, fist, two‑finger pinch, three‑finger pinch,
/// side pinch, single‑finger point.
/// Revo1 supports up to 6 custom action sequences: IDs 10~15.
/// Revo2 supports up to 24 custom action sequences: IDs 7~30.
enum ActionSequenceId : uint8_t {
  ACTION_SEQUENCE_ID_DEFAULT_GESTURE_OPEN = 1,
  ACTION_SEQUENCE_ID_DEFAULT_GESTURE_FIST = 2,
  ACTION_SEQUENCE_ID_DEFAULT_GESTURE_PINCH_TWO = 3,
  ACTION_SEQUENCE_ID_DEFAULT_GESTURE_PINCH_THREE = 4,
  ACTION_SEQUENCE_ID_DEFAULT_GESTURE_PINCH_SIDE = 5,
  ACTION_SEQUENCE_ID_DEFAULT_GESTURE_POINT = 6,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE22 = 7,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE23 = 8,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE24 = 9,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE1 = 10,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE2 = 11,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE3 = 12,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE4 = 13,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE5 = 14,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE6 = 15,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE7 = 16,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE8 = 17,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE9 = 18,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE10 = 19,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE11 = 20,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE12 = 21,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE13 = 22,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE14 = 23,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE15 = 24,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE16 = 25,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE17 = 26,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE18 = 27,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE19 = 28,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE20 = 29,
  ACTION_SEQUENCE_ID_CUSTOM_GESTURE21 = 30,
};

/// DFU (Device Firmware Update) state
/// Used in DFU state callback to indicate current upgrade status
enum DfuState : uint8_t {
  /// DFU not started
  DFU_STATE_IDLE = 0,
  /// Preparing to start DFU
  DFU_STATE_STARTING = 1,
  /// DFU started, ready to transfer
  DFU_STATE_STARTED = 2,
  /// Transferring firmware data
  DFU_STATE_TRANSFER = 3,
  /// DFU completed successfully
  DFU_STATE_COMPLETED = 4,
  /// DFU aborted or failed
  DFU_STATE_ABORTED = 5,
};

/// EtherCAT FoE (File over EtherCAT) firmware type
/// Used for firmware upgrade over EtherCAT
enum EtherCATFoeType : uint8_t {
  /// Wrist module firmware
  ETHER_CAT_FOE_TYPE_WRIST = 1,
  /// Main controller firmware
  ETHER_CAT_FOE_TYPE_CONTROL = 2,
};

/// Finger control unit mode
/// Determines how position/speed/current values are interpreted
enum FingerUnitMode : uint8_t {
  /// Normalized mode: values in range 0-1000 (default)
  FINGER_UNIT_MODE_NORMALIZED = 0,
  /// Physical mode: values in physical units (degrees, °/s, mA)
  FINGER_UNIT_MODE_PHYSICAL = 1,
};

enum ForceLevel : uint8_t {
  FORCE_LEVEL_SMALL = 1,
  FORCE_LEVEL_NORMAL = 2,
  FORCE_LEVEL_FULL = 3,
};
enum HandType : uint8_t {
  HAND_TYPE_LEFT = 0,
  HAND_TYPE_RIGHT = 1,
};
enum LedColor : uint8_t {
  LED_COLOR_UNCHANGED = 0,
  LED_COLOR_R = 1,
  LED_COLOR_G = 2,
  LED_COLOR_RG = 3,
  LED_COLOR_B = 4,
  LED_COLOR_RB = 5,
  LED_COLOR_GB = 6,
  LED_COLOR_RGB = 7,
};
enum LedMode : uint8_t {
  LED_MODE_NONE = 0,
  LED_MODE_SHUTDOWN = 1,
  LED_MODE_KEEP = 2,
  LED_MODE_BLINK = 3,
  LED_MODE_ONE_SHOT = 4,
  LED_MODE_BLINK0_5HZ = 5,
  LED_MODE_BLINK2HZ = 6,
};
enum LogLevel : uint8_t {
  LOG_LEVEL_ERROR = 0,
  LOG_LEVEL_WARN = 1,
  LOG_LEVEL_INFO = 2,
  LOG_LEVEL_DEBUG = 3,
  LOG_LEVEL_TRACE = 4,
};

/// Motor state
/// Indicates the current operating state of a finger motor
enum MotorState : uint8_t {
  /// Motor is idle (not moving)
  MOTOR_STATE_IDLE = 0,
  /// Motor is running (moving)
  MOTOR_STATE_RUNNING = 1,
  /// Motor is stalled (blocked or reached limit)
  MOTOR_STATE_STALL = 2,
  /// Motor is in turbo mode (continuous force)
  MOTOR_STATE_TURBO = 3,
  /// Unknown state
  MOTOR_STATE_UNKNOWN = 255,
};

/// Button press state
/// Used in button event callbacks
enum PressState : uint8_t {
  /// No button event
  PRESS_STATE_NONE = 0,
  /// Button pressed down
  PRESS_STATE_DOWN = 1,
  /// Button released
  PRESS_STATE_UP = 2,
};

/// SKU type (device hand type)
/// Identifies the hand side (left/right). Size is determined by hardware_type.
/// Note: Currently only Medium size is available. Small size values are reserved.
enum SkuType : uint8_t {
  /// Medium size, right hand
  SKU_TYPE_MEDIUM_RIGHT = 1,
  /// Medium size, left hand
  SKU_TYPE_MEDIUM_LEFT = 2,
  /// Small size, right hand (reserved, not currently used)
  SKU_TYPE_SMALL_RIGHT = 3,
  /// Small size, left hand (reserved, not currently used)
  SKU_TYPE_SMALL_LEFT = 4,
};

/// Finger identifier
/// Used to specify which finger to control or query
enum StarkFingerId : uint8_t {
  /// Thumb (main joint)
  STARK_FINGER_ID_THUMB = 1,
  /// Thumb auxiliary (rotation joint, Revo2 only)
  STARK_FINGER_ID_THUMB_AUX = 2,
  /// Index finger
  STARK_FINGER_ID_INDEX = 3,
  /// Middle finger
  STARK_FINGER_ID_MIDDLE = 4,
  /// Ring finger
  STARK_FINGER_ID_RING = 5,
  /// Pinky finger
  STARK_FINGER_ID_PINKY = 6,
};

/// Stark hardware type
/// Identifies the device generation and capabilities
///
/// Value ranges:
///   Revo1: 0~9
///   Revo2: 10~19
enum StarkHardwareType : uint8_t {
  /// Revo1 with legacy Protobuf protocol
  STARK_HARDWARE_TYPE_REVO1_PROTOBUF = 0,
  /// Revo1 Basic (no touch sensor)
  STARK_HARDWARE_TYPE_REVO1_BASIC = 1,
  /// Revo1 with capacitive touch sensor
  STARK_HARDWARE_TYPE_REVO1_TOUCH = 2,
  /// Revo1 Advanced: wide voltage, multi-interface support
  STARK_HARDWARE_TYPE_REVO1_ADVANCED = 3,
  /// Revo1 Advanced with capacitive touch sensor
  STARK_HARDWARE_TYPE_REVO1_ADVANCED_TOUCH = 4,
  /// Revo2 Basic (no touch sensor)
  STARK_HARDWARE_TYPE_REVO2_BASIC = 10,
  /// Revo2 with capacitive touch sensor
  STARK_HARDWARE_TYPE_REVO2_TOUCH = 11,
  /// Revo2 with pressure/modulus touch sensor
  STARK_HARDWARE_TYPE_REVO2_TOUCH_PRESSURE = 12,
  /// Revo2 with 3D force matrix touch sensor
  STARK_HARDWARE_TYPE_REVO2_TOUCH_FORCE3D = 13,
  /// Revo2 with array pressure touch sensor
  STARK_HARDWARE_TYPE_REVO2_TOUCH_ARRAY_PRESSURE = 14,
};

/// Communication protocol type
/// Determines how the SDK communicates with the device
enum StarkProtocolType : uint8_t {
  /// Auto-detect protocol (used in stark_auto_detect)
  STARK_PROTOCOL_TYPE_AUTO = 0,
  /// Modbus RTU over RS485 serial
  STARK_PROTOCOL_TYPE_MODBUS = 1,
  /// CAN 2.0 protocol (1Mbps)
  STARK_PROTOCOL_TYPE_CAN = 2,
  /// CAN FD protocol (1Mbps arbitration, 5Mbps data)
  STARK_PROTOCOL_TYPE_CAN_FD = 3,
  /// EtherCAT protocol (Linux only)
  STARK_PROTOCOL_TYPE_ETHER_CAT = 4,
  /// Legacy Protobuf protocol (Revo1 only)
  STARK_PROTOCOL_TYPE_PROTOBUF = 5,
};

/// Touch sensor status
/// Indicates the health status of a touch sensor
enum TouchSensorStatus : uint8_t {
  /// Sensor data is valid
  TOUCH_SENSOR_STATUS_NORMAL = 0,
  /// Sensor data is abnormal
  TOUCH_SENSOR_STATUS_ABNORMAL = 1,
  /// Communication error with sensor
  TOUCH_SENSOR_STATUS_COMMUNICATION_ERROR = 2,
  /// Unknown state
  TOUCH_SENSOR_STATUS_UNKNOWN = 255,
};

/// Opaque handle for ArrayPressureTouchDataBuffer
struct CArrayPressureTouchItemBuffer;

/// Opaque handle for DataCollector
struct CDataCollector;

/// Opaque handle for MotorStatusBuffer
struct CMotorStatusBuffer;

/// Opaque handle for PressureDetailedBuffer
struct CPressureDetailedBuffer;

/// Opaque handle for PressureSummaryBuffer
struct CPressureSummaryBuffer;

/// Opaque handle for TouchStatusBuffer
struct CTouchStatusBuffer;

/// Device handler for C API
/// This is an opaque handle that wraps the internal device context.
/// Use `modbus_open` or `init_device_handler` to create, and `modbus_close`
/// or `close_device_handler` to release.
struct DeviceHandler;

/// Motor status data for all 6 finger joints.
/// Returned by `stark_get_motor_status`. Call `free_motor_status_data` to release.
/// Array order: [Thumb, ThumbAux, Index, Middle, Ring, Pinky]
struct CMotorStatusData {
  /// Position values in unified range 0-1000 (0=open, 1000=closed)
  uint16_t positions[6];
  /// Speed values in unified range -1000 to +1000 (positive=closing)
  int16_t speeds[6];
  /// Current values in unified range -1000 to +1000 (positive=closing)
  int16_t currents[6];
  /// Motor states (see MotorState enum)
  uint8_t states[6];
};

/// Tactile sensor data (C API)
/// 3D force values, self-capacitance, mutual-capacitance values, and sensor status.
/// Revo2 touch hand only has normal force, tangential force, tangential force
/// direction, and proximity; other fields are zero.
struct CTouchFingerItem {
  uint16_t normal_force1;
  uint16_t normal_force2;
  uint16_t normal_force3;
  uint16_t tangential_force1;
  uint16_t tangential_force2;
  uint16_t tangential_force3;
  uint16_t tangential_direction1;
  uint16_t tangential_direction2;
  uint16_t tangential_direction3;
  uint32_t self_proximity1;
  uint32_t self_proximity2;
  uint32_t mutual_proximity;
  uint16_t status;
};

/// Pressure sensor detailed data (Detailed mode)
///
/// For Modulus pressure touch sensor detailed sensor point data
/// - Fingers: 9 sensor points
/// - Palm: 46 sensor points
struct PressureDetailedItem {
  /// Number of sensor points (thumb/index/middle/ring/pinky: 9, palm: 46)
  uint8_t sensor_count;
  /// Sensor data (up to 46 sensor points)
  uint16_t sensors_data[46];
};

/// ArrayPressure sensor status.
struct CArrayPressureStatus {
  /// Sensor status (5 bits, one per finger, 1=abnormal)
  uint16_t sensor_status;
  /// Warmup status (0=warming up, 1=complete)
  uint8_t warmup_complete;
};

/// ArrayPressure touch data (25 registers = 50 bytes).
/// Call `free_array_pressure_touch_data` to release.
struct CArrayPressureTouchData {
  CArrayPressureStatus status;
  uint16_t data[25];
  uint16_t data_len;
};

/// Device configuration returned by auto-detect functions.
/// Contains the detected protocol, port, baudrate, and slave ID.
/// Call `free_device_config` to release memory.
struct CDeviceConfig {
  /// Communication protocol type
  StarkProtocolType protocol;
  /// Serial port name (e.g., "/dev/ttyUSB0" or "COM3")
  const char *port_name;
  /// Baud rate in bps
  uint32_t baudrate;
  /// Slave ID on the bus
  uint8_t slave_id;
};

/// ZQWL device info struct (C interface)
struct CZqwlDeviceInfo {
  /// Device type (0x0100=dual-channel CANFD, 0x0101=single-channel CANFD, 0x0102=dual-channel CAN, etc.)
  uint16_t device_type;
  /// Serial port name
  char *port_name;
  /// USB VID
  uint16_t vid;
  /// USB PID
  uint16_t pid;
  /// Whether CANFD is supported
  bool supports_canfd;
  /// Number of channels
  uint8_t channel_count;
};

/// ZQWL device list struct (C interface)
struct ZqwlDeviceList {
  /// Device array pointer
  CZqwlDeviceInfo *devices;
  /// Device count
  uintptr_t count;
};

/// SocketCAN device info struct (C interface)
struct CSocketCanDeviceInfo {
  /// Interface name (e.g. "can0")
  char *iface;
  /// Whether CANFD is supported
  bool supports_canfd;
  /// Whether interface is up
  bool is_up;
};

/// SocketCAN device list struct (C interface)
struct SocketCanDeviceList {
  /// Device array pointer
  CSocketCanDeviceInfo *devices;
  /// Device count
  uintptr_t count;
};

/// Detected device information (C interface)
struct CDetectedDevice {
  /// Protocol type
  StarkProtocolType protocol;
  /// Port name (serial port or CAN adapter port)
  char *port_name;
  /// Slave ID on the bus
  uint8_t slave_id;
  /// Baudrate (for Modbus/serial protocols, or CAN arbitration baudrate)
  uint32_t baudrate;
  /// Data baudrate (for CANFD only, 0 for other protocols)
  uint32_t data_baudrate;
  /// Hardware type
  StarkHardwareType hardware_type;
  /// SKU type
  SkuType sku_type;
  /// Serial number (NULL if not detected)
  char *serial_number;
  /// Firmware version (NULL if not detected)
  char *firmware_version;
};

/// Detected device list (C interface)
struct CDetectedDeviceList {
  /// Device array pointer
  CDetectedDevice *devices;
  /// Device count
  uintptr_t count;
};

/// Modbus async read/write result callback.
/// This callback processes results of asynchronous Modbus operations.
/// Return value: 0 on success, non‑zero on failure.
using ModbusOperationResultCallback = void(*)(uint8_t*, int, int, void*);

/// Modbus async read/write callback type.
/// Return value: 0 on success, non‑zero on failure.
using ModbusOperationCallback = int32_t(*)(const uint8_t *values,
                                           int len,
                                           ModbusOperationResultCallback callback,
                                           void *user_data);

/// Custom Modbus RX callback.
/// Return value: 0 on success, non‑zero on failure.
using ModbusRxCallback = int32_t(*)(uint8_t slave_id,
                                    uint16_t register_address,
                                    uint16_t *data_out,
                                    uint16_t count);

/// Custom Modbus TX callback.
/// Return value: 0 on success, non‑zero on failure.
using ModbusTxCallback = int32_t(*)(uint8_t slave_id,
                                    uint16_t register_address,
                                    const uint16_t *data,
                                    uint16_t count);

/// CAN/CANFD RX callback.
///
/// # Parameters
/// - `slave_id`: Slave ID
/// - `expected_can_id`: Expected CAN ID to filter responses
///   - CAN 2.0: `= 0` for DFU mode (accept any), `> 0` for normal filtering
///   - CANFD: Always `> 0`, matches by slave_id and master_id
/// - `expected_frames`: `0` = auto-detect multi-frame, `> 0` = specific frame count
/// - `can_id_out`: Output CAN ID
/// - `data_out`: Output data buffer (at least 512 bytes for multi-frame)
/// - `data_len_out`: Output data length
///
/// # Return value
/// 0 on success, non‑zero on failure.
using CanRxCallback = int32_t(*)(uint8_t slave_id,
                                 uint32_t expected_can_id,
                                 uint8_t expected_frames,
                                 uint32_t *can_id_out,
                                 uint8_t *data_out,
                                 uintptr_t *data_len_out);

/// CAN/CANFD TX callback.
/// Return value: 0 on success, non‑zero on failure.
using CanTxCallback = int32_t(*)(uint8_t slave_id,
                                 uint32_t can_id,
                                 const uint8_t *data,
                                 uintptr_t data_len);

/// DFU state callback, `state` corresponds to `DfuState`.
using DfuStateCallback = void(*)(uint8_t slave_id, uint8_t state);

/// DFU progress callback.
using DfuProgressCallback = void(*)(uint8_t slave_id, float progress);

/// Device information returned by `stark_get_device_info`.
/// Contains device identification and version information.
/// Call `free_device_info` to release memory.
struct CDeviceInfo {
  /// Device SKU (hand side: left/right) (Deprecated, use hand_type instead)
  SkuType sku_type;
  /// Device hand type (left/right)
  HandType hand_type;
  /// Hardware type (device generation and capabilities)
  StarkHardwareType hardware_type;
  /// Serial number string (null-terminated)
  const char *serial_number;
  /// Firmware version string (null-terminated)
  const char *firmware_version;
  /// Hardware version string (reserved; empty for current devices)
  const char *hardware_version;
};

/// Raw capacitance data from touch sensors.
/// Contains raw ADC values for each sensor channel.
/// Call `free_touch_raw_data` to release.
struct CTouchRawData {
  /// Thumb sensor channels (7 channels)
  uint32_t thumb[7];
  /// Index finger sensor channels (11 channels)
  uint32_t index[11];
  /// Middle finger sensor channels (11 channels)
  uint32_t middle[11];
  /// Ring finger sensor channels (11 channels)
  uint32_t ring[11];
  /// Pinky finger sensor channels (7 channels)
  uint32_t pinky[7];
};

/// Touch data for all 5 fingers.
/// Returned by `stark_get_touch_status`. Call `free_touch_finger_data` to release.
/// Array order: [Thumb, Index, Middle, Ring, Pinky]
struct CTouchFingerData {
  /// Touch data for each finger
  CTouchFingerItem items[5];
};

/// 3D force data for a single measurement point.
/// Fx, Fy are signed (-128 ~ +127), Fz is unsigned (0 ~ 255).
struct CForce3DPoint {
  int8_t fx;
  int8_t fy;
  uint16_t fz;
};

/// Force3D summary data for 4 fingers (no thumb).
/// Call `free_force3d_touch_summary` to release.
struct CForce3DTouchSummary {
  CForce3DPoint index;
  CForce3DPoint middle;
  CForce3DPoint ring;
  CForce3DPoint pinky;
};

/// Force3D array data for a single finger (31 measurement points).
/// Call `free_force3d_finger_array` to release.
struct CForce3DFingerArray {
  CForce3DPoint points[31];
  uint16_t count;
};

/// Turbo mode configuration.
/// Turbo mode enables continuous gripping force.
/// Call `free_turbo_config` to release.
struct CTurboConfig {
  /// Interval between turbo pulses in milliseconds
  uint16_t interval;
  /// Duration of each turbo pulse in milliseconds
  uint16_t duration;
};

/// LED information returned by `stark_get_led_info`.
/// Call `free_led_info` to release.
struct CLedInfo {
  /// Current LED color
  LedColor color;
  /// Current LED mode (blinking pattern)
  LedMode mode;
};

/// Button press event returned by `stark_get_button_event`.
/// Call `free_button_event` to release.
struct CButtonPressEvent {
  /// Event timestamp in milliseconds
  int32_t timestamp;
  /// Button identifier
  int32_t button_id;
  /// Press state (down/up)
  PressState press_state;
};

extern "C" {

/// Create a new motor status buffer
///
/// @param max_size Maximum buffer capacity (default 1000)
/// @return Pointer to CMotorStatusBuffer, or NULL on failure
CMotorStatusBuffer *motor_buffer_new(uintptr_t max_size);

/// Free a motor status buffer
///
/// @param buffer Pointer to CMotorStatusBuffer
void motor_buffer_free(CMotorStatusBuffer *buffer);

/// Get all motor status data from buffer
///
/// @param buffer Pointer to CMotorStatusBuffer
/// @param out_data Pointer to array to store data (caller must allocate, no need to free returned data)
/// @param max_count Maximum number of items to return (size of out_data array)
/// @param out_count Pointer to store the number of items actually returned
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffer. Caller is responsible for
///       allocating out_data array before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int motor_buffer_pop_all(CMotorStatusBuffer *buffer,
                         CMotorStatusData *out_data,
                         uintptr_t max_count,
                         uintptr_t *out_count);

/// Get the number of items in the buffer
///
/// @param buffer Pointer to CMotorStatusBuffer
/// @return Number of items, or 0 if buffer is NULL
uintptr_t motor_buffer_len(const CMotorStatusBuffer *buffer);

/// Check if buffer is empty
///
/// @param buffer Pointer to CMotorStatusBuffer
/// @return 1 if empty, 0 if not empty, -1 if buffer is NULL
int motor_buffer_is_empty(const CMotorStatusBuffer *buffer);

/// Clear all data from buffer
///
/// @param buffer Pointer to CMotorStatusBuffer
void motor_buffer_clear(CMotorStatusBuffer *buffer);

/// Create a new touch status buffer
///
/// @param max_size Maximum buffer capacity per finger (default 1000)
/// @return Pointer to CTouchStatusBuffer, or NULL on failure
CTouchStatusBuffer *touch_buffer_new(uintptr_t max_size);

/// Free a touch status buffer
///
/// @param buffer Pointer to CTouchStatusBuffer
void touch_buffer_free(CTouchStatusBuffer *buffer);

/// Get all touch data for all fingers
///
/// @param buffer Pointer to CTouchStatusBuffer
/// @param out_data Pointer to array of 5 arrays to store data (caller must allocate, no need to free returned data)
/// @param max_counts Pointer to array of 5 max sizes (capacity of each out_data array)
/// @param out_counts Pointer to array of 5 sizes to store actual counts per finger
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffers. Caller is responsible for
///       allocating out_data arrays before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int touch_buffer_pop_all(CTouchStatusBuffer *buffer,
                         CTouchFingerItem **out_data,
                         const uintptr_t *max_counts,
                         uintptr_t *out_counts);

/// Get touch data for a single finger
///
/// @param buffer Pointer to CTouchStatusBuffer
/// @param finger_index Finger index (0-4)
/// @param out_data Pointer to array to store data (caller must allocate, no need to free returned data)
/// @param max_count Maximum number of items to return (size of out_data array)
/// @param out_count Pointer to store the number of items actually returned
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffer. Caller is responsible for
///       allocating out_data array before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int touch_buffer_pop_finger(CTouchStatusBuffer *buffer,
                            uintptr_t finger_index,
                            CTouchFingerItem *out_data,
                            uintptr_t max_count,
                            uintptr_t *out_count);

/// Get buffer lengths for all fingers
///
/// @param buffer Pointer to CTouchStatusBuffer
/// @param out_lengths Pointer to array of 5 sizes
/// @return 0 on success, -1 on failure
int touch_buffer_len_all(const CTouchStatusBuffer *buffer, uintptr_t *out_lengths);

/// Clear all touch buffers
///
/// @param buffer Pointer to CTouchStatusBuffer
void touch_buffer_clear(CTouchStatusBuffer *buffer);

/// Create a new pressure summary buffer
///
/// @param max_size Maximum buffer capacity per finger (default 1000)
/// @return Pointer to CPressureSummaryBuffer, or NULL on failure
CPressureSummaryBuffer *pressure_summary_buffer_new(uintptr_t max_size);

/// Free a pressure summary buffer
///
/// @param buffer Pointer to CPressureSummaryBuffer
void pressure_summary_buffer_free(CPressureSummaryBuffer *buffer);

/// Get all pressure summary data for all fingers
///
/// @param buffer Pointer to CPressureSummaryBuffer
/// @param out_data Pointer to array of 6 arrays to store data (caller must allocate, no need to free returned data)
/// @param max_counts Pointer to array of 6 max sizes (capacity of each out_data array)
/// @param out_counts Pointer to array of 6 sizes to store actual counts per finger
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffers. Caller is responsible for
///       allocating out_data arrays before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int pressure_summary_buffer_pop_all(CPressureSummaryBuffer *buffer,
                                    uint16_t **out_data,
                                    const uintptr_t *max_counts,
                                    uintptr_t *out_counts);

/// Get pressure summary data for a single part (finger or palm)
///
/// @param buffer Pointer to CPressureSummaryBuffer
/// @param finger_index Part index (0-5: 0-4=fingers, 5=palm)
/// @param out_data Pointer to array to store data (caller must allocate, no need to free returned data)
/// @param max_count Maximum number of items to return (size of out_data array)
/// @param out_count Pointer to store the number of items actually returned
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffer. Caller is responsible for
///       allocating out_data array before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int pressure_summary_buffer_pop_finger(CPressureSummaryBuffer *buffer,
                                       uintptr_t finger_index,
                                       uint16_t *out_data,
                                       uintptr_t max_count,
                                       uintptr_t *out_count);

/// Clear all pressure summary buffers
///
/// @param buffer Pointer to CPressureSummaryBuffer
void pressure_summary_buffer_clear(CPressureSummaryBuffer *buffer);

/// Create a new pressure detailed buffer
///
/// @param max_size Maximum buffer capacity per finger (default 1000)
/// @return Pointer to CPressureDetailedBuffer, or NULL on failure
CPressureDetailedBuffer *pressure_detailed_buffer_new(uintptr_t max_size);

/// Free a pressure detailed buffer
///
/// @param buffer Pointer to CPressureDetailedBuffer
void pressure_detailed_buffer_free(CPressureDetailedBuffer *buffer);

/// Get all pressure detailed data for all fingers
///
/// @param buffer Pointer to CPressureDetailedBuffer
/// @param out_data Pointer to array of 6 arrays to store data (caller must allocate, no need to free returned data)
/// @param max_counts Pointer to array of 6 max sizes (capacity of each out_data array)
/// @param out_counts Pointer to array of 6 sizes to store actual counts per finger
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffers. Caller is responsible for
///       allocating out_data arrays before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int pressure_detailed_buffer_pop_all(CPressureDetailedBuffer *buffer,
                                     PressureDetailedItem **out_data,
                                     const uintptr_t *max_counts,
                                     uintptr_t *out_counts);

/// Get pressure detailed data for a single part (finger or palm)
///
/// @param buffer Pointer to CPressureDetailedBuffer
/// @param finger_index Part index (0-5: 0-4=fingers, 5=palm)
/// @param out_data Pointer to array to store data (caller must allocate, no need to free returned data)
/// @param max_count Maximum number of items to return (size of out_data array)
/// @param out_count Pointer to store the number of items actually returned
/// @return 0 on success, -1 on failure
///
/// @note Data is copied to caller-allocated buffer. Caller is responsible for
///       allocating out_data array before calling, but does NOT need to free
///       the returned data (it's stack/heap memory owned by caller).
int pressure_detailed_buffer_pop_finger(CPressureDetailedBuffer *buffer,
                                        uintptr_t finger_index,
                                        PressureDetailedItem *out_data,
                                        uintptr_t max_count,
                                        uintptr_t *out_count);

/// Clear all pressure detailed buffers
///
/// @param buffer Pointer to CPressureDetailedBuffer
void pressure_detailed_buffer_clear(CPressureDetailedBuffer *buffer);

CArrayPressureTouchItemBuffer *array_pressure_touch_buffer_new(uintptr_t max_size);

void array_pressure_touch_buffer_free(CArrayPressureTouchItemBuffer *buffer);

int array_pressure_touch_buffer_pop_all(CArrayPressureTouchItemBuffer *buffer,
                                        CArrayPressureTouchData *out_data,
                                        uintptr_t max_count);

uintptr_t array_pressure_touch_buffer_len(const CArrayPressureTouchItemBuffer *buffer);

void array_pressure_touch_buffer_clear(CArrayPressureTouchItemBuffer *buffer);

/// Create a new data collector - Basic version (motor only)
///
/// @param handle Device handler
/// @param motor_buffer Motor status buffer
/// @param slave_id Slave ID (default 1)
/// @param motor_frequency Motor sampling frequency in Hz (default 1000)
/// @param enable_stats Whether to print statistics (1=true, 0=false)
/// @return Pointer to CDataCollector, or NULL on failure
CDataCollector *data_collector_new_basic(DeviceHandler *handle,
                                         CMotorStatusBuffer *motor_buffer,
                                         unsigned char slave_id,
                                         uint32_t motor_frequency,
                                         int enable_stats);

/// Create a new data collector - Capacitive touch version
///
/// @param handle Device handler
/// @param motor_buffer Motor status buffer
/// @param touch_buffer Touch status buffer
/// @param slave_id Slave ID (default 1)
/// @param motor_frequency Motor sampling frequency in Hz (default 1000)
/// @param touch_frequency Touch sampling frequency in Hz (default 100)
/// @param enable_stats Whether to print statistics (1=true, 0=false)
/// @return Pointer to CDataCollector, or NULL on failure
CDataCollector *data_collector_new_capacitive(DeviceHandler *handle,
                                              CMotorStatusBuffer *motor_buffer,
                                              CTouchStatusBuffer *touch_buffer,
                                              unsigned char slave_id,
                                              uint32_t motor_frequency,
                                              uint32_t touch_frequency,
                                              int enable_stats);

/// Create a new data collector - Pressure Summary version
///
/// @param handle Device handler
/// @param motor_buffer Motor status buffer
/// @param pressure_summary_buffer Pressure summary buffer
/// @param slave_id Slave ID (default 1)
/// @param motor_frequency Motor sampling frequency in Hz (default 1000)
/// @param touch_frequency Touch sampling frequency in Hz (default 100)
/// @param enable_stats Whether to print statistics (1=true, 0=false)
/// @return Pointer to CDataCollector, or NULL on failure
CDataCollector *data_collector_new_pressure_summary(DeviceHandler *handle,
                                                    CMotorStatusBuffer *motor_buffer,
                                                    CPressureSummaryBuffer *pressure_summary_buffer,
                                                    unsigned char slave_id,
                                                    uint32_t motor_frequency,
                                                    uint32_t touch_frequency,
                                                    int enable_stats);

/// Create a new data collector - Pressure Detailed version
///
/// @param handle Device handler
/// @param motor_buffer Motor status buffer
/// @param pressure_detailed_buffer Pressure detailed buffer
/// @param slave_id Slave ID (default 1)
/// @param motor_frequency Motor sampling frequency in Hz (default 1000)
/// @param touch_frequency Touch sampling frequency in Hz (default 10)
/// @param enable_stats Whether to print statistics (1=true, 0=false)
/// @return Pointer to CDataCollector, or NULL on failure
CDataCollector *data_collector_new_pressure_detailed(DeviceHandler *handle,
                                                     CMotorStatusBuffer *motor_buffer,
                                                     CPressureDetailedBuffer *pressure_detailed_buffer,
                                                     unsigned char slave_id,
                                                     uint32_t motor_frequency,
                                                     uint32_t touch_frequency,
                                                     int enable_stats);

/// Create a new data collector - Pressure Hybrid version (Summary + Detailed)
///
/// @param handle Device handler
/// @param motor_buffer Motor status buffer
/// @param pressure_summary_buffer Pressure summary buffer
/// @param pressure_detailed_buffer Pressure detailed buffer
/// @param slave_id Slave ID (default 1)
/// @param motor_frequency Motor sampling frequency in Hz (default 1000)
/// @param summary_frequency Summary sampling frequency in Hz (default 100)
/// @param detailed_frequency Detailed sampling frequency in Hz (default 10)
/// @param enable_stats Whether to print statistics (1=true, 0=false)
/// @return Pointer to CDataCollector, or NULL on failure
CDataCollector *data_collector_new_pressure_hybrid(DeviceHandler *handle,
                                                   CMotorStatusBuffer *motor_buffer,
                                                   CPressureSummaryBuffer *pressure_summary_buffer,
                                                   CPressureDetailedBuffer *pressure_detailed_buffer,
                                                   unsigned char slave_id,
                                                   uint32_t motor_frequency,
                                                   uint32_t summary_frequency,
                                                   uint32_t detailed_frequency,
                                                   int enable_stats);

/// Create a new data collector - ArrayPressure touch version
CDataCollector *data_collector_new_array_pressure(DeviceHandler *handle,
                                                  CMotorStatusBuffer *motor_buffer,
                                                  CArrayPressureTouchItemBuffer *touch_buffer,
                                                  unsigned char slave_id,
                                                  uint32_t motor_frequency,
                                                  uint32_t touch_frequency,
                                                  int enable_stats);

int data_collector_start(CDataCollector *collector);

int data_collector_stop(CDataCollector *collector);

int data_collector_wait(CDataCollector *collector);

int data_collector_is_running(const CDataCollector *collector);

void data_collector_free(CDataCollector *collector);

/// Initialize SDK logging.
/// log_level: Log level (Debug, Info, Warn, Error). Default is Info.
void init_logging(LogLevel log_level);

/// List all available Stark serial ports.
void list_available_ports();

/// Automatically detect a Stark device on a serial port.
/// It first tries Revo2 hands and then Revo1 hands.
/// port: Serial port name; when NULL, the function will auto‑detect ports.
/// quick: Whether to use quick detection. Default is true, which only checks
///        a subset of baudrates and slave IDs.
/// Returns a pointer to `DeviceConfig` (protocol, port, baudrate, slave ID);
/// call `free_device_config` to free the memory.
/// On failure, returns NULL.
/// Note: When `quick` is false, this function scans slave IDs in [1, 247],
///       which may take a long time.
///
/// @deprecated Use `stark_auto_detect` + `init_from_detected` instead for better
///             multi-protocol support (Modbus, CAN, CANFD).
CDeviceConfig *auto_detect_device(const char *port, bool quick);

/// Automatically detect a Revo1 hand over Modbus.
/// port: Serial port name; when NULL, the function will auto‑detect ports.
/// quick: Whether to use quick detection. Default is true, which only checks
///        a subset of baudrates and slave IDs.
/// Returns a pointer to `DeviceConfig` (protocol, port, baudrate, slave ID);
/// call `free_device_config` to free the memory.
/// On failure, returns NULL.
/// Note: When `quick` is false, this function scans slave IDs in [1, 247],
///       which may take a long time.
///
/// @deprecated Use `stark_auto_detect` + `init_from_detected` instead for better
///             multi-protocol support (Modbus, CAN, CANFD).
CDeviceConfig *auto_detect_modbus_revo1(const char *port, bool quick);

/// Automatically detect a Revo2 hand over Modbus.
/// port: Serial port name; when NULL, the function will auto‑detect ports.
/// quick: Whether to use quick detection. Default is true, which only checks
///        a subset of baudrates and slave IDs.
/// Returns a pointer to `DeviceConfig` (protocol, port, baudrate, slave ID);
/// call `free_device_config` to free the memory.
/// On failure, returns NULL.
/// Note: When `quick` is false, this function scans slave IDs in [1, 247],
///       which may take a long time.
///
/// @deprecated Use `stark_auto_detect` + `init_from_detected` instead for better
///             multi-protocol support (Modbus, CAN, CANFD).
CDeviceConfig *auto_detect_modbus_revo2(const char *port, bool quick);

/// Open a serial port.
/// port: Serial port name, for example "/dev/ttyUSB0" or "COM1".
/// baudrate: Baud rate, one of 115200, 57600, 19200, 460800.
///           Revo1 default is 115200; Revo2 default is 460800, and Revo2 also
///           supports 1M, 2M, 5M.
/// Returns a pointer to `DeviceHandler`; call `modbus_close` to free it.
/// On failure, returns NULL.
DeviceHandler *modbus_open(const char *port, uint32_t baudrate);

/// Close serial port
void modbus_close(DeviceHandler *handle);

/// Open a Protobuf protocol serial port.
///
/// Protobuf protocol uses default baudrate 115200 and default slave_id 10.
/// Position range is 0-100 (not 0-1000 like Modbus/CAN).
///
/// @param port Serial port name, for example "/dev/ttyUSB0" or "COM1".
/// @param slave_id Device slave ID (default is 10)
/// @param baudrate Baudrate (pass 0 to use default 115200)
/// @return Pointer to `DeviceHandler`; call `protobuf_close` to free it.
///         On failure, returns NULL.
DeviceHandler *protobuf_open(const char *port, uint8_t slave_id, uint32_t baudrate);

/// Close Protobuf serial port
void protobuf_close(DeviceHandler *handle);

/// @brief  Create a device handler with specified protocol and optional master ID.
/// @param protocol_type Protocol type (Modbus, CAN, CanFd, EtherCAT, Protobuf)
/// @param master_id Master ID (required for CanFd and EtherCAT, 0 for others)
/// @return Pointer to the newly created `DeviceHandler`. Call
///         `close_device_handler` to release it.
DeviceHandler *init_device_handler(StarkProtocolType protocol_type, uint8_t master_id);

/// @brief  Create a device handler for CAN/CANFD protocol.
///
/// This function creates a device handler and stores the CAN baudrate information.
///
/// @param protocol_type Protocol type (STARK_PROTOCOL_TYPE_CAN or STARK_PROTOCOL_TYPE_CAN_FD)
/// @param master_id Master ID (typically 1)
/// @param arb_baudrate Arbitration baudrate in bps (e.g., 1000000 for 1 Mbps)
/// @param data_baudrate Data baudrate in bps (for CANFD; equals arb_baudrate for CAN 2.0)
/// @return Pointer to the newly created `DeviceHandler`. Call
///         `close_device_handler` to release it.
DeviceHandler *init_device_handler_can(StarkProtocolType protocol_type,
                                       uint8_t master_id,
                                       uint32_t arb_baudrate,
                                       uint32_t data_baudrate);

/// @brief  Create a device handler for CAN/CANFD protocol with hardware type pre-set.
///
/// @param protocol_type Protocol type (STARK_PROTOCOL_TYPE_CAN or STARK_PROTOCOL_TYPE_CAN_FD)
/// @param master_id Master ID (typically 1)
/// @param slave_id Slave ID to set hardware type for
/// @param arb_baudrate Arbitration baudrate in bps (e.g., 1000000 for 1 Mbps)
/// @param data_baudrate Data baudrate in bps (for CANFD; equals arb_baudrate for CAN 2.0)
/// @param hw_type Hardware type (StarkHardwareType enum value)
/// @return Pointer to the newly created `DeviceHandler`. Call
///         `close_device_handler` to release it.
DeviceHandler *init_device_handler_can_with_hw_type(StarkProtocolType protocol_type,
                                                    uint8_t master_id,
                                                    uint8_t slave_id,
                                                    uint32_t arb_baudrate,
                                                    uint32_t data_baudrate,
                                                    StarkHardwareType hw_type);

/// @brief  Create a device handler with hardware type pre-set.
///
/// This is useful when you already know the hardware type (e.g., from auto_detect)
/// and want to avoid an extra get_device_info call.
///
/// @param protocol_type Protocol type (Modbus, CAN, CanFd, EtherCAT, Protobuf)
/// @param master_id Master ID (required for CanFd and EtherCAT, 0 for others)
/// @param slave_id Slave ID to set hardware type for
/// @param hw_type Hardware type (StarkHardwareType enum value)
/// @return Pointer to the newly created `DeviceHandler`. Call
///         `close_device_handler` to release it.
DeviceHandler *init_device_handler_with_hw_type(StarkProtocolType protocol_type,
                                                uint8_t master_id,
                                                uint8_t slave_id,
                                                StarkHardwareType hw_type);

/// List all ZQWL USB CAN/CANFD devices
///
/// Returns device list pointer. Call `free_zqwl_device_list` to free memory after use.
/// Returns list with count=0 if no devices found.
///
/// @note This is a low-level API. Recommend using high-level API `stark_auto_detect` + `init_from_detected`
///       for automatic device detection and initialization. Low-level API is for advanced users
///       who need manual control of CAN adapter.
ZqwlDeviceList *list_zqwl_devices();

/// Free ZQWL device list memory
void free_zqwl_device_list(ZqwlDeviceList *list);

/// Initialize ZQWL CAN device (CAN 2.0 mode)
///
/// For Revo1 devices, baudrate is typically 1Mbps
///
/// @param port_name Serial port name, e.g. "/dev/cu.usbmodem*" (macOS) or "COM3" (Windows)
/// @param arb_baudrate Arbitration baudrate (bps), typically 1000000
/// @return 0: success, -1: failure
///
/// @note This is a low-level API. Recommend using high-level API `stark_auto_detect` + `init_from_detected`
///       for automatic device detection and initialization. Low-level API is for advanced users
///       who need manual control of CAN adapter.
int init_zqwl_can(const char *port_name,
                  uint32_t arb_baudrate);

/// Initialize ZQWL CANFD device
///
/// For Revo2 devices, arbitration baudrate is typically 1Mbps, data baudrate is typically 5Mbps
///
/// @param port_name Serial port name
/// @param arb_baudrate Arbitration baudrate (bps), typically 1000000
/// @param data_baudrate Data baudrate (bps), typically 5000000
/// @return 0: success, -1: failure
///
/// @note This is a low-level API. Recommend using high-level API `stark_auto_detect` + `init_from_detected`
///       for automatic device detection and initialization. Low-level API is for advanced users
///       who need manual control of CAN adapter.
int init_zqwl_canfd(const char *port_name,
                    uint32_t arb_baudrate,
                    uint32_t data_baudrate);

/// Close ZQWL CAN/CANFD device
///
/// @note This is a low-level API. If device was initialized with `init_from_detected`,
///       use `close_device_handler` instead, which automatically handles ZQWL resource cleanup.
void close_zqwl();

/// List all SocketCAN interfaces (Linux only)
///
/// Scans /sys/class/net/ for CAN interfaces.
/// Returns device list pointer. Call `free_socketcan_device_list` to free memory.
/// Returns list with count=0 on non-Linux platforms or if no interfaces found.
SocketCanDeviceList *list_socketcan_devices();

/// Free SocketCAN device list memory
void free_socketcan_device_list(SocketCanDeviceList *list);

/// Initialize SocketCAN CAN 2.0 device (Linux only)
///
/// @param iface Interface name (e.g. "can0"). If NULL, uses STARK_SOCKETCAN_IFACE env var or "can0"
/// @return 0: success, -1: failure (or non-Linux platform)
int init_socketcan_can(const char *iface);

/// Initialize SocketCAN CANFD device (Linux only)
///
/// @param iface Interface name (e.g. "can0"). If NULL, uses STARK_SOCKETCAN_IFACE env var or "can0"
/// @return 0: success, -1: failure (or non-Linux platform)
int init_socketcan_canfd(const char *iface);

/// Close SocketCAN device (Linux only)
void close_socketcan();

/// Check if a SocketCAN interface is available and up (Linux only)
///
/// @param iface Interface name (e.g. "can0")
/// @return true if interface exists and is up, false otherwise
bool is_socketcan_available(const char *iface);

/// Scan CAN bus for devices (simple version)
///
/// Uses get_can_params to read SkuType for device detection
///
/// @param candidate_ids Pointer to array of candidate device IDs
/// @param candidate_count Number of candidate device IDs
/// @param timeout_ms Timeout in milliseconds
/// @return Found device ID (1-255), or 0 if no device found
uint8_t scan_can_devices(const uint8_t *candidate_ids,
                         uintptr_t candidate_count,
                         uint64_t timeout_ms);

/// Auto-detect Stark devices across all protocols
///
/// Scans for devices in priority order:
/// 1. ZQWL CANFD (IDs 0x7E, 0x7F) → CAN 2.0 (IDs 1, 2) (USB CDC, cross-platform)
/// 2. SocketCAN CANFD (IDs 0x7E, 0x7F) → CAN 2.0 (IDs 1, 2) (Linux only)
/// 3. Modbus/RS485 (IDs 0x7E, 0x7F, 1, 2 at 460800/115200/1Mbps/2Mbps)
/// 4. Protobuf (legacy RS485, ID 10, 115200 baud)
///
/// When a specific protocol is requested, only that protocol is scanned.
///
/// # Parameters
/// - scan_all: If true, scan for all devices. If false, stop at first found.
/// - port: Optional port name to scan. If NULL, scans all available ports.
/// - protocol: Protocol filter:
///   - STARK_PROTOCOL_TYPE_AUTO: Auto-detect all protocols (recommended)
///   - STARK_PROTOCOL_TYPE_MODBUS: Modbus only
///   - STARK_PROTOCOL_TYPE_CAN: CAN 2.0 only
///   - STARK_PROTOCOL_TYPE_CAN_FD: CANFD only
///   - STARK_PROTOCOL_TYPE_PROTOBUF: Protobuf only
///
/// # Returns
/// Pointer to CDetectedDeviceList. Call `free_detected_device_list` to free.
/// Returns empty list (count=0) if no devices found.
CDetectedDeviceList *stark_auto_detect(bool scan_all, const char *port, StarkProtocolType protocol);

/// Free detected device list memory
void free_detected_device_list(CDetectedDeviceList *list);

/// Initialize device handler from detected device info.
///
/// This function initializes the appropriate transport (Modbus, CAN, CANFD)
/// based on the detected device's protocol and returns a ready-to-use handler.
///
/// # Parameters
/// - device: Pointer to CDetectedDevice from stark_auto_detect()
///
/// # Returns
/// - Pointer to DeviceHandler on success
/// - NULL on failure
///
/// # Notes
/// - For CAN/CANFD: Initializes BrainCo/ZQWL/SocketCAN adapter automatically
/// - For Modbus: Opens serial port with detected baudrate
/// - Call `close_from_detected` to cleanup
DeviceHandler *init_from_detected(const CDetectedDevice *device);

/// Close device handler based on protocol type.
///
/// Convenience function that handles cleanup for any protocol type.
/// Automatically closes ZQWL adapter for CAN/CANFD protocols.
///
/// # Parameters
/// - handle: Device handler to close
/// - protocol: Protocol type (from CDetectedDevice.protocol)
void close_device_handler(DeviceHandler *handle, uint8_t protocol);

/// Configure SDO for an EtherCAT slave device.
void ethercat_setup_sdo(DeviceHandler *handle, uint16_t slave_pos);

void ethercat_reserve_master(DeviceHandler *handle);

/// Start EtherCAT cyclic loop with PDO communication (control & read).
/// dc_assign_activate: DC flags; 0x0000 means DC is not enabled.
/// sync0_cycle_time: SYNC0 cycle time in nanoseconds. The loop period matches
///                   SYNC0 cycle time.
/// sync0_shift_time: SYNC0 phase shift in nanoseconds.
/// sync1_cycle_time: SYNC1 cycle time in nanoseconds.
/// sync1_shift_time: SYNC1 phase shift in nanoseconds.
void ethercat_start_loop(DeviceHandler *handle,
                         const uint16_t *slave_positions,
                         int count,
                         uint16_t dc_assign_activate,
                         uint32_t sync0_cycle_time,
                         int32_t sync0_shift_time,
                         uint32_t sync1_cycle_time,
                         int32_t sync1_shift_time);

/// Stop the EtherCAT cyclic loop.
void ethercat_stop_loop(DeviceHandler *handle);

/// EtherCAT DFU: upgrade firmware via FoE protocol.
/// slave_pos: Slave position.
/// dfu_type: DFU type, Control or Wrist.
/// file_path: Firmware file path.
void ethercat_start_dfu(DeviceHandler *handle,
                        uint16_t slave_pos,
                        EtherCATFoeType dfu_type,
                        const char *file_path);

/// Set Modbus async read/write callback.
void set_modbus_operation_callback(ModbusOperationCallback cb);

/// Set Modbus read callback for input registers.
void set_modbus_read_input_callback(ModbusRxCallback cb);

/// Set Modbus read callback for holding registers.
void set_modbus_read_holding_callback(ModbusRxCallback cb);

/// Set Modbus write callback.
void set_modbus_write_callback(ModbusTxCallback cb);

/// Set CAN/CANFD RX callback.
void set_can_rx_callback(CanRxCallback cb);

/// Set CAN/CANFD TX callback.
void set_can_tx_callback(CanTxCallback cb);

/// Set DFU state callback.
void set_dfu_state_callback(DfuStateCallback cb);

/// Set DFU progress callback.
void set_dfu_progress_callback(DfuProgressCallback cb);

/// Get device information.
/// Returns a pointer to `DeviceInfo`; you must call `free_device_info` to free
/// it. Returns NULL on failure.
///
/// NOTE: Hardware type is determined by SN prefix. If the SN is not recognized,
/// hardware_type defaults to Revo2Basic. Use `stark_set_hardware_type()` to
/// manually override if needed.
CDeviceInfo *stark_get_device_info(DeviceHandler *handle, uint8_t slave_id);

/// Set hardware type for a specific slave device.
///
/// Use this to manually override the hardware type when SN-based auto-detection
/// in `stark_get_device_info()` returns an incorrect result (e.g. device SN not
/// yet programmed, defaults to Revo2Basic).
///
/// Can also be used to modify `CDetectedDevice.hardware_type` before calling
/// `init_from_detected()`, or to override after initialization.
///
/// # Parameters
/// - handle: Device handler
/// - slave_id: The slave ID
/// - hw_type: StarkHardwareType enum value
void stark_set_hardware_type(DeviceHandler *handle, uint8_t slave_id, StarkHardwareType hw_type);

/// Read holding registers (fast, no retry).
/// address: Start register address.
/// count: Number of registers to read.
/// out_data: Pointer to array to store data (caller must allocate enough space).
/// Returns 0 on success, -1 on failure.
int32_t stark_read_holding_registers(DeviceHandler *handle,
                                     uint8_t slave_id,
                                     uint16_t address,
                                     uint16_t count,
                                     uint16_t *out_data);

/// Read input registers (fast, no retry).
/// address: Start register address.
/// count: Number of registers to read.
/// out_data: Pointer to array to store data (caller must allocate enough space).
/// Returns 0 on success, -1 on failure.
int32_t stark_read_input_registers(DeviceHandler *handle,
                                   uint8_t slave_id,
                                   uint16_t address,
                                   uint16_t count,
                                   uint16_t *out_data);

/// Get the protocol type of the device handler.
/// Returns: StarkProtocolType enum value:
///   - STARK_PROTOCOL_TYPE_MODBUS = 1
///   - STARK_PROTOCOL_TYPE_CAN = 2
///   - STARK_PROTOCOL_TYPE_CAN_FD = 3
///   - STARK_PROTOCOL_TYPE_ETHER_CAT = 4
///   - STARK_PROTOCOL_TYPE_PROTOBUF = 5
StarkProtocolType stark_get_protocol_type(DeviceHandler *handle);

/// Get the serial port name of the device handler.
/// Returns: Port name string (e.g., "/dev/ttyUSB0" or "COM3"), or NULL if not available.
/// The returned string is owned by the DeviceHandler and should not be freed.
/// For CAN/CANFD protocols, this may return an empty string.
const char *stark_get_port_name(DeviceHandler *handle);

/// Get the baudrate of the device handler.
/// Returns: Baudrate in bps (e.g., 115200, 460800), or 0 if not applicable.
/// For Modbus/Protobuf: returns serial baudrate
/// For CAN/CANFD/EtherCAT: returns 0 (use stark_get_can_arb_baudrate/stark_get_can_data_baudrate instead)
///
/// Note: This function only returns serial port baudrate.
/// For CAN baudrate information, use:
///   - stark_get_can_arb_baudrate() - Get CAN arbitration baudrate
///   - stark_get_can_data_baudrate() - Get CAN data baudrate (CANFD only)
uint32_t stark_get_baudrate(DeviceHandler *handle);

/// Get the CAN arbitration baudrate.
/// Returns: Arbitration baudrate in bps (e.g., 1000000 for 1 Mbps), or 0 if not CAN/CANFD protocol.
/// For CAN 2.0: This is the only baudrate
/// For CANFD: This is the arbitration phase baudrate
uint32_t stark_get_can_arb_baudrate(DeviceHandler *handle);

/// Get the CAN data baudrate.
/// Returns: Data baudrate in bps (e.g., 5000000 for 5 Mbps), or 0 if not CANFD protocol.
/// For CAN 2.0: Returns the same as arbitration baudrate
/// For CANFD: Returns the data phase baudrate
uint32_t stark_get_can_data_baudrate(DeviceHandler *handle);

/// Get touch sensor vendor type by reading register 970.
/// Returns: 0=Unknown, 1=Capacitive, 2=Pressure
/// This should be called for Revo2 Touch devices to determine the actual touch sensor type.
uint8_t stark_get_touch_vendor(DeviceHandler *handle, uint8_t slave_id);

/// Set force level (only supported on Revo1 Basic).
///
/// @deprecated This function is deprecated and only works on Revo1 Basic devices.
/// Use `stark_set_finger_current` or `stark_set_finger_currents` instead for
/// more precise force control on all device types.
void stark_set_force_level(DeviceHandler *handle, uint8_t slave_id, ForceLevel level);

/// Get force level (only supported on Revo1 Basic).
///
/// @deprecated This function is deprecated and only works on Revo1 Basic devices.
/// Use `stark_get_motor_status` instead to get current values for all device types.
uint8_t stark_get_force_level(DeviceHandler *handle, uint8_t slave_id);

/// Get device supply voltage in mV.
uint16_t stark_get_voltage(DeviceHandler *handle, uint8_t slave_id);

/// Get LED enabled state.
bool get_led_enabled(DeviceHandler *handle, uint8_t slave_id);

/// Get buzzer enabled state.
bool get_buzzer_enabled(DeviceHandler *handle, uint8_t slave_id);

/// Get vibration enabled state.
bool get_vibration_enabled(DeviceHandler *handle, uint8_t slave_id);

/// Set LED enabled state.
void set_led_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);

/// Set buzzer enabled state.
void set_buzzer_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);

/// Set vibration enabled state.
void set_vibration_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);

/// Configure unit mode and finger parameters for Revo2.
/// This setting is reset after power‑cycle.
/// Parameter ranges are documented here:
/// https://brainco.yuque.com/tykrbo/hws0nr/pynh5qnmfa1bgamc
/// Sets the control unit mode:
/// normalized mode or physical‑quantity mode.
void stark_set_finger_unit_mode(DeviceHandler *handle, uint8_t slave_id, FingerUnitMode mode);

/// Get the current control unit mode.
/// Returns `FingerUnitMode`; on failure returns `FingerUnitMode::Normalized`.
FingerUnitMode stark_get_finger_unit_mode(DeviceHandler *handle, uint8_t slave_id);

/// Set maximum angle for a finger.
/// max_pos: Maximum angle value; default is 60 87 84 84 84 84.
void stark_set_finger_max_position(DeviceHandler *handle,
                                   uint8_t slave_id,
                                   StarkFingerId finger_id,
                                   uint16_t max_pos);

/// Set minimum angle for a finger.
/// min_pos: Minimum angle in degrees; default is 0 0 0 0 0 0.
void stark_set_finger_min_position(DeviceHandler *handle,
                                   uint8_t slave_id,
                                   StarkFingerId finger_id,
                                   uint16_t min_pos);

/// Set maximum speed for a finger.
/// max_speed: Maximum speed in °/s; default is 145 150 130 130 130 130.
void stark_set_finger_max_speed(DeviceHandler *handle,
                                uint8_t slave_id,
                                StarkFingerId finger_id,
                                uint16_t max_speed);

/// Set maximum current for a finger.
/// max_current: Maximum current in mA; default is 1000.
void stark_set_finger_max_current(DeviceHandler *handle,
                                  uint8_t slave_id,
                                  StarkFingerId finger_id,
                                  uint16_t max_current);

/// Set protection current for a finger.
/// protected_current: Protection current in mA, range 100~1500, default
///                    500 500 500 500 500 500.
void stark_set_finger_protected_current(DeviceHandler *handle,
                                        uint8_t slave_id,
                                        StarkFingerId finger_id,
                                        uint16_t protected_current);

/// Read maximum angle for a finger.
/// Returns 0 on failure.
uint16_t stark_get_finger_max_position(DeviceHandler *handle,
                                       uint8_t slave_id,
                                       StarkFingerId finger_id);

/// Read minimum angle for a finger.
/// min_pos: Minimum angle in degrees; default is 0 0 0 0 0 0.
uint16_t stark_get_finger_min_position(DeviceHandler *handle,
                                       uint8_t slave_id,
                                       StarkFingerId finger_id);

/// Read maximum speed for a finger.
/// max_speed: Maximum speed in °/s; default is 145 150 130 130 130 130.
/// Returns 0 on failure.
uint16_t stark_get_finger_max_speed(DeviceHandler *handle,
                                    uint8_t slave_id,
                                    StarkFingerId finger_id);

/// Read maximum current for a finger.
/// max_current: Maximum current in mA; default is 1000.
/// Returns 0 on failure.
uint16_t stark_get_finger_max_current(DeviceHandler *handle,
                                      uint8_t slave_id,
                                      StarkFingerId finger_id);

/// Read protection current for a finger.
/// protected_current: Protection current in mA, range 100~1500, default
///                    500 500 500 500 500 500.
/// Returns 0 on failure.
uint16_t stark_get_finger_protected_current(DeviceHandler *handle,
                                            uint8_t slave_id,
                                            StarkFingerId finger_id);

/// Configure thumb AUX lock current.
/// aux_lock_current: in mA, range 100~500, default 200.
/// Only supported on Revo2.
void stark_set_thumb_aux_lock_current(DeviceHandler *handle,
                                      uint8_t slave_id,
                                      uint16_t aux_lock_current);

/// Read thumb AUX lock current.
/// Only supported on Revo2.
uint16_t stark_get_thumb_aux_lock_current(DeviceHandler *handle, uint8_t slave_id);

/// Set the position of a single finger.
///
/// # Parameters
/// - `position`: Position in the unified range **0~1000** (all devices,
///   all protocols).
///   - The SDK converts this internally based on device type and protocol.
///   - 0 means fully open, 1000 means fully closed.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the public
/// API always uses the 0~1000 range; the SDK handles conversion internally.
void stark_set_finger_position(DeviceHandler *handle,
                               uint8_t slave_id,
                               StarkFingerId finger_id,
                               uint16_t position);

/// Set the speed of a single finger.
///
/// # Parameters
/// - `speed`: Speed in the unified range **-1000~+1000** (all devices,
///   all protocols).
///   - The SDK converts this internally based on device type and protocol.
///   - Positive: closing direction; negative: opening direction.
///   - 0: stop.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the public
/// API always uses the -1000~+1000 range; the SDK handles conversion internally.
void stark_set_finger_speed(DeviceHandler *handle,
                            uint8_t slave_id,
                            StarkFingerId finger_id,
                            int16_t speed);

/// Set the current of a single finger.
///
/// # Parameters
/// - `current`: Current in the unified range **-1000~+1000** (all devices,
///   all protocols).
///   - The SDK converts this internally based on device type and protocol.
///   - Positive: closing direction; negative: opening direction.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the public
/// API always uses the -1000~+1000 range; the SDK handles conversion internally.
void stark_set_finger_current(DeviceHandler *handle,
                              uint8_t slave_id,
                              StarkFingerId finger_id,
                              int16_t current);

/// Set the PWM of a single finger (Revo2 only).
///
/// # Parameters
/// - `pwm`: PWM value in the unified range **-1000~+1000** (all protocols).
///   - The SDK converts this internally based on protocol.
///   - Positive: closing direction; negative: opening direction.
///
/// # Unified range
/// For Modbus, CAN 2.0, and CANFD, the public API always uses the
/// -1000~+1000 range; the SDK handles conversion internally.
void stark_set_finger_pwm(DeviceHandler *handle,
                          uint8_t slave_id,
                          StarkFingerId finger_id,
                          int16_t pwm);

/// Set position + desired time for a single finger (Revo2 only).
///
/// # Parameters
/// - `position`: Position in the unified range **0~1000** (all protocols).
/// - `millis`: Desired time in milliseconds, range 1~2000.
///
/// # Unified range
/// Position always uses the 0~1000 range; the SDK handles conversion internally.
void stark_set_finger_position_with_millis(DeviceHandler *handle,
                                           uint8_t slave_id,
                                           StarkFingerId finger_id,
                                           uint16_t position,
                                           uint16_t millis);

/// Set position + desired speed for a single finger (Revo2 only).
///
/// # Parameters
/// - `position`: Position in the unified range **0~1000** (all protocols).
/// - `speed`: Speed value, range 1~1000.
///
/// # Unified range
/// Position always uses the 0~1000 range; the SDK handles conversion internally.
void stark_set_finger_position_with_speed(DeviceHandler *handle,
                                          uint8_t slave_id,
                                          StarkFingerId finger_id,
                                          uint16_t position,
                                          uint16_t speed);

/// Set positions for multiple fingers.
///
/// # Parameters
/// - `positions`: Array of length 6, positions in the unified range
///   **0~1000** (all devices, all protocols).
///   - The SDK converts this internally based on device type and protocol.
///   - 0 means fully open, 1000 means fully closed.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the public
/// API always uses the 0~1000 range; the SDK handles conversion internally.
void stark_set_finger_positions(DeviceHandler *handle,
                                uint8_t slave_id,
                                const uint16_t *positions,
                                uintptr_t len);

/// Set speeds for multiple fingers.
///
/// # Parameters
/// - `speeds`: Array of length 6, speeds in the unified range **-1000~+1000**
///   (all devices, all protocols).
///   - The SDK converts this internally based on device type and protocol.
///   - Positive: closing direction; negative: opening direction.
///   - 0: stop.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the public
/// API always uses the -1000~+1000 range; the SDK handles conversion internally.
void stark_set_finger_speeds(DeviceHandler *handle,
                             uint8_t slave_id,
                             const int16_t *speeds,
                             uintptr_t len);

/// Set currents for multiple fingers.
///
/// # Parameters
/// - `currents`: Array of length 6, currents in the unified range
///   **-1000~+1000** (all devices, all protocols).
///   - The SDK converts this internally based on device type and protocol.
///   - Positive: closing direction; negative: opening direction.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the public
/// API always uses the -1000~+1000 range; the SDK handles conversion internally.
void stark_set_finger_currents(DeviceHandler *handle,
                               uint8_t slave_id,
                               const int16_t *currents,
                               uintptr_t len);

/// Set PWM values for multiple fingers (Revo2 only).
///
/// # Parameters
/// - `pwms`: Array of length 6, PWM values in the unified range
///   **-1000~+1000** (all protocols).
///   - The SDK converts this internally based on protocol.
///   - Positive: closing direction; negative: opening direction.
///
/// # Unified range
/// For Modbus, CAN 2.0, and CANFD, the public API always uses the
/// -1000~+1000 range; the SDK handles conversion internally.
void stark_set_finger_pwms(DeviceHandler *handle,
                           uint8_t slave_id,
                           const int16_t *pwms,
                           uintptr_t len);

/// Set positions + desired times for multiple fingers (Revo2 only).
///
/// # Parameters
/// - `positions`: Array of length 6, positions in the unified range
///   **0~1000** (all protocols).
/// - `millis`: Array of length 6, desired times in milliseconds, range 1~2000.
///
/// # Unified range
/// Position always uses the 0~1000 range; the SDK handles conversion internally.
void stark_set_finger_positions_and_durations(DeviceHandler *handle,
                                              uint8_t slave_id,
                                              const uint16_t *positions,
                                              const uint16_t *millis,
                                              uintptr_t len);

/// Set positions + desired speeds for multiple fingers (Revo2 only).
///
/// # Parameters
/// - `positions`: Array of length 6, positions in the unified range
///   **0~1000** (all protocols).
/// - `speeds`: Array of length 6, speeds in the range 1~1000.
///
/// # Unified range
/// Position always uses the 0~1000 range; the SDK handles conversion internally.
void stark_set_finger_positions_and_speeds(DeviceHandler *handle,
                                           uint8_t slave_id,
                                           const uint16_t *positions,
                                           const uint16_t *speeds,
                                           uintptr_t len);

/// Get finger motor status.
///
/// # Return value
/// Returns a pointer to `MotorStatusData`, which contains:
/// - `positions`: Position array, unified range **0~1000** (all devices,
///   all protocols).
/// - `speeds`: Speed array, unified range **-1000~+1000** (all devices,
///   all protocols).
/// - `currents`: Current array, unified range **-1000~+1000** (all devices,
///   all protocols).
/// - `states`: Motor state array.
///
/// # Unified range
/// For both Revo1 and Revo2, and for Modbus, CAN 2.0, and CANFD, the returned
/// data is always converted to the unified ranges above; the SDK handles
/// conversion internally.
///
/// # Memory management
/// You must call `free_motor_status_data` to free the result.
/// Returns NULL on failure.
CMotorStatusData *stark_get_motor_status(DeviceHandler *handle, uint8_t slave_id);

/// Run an action sequence.
/// action_id: Action sequence ID.
void stark_run_action_sequence(DeviceHandler *handle, uint8_t slave_id, ActionSequenceId action_id);

/// Transfer action sequences to the device.
///
/// This function sends multiple action sequences. Each sequence is represented
/// by a fixed‑length array of `u16` parameters.
///
/// - `slave_id`: Slave device ID.
/// - `uses_revo2_motor_api`: Whether the device uses Revo2 Motor API.
///   (Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API)
/// - `action_id`: ID that uniquely identifies the action sequence.
/// - `sequences`: Flattened parameter array containing multiple sequences.
///
/// For Revo1, each action sequence contains 20 `u16` elements:
///   - Sequence index (u16): index of the sequence in the queue.
///   - Duration (u16): execution time in milliseconds.
///   - Finger positions (6 × u16): values in range 0~100.
///   - Finger speeds   (6 × u16): values in range 0~100.
///   - Finger forces   (6 × u16): values in range 0~100.
///
/// Example sequence array:
/// [0, 2000, 0, 0, 100, 100, 100, 100, 10, 20, 30, 40, 50, 60, 5, 10, 15, 20, 25, 30]
///
/// Meaning:
/// - `0`: sequence index.
/// - `2000`: duration in milliseconds.
/// - `0, 0, 100, 100, 100, 100`: 6 finger positions.
/// - `10, 20, 30, 40, 50, 60`: 6 finger speeds.
/// - `5, 10, 15, 20, 25, 30`: 6 finger forces.
///
/// For Revo2, each action sequence contains 27 `u16` elements:
///   - Sequence index (u16): index of the sequence in the queue.
///   - Duration (u16): execution time in milliseconds.
///   - Control mode (u16): 1=position+time, 2=position+speed,
///     3=current, 4=speed.
///   - Finger positions (6 × u16): physical angle in degrees; 65535 (0xFFFF)
///     means keep current angle.
///   - Finger speeds   (6 × u16): physical rotational speed in °/s.
///   - Finger currents (6 × u16): physical current in mA.
///
/// - `len`: Number of sequences, i.e. number of rows in the flattened array.
///
/// # Parameters
/// - `action_id`: Action sequence ID.
/// - `sequences`: Pointer to the flattened sequence array.
/// - `len`: Number of sequences.
///
/// # Error handling
/// - If `handle` or `sequences` is NULL, the function returns immediately.
/// - If `len` exceeds the maximum allowed steps (Revo1: 32, Revo2: 8), a
///   warning is logged and the function returns.
void stark_set_action_sequence(DeviceHandler *handle,
                               uint8_t slave_id,
                               bool uses_revo2_motor_api,
                               ActionSequenceId action_id,
                               const uint16_t *sequences,
                               uintptr_t len);

/// Enable tactile sensors.
/// bits: Bitmask of sensors to enable, range 0~31.
/// For example: 0b00000001 enables only the thumb sensor.
void stark_enable_touch_sensor(DeviceHandler *handle, uint8_t slave_id, uint8_t bits);

/// Get raw channel data from the tactile sensors.
/// Returns a pointer to `TouchRawData`; call `free_touch_raw_data` to free it.
/// Returns NULL on failure.
CTouchRawData *stark_get_touch_raw_data(DeviceHandler *handle, uint8_t slave_id);

/// Read 3D force, proximity and status for a single finger.
/// Returns a pointer to `TouchFingerItem`.
/// index: 0~4 for thumb, index, middle, ring, pinky.
/// Call `free_touch_finger_item` to free the result. Returns NULL on failure.
CTouchFingerItem *stark_get_single_touch_status(DeviceHandler *handle,
                                                uint8_t slave_id,
                                                uint8_t index);

/// Read 3D force, proximity and status for all five fingers.
/// Returns a pointer to `TouchFingerData` containing all fingers.
/// Call `free_touch_finger_data` to free the result. Returns NULL on failure.
CTouchFingerData *stark_get_touch_status(DeviceHandler *handle, uint8_t slave_id);

/// Reset tactile sensor measurement channels.
/// Try to keep the fingers unloaded (no force) when executing this command.
/// bits: Bitmask of sensors to reset, range 0~31.
/// For example: 0b00000001 resets the first sensor.
void stark_reset_touch_sensor(DeviceHandler *handle, uint8_t slave_id, uint8_t bits);

/// Get touch sensor type from hardware type.
/// Returns: 0=None, 1=Capacitive, 2=Pressure
/// This is a pure function based on hardware type classification.
uint8_t stark_get_touch_sensor_type(uint8_t hw_type);

/// Check if hardware type has touch sensor.
/// Returns: true if device has touch sensor, false otherwise.
bool stark_is_touch_device(uint8_t hw_type);

/// Check if hardware type is Revo1 device (motor API perspective).
/// Check if hardware type uses Revo1 Motor API.
/// Revo1 Basic/Touch use Revo1 Motor API.
/// Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
/// Note: Revo1Protobuf is legacy firmware, also uses Revo1 Motor API.
/// Returns: true if uses Revo1 Motor API, false if uses Revo2 Motor API.
bool stark_uses_revo1_motor_api(uint8_t hw_type);

/// Check if hardware type uses Revo1 Touch API.
/// Revo1 Touch API has different sensor counts per finger (capacitive).
/// Returns: true if uses Revo1 Touch API, false otherwise.
bool stark_uses_revo1_touch_api(uint8_t hw_type);

/// Calibrate tactile sensor parameters.
/// bits: Bitmask of sensors to calibrate, range 0~31.
/// For example: 0b00000001 calibrates the first sensor.
/// Use this when 3D force values are non‑zero in idle state.
/// https://www.brainco-hz.com/docs/revolimb-hand/protocol/stark_protocol_touch.html#_5-3-%E5%8F%82%E6%95%B0%E6%A0%A1%E5%87%864105
void stark_calibrate_touch_sensor(DeviceHandler *handle,
                                  uint8_t slave_id,
                                  uint8_t bits);

/// Check if hardware type uses Revo2 Touch API.
/// Revo2 Touch API has uniform sensor counts per finger (capacitive).
/// Returns: true if uses Revo2 Touch API, false otherwise.
bool stark_uses_revo2_touch_api(uint8_t hw_type);

/// Check if hardware type uses Pressure/Modulus Touch API.
/// Pressure Touch API uses completely different data structure (pressure sensors).
/// Returns: true if uses Pressure Touch API, false otherwise.
bool stark_uses_pressure_touch_api(uint8_t hw_type);

/// Get RS485 serial baud rate.
/// Valid values: 115200, 57600, 19200, 460800.
uint32_t stark_get_rs485_baudrate(DeviceHandler *handle, uint8_t slave_id);

/// Set RS485 serial baud rate.
/// Supported values: 115200, 57600, 19200, 460800.
void stark_set_rs485_baudrate(DeviceHandler *handle, uint8_t slave_id, uint32_t baudrate);

/// Get CANFD baud rate.
/// Supported values: 1M, 2M, 4M, 5M.
uint32_t stark_get_canfd_baudrate(DeviceHandler *handle, uint8_t slave_id);

/// Set CANFD baud rate.
/// Supported values: 1M, 2M, 4M, 5M.
void stark_set_canfd_baudrate(DeviceHandler *handle, uint8_t slave_id, uint32_t baudrate);

/// Set device slave ID.
/// Default is 1, valid range 1~247; 0 is the broadcast address.
/// Revo1 default ID is 1; Revo2 default left/right IDs are 0x7E and 0x7F.
/// When controlling multiple devices on the same bus, assign different IDs,
/// e.g. left=1, right=2.
/// Using broadcast ID 0 controls all devices on the bus; per Modbus spec,
/// broadcast commands do not receive responses.
void stark_set_slave_id(DeviceHandler *handle, uint8_t slave_id, uint8_t new_id);

/// Get Force3D touch summary data (4 fingers, no thumb).
/// Returns a pointer to `CForce3DTouchSummary`; call `free_force3d_touch_summary` to free it.
/// Returns NULL on failure.
CForce3DTouchSummary *stark_get_force3d_touch_summary(DeviceHandler *handle, uint8_t slave_id);

/// Free Force3D touch summary data.
void free_force3d_touch_summary(CForce3DTouchSummary *ptr);

/// Get Force3D finger array data (31 measurement points).
/// finger: 0=index, 1=middle, 2=ring, 3=pinky
/// Returns a pointer to `CForce3DFingerArray`; call `free_force3d_finger_array` to free it.
/// Returns NULL on failure.
CForce3DFingerArray *stark_get_force3d_finger_array(DeviceHandler *handle,
                                                    uint8_t slave_id,
                                                    uint8_t finger);

/// Free Force3D finger array data.
void free_force3d_finger_array(CForce3DFingerArray *ptr);

/// Check if device uses Revo2 Motor API.
///
/// Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
/// Revo1 Basic/Touch use Revo1 Motor API.
bool device_info_uses_revo2_motor_api(const CDeviceInfo *info);

/// Check if device uses Revo2 Touch API.
///
/// Includes capacitive (Revo2Touch), pressure (Revo2TouchPressure),
/// force3D (Revo2TouchForce3D), and array pressure (Revo2TouchArrayPressure) sensors.
bool device_info_uses_revo2_touch_api(const CDeviceInfo *info);

/// Check if device has any touch sensor
bool device_info_is_touch(const CDeviceInfo *info);

void free_motor_status_data(CMotorStatusData *data);

void free_touch_raw_data(CTouchRawData *data);

void free_touch_finger_data(CTouchFingerData *status);

void free_touch_finger_item(CTouchFingerItem *item);

void free_turbo_config(CTurboConfig *config);

void free_led_info(CLedInfo *info);

void free_button_event(CButtonPressEvent *event);

/// Get ArrayPressure touch data (status + 25 registers).
/// Returns a pointer to `CArrayPressureTouchData`; call `free_array_pressure_touch_data` to free it.
/// Returns NULL on failure.
CArrayPressureTouchData *stark_get_array_pressure_touch_data(DeviceHandler *handle,
                                                             uint8_t slave_id);

/// Free ArrayPressure touch data.
void free_array_pressure_touch_data(CArrayPressureTouchData *ptr);

/// Set ArrayPressure device sleep mode.
/// enable: 1=sleep, 0=wake
void stark_set_array_pressure_sleep(DeviceHandler *handle, uint8_t slave_id, bool enable);

/// Get finger backlash compensation values (6 values, unit °×10).
/// Returns pointer to array of 6 u16 values; caller must free with `free_u16_array`.
/// Returns NULL on failure.
uint16_t *stark_factory_get_backlash(DeviceHandler *handle, uint8_t slave_id, uint16_t *out_len);

/// Set finger backlash compensation values (6 values, unit °×10).
/// Requires factory key to be set first.
void stark_factory_set_backlash(DeviceHandler *handle,
                                uint8_t slave_id,
                                const uint16_t *values,
                                uint16_t len);

/// Trigger finger backlash self-check.
/// finger_id: 0=thumb_tip, 1=thumb_root, 2=index, 3=middle, 4=ring, 5=pinky
/// Requires factory key to be set first.
void stark_factory_backlash_self_check(DeviceHandler *handle, uint8_t slave_id, uint8_t finger_id);

/// Query whether automatic position calibration on power‑up is enabled.
bool stark_get_auto_calibration(DeviceHandler *handle, uint8_t slave_id);

/// Enable or disable automatic position calibration on power‑up.
void stark_set_auto_calibration(DeviceHandler *handle, uint8_t slave_id, bool enabled);

/// Send manual position‑calibration command.
void stark_send_calibrate_position(DeviceHandler *handle, uint8_t slave_id);

/// Reset default gestures to factory settings.
void stark_reset_default_gesture(DeviceHandler *handle, uint8_t slave_id);

/// Reset all settings to factory defaults.
/// ● Default IDs: left hand → 0x7E (126); right hand → 0x7F (127).
/// ● RS485 baud rate: 460800 bps.
/// ● CAN FD baud rate: 5 Mbps.
void stark_reset_default_settings(DeviceHandler *handle, uint8_t slave_id);

/// Check whether Turbo mode is enabled.
/// When enabled, the hand will keep squeezing continuously.
bool stark_get_turbo_mode_enabled(DeviceHandler *handle, uint8_t slave_id);

/// Enable or disable Turbo mode.
void stark_set_turbo_mode_enabled(DeviceHandler *handle, uint8_t slave_id, bool enabled);

/// Get Turbo mode configuration.
/// Returns a pointer to `TurboConfig`; call `free_turbo_config` to free it.
/// Returns NULL on failure.
CTurboConfig *stark_get_turbo_config(DeviceHandler *handle, uint8_t slave_id);

/// Get LED information.
/// Returns a pointer to `LedInfo`; call `free_led_info` to free it.
/// Returns NULL on failure.
CLedInfo *stark_get_led_info(DeviceHandler *handle, uint8_t slave_id);

/// Get button press event.
/// Returns a pointer to `ButtonPressEvent`; call `free_button_event` to free it.
/// Returns NULL on failure.
CButtonPressEvent *stark_get_button_event(DeviceHandler *handle, uint8_t slave_id);

/// Start the DFU (Device Firmware Update) process.
/// - `handle`: Device handler pointer.
/// - `slave_id`: Slave device ID.
/// - `dfu_file_path`: DFU file path, as a C string.
/// - `wait_secs`: Timeout for entering DFU mode, in seconds (default 5).
void start_dfu(DeviceHandler *handle,
               uint8_t slave_id,
               const char *dfu_file_path,
               uintptr_t wait_secs);

/// Stop the DFU process.
///
/// - `slave_id`: Slave device ID.
///
/// This stops an ongoing DFU session.
///
/// Note: If DFU has not started or has already completed, this function has no effect.
void stop_dfu(uint8_t slave_id);

void free_device_config(CDeviceConfig *config);

void free_device_info(CDeviceInfo *info);

/// Check if device uses Revo1 Motor API.
///
/// Revo1 Basic/Touch use Revo1 Motor API.
/// Revo1 Advanced/AdvancedTouch and all Revo2 use Revo2 Motor API.
bool device_info_uses_revo1_motor_api(const CDeviceInfo *info);

/// Check if device uses Revo1 Touch API.
///
/// Revo1 Touch API has different sensor counts per finger (4 sensors per finger).
/// Includes Revo1Touch and Revo1AdvancedTouch.
bool device_info_uses_revo1_touch_api(const CDeviceInfo *info);

}  // extern "C"

#endif  // STARK_SDK_H

SDK 仓库说明

brainco-hand-sdk 现仅面向 Revo 1 / Revo 2 系列示例;Revo 3 SDK 已迁移到独立的 brainco-revo3-sdk 仓库。旧版 linux/windows/ 示例已归档至 archive/,新项目建议使用 python/demo/c/demo/ 统一示例入口。


更新日志

v2.0.2 (2026/05)

仓库变更

  • Revo 3 SDK 已迁移至独立仓库 brainco-revo3-sdk
  • brainco-hand-sdk 现仅包含 Revo 1 / Revo 2 示例与预编译库。
  • Python Wheel 升级至 cp39-abi3 稳定 ABI,不再支持 Python 3.8。

修复

  • BrainCo USBCANFD 适配器新增多通道、多协议(CAN 2.0 / CANFD)自动检测。
  • 修复 Revo 2 手动电机校准失败的问题。
  • C/C++ ABI 变更(自 2.0.0 起):Baudrate 枚举值顺序调整(如 BAUD5MBPS 由 6 → 7)

v1.4.0 (2026/04/15)

新增触觉设备类型

  • 新增 阵列压阻触觉版 (Revo2TouchArrayPressure) — 3D 力与力矩数据采集(Fx, Fy, Fz, Mx, My),通过 ArrayPressureTouchDataBuffer
  • C++ 示例:hand_demohand_monitor 新增 array_pressure 模式
  • Python GUI:力/力矩数据 2D 矢量罗盘可视化
  • 触觉类型判断 API:
    • is_capacitive_touch() — 电容触觉(Revo1/Revo2 Touch)
    • is_pressure_touch() — 压阻触觉
    • is_force3d_touch() — 三维力触觉
    • is_array_pressure_touch() — 阵列压阻触觉

Python GUI

  • 触觉面板:热力图可视化,支持电容/压阻/三维力/阵列压阻/视触觉
  • 时序测试:Revo2 Worker,动态频率切换
  • 国际化支持(中/英)

SDK & API 变更

  • 新增硬件类型:Revo2TouchForce3DRevo2TouchArrayPressure
  • 新增 API:uses_array_pressure_touch_api()

🐛 问题修复

  • 修复 CAN 错误帧处理和自动检测协议分发
  • SocketCAN recv_can/recv_canfd 新增 CAN_ERR_FLAG 检查

📚 文档与项目结构

  • 弃用的 linux/windows/ 目录归档至 archive/
  • 新增 install_whl.sh 脚本用于 Python Wheel 安装

v1.1.9 (2026/03/03)

🔧 改进

  • 串口打开后新增 150ms 预热延迟,提升 Modbus 自动检测首次成功率

📚 新增示例

  • c/demo/debug_detect.cpp — C++ 调试工具,用于 Modbus 寄存器检查和原始 Protobuf 自动检测

v1.1.6 (2026/02/28)

🚀 新增功能

  • 自动检测新增 BrainCo USBCANFD 适配器支持

v1.1.5 (2026/02/09)

🐛 问题修复

  • 修复 CANFD 边界检查问题
  • SocketCAN 扫描改为遍历所有接口

🚀 新增功能

  • SocketCAN Python 绑定(init_socketcan_canfdclose_socketcansocketcan_scan_devices
  • 设备上下文查询 API:stark_get_protocol_typestark_get_port_namestark_get_baudrate
  • CAN 设备初始化:init_device_handler_can() / init_device_handler_can_with_hw_type()
  • StarkProtocolType::Auto = 0 枚举值,支持自动检测所有协议

🔧 示例改进

  • 运行时 CAN 后端选择,新增通信频率测试工具

v1.1.3 (2026/02/06)

🚀 新增功能

  • SocketCAN 内置支持 (Linux) - 无需外部代码
  • Protobuf 协议支持 - Revo 1 串口协议,波特率 115200,Slave ID 10-254

v1.1.0 (2025/02/05)

🚀 新增功能

  • ZQWL CAN 适配器内置支持(Linux / macOS / Windows,无需额外 DLL)
  • 统一设备自动检测 API:auto_detect()init_from_detected()close_device_handler()
  • Stark 1.8 触觉能力支持(RS-485 / CAN 协议)
  • 跨平台 C++ 示例(c/demo/
  • Python GUI 调试工具(电机控制、触觉数据、波形监控)

⚠️ Breaking Changes

  • 硬件类型枚举重构,新增 Revo1Advanced / Revo1AdvancedTouch
  • API 重命名:is_revo1()uses_revo1_motor_api()is_revo2()uses_revo2_motor_api()
  • 初始化拆分:init_config()init_logging() + init_device_handler()
  • C 结构体添加 C 前缀(如 MotorStatusDataCMotorStatusData
  • linux/windows/ 示例目录已弃用,请迁移至 c/

📚 迁移指南

详见 CHANGELOG.md


v1.0.0 (2025/12/08)

🎉 正式版本

  • 细节优化,正式升级到 1.0 版本

v0.9.9 (2025/11/19)

🚀 新增功能

  • 支持 Revo 1 进阶版设备
  • 统一控制参数范围:位置控制 0~1000,速度/电流/PWM 控制 -1000~+1000
  • 适用于 Modbus、CANFD 和 CAN2.0 所有通信协议

⚠️ 重要提示

  • Revo 1 进阶版设备需要 SDK v0.9.9 或更高版本
  • Revo 1 基础版和触觉版可使用任意版本

v0.9.8 (2025/11/04)

🚀 新增功能

  • CAN/CANFD 协议: 完整的 Revo 2 CAN2.0/CANFD 通信协议栈
  • ZLG CAN 支持: Python 接口(Windows/Linux),含驱动库封装
  • CANFD 分块读写: 支持超过 29 个寄存器的大数据传输
  • EtherCAT 触觉: 触觉传感器数据采集(PDO/SDO)
  • 压力触觉支持: EtherCAT/CANFD/RS-485 多协议通信
  • 保护电流接口: ProtectedCurrent 读写,支持 CAN/EtherCAT
  • 动作序列执行: run_action_sequence 支持 CAN 2.0
  • 设备类型判断: 基于序列号判断(get_hardware_by_sn
  • 多设备混用: 支持 Revo1/Revo2 同时使用

⚡ 高频通信优化

  • C/C++ 异步调用: set 类指令改为异步执行,避免阻塞主线程
  • 高频接口禁用重试: get/set_finger_*、触觉读取等,避免指令堆积
  • 低频接口重试优化: 设备信息读取等降至 2 次重试

🐛 问题修复

  • 修复 TurboConfig 字节序、Modbus C API 异步调用、OTA 升级包大小处理等问题

v0.9.0 (2025/09/20)

🐛 问题修复

  • 修复已知问题,提升稳定性

v0.8.6 (2025/08/20)

🚀 新增功能

  • 新增一代灵巧手 CAN2.0 协议支持

🔧 API 改进

  • 函数命名优化:
    • modbus_stark_(更通用的前缀,适用于 CANFD 和 EtherCAT)
    • create_device_handler() 更新命名,避免歧义
    • canfd_init(uint8_t master_id) 更新命名,避免歧义
    • init_cfg 不再需要传递固件类型,通过 get_device_info 接口自动获取

📚 示例代码

  • ROS 2 示例增加 CAN/CANFD 支持
  • 新增 CAN/CANFD C++ 示例

v0.7.0 (2025/07/18)

🚀 新增功能

  • 自动检测 Modbus 从机波特率和设备 ID
  • 二代灵巧手触觉版接口支持

🐛 问题修复

  • 修复 DFU 固件升级问题

v0.6.2 (2025/07/14)

🚀 新增功能

  • EtherCAT 协议支持:二代灵巧手支持 EtherCAT 高速通信协议
  • 扩展 RS485 波特率:新增 1M、2M 和 5M 波特率选项,满足高性能应用需求
  • Linux 串口性能优化:默认启用 LOW_LATENCY 模式,460800 波特率下通信频率提升 400%

🔧 API 改进

  • 重构设备上下文命名:
    • ModbusContextDeviceContext(更通用的设备上下文)
    • ModbusHandlerDeviceHandler(统一设备操作接口)

🛠 开发工具

  • 集成 python-stub-gen 工具链,自动生成类型存根文件(.pyi),提升 IDE 智能提示和类型检查体验

⚠️ 兼容性提示

  • 从旧版本迁移时,请注意 API 命名变更

v0.5.3 (2025/06/12)

🚀 新增功能

  • 自定义 Modbus 读写接口
  • 动作序列控制
  • LED、蜂鸣器、震动马达控制接口

🐛 问题修复

  • 修复实时位置/速度/电流返回值错误

v0.4.5 (2025/05/14)

🚀 新增功能

  • 新增 get_single_touch_status 单指触控状态检测

🔧 改进

  • 简化 modbus_open 函数,移除冗余参数

v0.4.4 (2025/05/06)

🚀 新增功能

  • 新增 CANFD 协议支持

🐛 问题修复

  • 修复多个已知问题,提升稳定性

v0.3.6 (2025/04/16)

🎉 里程碑

  • 首次支持二代灵巧手
  • 建立基础通信框架

v0.1.9 (2025/03/17)

📌 初始版本

  • Modbus 通信协议
  • Python / C 代码集成
  • SDK 基础架构
帮助