On Mon, 23 Mar 2009 05:30:04 -0500, Nick Craig-Wood <n...@craig-wood.com> wrote:
Jean-Paul Calderone <exar...@divmod.com> wrote:
[snip]
In the case of a TCP to serial forwarder, you don't actually have to
implement either a producer or a consumer, since both the TCP connection
and the serial connection are already both producers and consumers. All
you need to do is hook them up to each other so that when the send buffer
of one fills up, the other one gets paused, and when the buffer is empty
again, it gets resumed.
I eventually came up with this which seems to work, but I'm not sure
it is the best way of doing it as it had to mess about with the
twisted internals to get the number of bytes in the serial port
output buffer.
This is sort of on the right track. Here's how to do it without
touching implementation details:
class SerialPort(protocol.Protocol):
"""Create a serial port connection and pass data from it to a known list of TCP
ports."""
def __init__(self, port, reactor, baudrate, log_name=None):
self.tcp_ports = []
self.serial = serialport.SerialPort(self, reactor, port, baudrate,
rtscts=0)
Here, register this object to receive buffer full and not-full events from
the serial port:
self.serial.registerProducer(self, True)
And an attribute to keep track of our state:
self.paused = False
self.log = None
if log_name is not None:
self.log = file('%s-0' % log_name, 'w')
I'm not exactly sure where `self.tcp_ports´ gets populated, so I'll make a
method to do it:
def addPort(self, port):
if self.paused:
port.transport.pauseProducing()
self.tcp_ports.append(port)
Now a method to handle serial port buffer full events:
def pauseProducing(self):
self.paused = True
for port in self.tcp_ports:
port.transport.pauseProducing()
And a method to handle buffer no longer full events:
def resumeProducing(self):
self.paused = False
for port in self.tcp_ports:
port.transport.resumeProducing()
With these, you can get rid of `throttle´ entirely.
def write(self, data):
"""Write data to the serial port."""
self.serial.write(data)
if self.log:
self.log.write(data)
self.throttle()
def throttle(self):
"""
Pause the inputs if there is too much data in the output buffer
"""
bytes_in_buffer = len(self.serial.dataBuffer) + self.serial._tempDataLen
too_full = bytes_in_buffer > 1024
for tcp_port in self.tcp_ports:
if too_full:
tcp_port.transport.pauseProducing()
else:
tcp_port.transport.resumeProducing()
if too_full:
reactor.callLater(0.1, self.throttle)
Jean-Paul
--
http://mail.python.org/mailman/listinfo/python-list