blob: 165f3fd548780d83bc584b2f090dfefe0c6312a6 [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
cliechti8e99b6f2010-07-21 15:46:39 +00008# compatibility for older Python < 2.6
cliechti4a567a02009-07-27 22:09:31 +00009try:
10 bytes
11 bytearray
cliechtia3a811f2009-07-29 21:59:03 +000012except (NameError, AttributeError):
cliechti4a567a02009-07-27 22:09:31 +000013 # Python older than 2.6 do not have these types. Like for Python 2.6 they
cliechti2750b832009-07-28 00:13:52 +000014 # should behave like str. For Python older than 3.0 we want to work with
15 # strings anyway, only later versions have a true bytes type.
cliechti4a567a02009-07-27 22:09:31 +000016 bytes = str
17 # bytearray is a mutable type that is easily turned into an instance of
18 # bytes
19 class bytearray(list):
20 # for bytes(bytearray()) usage
21 def __str__(self): return ''.join(self)
cliechtic323f1f2010-07-22 00:14:26 +000022 def __repr__(self): return 'bytearray(%r)' % ''.join(self)
cliechti4a567a02009-07-27 22:09:31 +000023 # append automatically converts integers to characters
24 def append(self, item):
25 if isinstance(item, str):
26 list.append(self, item)
27 else:
28 list.append(self, chr(item))
cliechti1de32cd2009-08-07 19:05:09 +000029 # +=
30 def __iadd__(self, other):
31 for byte in other:
32 self.append(byte)
33 return self
cliechti0bbebbf2009-07-30 17:23:42 +000034
cliechtic323f1f2010-07-22 00:14:26 +000035 def __getslice__(self, i, j):
36 return bytearray(list.__getslice__(self, i, j))
37
38 def __getitem__(self, item):
39 if isinstance(item, slice):
40 return bytearray(list.__getitem__(self, item))
41 else:
42 return ord(list.__getitem__(self, item))
43
44 def __eq__(self, other):
45 if isinstance(other, basestring):
46 other = bytearray(other)
47 return list.__eq__(self, other)
48
cliechti38077122013-10-16 02:57:27 +000049# ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
50# isn't returning the contents (very unfortunate). Therefore we need special
51# cases and test for it. Ensure that there is a ``memoryview`` object for older
52# Python versions. This is easier than making every test dependent on its
53# existence.
54try:
55 memoryview
56except (NameError, AttributeError):
57 # implementation does not matter as we do not realy use it.
58 # it just must not inherit from something else we might care for.
59 class memoryview:
60 pass
61
62
63# all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
64# so a simple ``bytes(sequence)`` doesn't work for all versions
cliechti32c10332009-08-05 13:23:43 +000065def to_bytes(seq):
66 """convert a sequence to a bytes type"""
cliechti38077122013-10-16 02:57:27 +000067 if isinstance(seq, bytes):
68 return seq
69 elif isinstance(seq, bytearray):
70 return bytes(seq)
71 elif isinstance(seq, memoryview):
72 return seq.tobytes()
73 else:
74 b = bytearray()
75 for item in seq:
cliechtie30868d2013-10-16 15:35:11 +000076 b.append(item) # this one handles int and str for our emulation and ints for Python 3.x
cliechti38077122013-10-16 02:57:27 +000077 return bytes(b)
cliechti32c10332009-08-05 13:23:43 +000078
79# create control bytes
80XON = to_bytes([17])
81XOFF = to_bytes([19])
cliechti4a567a02009-07-27 22:09:31 +000082
cliechti8e99b6f2010-07-21 15:46:39 +000083CR = to_bytes([13])
84LF = to_bytes([10])
85
cliechtia3a811f2009-07-29 21:59:03 +000086
cliechti0d6029a2008-06-21 01:28:46 +000087PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
cliechti58b481c2009-02-16 20:42:32 +000088STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
cliechti14b274a2009-02-07 00:27:05 +000089FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
cliechtid6bf52c2003-10-01 02:28:12 +000090
91PARITY_NAMES = {
cliechti4a567a02009-07-27 22:09:31 +000092 PARITY_NONE: 'None',
93 PARITY_EVEN: 'Even',
94 PARITY_ODD: 'Odd',
95 PARITY_MARK: 'Mark',
96 PARITY_SPACE: 'Space',
cliechtid6bf52c2003-10-01 02:28:12 +000097}
98
cliechti1dbe4b62002-02-14 02:49:25 +000099
cliechti4a567a02009-07-27 22:09:31 +0000100class SerialException(IOError):
cliechtid6bf52c2003-10-01 02:28:12 +0000101 """Base class for serial port related exceptions."""
cliechti7fe54d52002-03-03 20:11:47 +0000102
cliechtid6bf52c2003-10-01 02:28:12 +0000103
cliechti62611612004-04-20 01:55:43 +0000104class SerialTimeoutException(SerialException):
105 """Write timeouts give an exception"""
106
cliechti4a567a02009-07-27 22:09:31 +0000107
cliechti4b20ec62012-08-16 01:04:44 +0000108writeTimeoutError = SerialTimeoutException('Write timeout')
109portNotOpenError = SerialException('Attempting to use a port that is not open')
cliechti62611612004-04-20 01:55:43 +0000110
cliechtif81362e2009-07-25 03:44:33 +0000111
cliechtid6bf52c2003-10-01 02:28:12 +0000112class FileLike(object):
cliechti7d448562014-08-03 21:57:45 +0000113 """\
114 An abstract file like class.
cliechti14b274a2009-02-07 00:27:05 +0000115
cliechti1dbe4b62002-02-14 02:49:25 +0000116 This class implements readline and readlines based on read and
117 writelines based on write.
118 This class is used to provide the above functions for to Serial
119 port objects.
cliechti14b274a2009-02-07 00:27:05 +0000120
cliechti1dbe4b62002-02-14 02:49:25 +0000121 Note that when the serial port was opened with _NO_ timeout that
122 readline blocks until it sees a newline (or the specified size is
123 reached) and that readlines would never return and therefore
124 refuses to work (it raises an exception in this case)!
125 """
126
cliechtif81362e2009-07-25 03:44:33 +0000127 def __init__(self):
128 self.closed = True
129
130 def close(self):
131 self.closed = True
132
133 # so that ports are closed when objects are discarded
134 def __del__(self):
135 """Destructor. Calls close()."""
136 # The try/except block is in case this is called at program
137 # exit time, when it's possible that globals have already been
138 # deleted, and then the close() call might fail. Since
139 # there's nothing we can do about such failures and they annoy
140 # the end users, we suppress the traceback.
141 try:
142 self.close()
143 except:
144 pass
145
cliechti1dbe4b62002-02-14 02:49:25 +0000146 def writelines(self, sequence):
147 for line in sequence:
148 self.write(line)
149
150 def flush(self):
cliechti1bb1bb22002-08-18 00:43:58 +0000151 """flush of file like objects"""
152 pass
cliechti1dbe4b62002-02-14 02:49:25 +0000153
cliechti980e4b02005-12-20 23:19:58 +0000154 # iterator for e.g. "for line in Serial(0): ..." usage
155 def next(self):
156 line = self.readline()
157 if not line: raise StopIteration
158 return line
159
160 def __iter__(self):
161 return self
162
cliechti8e99b6f2010-07-21 15:46:39 +0000163 def readline(self, size=None, eol=LF):
cliechti7d448562014-08-03 21:57:45 +0000164 """\
165 Read a line which is terminated with end-of-line (eol) character
166 ('\n' by default) or until timeout.
167 """
cliechti8e99b6f2010-07-21 15:46:39 +0000168 leneol = len(eol)
169 line = bytearray()
170 while True:
171 c = self.read(1)
172 if c:
173 line += c
174 if line[-leneol:] == eol:
175 break
176 if size is not None and len(line) >= size:
177 break
178 else:
179 break
180 return bytes(line)
181
cliechtic323f1f2010-07-22 00:14:26 +0000182 def readlines(self, sizehint=None, eol=LF):
cliechti7d448562014-08-03 21:57:45 +0000183 """\
184 Read a list of lines, until timeout.
185 sizehint is ignored.
186 """
cliechti8e99b6f2010-07-21 15:46:39 +0000187 if self.timeout is None:
188 raise ValueError("Serial port MUST have enabled timeout for this function!")
cliechti0f2bd582011-08-05 02:58:37 +0000189 leneol = len(eol)
cliechti8e99b6f2010-07-21 15:46:39 +0000190 lines = []
191 while True:
192 line = self.readline(eol=eol)
193 if line:
194 lines.append(line)
cliechti0f2bd582011-08-05 02:58:37 +0000195 if line[-leneol:] != eol: # was the line received with a timeout?
cliechti8e99b6f2010-07-21 15:46:39 +0000196 break
197 else:
198 break
199 return lines
200
201 def xreadlines(self, sizehint=None):
cliechti7d448562014-08-03 21:57:45 +0000202 """\
203 Read lines, implemented as generator. It will raise StopIteration on
204 timeout (empty read). sizehint is ignored.
205 """
cliechti8e99b6f2010-07-21 15:46:39 +0000206 while True:
207 line = self.readline()
208 if not line: break
209 yield line
210
cliechtif81362e2009-07-25 03:44:33 +0000211 # other functions of file-likes - not used by pySerial
cliechti980e4b02005-12-20 23:19:58 +0000212
cliechtif81362e2009-07-25 03:44:33 +0000213 #~ readinto(b)
214
215 def seek(self, pos, whence=0):
216 raise IOError("file is not seekable")
217
218 def tell(self):
219 raise IOError("file is not seekable")
220
221 def truncate(self, n=None):
222 raise IOError("file is not seekable")
223
224 def isatty(self):
225 return False
226
227
228class SerialBase(object):
cliechti7d448562014-08-03 21:57:45 +0000229 """\
230 Serial port base class. Provides __init__ function and properties to
231 get/set port settings.
232 """
cliechti14b274a2009-02-07 00:27:05 +0000233
cliechtidfec0c82009-07-21 01:35:41 +0000234 # default values, may be overridden in subclasses that do not support all values
cliechtif81362e2009-07-25 03:44:33 +0000235 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
236 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
237 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
238 3000000, 3500000, 4000000)
cliechtid6bf52c2003-10-01 02:28:12 +0000239 BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
cliechti14b274a2009-02-07 00:27:05 +0000240 PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
cliechti6ffdb8f2009-07-22 00:48:57 +0000241 STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
cliechti14b274a2009-02-07 00:27:05 +0000242
cliechtid6bf52c2003-10-01 02:28:12 +0000243 def __init__(self,
cliechti14b274a2009-02-07 00:27:05 +0000244 port = None, # number of device, numbering starts at
245 # zero. if everything fails, the user
246 # can specify a device string, note
247 # that this isn't portable anymore
248 # port will be opened if one is specified
cliechtidfec0c82009-07-21 01:35:41 +0000249 baudrate=9600, # baud rate
250 bytesize=EIGHTBITS, # number of data bits
cliechti14b274a2009-02-07 00:27:05 +0000251 parity=PARITY_NONE, # enable parity checking
cliechtidfec0c82009-07-21 01:35:41 +0000252 stopbits=STOPBITS_ONE, # number of stop bits
cliechti14b274a2009-02-07 00:27:05 +0000253 timeout=None, # set a timeout value, None to wait forever
cliechti74308e42010-07-21 14:03:59 +0000254 xonxoff=False, # enable software flow control
255 rtscts=False, # enable RTS/CTS flow control
cliechti14b274a2009-02-07 00:27:05 +0000256 writeTimeout=None, # set a timeout for writes
cliechti58a2aee2010-05-20 23:37:57 +0000257 dsrdtr=False, # None: use rtscts setting, dsrdtr override if True or False
cliechti14b274a2009-02-07 00:27:05 +0000258 interCharTimeout=None # Inter-character timeout, None to disable
cliechtid6bf52c2003-10-01 02:28:12 +0000259 ):
cliechti7d448562014-08-03 21:57:45 +0000260 """\
261 Initialize comm port object. If a port is given, then the port will be
262 opened immediately. Otherwise a Serial port object in closed state
263 is returned.
264 """
cliechtid6bf52c2003-10-01 02:28:12 +0000265
266 self._isOpen = False
cliechti4a567a02009-07-27 22:09:31 +0000267 self._port = None # correct value is assigned below through properties
268 self._baudrate = None # correct value is assigned below through properties
269 self._bytesize = None # correct value is assigned below through properties
270 self._parity = None # correct value is assigned below through properties
271 self._stopbits = None # correct value is assigned below through properties
272 self._timeout = None # correct value is assigned below through properties
273 self._writeTimeout = None # correct value is assigned below through properties
274 self._xonxoff = None # correct value is assigned below through properties
275 self._rtscts = None # correct value is assigned below through properties
276 self._dsrdtr = None # correct value is assigned below through properties
277 self._interCharTimeout = None # correct value is assigned below through properties
cliechti14b274a2009-02-07 00:27:05 +0000278
279 # assign values using get/set methods using the properties feature
cliechtid6bf52c2003-10-01 02:28:12 +0000280 self.port = port
281 self.baudrate = baudrate
282 self.bytesize = bytesize
283 self.parity = parity
284 self.stopbits = stopbits
285 self.timeout = timeout
cliechti62611612004-04-20 01:55:43 +0000286 self.writeTimeout = writeTimeout
cliechtid6bf52c2003-10-01 02:28:12 +0000287 self.xonxoff = xonxoff
288 self.rtscts = rtscts
cliechtif46e0a82005-05-19 15:24:57 +0000289 self.dsrdtr = dsrdtr
cliechti679bfa62008-06-20 23:58:15 +0000290 self.interCharTimeout = interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000291
cliechtid6bf52c2003-10-01 02:28:12 +0000292 if port is not None:
293 self.open()
294
295 def isOpen(self):
296 """Check if the port is opened."""
297 return self._isOpen
298
299 # - - - - - - - - - - - - - - - - - - - - - - - -
300
cliechti9147c442009-07-21 22:12:16 +0000301 # TODO: these are not really needed as the is the BAUDRATES etc. attribute...
cliechti14b274a2009-02-07 00:27:05 +0000302 # maybe i remove them before the final release...
303
cliechtid6bf52c2003-10-01 02:28:12 +0000304 def getSupportedBaudrates(self):
305 return [(str(b), b) for b in self.BAUDRATES]
306
307 def getSupportedByteSizes(self):
308 return [(str(b), b) for b in self.BYTESIZES]
cliechti14b274a2009-02-07 00:27:05 +0000309
cliechtid6bf52c2003-10-01 02:28:12 +0000310 def getSupportedStopbits(self):
311 return [(str(b), b) for b in self.STOPBITS]
312
313 def getSupportedParities(self):
314 return [(PARITY_NAMES[b], b) for b in self.PARITIES]
315
316 # - - - - - - - - - - - - - - - - - - - - - - - -
317
318 def setPort(self, port):
cliechti7d448562014-08-03 21:57:45 +0000319 """\
320 Change the port. The attribute portstr is set to a string that
321 contains the name of the port.
322 """
cliechti14b274a2009-02-07 00:27:05 +0000323
cliechtid6bf52c2003-10-01 02:28:12 +0000324 was_open = self._isOpen
325 if was_open: self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200326 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000327 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000328 self.name = self.portstr
cliechtid6bf52c2003-10-01 02:28:12 +0000329 if was_open: self.open()
cliechti14b274a2009-02-07 00:27:05 +0000330
cliechtid6bf52c2003-10-01 02:28:12 +0000331 def getPort(self):
cliechti7d448562014-08-03 21:57:45 +0000332 """\
333 Get the current port setting. The value that was passed on init or using
334 setPort() is passed back. See also the attribute portstr which contains
335 the name of the port as a string.
336 """
cliechtid6bf52c2003-10-01 02:28:12 +0000337 return self._port
338
cliechti0276f5e2004-11-13 03:14:11 +0000339 port = property(getPort, setPort, doc="Port setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000340
341
342 def setBaudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000343 """\
344 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000345 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000346 accepted and the exception is raised when the port is opened.
347 """
cliechti107db8d2004-01-15 01:20:23 +0000348 try:
cliechtie30868d2013-10-16 15:35:11 +0000349 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000350 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000351 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000352 else:
cliechtie30868d2013-10-16 15:35:11 +0000353 if b <= 0:
354 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
355 self._baudrate = b
cliechti107db8d2004-01-15 01:20:23 +0000356 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000357
cliechtid6bf52c2003-10-01 02:28:12 +0000358 def getBaudrate(self):
cliechti4a567a02009-07-27 22:09:31 +0000359 """Get the current baud rate setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000360 return self._baudrate
cliechti14b274a2009-02-07 00:27:05 +0000361
cliechti4a567a02009-07-27 22:09:31 +0000362 baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000363
364
365 def setByteSize(self, bytesize):
366 """Change byte size."""
cliechti93db61b2006-08-26 19:16:18 +0000367 if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000368 self._bytesize = bytesize
369 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000370
cliechtid6bf52c2003-10-01 02:28:12 +0000371 def getByteSize(self):
372 """Get the current byte size setting."""
373 return self._bytesize
cliechti14b274a2009-02-07 00:27:05 +0000374
cliechti0276f5e2004-11-13 03:14:11 +0000375 bytesize = property(getByteSize, setByteSize, doc="Byte size setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000376
377
378 def setParity(self, parity):
379 """Change parity setting."""
cliechti93db61b2006-08-26 19:16:18 +0000380 if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000381 self._parity = parity
382 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000383
cliechtid6bf52c2003-10-01 02:28:12 +0000384 def getParity(self):
385 """Get the current parity setting."""
386 return self._parity
cliechti14b274a2009-02-07 00:27:05 +0000387
cliechti0276f5e2004-11-13 03:14:11 +0000388 parity = property(getParity, setParity, doc="Parity setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000389
390
391 def setStopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000392 """Change stop bits size."""
393 if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000394 self._stopbits = stopbits
395 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000396
cliechtid6bf52c2003-10-01 02:28:12 +0000397 def getStopbits(self):
cliechti4a567a02009-07-27 22:09:31 +0000398 """Get the current stop bits setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000399 return self._stopbits
cliechti14b274a2009-02-07 00:27:05 +0000400
cliechti4a567a02009-07-27 22:09:31 +0000401 stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000402
403
404 def setTimeout(self, timeout):
405 """Change timeout setting."""
406 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000407 try:
cliechti14b274a2009-02-07 00:27:05 +0000408 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000409 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000410 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti2750b832009-07-28 00:13:52 +0000411 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000412 self._timeout = timeout
413 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000414
cliechtid6bf52c2003-10-01 02:28:12 +0000415 def getTimeout(self):
416 """Get the current timeout setting."""
417 return self._timeout
cliechti14b274a2009-02-07 00:27:05 +0000418
cliechti0276f5e2004-11-13 03:14:11 +0000419 timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()")
cliechti62611612004-04-20 01:55:43 +0000420
421
422 def setWriteTimeout(self, timeout):
423 """Change timeout setting."""
424 if timeout is not None:
cliechti93db61b2006-08-26 19:16:18 +0000425 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000426 try:
427 timeout + 1 #test if it's a number, will throw a TypeError if not...
428 except TypeError:
429 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000430
cliechti62611612004-04-20 01:55:43 +0000431 self._writeTimeout = timeout
432 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000433
cliechti62611612004-04-20 01:55:43 +0000434 def getWriteTimeout(self):
435 """Get the current timeout setting."""
436 return self._writeTimeout
cliechti14b274a2009-02-07 00:27:05 +0000437
cliechti0276f5e2004-11-13 03:14:11 +0000438 writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()")
cliechtid6bf52c2003-10-01 02:28:12 +0000439
440
441 def setXonXoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000442 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000443 self._xonxoff = xonxoff
444 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000445
cliechtid6bf52c2003-10-01 02:28:12 +0000446 def getXonXoff(self):
cliechti4a567a02009-07-27 22:09:31 +0000447 """Get the current XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000448 return self._xonxoff
cliechti14b274a2009-02-07 00:27:05 +0000449
cliechti4a567a02009-07-27 22:09:31 +0000450 xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000451
452 def setRtsCts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000453 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000454 self._rtscts = rtscts
455 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000456
cliechtid6bf52c2003-10-01 02:28:12 +0000457 def getRtsCts(self):
cliechti4a567a02009-07-27 22:09:31 +0000458 """Get the current RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000459 return self._rtscts
cliechti14b274a2009-02-07 00:27:05 +0000460
cliechtif46e0a82005-05-19 15:24:57 +0000461 rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000462
cliechtif46e0a82005-05-19 15:24:57 +0000463 def setDsrDtr(self, dsrdtr=None):
464 """Change DsrDtr flow control setting."""
465 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000466 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000467 self._dsrdtr = self._rtscts
468 else:
cliechti14b274a2009-02-07 00:27:05 +0000469 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000470 self._dsrdtr = dsrdtr
471 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000472
cliechtif46e0a82005-05-19 15:24:57 +0000473 def getDsrDtr(self):
cliechti4a567a02009-07-27 22:09:31 +0000474 """Get the current DSR/DTR flow control setting."""
cliechtif46e0a82005-05-19 15:24:57 +0000475 return self._dsrdtr
cliechti14b274a2009-02-07 00:27:05 +0000476
cliechtif46e0a82005-05-19 15:24:57 +0000477 dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
cliechti679bfa62008-06-20 23:58:15 +0000478
479 def setInterCharTimeout(self, interCharTimeout):
480 """Change inter-character timeout setting."""
481 if interCharTimeout is not None:
482 if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
483 try:
cliechti14b274a2009-02-07 00:27:05 +0000484 interCharTimeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti679bfa62008-06-20 23:58:15 +0000485 except TypeError:
486 raise ValueError("Not a valid timeout: %r" % interCharTimeout)
cliechti14b274a2009-02-07 00:27:05 +0000487
cliechti679bfa62008-06-20 23:58:15 +0000488 self._interCharTimeout = interCharTimeout
489 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000490
cliechti679bfa62008-06-20 23:58:15 +0000491 def getInterCharTimeout(self):
492 """Get the current inter-character timeout setting."""
493 return self._interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000494
cliechti679bfa62008-06-20 23:58:15 +0000495 interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()")
496
cliechti4065dce2009-08-10 00:55:46 +0000497 # - - - - - - - - - - - - - - - - - - - - - - - -
498
499 _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
500 'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
501
502 def getSettingsDict(self):
cliechti7d448562014-08-03 21:57:45 +0000503 """\
504 Get current port settings as a dictionary. For use with
505 applySettingsDict.
506 """
cliechti4065dce2009-08-10 00:55:46 +0000507 return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
508
509 def applySettingsDict(self, d):
cliechti7d448562014-08-03 21:57:45 +0000510 """\
511 apply stored settings from a dictionary returned from
cliechti4065dce2009-08-10 00:55:46 +0000512 getSettingsDict. it's allowed to delete keys from the dictionary. these
cliechti7d448562014-08-03 21:57:45 +0000513 values will simply left unchanged.
514 """
cliechti4065dce2009-08-10 00:55:46 +0000515 for key in self._SETTINGS:
516 if d[key] != getattr(self, '_'+key): # check against internal "_" value
517 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000518
cliechtid6bf52c2003-10-01 02:28:12 +0000519 # - - - - - - - - - - - - - - - - - - - - - - - -
520
521 def __repr__(self):
522 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000523 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 +0000524 self.__class__.__name__,
525 id(self),
526 self._isOpen,
527 self.portstr,
528 self.baudrate,
529 self.bytesize,
530 self.parity,
531 self.stopbits,
532 self.timeout,
533 self.xonxoff,
534 self.rtscts,
cliechtif46e0a82005-05-19 15:24:57 +0000535 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000536 )
537
cliechti4a567a02009-07-27 22:09:31 +0000538
539 # - - - - - - - - - - - - - - - - - - - - - - - -
540 # compatibility with io library
541
542 def readable(self): return True
543 def writable(self): return True
544 def seekable(self): return False
545 def readinto(self, b):
546 data = self.read(len(b))
547 n = len(data)
548 try:
549 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200550 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000551 import array
552 if not isinstance(b, array.array):
553 raise err
554 b[:n] = array.array('b', data)
555 return n
cliechtif81362e2009-07-25 03:44:33 +0000556
557
cliechtid6bf52c2003-10-01 02:28:12 +0000558if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000559 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000560 s = SerialBase()
cliechtif81362e2009-07-25 03:44:33 +0000561 sys.stdout.write('port name: %s\n' % s.portstr)
562 sys.stdout.write('baud rates: %s\n' % s.getSupportedBaudrates())
563 sys.stdout.write('byte sizes: %s\n' % s.getSupportedByteSizes())
564 sys.stdout.write('parities: %s\n' % s.getSupportedParities())
565 sys.stdout.write('stop bits: %s\n' % s.getSupportedStopbits())
566 sys.stdout.write('%s\n' % s)