使用Python Twisted框架连接多个串口套接字
我现在用 twisted 这个库来连接我手上的一个串口设备,代码大概是这样的。
from twisted.internet import reactor
SerialPort(Handler(), "/dev/ttyACM1", reactor, baudrate='9600')
reactor.run()
不过,我现在需要扩展这个应用程序,让它能够监控新串口设备的添加和移除。我现在用 pyinotify 来查看设备的新增和移除,这个方法似乎效果不错。
class EventHandler(pyinotify.ProcessEvent):
def process_IN_CREATE(self, event):
... connect to serial device
...
目前我遇到了一些问题。我觉得最大的问题是我对 Twisted 了解得不够,不知道怎么做才算是“正确”的方式。
现在我的代码是,pyinotify 的事件处理器在一个单独的线程中运行,这意味着 reactor(反应器)并没有在主线程中运行。这会有问题吗?
一旦第一个设备连接上,我就很难再添加第二个设备——因为在添加第二个设备时,reactor 已经在运行了。即使我用一个
if not reactor.running:
来保护这个过程,第二个连接也没有正确添加到 reactor 中(至少 connectionMade 和 dataReceived 这两个方法没有被调用)。
如果我先启动 reactor,然后让 pyinotify 的事件尝试添加到正在运行的 reactor,这似乎也不行——设备确实连接上了,但 dataReceived 方法从来没有被调用。
总之,我相信一定有一个好的方法可以让这个工作正常,但我一直找不到,不管是通过谷歌搜索还是自己尝试。有没有人能给我一些建议,告诉我怎么才能让这个正常工作呢?
非常感谢你们能提供的任何帮助,
西蒙
1 个回答
7
每当你想使用Twisted的API,但你的代码并没有在和反应器同一个线程里运行时,你可以用 reactor.callFromThread
让反应器在它自己的线程里调用你的代码。比如,你可以这样做:
def process_IN_CREATE(self, event):
reactor.callFromThread(
SerialPort, Handler(), "/dev/ttyACM1", reactor, baudrate='9600')
不过,其实你并不需要额外的线程来完成你所描述的事情。与其使用 pyinotify
,不如使用 twisted.internet.inotify
:
from twisted.python.filepath import FilePath
from twisted.internet.inotify import IN_CREATE, INotify
from twisted.internet import reactor
def created(ignored, path, mask):
SerialPort(
Handler(),
"/dev/ttyACM1", # Or... use `path` here?
reactor, baudrate='9600')
notifier = INotify()
notifier.watch(FilePath("/some/directory"), IN_CREATE, callbacks=[created])
notifier.startReading()
reactor.run()