如何在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
相关产品推荐
相关产品推荐

