blob: 5ed354f655763ff00ec0ca149af5e6e5545da89c [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
146 def setPort(self, port):
cliechti7d448562014-08-03 21:57:45 +0000147 """\
148 Change the port. The attribute portstr is set to a string that
149 contains the name of the port.
150 """
cliechti14b274a2009-02-07 00:27:05 +0000151
cliechtid6bf52c2003-10-01 02:28:12 +0000152 was_open = self._isOpen
153 if was_open: self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200154 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000155 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000156 self.name = self.portstr
cliechtid6bf52c2003-10-01 02:28:12 +0000157 if was_open: self.open()
cliechti14b274a2009-02-07 00:27:05 +0000158
cliechtid6bf52c2003-10-01 02:28:12 +0000159 def getPort(self):
cliechti7d448562014-08-03 21:57:45 +0000160 """\
161 Get the current port setting. The value that was passed on init or using
162 setPort() is passed back. See also the attribute portstr which contains
163 the name of the port as a string.
164 """
cliechtid6bf52c2003-10-01 02:28:12 +0000165 return self._port
166
cliechti0276f5e2004-11-13 03:14:11 +0000167 port = property(getPort, setPort, doc="Port setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000168
169
170 def setBaudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000171 """\
172 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000173 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000174 accepted and the exception is raised when the port is opened.
175 """
cliechti107db8d2004-01-15 01:20:23 +0000176 try:
cliechtie30868d2013-10-16 15:35:11 +0000177 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000178 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000179 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000180 else:
cliechtie30868d2013-10-16 15:35:11 +0000181 if b <= 0:
182 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
183 self._baudrate = b
cliechti107db8d2004-01-15 01:20:23 +0000184 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000185
cliechtid6bf52c2003-10-01 02:28:12 +0000186 def getBaudrate(self):
cliechti4a567a02009-07-27 22:09:31 +0000187 """Get the current baud rate setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000188 return self._baudrate
cliechti14b274a2009-02-07 00:27:05 +0000189
cliechti4a567a02009-07-27 22:09:31 +0000190 baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000191
192
193 def setByteSize(self, bytesize):
194 """Change byte size."""
cliechti93db61b2006-08-26 19:16:18 +0000195 if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000196 self._bytesize = bytesize
197 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000198
cliechtid6bf52c2003-10-01 02:28:12 +0000199 def getByteSize(self):
200 """Get the current byte size setting."""
201 return self._bytesize
cliechti14b274a2009-02-07 00:27:05 +0000202
cliechti0276f5e2004-11-13 03:14:11 +0000203 bytesize = property(getByteSize, setByteSize, doc="Byte size setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000204
205
206 def setParity(self, parity):
207 """Change parity setting."""
cliechti93db61b2006-08-26 19:16:18 +0000208 if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000209 self._parity = parity
210 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000211
cliechtid6bf52c2003-10-01 02:28:12 +0000212 def getParity(self):
213 """Get the current parity setting."""
214 return self._parity
cliechti14b274a2009-02-07 00:27:05 +0000215
cliechti0276f5e2004-11-13 03:14:11 +0000216 parity = property(getParity, setParity, doc="Parity setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000217
218
219 def setStopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000220 """Change stop bits size."""
221 if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000222 self._stopbits = stopbits
223 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000224
cliechtid6bf52c2003-10-01 02:28:12 +0000225 def getStopbits(self):
cliechti4a567a02009-07-27 22:09:31 +0000226 """Get the current stop bits setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000227 return self._stopbits
cliechti14b274a2009-02-07 00:27:05 +0000228
cliechti4a567a02009-07-27 22:09:31 +0000229 stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000230
231
232 def setTimeout(self, timeout):
233 """Change timeout setting."""
234 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000235 try:
cliechti14b274a2009-02-07 00:27:05 +0000236 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000237 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000238 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti2750b832009-07-28 00:13:52 +0000239 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000240 self._timeout = timeout
241 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000242
cliechtid6bf52c2003-10-01 02:28:12 +0000243 def getTimeout(self):
244 """Get the current timeout setting."""
245 return self._timeout
cliechti14b274a2009-02-07 00:27:05 +0000246
cliechti0276f5e2004-11-13 03:14:11 +0000247 timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()")
cliechti62611612004-04-20 01:55:43 +0000248
249
250 def setWriteTimeout(self, timeout):
251 """Change timeout setting."""
252 if timeout is not None:
cliechti93db61b2006-08-26 19:16:18 +0000253 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000254 try:
255 timeout + 1 #test if it's a number, will throw a TypeError if not...
256 except TypeError:
257 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000258
cliechti62611612004-04-20 01:55:43 +0000259 self._writeTimeout = timeout
260 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000261
cliechti62611612004-04-20 01:55:43 +0000262 def getWriteTimeout(self):
263 """Get the current timeout setting."""
264 return self._writeTimeout
cliechti14b274a2009-02-07 00:27:05 +0000265
cliechti0276f5e2004-11-13 03:14:11 +0000266 writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()")
cliechtid6bf52c2003-10-01 02:28:12 +0000267
268
269 def setXonXoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000270 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000271 self._xonxoff = xonxoff
272 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000273
cliechtid6bf52c2003-10-01 02:28:12 +0000274 def getXonXoff(self):
cliechti4a567a02009-07-27 22:09:31 +0000275 """Get the current XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000276 return self._xonxoff
cliechti14b274a2009-02-07 00:27:05 +0000277
cliechti4a567a02009-07-27 22:09:31 +0000278 xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000279
280 def setRtsCts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000281 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000282 self._rtscts = rtscts
283 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000284
cliechtid6bf52c2003-10-01 02:28:12 +0000285 def getRtsCts(self):
cliechti4a567a02009-07-27 22:09:31 +0000286 """Get the current RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000287 return self._rtscts
cliechti14b274a2009-02-07 00:27:05 +0000288
cliechtif46e0a82005-05-19 15:24:57 +0000289 rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000290
cliechtif46e0a82005-05-19 15:24:57 +0000291 def setDsrDtr(self, dsrdtr=None):
292 """Change DsrDtr flow control setting."""
293 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000294 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000295 self._dsrdtr = self._rtscts
296 else:
cliechti14b274a2009-02-07 00:27:05 +0000297 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000298 self._dsrdtr = dsrdtr
299 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000300
cliechtif46e0a82005-05-19 15:24:57 +0000301 def getDsrDtr(self):
cliechti4a567a02009-07-27 22:09:31 +0000302 """Get the current DSR/DTR flow control setting."""
cliechtif46e0a82005-05-19 15:24:57 +0000303 return self._dsrdtr
cliechti14b274a2009-02-07 00:27:05 +0000304
cliechtif46e0a82005-05-19 15:24:57 +0000305 dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
cliechti679bfa62008-06-20 23:58:15 +0000306
307 def setInterCharTimeout(self, interCharTimeout):
308 """Change inter-character timeout setting."""
309 if interCharTimeout is not None:
310 if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
311 try:
cliechti14b274a2009-02-07 00:27:05 +0000312 interCharTimeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti679bfa62008-06-20 23:58:15 +0000313 except TypeError:
314 raise ValueError("Not a valid timeout: %r" % interCharTimeout)
cliechti14b274a2009-02-07 00:27:05 +0000315
cliechti679bfa62008-06-20 23:58:15 +0000316 self._interCharTimeout = interCharTimeout
317 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000318
cliechti679bfa62008-06-20 23:58:15 +0000319 def getInterCharTimeout(self):
320 """Get the current inter-character timeout setting."""
321 return self._interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000322
cliechti679bfa62008-06-20 23:58:15 +0000323 interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()")
324
cliechti4065dce2009-08-10 00:55:46 +0000325 # - - - - - - - - - - - - - - - - - - - - - - - -
326
327 _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
328 'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
329
330 def getSettingsDict(self):
cliechti7d448562014-08-03 21:57:45 +0000331 """\
332 Get current port settings as a dictionary. For use with
333 applySettingsDict.
334 """
cliechti4065dce2009-08-10 00:55:46 +0000335 return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
336
337 def applySettingsDict(self, d):
cliechti7d448562014-08-03 21:57:45 +0000338 """\
339 apply stored settings from a dictionary returned from
cliechti4065dce2009-08-10 00:55:46 +0000340 getSettingsDict. it's allowed to delete keys from the dictionary. these
cliechti7d448562014-08-03 21:57:45 +0000341 values will simply left unchanged.
342 """
cliechti4065dce2009-08-10 00:55:46 +0000343 for key in self._SETTINGS:
344 if d[key] != getattr(self, '_'+key): # check against internal "_" value
345 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000346
cliechtid6bf52c2003-10-01 02:28:12 +0000347 # - - - - - - - - - - - - - - - - - - - - - - - -
348
349 def __repr__(self):
350 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000351 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 +0000352 self.__class__.__name__,
353 id(self),
354 self._isOpen,
355 self.portstr,
356 self.baudrate,
357 self.bytesize,
358 self.parity,
359 self.stopbits,
360 self.timeout,
361 self.xonxoff,
362 self.rtscts,
cliechtif46e0a82005-05-19 15:24:57 +0000363 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000364 )
365
cliechti4a567a02009-07-27 22:09:31 +0000366
367 # - - - - - - - - - - - - - - - - - - - - - - - -
368 # compatibility with io library
369
370 def readable(self): return True
371 def writable(self): return True
372 def seekable(self): return False
373 def readinto(self, b):
374 data = self.read(len(b))
375 n = len(data)
376 try:
377 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200378 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000379 import array
380 if not isinstance(b, array.array):
381 raise err
382 b[:n] = array.array('b', data)
383 return n
cliechtif81362e2009-07-25 03:44:33 +0000384
Chris Liechti70b89232015-08-04 03:00:52 +0200385 # - - - - - - - - - - - - - - - - - - - - - - - -
386 # additional functionality
387
388 def read_until(self, terminator=LF, size=None):
389 """\
390 Read until a termination sequence is found ('\n' by default), the size
391 is exceeded or until timeout occurs.
392 """
393 lenterm = len(terminator)
394 line = bytearray()
395 while True:
396 c = self.read(1)
397 if c:
398 line += c
399 if line[-lenterm:] == terminator:
400 break
401 if size is not None and len(line) >= size:
402 break
403 else:
404 break
405 return bytes(line)
406
407
408 def iread_until(self, *args, **kwargs):
409 """\
410 Read lines, implemented as generator. It will raise StopIteration on
411 timeout (empty read).
412 """
413 while True:
414 line = self.read_until(*args, **kwargs)
415 if not line: break
416 yield line
cliechtif81362e2009-07-25 03:44:33 +0000417
cliechtid6bf52c2003-10-01 02:28:12 +0000418if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000419 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000420 s = SerialBase()
cliechtif81362e2009-07-25 03:44:33 +0000421 sys.stdout.write('port name: %s\n' % s.portstr)
422 sys.stdout.write('baud rates: %s\n' % s.getSupportedBaudrates())
423 sys.stdout.write('byte sizes: %s\n' % s.getSupportedByteSizes())
424 sys.stdout.write('parities: %s\n' % s.getSupportedParities())
425 sys.stdout.write('stop bits: %s\n' % s.getSupportedStopbits())
426 sys.stdout.write('%s\n' % s)