blob: af0d2f64029ac87b3e7eac26b380489569b2247f [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#
cliechtic323f1f2010-07-22 00:14:26 +00005# (C) 2001-2010 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()
326 if port is not None:
cliechtif81362e2009-07-25 03:44:33 +0000327 if isinstance(port, basestring):
cliechtid6bf52c2003-10-01 02:28:12 +0000328 self.portstr = port
329 else:
330 self.portstr = self.makeDeviceName(port)
331 else:
332 self.portstr = None
333 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000334 self.name = self.portstr
cliechtid6bf52c2003-10-01 02:28:12 +0000335 if was_open: self.open()
cliechti14b274a2009-02-07 00:27:05 +0000336
cliechtid6bf52c2003-10-01 02:28:12 +0000337 def getPort(self):
cliechti7d448562014-08-03 21:57:45 +0000338 """\
339 Get the current port setting. The value that was passed on init or using
340 setPort() is passed back. See also the attribute portstr which contains
341 the name of the port as a string.
342 """
cliechtid6bf52c2003-10-01 02:28:12 +0000343 return self._port
344
cliechti0276f5e2004-11-13 03:14:11 +0000345 port = property(getPort, setPort, doc="Port setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000346
347
348 def setBaudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000349 """\
350 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000351 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000352 accepted and the exception is raised when the port is opened.
353 """
cliechti107db8d2004-01-15 01:20:23 +0000354 try:
cliechtie30868d2013-10-16 15:35:11 +0000355 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000356 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000357 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000358 else:
cliechtie30868d2013-10-16 15:35:11 +0000359 if b <= 0:
360 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
361 self._baudrate = b
cliechti107db8d2004-01-15 01:20:23 +0000362 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000363
cliechtid6bf52c2003-10-01 02:28:12 +0000364 def getBaudrate(self):
cliechti4a567a02009-07-27 22:09:31 +0000365 """Get the current baud rate setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000366 return self._baudrate
cliechti14b274a2009-02-07 00:27:05 +0000367
cliechti4a567a02009-07-27 22:09:31 +0000368 baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000369
370
371 def setByteSize(self, bytesize):
372 """Change byte size."""
cliechti93db61b2006-08-26 19:16:18 +0000373 if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000374 self._bytesize = bytesize
375 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000376
cliechtid6bf52c2003-10-01 02:28:12 +0000377 def getByteSize(self):
378 """Get the current byte size setting."""
379 return self._bytesize
cliechti14b274a2009-02-07 00:27:05 +0000380
cliechti0276f5e2004-11-13 03:14:11 +0000381 bytesize = property(getByteSize, setByteSize, doc="Byte size setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000382
383
384 def setParity(self, parity):
385 """Change parity setting."""
cliechti93db61b2006-08-26 19:16:18 +0000386 if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000387 self._parity = parity
388 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000389
cliechtid6bf52c2003-10-01 02:28:12 +0000390 def getParity(self):
391 """Get the current parity setting."""
392 return self._parity
cliechti14b274a2009-02-07 00:27:05 +0000393
cliechti0276f5e2004-11-13 03:14:11 +0000394 parity = property(getParity, setParity, doc="Parity setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000395
396
397 def setStopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000398 """Change stop bits size."""
399 if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000400 self._stopbits = stopbits
401 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000402
cliechtid6bf52c2003-10-01 02:28:12 +0000403 def getStopbits(self):
cliechti4a567a02009-07-27 22:09:31 +0000404 """Get the current stop bits setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000405 return self._stopbits
cliechti14b274a2009-02-07 00:27:05 +0000406
cliechti4a567a02009-07-27 22:09:31 +0000407 stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000408
409
410 def setTimeout(self, timeout):
411 """Change timeout setting."""
412 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000413 try:
cliechti14b274a2009-02-07 00:27:05 +0000414 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000415 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000416 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti2750b832009-07-28 00:13:52 +0000417 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000418 self._timeout = timeout
419 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000420
cliechtid6bf52c2003-10-01 02:28:12 +0000421 def getTimeout(self):
422 """Get the current timeout setting."""
423 return self._timeout
cliechti14b274a2009-02-07 00:27:05 +0000424
cliechti0276f5e2004-11-13 03:14:11 +0000425 timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()")
cliechti62611612004-04-20 01:55:43 +0000426
427
428 def setWriteTimeout(self, timeout):
429 """Change timeout setting."""
430 if timeout is not None:
cliechti93db61b2006-08-26 19:16:18 +0000431 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000432 try:
433 timeout + 1 #test if it's a number, will throw a TypeError if not...
434 except TypeError:
435 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000436
cliechti62611612004-04-20 01:55:43 +0000437 self._writeTimeout = timeout
438 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000439
cliechti62611612004-04-20 01:55:43 +0000440 def getWriteTimeout(self):
441 """Get the current timeout setting."""
442 return self._writeTimeout
cliechti14b274a2009-02-07 00:27:05 +0000443
cliechti0276f5e2004-11-13 03:14:11 +0000444 writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()")
cliechtid6bf52c2003-10-01 02:28:12 +0000445
446
447 def setXonXoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000448 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000449 self._xonxoff = xonxoff
450 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000451
cliechtid6bf52c2003-10-01 02:28:12 +0000452 def getXonXoff(self):
cliechti4a567a02009-07-27 22:09:31 +0000453 """Get the current XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000454 return self._xonxoff
cliechti14b274a2009-02-07 00:27:05 +0000455
cliechti4a567a02009-07-27 22:09:31 +0000456 xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000457
458 def setRtsCts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000459 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000460 self._rtscts = rtscts
461 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000462
cliechtid6bf52c2003-10-01 02:28:12 +0000463 def getRtsCts(self):
cliechti4a567a02009-07-27 22:09:31 +0000464 """Get the current RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000465 return self._rtscts
cliechti14b274a2009-02-07 00:27:05 +0000466
cliechtif46e0a82005-05-19 15:24:57 +0000467 rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000468
cliechtif46e0a82005-05-19 15:24:57 +0000469 def setDsrDtr(self, dsrdtr=None):
470 """Change DsrDtr flow control setting."""
471 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000472 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000473 self._dsrdtr = self._rtscts
474 else:
cliechti14b274a2009-02-07 00:27:05 +0000475 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000476 self._dsrdtr = dsrdtr
477 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000478
cliechtif46e0a82005-05-19 15:24:57 +0000479 def getDsrDtr(self):
cliechti4a567a02009-07-27 22:09:31 +0000480 """Get the current DSR/DTR flow control setting."""
cliechtif46e0a82005-05-19 15:24:57 +0000481 return self._dsrdtr
cliechti14b274a2009-02-07 00:27:05 +0000482
cliechtif46e0a82005-05-19 15:24:57 +0000483 dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
cliechti679bfa62008-06-20 23:58:15 +0000484
485 def setInterCharTimeout(self, interCharTimeout):
486 """Change inter-character timeout setting."""
487 if interCharTimeout is not None:
488 if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
489 try:
cliechti14b274a2009-02-07 00:27:05 +0000490 interCharTimeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti679bfa62008-06-20 23:58:15 +0000491 except TypeError:
492 raise ValueError("Not a valid timeout: %r" % interCharTimeout)
cliechti14b274a2009-02-07 00:27:05 +0000493
cliechti679bfa62008-06-20 23:58:15 +0000494 self._interCharTimeout = interCharTimeout
495 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000496
cliechti679bfa62008-06-20 23:58:15 +0000497 def getInterCharTimeout(self):
498 """Get the current inter-character timeout setting."""
499 return self._interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000500
cliechti679bfa62008-06-20 23:58:15 +0000501 interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()")
502
cliechti4065dce2009-08-10 00:55:46 +0000503 # - - - - - - - - - - - - - - - - - - - - - - - -
504
505 _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
506 'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
507
508 def getSettingsDict(self):
cliechti7d448562014-08-03 21:57:45 +0000509 """\
510 Get current port settings as a dictionary. For use with
511 applySettingsDict.
512 """
cliechti4065dce2009-08-10 00:55:46 +0000513 return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
514
515 def applySettingsDict(self, d):
cliechti7d448562014-08-03 21:57:45 +0000516 """\
517 apply stored settings from a dictionary returned from
cliechti4065dce2009-08-10 00:55:46 +0000518 getSettingsDict. it's allowed to delete keys from the dictionary. these
cliechti7d448562014-08-03 21:57:45 +0000519 values will simply left unchanged.
520 """
cliechti4065dce2009-08-10 00:55:46 +0000521 for key in self._SETTINGS:
522 if d[key] != getattr(self, '_'+key): # check against internal "_" value
523 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000524
cliechtid6bf52c2003-10-01 02:28:12 +0000525 # - - - - - - - - - - - - - - - - - - - - - - - -
526
527 def __repr__(self):
528 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000529 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 +0000530 self.__class__.__name__,
531 id(self),
532 self._isOpen,
533 self.portstr,
534 self.baudrate,
535 self.bytesize,
536 self.parity,
537 self.stopbits,
538 self.timeout,
539 self.xonxoff,
540 self.rtscts,
cliechtif46e0a82005-05-19 15:24:57 +0000541 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000542 )
543
cliechti4a567a02009-07-27 22:09:31 +0000544
545 # - - - - - - - - - - - - - - - - - - - - - - - -
546 # compatibility with io library
547
548 def readable(self): return True
549 def writable(self): return True
550 def seekable(self): return False
551 def readinto(self, b):
552 data = self.read(len(b))
553 n = len(data)
554 try:
555 b[:n] = data
556 except TypeError, err:
557 import array
558 if not isinstance(b, array.array):
559 raise err
560 b[:n] = array.array('b', data)
561 return n
cliechtif81362e2009-07-25 03:44:33 +0000562
563
cliechtid6bf52c2003-10-01 02:28:12 +0000564if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000565 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000566 s = SerialBase()
cliechtif81362e2009-07-25 03:44:33 +0000567 sys.stdout.write('port name: %s\n' % s.portstr)
568 sys.stdout.write('baud rates: %s\n' % s.getSupportedBaudrates())
569 sys.stdout.write('byte sizes: %s\n' % s.getSupportedByteSizes())
570 sys.stdout.write('parities: %s\n' % s.getSupportedParities())
571 sys.stdout.write('stop bits: %s\n' % s.getSupportedStopbits())
572 sys.stdout.write('%s\n' % s)