Skip to main content

PyCH9329-HID is a high-level Python package for CH9329 HID chip, designed to provide seamless, OS-independent peripheral control via serial communication.

Project description

PyCH9329-HID

PyCH9329-HID is a high-level Python package for CH9329 HID chip, designed to provide seamless, OS-independent peripheral control via serial communication.


🎯 Target Use Cases

Use Case Description
AI Vision Agents Perfect for models like UI-TARS or Claude Computer Use that require high-fidelity interaction with a screen based on visual coordinates
Test Automation Reliable UI testing on macOS/Windows/Linux without requiring OS-level accessibility permissions
Embedded Robotics Controlling computers via Raspberry Pi or ESP32 using a physical CH9329 USB dongle

📦 Installation

pip install pych9329-hid

Requirements

  • Python >= 3
  • pyserial

Import Options

You can use either of the full package name or shorter alias:

# Option 1: Full package name
from pych9329_hid import HIDController, CH9329, SerialTransport

# Option 2: Short alias (recommended)
from pych9329 import HIDController, CH9329, SerialTransport

Both options work identically - choose whichever you prefer!


🚀 Quick Start

Basic Usage - Low Level Protocol

from pych9329 import CH9329, SerialTransport

# Create transport and CH9329 instance
with SerialTransport(port='/dev/ttyUSB0', baudrate=115200) as transport:
    ch9329 = CH9329(transport)
    
    # Send keyboard report
    ch9329.send_keyboard(modifier=0, keycodes=[0x04])
    
    # Send relative mouse movement
    ch9329.send_mouse_rel(dx=10, dy=5, buttons=0x01)
    
    # Send absolute mouse position
    ch9329.send_mouse_abs(x=100, y=200, buttons=0x01)

Keymap Support:

  • Characters: a-z, A-Z, 0-9, space, punctuation
  • Special keys: f1-f12, enter, backspace, tab, esc, home, end, pageup, pagedown, insert, delete, arrows
  • Modifiers: ctrl, shift, alt, cmd (also supports: control, option, win, command, meta, super)

High-Level HID Controller

from pych9329 import HIDController, CH9329, SerialTransport

# Create HID controller
with SerialTransport(port='/dev/ttyUSB0', baudrate=115200) as transport:
    ch9329 = CH9329(transport)
    controller = HIDController(ch9329, screen_width=1920, screen_height=1080)
    
    # Keyboard operations
    controller.press('a')
    controller.write('Hello World')
    controller.hotkey('cmd', 'space')
    
    # Mouse operations
    controller.moveTo(100, 200, duration=0.5)
    controller.click(button='left')
    controller.dragRel(50, 30)
    
    # Scrolling
    controller.scroll(5)  # Scroll up
    controller.hscroll(-2)  # Scroll left

📚 API Reference

⚠️ Error Handling

CH9329 Layer

The CH9329 protocol layer uses a hybrid error handling strategy:

  • Soft Errors (timeout, ACK error): Return False with a warning

    • Device doesn't respond within timeout
    • Device returns error status in ACK
  • Hard Errors (transport failure): Raise SerialTransportError

    • Serial port disconnected
    • Serial port read/write failure
    • Invalid serial port configuration

Example:

# Handle soft errors (timeout/ACK error)
if not ch9329.send_keyboard(modifier=0, keycodes=[0x04]):
    print("Timeout or ACK error, but continuing...")

# Handle hard errors (transport failure)
try:
    ch9329.send_mouse_abs(x=100, y=200)
except SerialTransportError as e:
    print(f"Transport error: {e}")
    # Reconnect or exit

HIDController Layer

HIDController does not check return values from CH9329 - failures propagate naturally to the caller. This allows users to decide how to handle errors based on their use case.

Example:

# Option 1: Ignore failures
controller.press('a')  # Continues even if timeout

# Option 2: Check and retry
for _ in range(3):
    if controller.press('a'):
        break
    time.sleep(0.1)

# Option 3: Handle explicitly
try:
    controller.moveTo(100, 200)
except SerialTransportError as e:
    print(f"Fatal error: {e}")
    sys.exit(1)

SerialTransport Layer

The transport layer provides custom exceptions:

  • SerialTransportError: Base exception for transport errors
  • SerialTransportClosedError: Raised when operation attempted on closed transport

Example:

try:
    with SerialTransport(port='/dev/ttyUSB0') as transport:
        ch9329 = CH9329(transport)
        # ... use ch9329
except SerialTransportError as e:
    print(f"Failed to open serial port: {e}")

CH9329 (Low-Level Protocol)

