我正在尝试实现一个通用的BLE接口,该接口将在OS / X上运行并与BLE外围设备通信。外围设备非常复杂:可以查询,发送数百个不同的命令,提供通知等。我需要能够连接它,发送命令,读取响应,获取更新等。
我拥有我需要的所有代码,但是我被一件事感到沮丧:从我在网上找到的有限信息来看,看起来像是通过运行来调用CoreBluetooth的委托回调的唯一方法是:
from PyObjCTools import AppHelper
# [functional CoreBluetooth code that scans for peripherals]
AppHelper.runConsoleEventLoop()
问题是AppHelper.runConsoleEventLoop
阻止主线程继续,所以我无法执行代码与外设交互。
我尝试过运行事件循环:
The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
multiprocessing.Pool(1).apply_async(f)
---> Python崩溃并显示错误消息:The process has forked and you cannot use this CoreFoundation functionality safely. You MUST exec().
我不理解AppHelper.runConsoleEventLoop
的性质。为什么需要运行它才能调用CoreBluetooth委托回调?是否有一些其他版本可以调用,不必在主线程上运行?我在网上读到了与GUI相关的内容,因此必须在主线程上运行,但我的python应用程序没有任何GUI元素。是否有一个标志或API不太关注我可以使用的GUI?
非常感谢任何帮助。谢谢你的时间!
更新
我在工作中与iOS / CoreBluetooth专家交谈,发现Dispatch Queues可能是解决方案。我进一步挖掘,发现PyObjC软件包的作者最近发布了一个v4.1,它增加了对迄今为止缺失的调度队列的支持。
我已经阅读了几个小时的Apple开发人员文档,我知道可以创建Dispatch Source对象来监视某些系统事件(例如我感兴趣的BLE外围事件),并且配置它们涉及创建和分配一个Dispatch Queue,它是调用我的CBCentralManager委托回调方法的类。我仍然缺少的一个难题是如何将调度源/队列内容连接到调用AppHelper.runConsoleEventLoop
的{{1}}。如果我将调用Foundation.NSRunLoop.currentRunLoop()
放在一个单独的线程上,如何告诉它使用哪个Dispatch Source / Queue来获取事件信息?
答案 0 :(得分:0)
所以我终于明白了。如果要在单独的线程上运行事件循环,以免失去对主线程的控制,则必须创建一个新的调度队列并使用它初始化CBCentralManager。
GridLayout