blob: 1bd0f0cc2a1137449794875ead65e180549ba5d8 [file] [log] [blame]
cliechtid6bf52c2003-10-01 02:28:12 +00001#! python
cliechtic54b2c82008-06-21 01:59:08 +00002# Python Serial Port Extension for Win32, Linux, BSD, Jython
3# see __init__.py
cliechtid6bf52c2003-10-01 02:28:12 +00004#
Chris Liechti68340d72015-08-03 14:15:48 +02005# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
cliechtid6bf52c2003-10-01 02:28:12 +00006# this is distributed under a free software license, see license.txt
7
cliechtic323f1f2010-07-22 00:14:26 +00008
cliechti38077122013-10-16 02:57:27 +00009# ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
10# isn't returning the contents (very unfortunate). Therefore we need special
11# cases and test for it. Ensure that there is a ``memoryview`` object for older
12# Python versions. This is easier than making every test dependent on its
13# existence.
14try:
15 memoryview
16except (NameError, AttributeError):
17 # implementation does not matter as we do not realy use it.
18 # it just must not inherit from something else we might care for.
Chris Liechti70b89232015-08-04 03:00:52 +020019 class memoryview(object):
cliechti38077122013-10-16 02:57:27 +000020 pass
21
22
23# all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
24# so a simple ``bytes(sequence)`` doesn't work for all versions
cliechti32c10332009-08-05 13:23:43 +000025def to_bytes(seq):
26 """convert a sequence to a bytes type"""
cliechti38077122013-10-16 02:57:27 +000027 if isinstance(seq, bytes):
28 return seq
29 elif isinstance(seq, bytearray):
30 return bytes(seq)
31 elif isinstance(seq, memoryview):
32 return seq.tobytes()
33 else:
34 b = bytearray()
35 for item in seq:
cliechtie30868d2013-10-16 15:35:11 +000036 b.append(item) # this one handles int and str for our emulation and ints for Python 3.x
cliechti38077122013-10-16 02:57:27 +000037 return bytes(b)
cliechti32c10332009-08-05 13:23:43 +000038
39# create control bytes
40XON = to_bytes([17])
41XOFF = to_bytes([19])
cliechti4a567a02009-07-27 22:09:31 +000042
cliechti8e99b6f2010-07-21 15:46:39 +000043CR = to_bytes([13])
44LF = to_bytes([10])
45
cliechtia3a811f2009-07-29 21:59:03 +000046
cliechti0d6029a2008-06-21 01:28:46 +000047PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
cliechti58b481c2009-02-16 20:42:32 +000048STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
cliechti14b274a2009-02-07 00:27:05 +000049FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
cliechtid6bf52c2003-10-01 02:28:12 +000050
51PARITY_NAMES = {
cliechti4a567a02009-07-27 22:09:31 +000052 PARITY_NONE: 'None',
53 PARITY_EVEN: 'Even',
54 PARITY_ODD: 'Odd',
55 PARITY_MARK: 'Mark',
56 PARITY_SPACE: 'Space',
cliechtid6bf52c2003-10-01 02:28:12 +000057}
58
cliechti1dbe4b62002-02-14 02:49:25 +000059
cliechti4a567a02009-07-27 22:09:31 +000060class SerialException(IOError):
cliechtid6bf52c2003-10-01 02:28:12 +000061 """Base class for serial port related exceptions."""
cliechti7fe54d52002-03-03 20:11:47 +000062
cliechtid6bf52c2003-10-01 02:28:12 +000063
cliechti62611612004-04-20 01:55:43 +000064class SerialTimeoutException(SerialException):
65 """Write timeouts give an exception"""
66
cliechti4a567a02009-07-27 22:09:31 +000067
cliechti4b20ec62012-08-16 01:04:44 +000068writeTimeoutError = SerialTimeoutException('Write timeout')
69portNotOpenError = SerialException('Attempting to use a port that is not open')
cliechti62611612004-04-20 01:55:43 +000070
cliechtif81362e2009-07-25 03:44:33 +000071
cliechtif81362e2009-07-25 03:44:33 +000072class SerialBase(object):
cliechti7d448562014-08-03 21:57:45 +000073 """\
74 Serial port base class. Provides __init__ function and properties to
75 get/set port settings.
76 """
cliechti14b274a2009-02-07 00:27:05 +000077
cliechtidfec0c82009-07-21 01:35:41 +000078 # default values, may be overridden in subclasses that do not support all values
cliechtif81362e2009-07-25 03:44:33 +000079 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
80 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
81 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
82 3000000, 3500000, 4000000)
cliechtid6bf52c2003-10-01 02:28:12 +000083 BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
cliechti14b274a2009-02-07 00:27:05 +000084 PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
cliechti6ffdb8f2009-07-22 00:48:57 +000085 STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
cliechti14b274a2009-02-07 00:27:05 +000086
cliechtid6bf52c2003-10-01 02:28:12 +000087 def __init__(self,
cliechti14b274a2009-02-07 00:27:05 +000088 port = None, # number of device, numbering starts at
89 # zero. if everything fails, the user
90 # can specify a device string, note
91 # that this isn't portable anymore
92 # port will be opened if one is specified
cliechtidfec0c82009-07-21 01:35:41 +000093 baudrate=9600, # baud rate
94 bytesize=EIGHTBITS, # number of data bits
cliechti14b274a2009-02-07 00:27:05 +000095 parity=PARITY_NONE, # enable parity checking
cliechtidfec0c82009-07-21 01:35:41 +000096 stopbits=STOPBITS_ONE, # number of stop bits
cliechti14b274a2009-02-07 00:27:05 +000097 timeout=None, # set a timeout value, None to wait forever
cliechti74308e42010-07-21 14:03:59 +000098 xonxoff=False, # enable software flow control
99 rtscts=False, # enable RTS/CTS flow control
cliechti14b274a2009-02-07 00:27:05 +0000100 writeTimeout=None, # set a timeout for writes
cliechti58a2aee2010-05-20 23:37:57 +0000101 dsrdtr=False, # None: use rtscts setting, dsrdtr override if True or False
cliechti14b274a2009-02-07 00:27:05 +0000102 interCharTimeout=None # Inter-character timeout, None to disable
cliechtid6bf52c2003-10-01 02:28:12 +0000103 ):
cliechti7d448562014-08-03 21:57:45 +0000104 """\
105 Initialize comm port object. If a port is given, then the port will be
106 opened immediately. Otherwise a Serial port object in closed state
107 is returned.
108 """
cliechtid6bf52c2003-10-01 02:28:12 +0000109
110 self._isOpen = False
cliechti4a567a02009-07-27 22:09:31 +0000111 self._port = None # correct value is assigned below through properties
112 self._baudrate = None # correct value is assigned below through properties
113 self._bytesize = None # correct value is assigned below through properties
114 self._parity = None # correct value is assigned below through properties
115 self._stopbits = None # correct value is assigned below through properties
116 self._timeout = None # correct value is assigned below through properties
117 self._writeTimeout = None # correct value is assigned below through properties
118 self._xonxoff = None # correct value is assigned below through properties
119 self._rtscts = None # correct value is assigned below through properties
120 self._dsrdtr = None # correct value is assigned below through properties
121 self._interCharTimeout = None # correct value is assigned below through properties
cliechti14b274a2009-02-07 00:27:05 +0000122
123 # assign values using get/set methods using the properties feature
cliechtid6bf52c2003-10-01 02:28:12 +0000124 self.port = port
125 self.baudrate = baudrate
126 self.bytesize = bytesize
127 self.parity = parity
128 self.stopbits = stopbits
129 self.timeout = timeout
cliechti62611612004-04-20 01:55:43 +0000130 self.writeTimeout = writeTimeout
cliechtid6bf52c2003-10-01 02:28:12 +0000131 self.xonxoff = xonxoff
132 self.rtscts = rtscts
cliechtif46e0a82005-05-19 15:24:57 +0000133 self.dsrdtr = dsrdtr
cliechti679bfa62008-06-20 23:58:15 +0000134 self.interCharTimeout = interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000135
cliechtid6bf52c2003-10-01 02:28:12 +0000136 if port is not None:
137 self.open()
138
139 def isOpen(self):
140 """Check if the port is opened."""
141 return self._isOpen
142
cliechtid6bf52c2003-10-01 02:28:12 +0000143
144 # - - - - - - - - - - - - - - - - - - - - - - - -
145
Chris Liechti779b1a22015-08-04 14:54:22 +0200146 @property
147 def port(self):
148 """\
149 Get the current port setting. The value that was passed on init or using
150 setPort() is passed back. See also the attribute portstr which contains
151 the name of the port as a string.
152 """
153 return self._port
154
155 @port.setter
156 def port(self, port):
cliechti7d448562014-08-03 21:57:45 +0000157 """\
158 Change the port. The attribute portstr is set to a string that
159 contains the name of the port.
160 """
cliechti14b274a2009-02-07 00:27:05 +0000161
cliechtid6bf52c2003-10-01 02:28:12 +0000162 was_open = self._isOpen
163 if was_open: self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200164 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000165 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000166 self.name = self.portstr
cliechtid6bf52c2003-10-01 02:28:12 +0000167 if was_open: self.open()
cliechti14b274a2009-02-07 00:27:05 +0000168
cliechtid6bf52c2003-10-01 02:28:12 +0000169
Chris Liechti779b1a22015-08-04 14:54:22 +0200170 @property
171 def baudrate(self):
172 """Get the current baud rate setting."""
173 return self._baudrate
cliechtid6bf52c2003-10-01 02:28:12 +0000174
Chris Liechti779b1a22015-08-04 14:54:22 +0200175 @baudrate.setter
176 def baudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000177 """\
178 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000179 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000180 accepted and the exception is raised when the port is opened.
181 """
cliechti107db8d2004-01-15 01:20:23 +0000182 try:
cliechtie30868d2013-10-16 15:35:11 +0000183 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000184 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000185 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000186 else:
cliechtie30868d2013-10-16 15:35:11 +0000187 if b <= 0:
188 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
189 self._baudrate = b
cliechti107db8d2004-01-15 01:20:23 +0000190 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000191
cliechti14b274a2009-02-07 00:27:05 +0000192
Chris Liechti779b1a22015-08-04 14:54:22 +0200193 @property
194 def bytesize(self):
195 """Get the current byte size setting."""
196 return self._bytesize
cliechtid6bf52c2003-10-01 02:28:12 +0000197
Chris Liechti779b1a22015-08-04 14:54:22 +0200198 @bytesize.setter
199 def bytesize(self, bytesize):
cliechtid6bf52c2003-10-01 02:28:12 +0000200 """Change byte size."""
cliechti93db61b2006-08-26 19:16:18 +0000201 if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000202 self._bytesize = bytesize
203 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000204
cliechtid6bf52c2003-10-01 02:28:12 +0000205
206
Chris Liechti779b1a22015-08-04 14:54:22 +0200207 @property
208 def parity(self):
209 """Get the current parity setting."""
210 return self._parity
211
212 @parity.setter
213 def parity(self, parity):
cliechtid6bf52c2003-10-01 02:28:12 +0000214 """Change parity setting."""
cliechti93db61b2006-08-26 19:16:18 +0000215 if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000216 self._parity = parity
217 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000218
cliechtid6bf52c2003-10-01 02:28:12 +0000219
220
Chris Liechti779b1a22015-08-04 14:54:22 +0200221 @property
222 def stopbits(self):
223 """Get the current stop bits setting."""
224 return self._stopbits
225
226 @stopbits.setter
227 def stopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000228 """Change stop bits size."""
229 if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000230 self._stopbits = stopbits
231 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000232
cliechti14b274a2009-02-07 00:27:05 +0000233
Chris Liechti779b1a22015-08-04 14:54:22 +0200234 @property
235 def timeout(self):
236 """Get the current timeout setting."""
237 return self._timeout
cliechtid6bf52c2003-10-01 02:28:12 +0000238
Chris Liechti779b1a22015-08-04 14:54:22 +0200239 @timeout.setter
240 def timeout(self, timeout):
cliechtid6bf52c2003-10-01 02:28:12 +0000241 """Change timeout setting."""
242 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000243 try:
cliechti14b274a2009-02-07 00:27:05 +0000244 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000245 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000246 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti2750b832009-07-28 00:13:52 +0000247 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000248 self._timeout = timeout
249 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000250
Chris Liechti779b1a22015-08-04 14:54:22 +0200251
252 @property
253 def writeTimeout(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000254 """Get the current timeout setting."""
Chris Liechti779b1a22015-08-04 14:54:22 +0200255 return self._writeTimeout
cliechti14b274a2009-02-07 00:27:05 +0000256
Chris Liechti779b1a22015-08-04 14:54:22 +0200257 @writeTimeout.setter
258 def writeTimeout(self, timeout):
cliechti62611612004-04-20 01:55:43 +0000259 """Change timeout setting."""
260 if timeout is not None:
cliechti93db61b2006-08-26 19:16:18 +0000261 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000262 try:
263 timeout + 1 #test if it's a number, will throw a TypeError if not...
264 except TypeError:
265 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000266
cliechti62611612004-04-20 01:55:43 +0000267 self._writeTimeout = timeout
268 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000269
cliechti14b274a2009-02-07 00:27:05 +0000270
Chris Liechti779b1a22015-08-04 14:54:22 +0200271 @property
272 def xonxoff(self):
273 """Get the current XON/XOFF setting."""
274 return self._xonxoff
cliechtid6bf52c2003-10-01 02:28:12 +0000275
Chris Liechti779b1a22015-08-04 14:54:22 +0200276 @xonxoff.setter
277 def xonxoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000278 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000279 self._xonxoff = xonxoff
280 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000281
cliechti14b274a2009-02-07 00:27:05 +0000282
Chris Liechti779b1a22015-08-04 14:54:22 +0200283 @property
284 def rtscts(self):
285 """Get the current RTS/CTS flow control setting."""
286 return self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000287
Chris Liechti779b1a22015-08-04 14:54:22 +0200288 @rtscts.setter
289 def rtscts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000290 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000291 self._rtscts = rtscts
292 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000293
cliechti14b274a2009-02-07 00:27:05 +0000294
Chris Liechti779b1a22015-08-04 14:54:22 +0200295 @property
296 def dsrdtr(self):
297 """Get the current DSR/DTR flow control setting."""
298 return self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000299
Chris Liechti779b1a22015-08-04 14:54:22 +0200300 @dsrdtr.setter
301 def dsrdtr(self, dsrdtr=None):
cliechtif46e0a82005-05-19 15:24:57 +0000302 """Change DsrDtr flow control setting."""
303 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000304 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000305 self._dsrdtr = self._rtscts
306 else:
cliechti14b274a2009-02-07 00:27:05 +0000307 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000308 self._dsrdtr = dsrdtr
309 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000310
cliechti14b274a2009-02-07 00:27:05 +0000311
Chris Liechti779b1a22015-08-04 14:54:22 +0200312 @property
313 def interCharTimeout(self):
314 """Get the current inter-character timeout setting."""
315 return self._interCharTimeout
cliechti679bfa62008-06-20 23:58:15 +0000316
Chris Liechti779b1a22015-08-04 14:54:22 +0200317 @interCharTimeout.setter
318 def interCharTimeout(self, interCharTimeout):
cliechti679bfa62008-06-20 23:58:15 +0000319 """Change inter-character timeout setting."""
320 if interCharTimeout is not None:
321 if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
322 try:
cliechti14b274a2009-02-07 00:27:05 +0000323 interCharTimeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti679bfa62008-06-20 23:58:15 +0000324 except TypeError:
325 raise ValueError("Not a valid timeout: %r" % interCharTimeout)
cliechti14b274a2009-02-07 00:27:05 +0000326
cliechti679bfa62008-06-20 23:58:15 +0000327 self._interCharTimeout = interCharTimeout
328 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000329
cliechti679bfa62008-06-20 23:58:15 +0000330
cliechti4065dce2009-08-10 00:55:46 +0000331 # - - - - - - - - - - - - - - - - - - - - - - - -
332
333 _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
334 'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
335
336 def getSettingsDict(self):
cliechti7d448562014-08-03 21:57:45 +0000337 """\
338 Get current port settings as a dictionary. For use with
339 applySettingsDict.
340 """
cliechti4065dce2009-08-10 00:55:46 +0000341 return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
342
343 def applySettingsDict(self, d):
cliechti7d448562014-08-03 21:57:45 +0000344 """\
345 apply stored settings from a dictionary returned from
cliechti4065dce2009-08-10 00:55:46 +0000346 getSettingsDict. it's allowed to delete keys from the dictionary. these
cliechti7d448562014-08-03 21:57:45 +0000347 values will simply left unchanged.
348 """
cliechti4065dce2009-08-10 00:55:46 +0000349 for key in self._SETTINGS:
Chris Liechtib74be012015-08-04 16:36:01 +0200350 if key in d and d[key] != getattr(self, '_'+key): # check against internal "_" value
cliechti4065dce2009-08-10 00:55:46 +0000351 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000352
cliechtid6bf52c2003-10-01 02:28:12 +0000353 # - - - - - - - - - - - - - - - - - - - - - - - -
354
355 def __repr__(self):
356 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000357 return "%s<id=0x%x, open=%s>(port=%r, baudrate=%r, bytesize=%r, parity=%r, stopbits=%r, timeout=%r, xonxoff=%r, rtscts=%r, dsrdtr=%r)" % (
cliechtid6bf52c2003-10-01 02:28:12 +0000358 self.__class__.__name__,
359 id(self),
360 self._isOpen,
361 self.portstr,
362 self.baudrate,
363 self.bytesize,
364 self.parity,
365 self.stopbits,
366 self.timeout,
367 self.xonxoff,
368 self.rtscts,
cliechtif46e0a82005-05-19 15:24:57 +0000369 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000370 )
371
cliechti4a567a02009-07-27 22:09:31 +0000372
373 # - - - - - - - - - - - - - - - - - - - - - - - -
374 # compatibility with io library
375
376 def readable(self): return True
377 def writable(self): return True
378 def seekable(self): return False
379 def readinto(self, b):
380 data = self.read(len(b))
381 n = len(data)
382 try:
383 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200384 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000385 import array
386 if not isinstance(b, array.array):
387 raise err
388 b[:n] = array.array('b', data)
389 return n
cliechtif81362e2009-07-25 03:44:33 +0000390
Chris Liechti70b89232015-08-04 03:00:52 +0200391 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti779b1a22015-08-04 14:54:22 +0200392 # context manager
393
394 def __enter__(self):
395 return self
396
397 def __exit__(self, *args, **kwargs):
398 self.close()
399
400 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti70b89232015-08-04 03:00:52 +0200401 # additional functionality
402
403 def read_until(self, terminator=LF, size=None):
404 """\
405 Read until a termination sequence is found ('\n' by default), the size
406 is exceeded or until timeout occurs.
407 """
408 lenterm = len(terminator)
409 line = bytearray()
410 while True:
411 c = self.read(1)
412 if c:
413 line += c
414 if line[-lenterm:] == terminator:
415 break
416 if size is not None and len(line) >= size:
417 break
418 else:
419 break
420 return bytes(line)
421
422
423 def iread_until(self, *args, **kwargs):
424 """\
425 Read lines, implemented as generator. It will raise StopIteration on
426 timeout (empty read).
427 """
428 while True:
429 line = self.read_until(*args, **kwargs)
430 if not line: break
431 yield line
cliechtif81362e2009-07-25 03:44:33 +0000432
Chris Liechti779b1a22015-08-04 14:54:22 +0200433
434# - - - - - - - - - - - - - - - - - - - - - - - - -
cliechtid6bf52c2003-10-01 02:28:12 +0000435if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000436 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000437 s = SerialBase()
Chris Liechti779b1a22015-08-04 14:54:22 +0200438 sys.stdout.write('port name: %s\n' % s.name)
439 sys.stdout.write('baud rates: %s\n' % s.BAUDRATES)
440 sys.stdout.write('byte sizes: %s\n' % s.BYTESIZES)
441 sys.stdout.write('parities: %s\n' % s.PARITIES)
442 sys.stdout.write('stop bits: %s\n' % s.STOPBITS)
cliechtif81362e2009-07-25 03:44:33 +0000443 sys.stdout.write('%s\n' % s)