Method Description Returns
send_keyboard(modifier, keycodes) Send keyboard report with modifier and keycodes True if successful, False if timeout/ACK error
send_mouse_rel(dx, dy, buttons, wheel) Send relative mouse movement True if successful, False if timeout/ACK error
send_mouse_abs(x, y, buttons, wheel) Send absolute mouse position True if successful, False if timeout/ACK error

HIDController (High-Level API)

Keyboard Operations

Method Description Example
press(key) Press and release a key controller.press('a')
keyDown(key) Press and hold a key controller.keyDown('shift')
keyUp(key) Release a key controller.keyUp('shift')
write(text) Type a string controller.write('Hello')
hotkey(*keys) Press key combination controller.hotkey('cmd', 'a')

Mouse Operations

Method Description Example
moveTo(x, y, duration) Move mouse to coordinates controller.moveTo(100, 200, duration=0.5)
moveRel(dx, dy, duration) Move mouse relatively controller.moveRel(10, 5)
click(button, clicks) Click mouse button controller.click('left', clicks=2)
mouseDown(button) Press and hold button controller.mouseDown('left')
mouseUp(button) Release button controller.mouseUp('left')
dragRel(dx, dy) Drag relatively controller.dragRel(50, 30)
dragTo(x, y) Drag to coordinates controller.dragTo(100, 200)

Scrolling

Method Description Example
scroll(clicks) Vertical scroll controller.scroll(5)
hscroll(clicks) Horizontal scroll controller.hscroll(-2)

SerialTransport (Transport Layer)

Method Description Returns
write(data) Write raw bytes to port None
read(size) Read up to size bytes bytes read (may be empty on timeout)
read_all() Read all available data All available bytes
is_open() Check if port is open bool
close() Close the serial port None

🔧 Configuration

SerialTransport Parameters

Parameter Type Default Description
port str Required Serial port path (e.g., '/dev/ttyUSB0' or 'COM3')
baudrate int 115200 Baud rate (115200 recommended for CH9329)
timeout float 0.005 Read/write timeout in seconds

HIDController Parameters

Parameter Type Default Description
screen_width int 1920 Screen width in pixels
screen_height int 1080 Screen height in pixels
dwelling_time float 0.01 Delay between operations (seconds)
move_interval float 0.015 Mouse movement interval (seconds)
keypress_hold_time float 0.05 Key press duration (seconds)
double_click_interval float 0.1 Double click interval (seconds)
scroll_multiplier int 5 Scroll sensitivity multiplier

📝 Examples

List Available Serial Devices

import serial.tools.list_ports

ports = serial.tools.list_ports.comports()
for port in ports:
    print(f"Port: {port.device}, Description: {port.description}")

Complete Automation Example

from pych9329_hid import HIDController, CH9329, SerialTransport
import time

with SerialTransport(port='/dev/ttyUSB0', baudrate=115200) as transport:
    ch9329 = CH9329(transport)
    controller = HIDController(ch9329, screen_width=1920, screen_height=1080)
    
    # Open Spotlight (macOS)
    controller.hotkey('cmd', 'space')
    time.sleep(0.5)
    
    # Type application name
    controller.write('Terminal')
    time.sleep(0.5)
    
    # Press Enter
    controller.press('enter')
    time.sleep(1)
    
    # Type command
    controller.write('echo "Hello from CH9329!"')
    controller.press('enter')

✨ Features

  • Low-level CH9329 protocol implementation with ACK verification
  • High-level HID automation API (keyboard, mouse, scrolling, dragging)
  • Smooth mouse movement with interpolation
  • Drag and drop support for UI automation
  • OS-independent - works on macOS, Windows, Linux

📄 License

MIT License - see LICENSE file for details

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pych9329_hid-0.1.5.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pych9329_hid-0.1.5-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file pych9329_hid-0.1.5.tar.gz.

File metadata

  • Download URL: pych9329_hid-0.1.5.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for pych9329_hid-0.1.5.tar.gz
Algorithm Hash digest
SHA256 2328f1ae0835b9e8a2ccdd512b1b510cd1853ac8f22c694d54fe579e3b6d6b79
MD5 88ca1a43684f9064eae1b8518f420459
BLAKE2b-256 90b9e58c50258f5d9ab5160b30486ca8376cc29291c40eac8673b74303d46838

See more details on using hashes here.

File details

Details for the file pych9329_hid-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: pych9329_hid-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.9.6

File hashes

Hashes for pych9329_hid-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 9531d7bd45c37c5acb7587898627fe780c953ca5c3ea5a3129622dbf27bb790f
MD5 76445fd328805b0df8638579f5281936
BLAKE2b-256 55fa12b72a313e52badf9778e1cea51ace832b943b07b826b5e240b317e409ce

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page