You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu系统下如何将蓝牙键盘作为非系统HID设备连接并通过Python捕获按键以自定义功能

在Ubuntu上用Python捕获蓝牙HID键盘的自定义按键操作

没问题,完全可以做到!既然你的键盘是标准HID设备,我们只需要两步核心操作:先让系统别把它当成普通输入键盘,再用Python直接读取它的原始HID数据来实现自定义功能。下面是详细步骤:

一、阻止系统将键盘识别为常规输入设备

默认情况下,Ubuntu会自动把HID键盘纳入输入子系统,导致按键直接输出字符。我们可以通过udev规则来屏蔽这个行为:

  1. 找到键盘的Vendor ID和Product ID
    先配对你的蓝牙键盘,然后打开终端执行命令:

    udevadm info --name=/dev/input/eventX --attribute-walk
    

    这里的eventX需要替换成你键盘对应的输入设备号(可以用ls /dev/input/event*查看,或者通过evtest工具确认哪个是你的蓝牙键盘)。在输出里找到类似ATTRS{idVendor}=="1234"和ATTRS{idProduct}=="5678"的行,记下这两个十六进制值。

    也可以用后面Python代码里的hid.enumerate()来枚举设备,直接获取这两个ID。

  2. 创建udev规则文件
    用文本编辑器创建规则文件:

    sudo nano /etc/udev/rules.d/99-bluetooth-custom-keyboard.rules
    

    写入以下内容(替换xxxx和yyyy为你刚才拿到的Vendor ID和Product ID):

    ACTION=="add", ATTRS{idVendor}=="xxxx", ATTRS{idProduct}=="yyyy", ENV{ID_INPUT_KEYBOARD}="0", MODE="0666"
    

    这条规则会告诉系统:这个设备不是常规键盘,同时给普通用户读写权限。

  3. 重新加载udev规则
    执行命令让规则生效:

    sudo udevadm control --reload-rules
    sudo udevadm trigger
    

    之后重新连接蓝牙键盘,它就不会再输出字符了。

二、用Python 3捕获并处理按键

我们可以用hidapi库直接和HID设备通信,读取键盘的原始按键报告。

  1. 安装依赖
    先安装系统级的hidapi库:

    sudo apt install libhidapi-hidraw0
    

    然后安装Python的hidapi绑定:

    pip install hidapi
    
  2. 编写Python代码示例
    下面是一个基础示例,它会枚举设备、连接键盘,实时读取并解析按键:

    import hid
    
    # 替换成你的键盘的Vendor ID和Product ID(十进制或十六进制都可以)
    VENDOR_ID = 0x1234
    PRODUCT_ID = 0x5678
    
    def find_keyboard():
        # 枚举所有HID设备,找到目标设备
        for device in hid.enumerate(VENDOR_ID, PRODUCT_ID):
            if device['interface_number'] == 0:  # 一般HID键盘的接口号是0
                return device['path']
        return None
    
    def parse_hid_report(report):
        # HID键盘报告通常是8字节:
        # 字节0:修饰键(Ctrl/Shift/Alt等,每个位对应一个修饰键)
        # 字节1:保留位
        # 字节2-7:按下的按键码(最多同时6个按键)
        modifiers = report[0]
        keys = report[2:8]
        
        # 修饰键映射(根据HID规范)
        modifier_map = {
            0x01: 'Left Ctrl',
            0x02: 'Left Shift',
            0x04: 'Left Alt',
            0x08: 'Left GUI',
            0x10: 'Right Ctrl',
            0x20: 'Right Shift',
            0x40: 'Right Alt',
            0x80: 'Right GUI'
        }
        
        # 常用按键码映射(可根据HID Usage Table补充更多)
        key_map = {
            0x04: 'a', 0x05: 'b', 0x06: 'c', 0x07: 'd', 0x08: 'e', 0x09: 'f', 0x0a: 'g',
            0x0b: 'h', 0x0c: 'i', 0x0d: 'j', 0x0e: 'k', 0x0f: 'l', 0x10: 'm', 0x11: 'n',
            0x12: 'o', 0x13: 'p', 0x14: 'q', 0x15: 'r', 0x16: 's', 0x17: 't', 0x18: 'u',
            0x19: 'v', 0x1a: 'w', 0x1b: 'x', 0x1c: 'y', 0x1d: 'z',
            0x1e: '1', 0x1f: '2', 0x20: '3', 0x21: '4', 0x22: '5', 0x23: '6', 0x24: '7',
            0x25: '8', 0x26: '9', 0x27: '0',
            0x28: 'Enter', 0x29: 'Escape', 0x2a: 'Backspace', 0x2b: 'Tab', 0x2c: 'Space',
            0x2d: '-', 0x2e: '=', 0x2f: '[', 0x30: ']', 0x31: '\\', 0x32: '#', 0x33: ';',
            0x34: '\'', 0x35: '`', 0x36: ',', 0x37: '.', 0x38: '/'
        }
        
        pressed_modifiers = [name for bit, name in modifier_map.items() if modifiers & bit]
        pressed_keys = [key_map.get(key, f'Unknown(0x{key:02x})') for key in keys if key != 0]
        
        return pressed_modifiers, pressed_keys
    
    def main():
        device_path = find_keyboard()
        if not device_path:
            print("找不到目标蓝牙键盘!")
            return
        
        try:
            with hid.Device(path=device_path) as h:
                print(f"已连接到键盘:{h.get_manufacturer_string()} {h.get_product_string()}")
                print("开始监听按键(按Ctrl+C退出)...")
                
                while True:
                    # 读取HID报告,超时时间1000ms
                    report = h.read(64, timeout=1000)
                    if report:
                        modifiers, keys = parse_hid_report(report)
                        if keys or modifiers:
                            print(f"修饰键: {modifiers} | 按键: {keys}")
                            # 在这里添加你的自定义功能逻辑
                            if 'a' in keys:
                                print("执行自定义功能:打开浏览器!")
                                # 示例:调用系统命令
                                # import subprocess
                                # subprocess.run(['xdg-open', 'https://google.com'])
                            elif 'Enter' in keys:
                                print("执行自定义功能:暂停音乐!")
        except KeyboardInterrupt:
            print("\n已退出监听")
        except Exception as e:
            print(f"错误:{e}")
    
    if __name__ == "__main__":
        main()
    
  3. 代码说明

    • find_keyboard():根据设置的ID找到目标设备的路径
    • parse_hid_report():把HID原始字节数据转换成可读的按键名称
    • 在main()的循环里,你可以根据pressed_keys和pressed_modifiers添加任意自定义功能,比如调用系统命令、启动程序等

三、注意事项

  • 如果运行代码提示权限不足,检查udev规则里的MODE="0666"是否正确,或者暂时用sudo运行脚本
  • 不同键盘的HID报告格式可能略有差异,如果解析不对,可以用hidapi的get_report_descriptor()方法获取键盘的HID描述符,调整解析逻辑
  • 如果蓝牙键盘断开重连,可能需要重新运行脚本,你可以添加重连逻辑来优化

内容的提问来源于stack exchange,提问作者xnsdfgr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 22:12:45