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

如何在macOS上通过Python调用IOHIDManager获取蓝牙设备通知

macOS下Python监听蓝牙HID设备连接/断开通知方案

我有一个Python应用,在macOS上使用hid模块与多个蓝牙设备交互。目前只能通过轮询hid.enumerate()来检测设备状态,这种方式会大量消耗CPU资源。我希望能在蓝牙设备连接/断开时收到系统级的通知,而非轮询。

已知通过IOKit可以实现该功能,但尝试用Cocoa、PyObjC、ctypes实现时无从下手,需要可行方案。


基于PyObjC的实现方案

PyObjC是Python与Cocoa框架的桥接工具,可直接调用IOKit相关API,对应提供的Objective-C代码,可转写成如下Python实现:

1. 安装依赖

先确保安装PyObjC相关包:

pip install pyobjc-framework-IOKit pyobjc-core

2. 完整代码示例

import objc
from Foundation import *
from IOKit.hid import *

def device_added_callback(context, result, sender, device):
    """设备连接时的回调函数"""
    # 获取设备属性信息
    manufacturer = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDManufacturerKey))
    product_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))
    print(f"设备已连接: 制造商={manufacturer}, 产品名={product_name}")

def device_removed_callback(context, result, sender, device):
    """设备断开时的回调函数"""
    product_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey))
    print(f"设备已断开: 产品名={product_name}")

def start_hid_notification():
    # 创建HID管理器实例
    hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone)
    
    # 构建设备匹配字典,可按需过滤设备
    matching_dict = IOServiceMatching(kIOHIDDeviceKey)
    # 示例:仅匹配Apple品牌设备,注释此行则监听所有HID设备
    CFDictionaryAddValue(matching_dict, CFSTR(kIOHIDManufacturerKey), CFSTR("Apple"))
    
    # 设置HID管理器的设备匹配规则
    IOHIDManagerSetDeviceMatching(hid_manager, matching_dict)
    
    # 注册设备连接、断开的回调函数
    IOHIDManagerRegisterDeviceMatchingCallback(hid_manager, device_added_callback, None)
    IOHIDManagerRegisterDeviceRemovalCallback(hid_manager, device_removed_callback, None)
    
    # 将HID管理器加入当前RunLoop,以接收事件
    current_runloop = CFRunLoopGetCurrent()
    IOHIDManagerScheduleWithRunLoop(
        hid_manager,
        current_runloop,
        kCFRunLoopDefaultMode
    )
    
    # 打开HID管理器开始监听
    IOHIDManagerOpen(hid_manager, kIOHIDManagerOptionNone)
    
    # 启动RunLoop,保持程序运行以监听事件
    CFRunLoopRun()

if __name__ == "__main__":
    print("开始监听HID设备连接/断开事件...")
    try:
        start_hid_notification()
    except KeyboardInterrupt:
        print("已停止监听")

代码说明

  • 回调函数:device_added_callback和device_removed_callback分别处理设备连接、断开事件,可通过IOHIDDeviceGetProperty获取设备的更多属性(如产品ID、序列号等)
  • 设备过滤:通过matching_dict可设置过滤条件,比如指定制造商、产品ID,只监听特定设备
  • RunLoop机制:macOS基于RunLoop处理事件,CFRunLoopRun()会让程序持续运行以接收设备事件,按下Ctrl+C可终止监听

替代方案:ctypes调用IOKit

若不想依赖PyObjC,也可通过ctypes直接调用IOKit的C API,但需要手动处理Core Foundation类型的内存管理、字符串转换等操作,实现复杂度较高,PyObjC是更简洁的选择。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:15:35