blob: 0844ecd0eecd88638845e5220e191c41990c5ca1 [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:
Chris Liechti07447732015-08-05 00:39:12 +020036 # this one handles int and bytes in Python 2.7
37 # add conversion in case of Python 3.x
38 if isinstance(item, bytes):
39 item = ord(item)
40 b.append(item)
cliechti38077122013-10-16 02:57:27 +000041 return bytes(b)
cliechti32c10332009-08-05 13:23:43 +000042
43# create control bytes
44XON = to_bytes([17])
45XOFF = to_bytes([19])
cliechti4a567a02009-07-27 22:09:31 +000046
cliechti8e99b6f2010-07-21 15:46:39 +000047CR = to_bytes([13])
48LF = to_bytes([10])
49
cliechtia3a811f2009-07-29 21:59:03 +000050
cliechti0d6029a2008-06-21 01:28:46 +000051PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
cliechti58b481c2009-02-16 20:42:32 +000052STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
cliechti14b274a2009-02-07 00:27:05 +000053FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
cliechtid6bf52c2003-10-01 02:28:12 +000054
55PARITY_NAMES = {
cliechti4a567a02009-07-27 22:09:31 +000056 PARITY_NONE: 'None',
57 PARITY_EVEN: 'Even',
58 PARITY_ODD: 'Odd',
59 PARITY_MARK: 'Mark',
60 PARITY_SPACE: 'Space',
cliechtid6bf52c2003-10-01 02:28:12 +000061}
62
cliechti1dbe4b62002-02-14 02:49:25 +000063
cliechti4a567a02009-07-27 22:09:31 +000064class SerialException(IOError):
cliechtid6bf52c2003-10-01 02:28:12 +000065 """Base class for serial port related exceptions."""
cliechti7fe54d52002-03-03 20:11:47 +000066
cliechtid6bf52c2003-10-01 02:28:12 +000067
cliechti62611612004-04-20 01:55:43 +000068class SerialTimeoutException(SerialException):
69 """Write timeouts give an exception"""
70
cliechti4a567a02009-07-27 22:09:31 +000071
cliechti4b20ec62012-08-16 01:04:44 +000072writeTimeoutError = SerialTimeoutException('Write timeout')
73portNotOpenError = SerialException('Attempting to use a port that is not open')
cliechti62611612004-04-20 01:55:43 +000074
cliechtif81362e2009-07-25 03:44:33 +000075
cliechtif81362e2009-07-25 03:44:33 +000076class SerialBase(object):
cliechti7d448562014-08-03 21:57:45 +000077 """\
78 Serial port base class. Provides __init__ function and properties to
79 get/set port settings.
80 """
cliechti14b274a2009-02-07 00:27:05 +000081
cliechtidfec0c82009-07-21 01:35:41 +000082 # default values, may be overridden in subclasses that do not support all values
cliechtif81362e2009-07-25 03:44:33 +000083 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
84 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
85 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
86 3000000, 3500000, 4000000)
cliechtid6bf52c2003-10-01 02:28:12 +000087 BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
cliechti14b274a2009-02-07 00:27:05 +000088 PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
cliechti6ffdb8f2009-07-22 00:48:57 +000089 STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
cliechti14b274a2009-02-07 00:27:05 +000090
cliechtid6bf52c2003-10-01 02:28:12 +000091 def __init__(self,
cliechti14b274a2009-02-07 00:27:05 +000092 port = None, # number of device, numbering starts at
93 # zero. if everything fails, the user
94 # can specify a device string, note
95 # that this isn't portable anymore
96 # port will be opened if one is specified
cliechtidfec0c82009-07-21 01:35:41 +000097 baudrate=9600, # baud rate
98 bytesize=EIGHTBITS, # number of data bits
cliechti14b274a2009-02-07 00:27:05 +000099 parity=PARITY_NONE, # enable parity checking
cliechtidfec0c82009-07-21 01:35:41 +0000100 stopbits=STOPBITS_ONE, # number of stop bits
cliechti14b274a2009-02-07 00:27:05 +0000101 timeout=None, # set a timeout value, None to wait forever
cliechti74308e42010-07-21 14:03:59 +0000102 xonxoff=False, # enable software flow control
103 rtscts=False, # enable RTS/CTS flow control
cliechti14b274a2009-02-07 00:27:05 +0000104 writeTimeout=None, # set a timeout for writes
cliechti58a2aee2010-05-20 23:37:57 +0000105 dsrdtr=False, # None: use rtscts setting, dsrdtr override if True or False
cliechti14b274a2009-02-07 00:27:05 +0000106 interCharTimeout=None # Inter-character timeout, None to disable
cliechtid6bf52c2003-10-01 02:28:12 +0000107 ):
cliechti7d448562014-08-03 21:57:45 +0000108 """\
109 Initialize comm port object. If a port is given, then the port will be
110 opened immediately. Otherwise a Serial port object in closed state
111 is returned.
112 """
cliechtid6bf52c2003-10-01 02:28:12 +0000113
114 self._isOpen = False
cliechti4a567a02009-07-27 22:09:31 +0000115 self._port = None # correct value is assigned below through properties
116 self._baudrate = None # correct value is assigned below through properties
117 self._bytesize = None # correct value is assigned below through properties
118 self._parity = None # correct value is assigned below through properties
119 self._stopbits = None # correct value is assigned below through properties
120 self._timeout = None # correct value is assigned below through properties
121 self._writeTimeout = None # correct value is assigned below through properties
122 self._xonxoff = None # correct value is assigned below through properties
123 self._rtscts = None # correct value is assigned below through properties
124 self._dsrdtr = None # correct value is assigned below through properties
125 self._interCharTimeout = None # correct value is assigned below through properties
cliechti14b274a2009-02-07 00:27:05 +0000126
127 # assign values using get/set methods using the properties feature
cliechtid6bf52c2003-10-01 02:28:12 +0000128 self.port = port
129 self.baudrate = baudrate
130 self.bytesize = bytesize
131 self.parity = parity
132 self.stopbits = stopbits
133 self.timeout = timeout
cliechti62611612004-04-20 01:55:43 +0000134 self.writeTimeout = writeTimeout
cliechtid6bf52c2003-10-01 02:28:12 +0000135 self.xonxoff = xonxoff
136 self.rtscts = rtscts
cliechtif46e0a82005-05-19 15:24:57 +0000137 self.dsrdtr = dsrdtr
cliechti679bfa62008-06-20 23:58:15 +0000138 self.interCharTimeout = interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000139
cliechtid6bf52c2003-10-01 02:28:12 +0000140 if port is not None:
141 self.open()
142
143 def isOpen(self):
144 """Check if the port is opened."""
145 return self._isOpen
146
cliechtid6bf52c2003-10-01 02:28:12 +0000147
148 # - - - - - - - - - - - - - - - - - - - - - - - -
149
Chris Liechti779b1a22015-08-04 14:54:22 +0200150 @property
151 def port(self):
152 """\
153 Get the current port setting. The value that was passed on init or using
154 setPort() is passed back. See also the attribute portstr which contains
155 the name of the port as a string.
156 """
157 return self._port
158
159 @port.setter
160 def port(self, port):
cliechti7d448562014-08-03 21:57:45 +0000161 """\
162 Change the port. The attribute portstr is set to a string that
163 contains the name of the port.
164 """
cliechti14b274a2009-02-07 00:27:05 +0000165
cliechtid6bf52c2003-10-01 02:28:12 +0000166 was_open = self._isOpen
167 if was_open: self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200168 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000169 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000170 self.name = self.portstr
cliechtid6bf52c2003-10-01 02:28:12 +0000171 if was_open: self.open()
cliechti14b274a2009-02-07 00:27:05 +0000172
cliechtid6bf52c2003-10-01 02:28:12 +0000173
Chris Liechti779b1a22015-08-04 14:54:22 +0200174 @property
175 def baudrate(self):
176 """Get the current baud rate setting."""
177 return self._baudrate
cliechtid6bf52c2003-10-01 02:28:12 +0000178
Chris Liechti779b1a22015-08-04 14:54:22 +0200179 @baudrate.setter
180 def baudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000181 """\
182 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000183 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000184 accepted and the exception is raised when the port is opened.
185 """
cliechti107db8d2004-01-15 01:20:23 +0000186 try:
cliechtie30868d2013-10-16 15:35:11 +0000187 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000188 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000189 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000190 else:
cliechtie30868d2013-10-16 15:35:11 +0000191 if b <= 0:
192 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
193 self._baudrate = b
cliechti107db8d2004-01-15 01:20:23 +0000194 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000195
cliechti14b274a2009-02-07 00:27:05 +0000196
Chris Liechti779b1a22015-08-04 14:54:22 +0200197 @property
198 def bytesize(self):
199 """Get the current byte size setting."""
200 return self._bytesize
cliechtid6bf52c2003-10-01 02:28:12 +0000201
Chris Liechti779b1a22015-08-04 14:54:22 +0200202 @bytesize.setter
203 def bytesize(self, bytesize):
cliechtid6bf52c2003-10-01 02:28:12 +0000204 """Change byte size."""
cliechti93db61b2006-08-26 19:16:18 +0000205 if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000206 self._bytesize = bytesize
207 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000208
cliechtid6bf52c2003-10-01 02:28:12 +0000209
210
Chris Liechti779b1a22015-08-04 14:54:22 +0200211 @property
212 def parity(self):
213 """Get the current parity setting."""
214 return self._parity
215
216 @parity.setter
217 def parity(self, parity):
cliechtid6bf52c2003-10-01 02:28:12 +0000218 """Change parity setting."""
cliechti93db61b2006-08-26 19:16:18 +0000219 if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000220 self._parity = parity
221 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000222
cliechtid6bf52c2003-10-01 02:28:12 +0000223
224
Chris Liechti779b1a22015-08-04 14:54:22 +0200225 @property
226 def stopbits(self):
227 """Get the current stop bits setting."""
228 return self._stopbits
229
230 @stopbits.setter
231 def stopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000232 """Change stop bits size."""
233 if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000234 self._stopbits = stopbits
235 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000236
cliechti14b274a2009-02-07 00:27:05 +0000237
Chris Liechti779b1a22015-08-04 14:54:22 +0200238 @property
239 def timeout(self):
240 """Get the current timeout setting."""
241 return self._timeout
cliechtid6bf52c2003-10-01 02:28:12 +0000242
Chris Liechti779b1a22015-08-04 14:54:22 +0200243 @timeout.setter
244 def timeout(self, timeout):
cliechtid6bf52c2003-10-01 02:28:12 +0000245 """Change timeout setting."""
246 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000247 try:
cliechti14b274a2009-02-07 00:27:05 +0000248 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000249 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000250 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti2750b832009-07-28 00:13:52 +0000251 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000252 self._timeout = timeout
253 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000254
Chris Liechti779b1a22015-08-04 14:54:22 +0200255
256 @property
257 def writeTimeout(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000258 """Get the current timeout setting."""
Chris Liechti779b1a22015-08-04 14:54:22 +0200259 return self._writeTimeout
cliechti14b274a2009-02-07 00:27:05 +0000260
Chris Liechti779b1a22015-08-04 14:54:22 +0200261 @writeTimeout.setter
262 def writeTimeout(self, timeout):
cliechti62611612004-04-20 01:55:43 +0000263 """Change timeout setting."""
264 if timeout is not None:
cliechti93db61b2006-08-26 19:16:18 +0000265 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000266 try:
267 timeout + 1 #test if it's a number, will throw a TypeError if not...
268 except TypeError:
269 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000270
cliechti62611612004-04-20 01:55:43 +0000271 self._writeTimeout = timeout
272 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000273
cliechti14b274a2009-02-07 00:27:05 +0000274
Chris Liechti779b1a22015-08-04 14:54:22 +0200275 @property
276 def xonxoff(self):
277 """Get the current XON/XOFF setting."""
278 return self._xonxoff
cliechtid6bf52c2003-10-01 02:28:12 +0000279
Chris Liechti779b1a22015-08-04 14:54:22 +0200280 @xonxoff.setter
281 def xonxoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000282 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000283 self._xonxoff = xonxoff
284 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000285
cliechti14b274a2009-02-07 00:27:05 +0000286
Chris Liechti779b1a22015-08-04 14:54:22 +0200287 @property
288 def rtscts(self):
289 """Get the current RTS/CTS flow control setting."""
290 return self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000291
Chris Liechti779b1a22015-08-04 14:54:22 +0200292 @rtscts.setter
293 def rtscts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000294 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000295 self._rtscts = rtscts
296 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000297
cliechti14b274a2009-02-07 00:27:05 +0000298
Chris Liechti779b1a22015-08-04 14:54:22 +0200299 @property
300 def dsrdtr(self):
301 """Get the current DSR/DTR flow control setting."""
302 return self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000303
Chris Liechti779b1a22015-08-04 14:54:22 +0200304 @dsrdtr.setter
305 def dsrdtr(self, dsrdtr=None):
cliechtif46e0a82005-05-19 15:24:57 +0000306 """Change DsrDtr flow control setting."""
307 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000308 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000309 self._dsrdtr = self._rtscts
310 else:
cliechti14b274a2009-02-07 00:27:05 +0000311 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000312 self._dsrdtr = dsrdtr
313 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000314
cliechti14b274a2009-02-07 00:27:05 +0000315
Chris Liechti779b1a22015-08-04 14:54:22 +0200316 @property
317 def interCharTimeout(self):
318 """Get the current inter-character timeout setting."""
319 return self._interCharTimeout
cliechti679bfa62008-06-20 23:58:15 +0000320
Chris Liechti779b1a22015-08-04 14:54:22 +0200321 @interCharTimeout.setter
322 def interCharTimeout(self, interCharTimeout):
cliechti679bfa62008-06-20 23:58:15 +0000323 """Change inter-character timeout setting."""
324 if interCharTimeout is not None:
325 if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
326 try:
cliechti14b274a2009-02-07 00:27:05 +0000327 interCharTimeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti679bfa62008-06-20 23:58:15 +0000328 except TypeError:
329 raise ValueError("Not a valid timeout: %r" % interCharTimeout)
cliechti14b274a2009-02-07 00:27:05 +0000330
cliechti679bfa62008-06-20 23:58:15 +0000331 self._interCharTimeout = interCharTimeout
332 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000333
cliechti679bfa62008-06-20 23:58:15 +0000334
cliechti4065dce2009-08-10 00:55:46 +0000335 # - - - - - - - - - - - - - - - - - - - - - - - -
336
337 _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
338 'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
339
340 def getSettingsDict(self):
cliechti7d448562014-08-03 21:57:45 +0000341 """\
342 Get current port settings as a dictionary. For use with
343 applySettingsDict.
344 """
cliechti4065dce2009-08-10 00:55:46 +0000345 return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
346
347 def applySettingsDict(self, d):
cliechti7d448562014-08-03 21:57:45 +0000348 """\
349 apply stored settings from a dictionary returned from
cliechti4065dce2009-08-10 00:55:46 +0000350 getSettingsDict. it's allowed to delete keys from the dictionary. these
cliechti7d448562014-08-03 21:57:45 +0000351 values will simply left unchanged.
352 """
cliechti4065dce2009-08-10 00:55:46 +0000353 for key in self._SETTINGS:
Chris Liechtib74be012015-08-04 16:36:01 +0200354 if key in d and d[key] != getattr(self, '_'+key): # check against internal "_" value
cliechti4065dce2009-08-10 00:55:46 +0000355 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000356
cliechtid6bf52c2003-10-01 02:28:12 +0000357 # - - - - - - - - - - - - - - - - - - - - - - - -
358
359 def __repr__(self):
360 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000361 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 +0000362 self.__class__.__name__,
363 id(self),
364 self._isOpen,
365 self.portstr,
366 self.baudrate,
367 self.bytesize,
368 self.parity,
369 self.stopbits,
370 self.timeout,
371 self.xonxoff,
372 self.rtscts,
cliechtif46e0a82005-05-19 15:24:57 +0000373 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000374 )
375
cliechti4a567a02009-07-27 22:09:31 +0000376
377 # - - - - - - - - - - - - - - - - - - - - - - - -
378 # compatibility with io library
379
380 def readable(self): return True
381 def writable(self): return True
382 def seekable(self): return False
383 def readinto(self, b):
384 data = self.read(len(b))
385 n = len(data)
386 try:
387 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200388 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000389 import array
390 if not isinstance(b, array.array):
391 raise err
392 b[:n] = array.array('b', data)
393 return n
cliechtif81362e2009-07-25 03:44:33 +0000394
Chris Liechti70b89232015-08-04 03:00:52 +0200395 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti779b1a22015-08-04 14:54:22 +0200396 # context manager
397
398 def __enter__(self):
399 return self
400
401 def __exit__(self, *args, **kwargs):
402 self.close()
403
404 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti70b89232015-08-04 03:00:52 +0200405 # additional functionality
406
407 def read_until(self, terminator=LF, size=None):
408 """\
409 Read until a termination sequence is found ('\n' by default), the size
410 is exceeded or until timeout occurs.
411 """
412 lenterm = len(terminator)
413 line = bytearray()
414 while True:
415 c = self.read(1)
416 if c:
417 line += c
418 if line[-lenterm:] == terminator:
419 break
420 if size is not None and len(line) >= size:
421 break
422 else:
423 break
424 return bytes(line)
425
426
427 def iread_until(self, *args, **kwargs):
428 """\
429 Read lines, implemented as generator. It will raise StopIteration on
430 timeout (empty read).
431 """
432 while True:
433 line = self.read_until(*args, **kwargs)
434 if not line: break
435 yield line
cliechtif81362e2009-07-25 03:44:33 +0000436
Chris Liechti779b1a22015-08-04 14:54:22 +0200437
438# - - - - - - - - - - - - - - - - - - - - - - - - -
cliechtid6bf52c2003-10-01 02:28:12 +0000439if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000440 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000441 s = SerialBase()
Chris Liechti779b1a22015-08-04 14:54:22 +0200442 sys.stdout.write('port name: %s\n' % s.name)
443 sys.stdout.write('baud rates: %s\n' % s.BAUDRATES)
444 sys.stdout.write('byte sizes: %s\n' % s.BYTESIZES)
445 sys.stdout.write('parities: %s\n' % s.PARITIES)
446 sys.stdout.write('stop bits: %s\n' % s.STOPBITS)
cliechtif81362e2009-07-25 03:44:33 +0000447 sys.stdout.write('%s\n' % s)