Note in your sample code
I donβt see how you create classes before registering them in the reactor. I expect this to fail badly. Here is a similar snippet of startup code:
# stuff to process messages coming from the serial port class 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...]
How / where do I accept CLI input from a user who then triggers sending a set of AT commands to modems?
Like you can register Serial handlers in Twisted, you can register handlers for standard io, for example:
# stuff to pull cbreak char input from stdin class 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 twisted keyboardobj = KeyEater() keyboardobj.serialobj = serialhandler stdio.StandardIO(keyboardobj,sys.stdin.fileno())
Correlation of information received in the command port for ttyUSB0 and ttyUSB1 for modem1, and similarly for another pair for modem2? Please note that each modem has its own state machine (device status and connection status)
In normal use, each instance of the connection will have its own state machine (wrapped in an instance of the class that you register in the reactor with the connection).
You, as a programmer, choose how you want to connect class states, but often by clicking on a link to partner classes.
Below this answer contains executable code that illustrates how data is related between states / interface. It is also shown in this SO: Permanent connection in twisted
Does any mechanism for managing multiple states twist the application?
If by "application" you mean "your twisted code," then the answer is absolutely YES!
A typical Twisted application is an array of state machines, all with some surprisingly well-defined interfaces. I started my Twisted adventure, intending to write an application with two state computers (serial and keyboard), but when I felt comfortable with a perverted one, I realized that it was trivial to add additional interfaces and state machines (through the whole miracle of tx libraries). I added everything in one day on the rough web interface, the web memory interface, and then put SSL on top of both and even added SSH to the debugging interface. Once you get rolling, adding the interfaces and states of the machines becomes trivial.
In many cases (all?) The twisted model is that the state-machine will be in an instance of the class attached to the connection, and which was registered in the main event (the same thing) -loop.
With the types of connections that new state machines generate (think of http connections), you register one factory-class / state-machine along with a listening connection, which together allows the application to propagate new classes / states for each new connection. Swirling applications are usually 10 or even 100 thousand out of thousands of simultaneous instances of state when run on a scale.
Twisted is amazing if you try to glue different protocols and states (... with all that it is in the event loop of your choice (select / epoll / kqueue / etc))
The following is sample code for an example that should illustrate many of these points. Read the comments before def main() for more information on the code:
#!/usr/bin/python
It is possible that the USB-serial connection to the modem will be destroyed due to disconnecting the modem and re-establishing it when connected to it. How can I detect such events and add monitoring of the corresponding device ports to the reactor? I am currently doing this statically in the main application.
After research, I do not have a simple answer. I still suspect that the following logic will be close to a solution, but I was not lucky to find code that implements this today.
I suppose there will be a reasonable way to find out if a USB event has occurred, and work if a serial device has been added. But I doubt that there will be a good way to find out if this is one of your serial devices - much less if its a command line interface or diagnostics (if your building cannot manage USB device identifiers)
Events are triggered with serial port errors (at least from my experience with Linux), but I'm not sure how / where the USB adapter will be disconnected.
Other links that may come in handy