Skip to content

Commit

Permalink
fixes to Packetizer/LineReader add context manager and connect method…
Browse files Browse the repository at this point in the history
… to SerialPortWorker
  • Loading branch information
zsquareplusc committed Oct 6, 2015
1 parent 9967c04 commit da3ccb5
Showing 1 changed file with 34 additions and 8 deletions.
42 changes: 34 additions & 8 deletions serial/threaded/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ def connection_lost(self, exc):
self.transport = None

def data_received(self, data):
self.line.extend(data)
while self.TERMINATOR in self.line:
self.buffer.extend(data)
while self.TERMINATOR in self.buffer:
packet, self.buffer = self.buffer.split(self.TERMINATOR)
self.handle_packet(packet)

Expand Down Expand Up @@ -78,8 +78,8 @@ class SerialPortWorker(threading.Thread):
Implement a serial port read loop and dispatch to a Protocol instance (like
the asyncio.Procotol) but do it with threads.
Calls to close will close the serial port but its also possible to just stop
this thread and continue the serial port instance otherwise.
Calls to close() will close the serial port but its also possible to just
stop() this thread and continue the serial port instance otherwise.
"""

def __init__(self, serial_instance, protocol_factory, use_logging=True):
Expand All @@ -96,16 +96,19 @@ def __init__(self, serial_instance, protocol_factory, use_logging=True):
self.use_logging = use_logging
self.alive = True
self.lock = threading.Lock()
self._connection_made = threading.Event()
self.protocol = None

def stop(self):
self.alive = False
self.join(2)

def run(self):
"""Reader loop"""
protocol = self.protocol_factory()
protocol.connection_made(self)
self.protocol = self.protocol_factory()
self.protocol.connection_made(self)
self.serial.timeout = 1
self._connection_made.set()
while self.alive and self.serial.is_open:
try:
# read all that is there or wait for one byte (blocking)
Expand All @@ -120,11 +123,12 @@ def run(self):
if data:
# make a separated try-except for user called code
try:
protocol.data_received(data)
self.protocol.data_received(data)
except:
if self.use_logging:
logging.exception('Error in %s (thread continues):', self.name)
protocol.connection_lost(None)
self.protocol.connection_lost(None)
self.protocol = None

def write(self, data):
"""Thread safe writing (uses lock)"""
Expand All @@ -139,6 +143,28 @@ def close(self):
self.stop()
self.serial.close()

def connect(self):
"""
Wait until connection is set up and return the transport and protocol
instances.
"""
if self.alive:
self._connection_made.wait()
return (self, self.protocol)
else:
raise RuntimeError('already stopped')

# - - context manager, returns protocol

def __enter__(self):
self.start()
self._connection_made.wait()
return self.protocol

def __exit__(self, *args, **kwargs):
self.close()


# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# test
if __name__ == '__main__':
Expand Down

0 comments on commit da3ccb5

Please sign in to comment.