如何使用双绞线处理多个串行端口的RW?

如何使用双绞线处理多个串行端口的RW?,第1张

如何使用双绞线处理多个串行端口的R / W? 请注意您的示例代码

我看不到您在将类注册到反应堆之前实例化您的类。我预计这将严重失败。这是我的运行代码的类似片段:

# stuff to process messages coming from the serial portclass SerialEater(basic.LineReceiver):    statusCallback = None    def __init__(self):        self.keyinprocess = None    def lineReceived(self, data):      self.dealWithSerial(data)    def connectionLost(self, reason):      if(reactor.running):        print "Serial lost but reactor still running! reason: " + str(reason) + " at time " + time.asctime()    [...etc...]# Register the serialport into twistedserialhandler = SerialEater()        # <------------- instantiateSerialPort(serialhandler, '/dev/ttyUSB0', reactor, baudrate=115200)

如何/在哪里接受用户的CLI输入,然后触发向调制解调器发送一组AT命令?

与将串行处理程序注册到Twisted中的方式非常相似,您可以为标准io注册处理程序,例如:

# stuff to pull cbreak char input from stdinclass KeyEater(basic.LineReceiver):    def __init__(self):      self.setRawMode() # Switch from line mode to "however much I got" mode    def connectionLost(self, reason):      if(reactor.running):        self.sendLine( "Keyboard lost but reactor still running! reason: " + str(reason) + " at time " + time.asctime())    def rawDataReceived(self, data):      key = str(data).lower()[0]      try:        if key == '?':          key = "help"     [...etc...]# register the stdio handler into twistedkeyboardobj = KeyEater()keyboardobj.serialobj = serialhandlerstdio.StandardIO(keyboardobj,sys.stdin.fileno())

将在命令端口上为tty1的ttyUSB0和ttyUSB1以及在调制解调器2的另一对接收的信息相关联?请注意,每个调制解调器都有自己的状态机(设备状态和连接状态)

在正常使用中,每个连接实例都将具有自己的状态机(在您与连接一起注册到反应堆中的类的实例中封装)。

作为程序员,您可以选择如何连接类的状态,但是通常可以通过将引用推入伙伴类来进行选择。

下面,此答案包含可运行的代码,这些代码将说明状态机/接口之间的数据连接方式。此SO中也对此进行了说明:扭曲的持久连接


扭曲是否提供通过应用程序管理多个状态机的机制?

如果通过“应用程序”表示“扭曲的代码”,那么答案是肯定的!

典型的Twisted应用程序是一系列状态机,所有状态机都有一些定义明确的界面。我开始了Twisted冒险,打算用两个状态机(一个串行接口和一个键盘)编写一个应用程序,但是当我对twisted感到满意时,我意识到添加额外的接口和状态机是微不足道的。的TX库)。整个下午,我都添加了一个粗糙的Web界面,即一个websocket界面,然后将SSL置于两者之上,甚至添加了一个SSH调试界面。一旦滚动,添加接口和状态机就变得微不足道了。

在许多(所有?)情况下,扭曲的模型是状态机将驻留在实例化类中,该实例化类与连接相关联并且已注册到(唯一一个)主事件循环中。

使用产生新状态机的连接类型(例如http连接),您可以注册一个工厂类/状态机以及侦听连接,这些监听类一起使该应用为每个新连接产生新类/状态机。大规模运行时,扭曲的应用程序通常会发生数十个甚至十万个并发状态实例。

如果您试图将不同的协议和状态粘合在一起,那么Twisted就是了不起的(…所有这些都位于您选择的事件循环中(select / epoll /
kqueue / etc))

以下是可运行的示例代码,应说明其中的许多要点。阅读之前的注释

def main()
以获取有关代码的更多背景信息:

