A Python library for game controller input handling
Project description
fly-stick
一个基于 Rust 和 PyO3 构建的高性能 Python 库,专门用于处理游戏控制器(操纵杆/手柄)输入设备。该库使用 Linux evdev 接口提供低延迟的设备监控和状态读取能力,特别适用于飞行模拟器等实时输入场景。
特性
- 🎮 多设备支持 - 同时监控多个游戏控制器设备
- ⚡ 高性能核心 - Rust 底层实现,提供毫秒级响应
- 🔄 异步/非阻塞双模式 - 支持
await fetch()与fetch_nowait() - 📊 设备池管理 - 统一管理多设备,读取逻辑设备状态
- 🛠️ TOML 配置 - 基于 TOML 的设备描述文件
- 🐍 完整 Python API - 直接从
fly_stick包导入核心类型 - 🎯 按钮模式控制 - 支持
trigger与hold两种按钮处理模式 - 📈 实时状态监控 - 轴、按钮、帽子开关状态实时更新
安装
系统要求
- Linux 系统(依赖 evdev)
- Python 3.10+
- Rust(仅开发或源码构建时需要)
从源码构建
# 克隆仓库
git clone https://github.com/WindLX/fly_stick.git
cd fly_stick
# 安装构建依赖
pip install maturin
# 构建并安装到当前 Python 环境
maturin develop
使用 uv(推荐)
uv sync
uv run maturin develop
快速开始
单设备监控
import asyncio
import fly_stick
async def monitor_single_device():
devices = fly_stick.fetch_connected_joysticks()
if not devices:
print("未找到设备")
return
dev = devices[0]
joystick = fly_stick.PyJoystick(dev.path)
print(f"监控设备: {dev.name} @ {dev.path}")
while True:
try:
state = joystick.get_state()
print(state.to_dict())
await asyncio.sleep(0.01)
except KeyboardInterrupt:
break
asyncio.run(monitor_single_device())
设备池异步监控
import asyncio
from fly_stick import PyDevicePool, DeviceDescription, DeviceButtonMode
async def monitor_device_pool():
pool = PyDevicePool(
device_descs={
"ta320": DeviceDescription.from_toml("devices/Thrustmaster/ta320.toml"),
"twcs": DeviceDescription.from_toml("devices/Thrustmaster/twcs.toml"),
},
debounce_seconds=0.1,
btn_mode=DeviceButtonMode.hold(),
)
# 使用设备池前先初始化监控
await pool.reset()
print("开始监控设备池...")
while True:
try:
states = await pool.fetch(timeout_seconds=1.0)
for device_name, state in states.items():
print(f"{device_name}: {state.to_dict()}")
except KeyboardInterrupt:
print("停止监控")
await pool.stop()
break
asyncio.run(monitor_device_pool())
设备池非阻塞读取
import asyncio
from fly_stick import PyDevicePool, DeviceDescription
async def monitor_nowait():
pool = PyDevicePool(
device_descs={
"ta320": DeviceDescription.from_toml("devices/Thrustmaster/ta320.toml"),
"twcs": DeviceDescription.from_toml("devices/Thrustmaster/twcs.toml"),
},
debounce_seconds=0.1,
)
await pool.reset()
try:
while True:
states = pool.fetch_nowait()
for name, state in states.items():
print(f"{name}: 轴={state.axes}, 按钮={state.buttons}, 帽子={state.hats}")
await asyncio.sleep(0.01)
except KeyboardInterrupt:
await pool.stop()
asyncio.run(monitor_nowait())
设备配置
DevicePool 的设备配置使用 TOML 格式描述,此描述文件约束了哪些按键才会被监控和记录数据。例如 devices/Thrustmaster/ta320.toml:
device_name = "Thrustmaster T.A320 Copilot"
author = "WindLX"
created = "2025-01-14"
description = "Thrustmaster T.A320 Copilot Device Description File"
[[axes]]
code = 0
alias = "ABS_X"
[[axes]]
code = 1
alias = "ABS_Y"
[[buttons]]
code = 288
alias = "BTN_TRIGGER"
[[hats]]
code = 16
alias = "ABS_HAT0X"
配置文件说明
device_name: 设备显示名称(用于匹配系统设备名)author: 配置文件作者(可选)created: 创建日期(可选)description: 设备描述(可选)axes: 轴配置列表,包含code与aliasbuttons: 按钮配置列表,包含code与aliashats: 帽子开关配置列表,包含code与alias
API 参考
核心函数
fetch_connected_joysticks()- 获取当前连接的输入设备列表
核心类
PyJoystick(device_path)PyJoystick.get_state()PyDevicePool(device_descs, debounce_seconds=0.1, btn_mode=DeviceButtonMode.hold())PyDevicePool.reset()PyDevicePool.fetch(timeout_seconds=None)PyDevicePool.fetch_nowait()PyDevicePool.stop()PyDevicePool.devices(属性)PyDevicePool.debounce_time(属性)PyDevicePool.button_mode(属性,可读写)
数据结构
JoystickInfo(path,name)JoystickState(axes,buttons,hats)JoystickState.to_dict()JoystickState.to_alias_dict(desc)JoystickState.get_alias_axes(desc)JoystickState.get_alias_buttons(desc)JoystickState.get_alias_hats(desc)DeviceDescriptionDeviceDescription.from_toml(toml_file)DeviceDescription.build_state()DeviceItemDeviceButtonMode.trigger()DeviceButtonMode.hold()
注意:使用
PyDevicePool.fetch()或fetch_nowait()前,需先调用await reset()。
示例
项目包含多个示例文件:
examples/single_device.py- 单设备异步监控examples/multi_device.py- 多设备异步监控examples/device_pool.py- 设备池非阻塞读取examples/device_pool_block.py- 设备池阻塞读取examples/alias.py- 按别名读取轴状态examples/btn_mode.py- 按钮触发模式示例
支持的设备
目前仓库内提供了以下设备描述文件:
devices/Thrustmaster/ta320.tomldevices/Thrustmaster/twcs.tomldevices/Thrustmaster/t16000m.tomldevices/Thrustmaster/tca_qeng.tomldevices/Thrustmaster/twcs_with_tfrp.tomldevices/Microsoft X-Box 360/pad.tomldevices/Microsoft X-Box 360/series_sx.toml
设备映射图
项目提供了设备按键映射图:
figures/Thrustmaster_TA320_Copilot.drawio.pngfigures/Thrustmaster_TWCS_Throttle.drawio.pngfigures/Thrustmaster T.16000M.drawio.pngfigures/Thrustmaster T.Flight Rudder Pedals.drawio.pngfigures/Thrustmaster TCA Q-Eng 1&2.drawio.png
开发
项目结构
fly_stick/
├── src/
│ ├── lib.rs
│ ├── utils.rs
│ ├── inner/
│ │ ├── description.rs
│ │ ├── device_pool.rs
│ │ ├── joystick.rs
│ │ └── mod.rs
│ ├── wrapper/
│ │ ├── device_pool_wrapper.rs
│ │ ├── joystick_wrapper.rs
│ │ └── mod.rs
│ └── fly_stick/
│ ├── __init__.py
│ └── _core.pyi
├── examples/
├── devices/
├── figures/
├── Cargo.toml
└── pyproject.toml
构建与测试
# Rust 单元测试
cargo test
# Python 测试(如项目中提供测试用例)
pytest
# 构建发布 wheel
maturin build --release
性能特性
- 低延迟: Rust 核心实现,输入处理延迟低
- 按钮模式控制: 支持 Trigger/Hold 两种按钮语义
- 非阻塞读取: 可使用
fetch_nowait()做高频轮询 - 内存安全: Rust 提供内存安全保障
TODO
-
alias支持 - 按钮触发逻辑优化
许可证
本项目采用 MIT 许可证,详见 LICENSE。
贡献
欢迎提交 Issue 和 Pull Request。
建议在提交前完成:
- 代码风格自检
- 必要测试补充
- 文档同步更新
作者
- windlx - 初始开发 - https://github.com/WindLX
注意:该库当前仅支持 Linux(evdev)。未来可按需扩展到其他平台。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fly_stick-0.1.0.tar.gz.
File metadata
- Download URL: fly_stick-0.1.0.tar.gz
- Upload date:
- Size: 22.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d55bbac86b39221f49e85339fbe10db19324710880faf8f6dc53358c821afaf9
|
|
| MD5 |
f616429aedf09d758ce489ae7e585b64
|
|
| BLAKE2b-256 |
562ee628e7264a27e18d420f7a418db4a9be8ded72661e28a6547885be9877b7
|
File details
Details for the file fly_stick-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: fly_stick-0.1.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 833.8 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8ab11242f8ca5102f7072458bd55191d5ab26ea4a666e1a16a2f82f0efa56f5
|
|
| MD5 |
c6fede1c362c7583bdddec66894910f6
|
|
| BLAKE2b-256 |
ef31a474b8aae252d329e588914a39c05d778a987a91051681554132550e4527
|
File details
Details for the file fly_stick-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: fly_stick-0.1.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 836.3 kB
- Tags: CPython 3.9+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.14.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5d28ba8d797b970f944d03153715f4812f1f4c71dbc284eaf6c5a0c8622bde20
|
|
| MD5 |
4c06ae77d561efb95330e6d7041c03b4
|
|
| BLAKE2b-256 |
bcec52691c7c7ca3ab332b9bc6b118d1959f8ba5f7baff9493a0c3f09f171c08
|