#!/usr/bin/python## Frankenstein-esk amalgam of example pre#   Key of which comes from the Twisted "Chat" example#   (such as: http://twistedmatrix.com/documents/12.0.0/core/examples/chatserver.py)import sys # so I can get at stdinimport os # for isattyimport termios, tty # access to posix IO settingsfrom random import randomfrom twisted.internet import reactorfrom twisted.internet import stdio # the stdio equiv of listenXXXfrom twisted.protocols import basic # for lineReceiver for keyboardfrom twisted.internet.protocol import Protocol, ServerFactoryclass MyClientConnections(basic.LineReceiver):    def __init__(self):        self.storedState = "Idle"        self.connectionpos = None    def connectionMade(self):        self.factory.clients.append(self) # <--- magic here : # protocol automagically has a link to its factory class, and # in this case that is being used to push each new connection # (which is in the form of this class) into a list that the # factory can then access to get at each of the connections        self.connectionpos = str(self.factory.clients.index(self)) # figure out      # where I am in the connection array        print "Got new client! (index:", self.connectionpos + ")"        self.transport.write("---nYour connection: " + self.connectionpos + "n---n")    def connectionLost(self, reason):        print "Lost a client!"        self.factory.clients.remove(self)    # used to pretend that something was typed on a telnet connection    def fakeInput(self, message):        self.transport.write("FAKING Input: '" + message + "'n")        self.lineReceived(message)    #this is only in a def on its own so I can lump my demo callLater    def stateUpdate(self, newState, delay):        self.storedState = newState        # the following is a hack to fake data coming in this interface        reactor.callLater(delay, self.fakeInput, newState + " DONE")    def processInput(self, newState):        # all the logic in here is junk to make a demo, real pre may or may-not look like        # this.  This junk logic is an example statemachine though        if self.storedState == "Idle": if newState == "start":     self.stateUpdate("State A", 1)  # send a message to this connection     self.transport.write("starting state machinen")     # send a message to the term in which the script it running     print "Connection [" + self.connectionpos + "] starting state machine"        elif self.storedState == "State A": if newState == "State A DONE":     self.transport.write("Beginning state Bn")     self.stateUpdate("State B", 2)        elif self.storedState == "State B": if newState == "State B DONE":     self.transport.write("Beginning state Cn")     self.stateUpdate("State C", 2)        elif self.storedState == "State C": if newState == "State C DONE":     self.storedState = "Idle"     # send a message to this connection     self.transport.write("Returning to Idle staten")     # send a message to the term in which the script it running     print "Connection [" + self.connectionpos + "] return to Idle state"    def lineReceived(self, line):        # print "received '" + line +"' from connection", self.factory.clients.index(self)        self.processInput(line)class MyServerFactory(ServerFactory):    protocol = MyClientConnections    def __init__(self):        self.clients = [] # this gets filled from the class above    def sendToAll(self, message):      for c in self.clients:  # Read MyClientConnections class for background        c.transport.write(message)    def randStart(self, width):      for c in self.clients:        startDelay = random() * width        print "Starting client " + str(c.connectionpos) + " in " +str(startDelay) + " secs"         reactor.callLater(startDelay, c.processInput, "start")# to set keyboard into cbreak mode -- just because I like it that way...class Cbreaktty(object):    org_termio = None    my_termio = None    def __init__(self, ttyfd):        if(os.isatty(ttyfd)): self.org_termio = (ttyfd, termios.tcgetattr(ttyfd)) tty.setcbreak(ttyfd) print '  Set cbreak mode' self.my_termio = (ttyfd, termios.tcgetattr(ttyfd))        else:          raise IOError #Not something I can set cbreak on!    def retToOrgState(self):        (tty, org) = self.org_termio        print '  Restoring terminal settings'        termios.tcsetattr(tty, termios.TCSANOW, org)class KeyEater(basic.LineReceiver):    def __init__(self, factoryObj):        self.setRawMode() # Switch from line mode to "however much I got" mode        # the following is one of the key connecting ideas in twisted, the object        # that contains another state machine (really all of the tcp statemachines)        # has been passed into this class via its init.        self.factoryObj = factoryObj    def rawDataReceived(self, data):        key = str(data).lower()[0]        if key == 's': # The following line is going to call (from within the factory object) # the random start def self.factoryObj.randStart(5)        elif key == 'd': print "State Dump of connections" print "-------------------------" for c in self.factoryObj.clients:     print "#" + str(c.connectionpos) + "      " + c.storedState        elif key == 'q': reactor.stop()        else: print "--------------" print "  If you haven't already, connect to this script via a" print "  'telnet localhost 5000' at least one (multiple connections" print "  are better)" print "Press:" print "      s  - randomly start all clients" print "      d  - dump the state of all connected clients" print "      q  - to cleanly shutdown" print " Note: you can type commands in the connections, things" print "       most useful of which is 'start'" print "---------------"# Custom tailored example for SO:30397425# # This pre is a mishmash of styles and techniques. Both to provide different examples of how# something can be done and because I'm lazy.  Its been built and tested on OSX and linux,# it should be portable (other then perhaps termal cbreak mode).  If you want to ask# questions about this pre contact me directly via mail to mike at partialmesh.com## While it isn't directly using serial ports, the tcp connections that its using are a good# parallel.## It should be used by running the script and then opening up many windows telnet'ing into# localhost 5000.## once running press any key in the window where the script was run and it will give# instructions.  # The normal use case would be to type "s" to queue statemachine# start-ups, then repeatedly press 'd' to dump the status of all the state machines## 'start' can be typed into any of the telnet connections to start them by hand too.def main():    client_connection_factory = MyServerFactory()    try:      termstate = Cbreaktty(sys.stdin.fileno())    except IOError:      sys.stderr.write("Error: " + sys.argv[0] + " only for use on interactive ttysn")      sys.exit(1)    keyboardobj = KeyEater(client_connection_factory)    stdio.StandardIO(keyboardobj,sys.stdin.fileno())    reactor.listenTCP(5000, client_connection_factory)    reactor.run()    termstate.retToOrgState()if __name__ == '__main__':  main()

调制解调器的USB串行连接可能会由于调制解调器被拔出而被破坏,并在插入后重新建立。如何检测此类事件,并将对相应设备端口的监视添加到反应堆?目前,我正在主应用程序中静态地执行此 *** 作。

经过研究,我没有一个简单的答案。我仍然怀疑以下逻辑将接近解决方案,但我今天没有运气找到实现此功能的代码。

我的猜测是,将有一种合理的方法来确定是否发生了USB事件,并确定是否已添加了串行设备。但是我怀疑是否有一个很好的方法可以确定它是否是您的串行设备之一-
如果它是您的Command或Diagnostic接口(除非是您的建筑硬件并可以控制设备的USB ID),那么就更难了。

发生串行端口错误时会触发事件(至少从我在Linux上的经验来看),但是我不确定USB拔出将如何/在何处注册。


其他可能对您有用的链接
  • 扭曲的实现
    Utilities for talking to a GSM modem over USB via AT commands
    :https : //github.com/smn/txgsm
  • 通过USB扭曲实现气象站:https : //gist.github.com/claws/2464017


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5667410.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存