blob: f4350070b41851da6922261d0c653b6526664f5a [file] [log] [blame]
cliechtid6bf52c2003-10-01 02:28:12 +00001#! python
cliechtid6bf52c2003-10-01 02:28:12 +00002#
Chris Liechti3e02f702015-12-16 23:06:04 +01003# Base class and support functions used by various backends.
4#
5# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechti68340d72015-08-03 14:15:48 +02006# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechtid6bf52c2003-10-01 02:28:12 +00009
Chris Liechtief6b7b42015-08-06 22:19:26 +020010import io
Chris Liechticf29a352015-10-23 22:03:40 +020011import time
cliechtic323f1f2010-07-22 00:14:26 +000012
cliechti38077122013-10-16 02:57:27 +000013# ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
14# isn't returning the contents (very unfortunate). Therefore we need special
15# cases and test for it. Ensure that there is a ``memoryview`` object for older
16# Python versions. This is easier than making every test dependent on its
17# existence.
18try:
19 memoryview
20except (NameError, AttributeError):
21 # implementation does not matter as we do not realy use it.
22 # it just must not inherit from something else we might care for.
Chris Liechti70b89232015-08-04 03:00:52 +020023 class memoryview(object):
cliechti38077122013-10-16 02:57:27 +000024 pass
25
Chris Liechti4a790ad2015-09-09 17:12:52 +020026try:
27 unicode
28except (NameError, AttributeError):
29 unicode = str # for Python 3
30
cliechti38077122013-10-16 02:57:27 +000031
Chris Liechtif99cd5c2015-08-13 22:54:16 +020032# "for byte in data" fails for python3 as it returns ints instead of bytes
33def iterbytes(b):
34 """Iterate over bytes, returning bytes instead of ints (python3)"""
Chris Liechti12a439f2015-08-20 23:01:53 +020035 if isinstance(b, memoryview):
36 b = b.tobytes()
Chris Liechtif99cd5c2015-08-13 22:54:16 +020037 x = 0
Chris Liechti5eaaa4e2015-08-17 03:08:55 +020038 while True:
Chris Liechti033f17c2015-08-30 21:28:04 +020039 a = b[x:x + 1]
Chris Liechtif99cd5c2015-08-13 22:54:16 +020040 x += 1
Chris Liechti5eaaa4e2015-08-17 03:08:55 +020041 if a:
42 yield a
43 else:
44 break
45
Chris Liechti033f17c2015-08-30 21:28:04 +020046
cliechti38077122013-10-16 02:57:27 +000047# all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
48# so a simple ``bytes(sequence)`` doesn't work for all versions
cliechti32c10332009-08-05 13:23:43 +000049def to_bytes(seq):
50 """convert a sequence to a bytes type"""
cliechti38077122013-10-16 02:57:27 +000051 if isinstance(seq, bytes):
52 return seq
53 elif isinstance(seq, bytearray):
54 return bytes(seq)
55 elif isinstance(seq, memoryview):
56 return seq.tobytes()
Chris Liechti4a790ad2015-09-09 17:12:52 +020057 elif isinstance(seq, unicode):
58 raise TypeError('unicode strings are not supported, please encode to bytes: %r' % (seq,))
cliechti38077122013-10-16 02:57:27 +000059 else:
60 b = bytearray()
61 for item in seq:
Chris Liechti07447732015-08-05 00:39:12 +020062 # this one handles int and bytes in Python 2.7
63 # add conversion in case of Python 3.x
64 if isinstance(item, bytes):
65 item = ord(item)
66 b.append(item)
cliechti38077122013-10-16 02:57:27 +000067 return bytes(b)
cliechti32c10332009-08-05 13:23:43 +000068
69# create control bytes
Chris Liechticf29a352015-10-23 22:03:40 +020070XON = to_bytes([17])
cliechti32c10332009-08-05 13:23:43 +000071XOFF = to_bytes([19])
cliechti4a567a02009-07-27 22:09:31 +000072
cliechti8e99b6f2010-07-21 15:46:39 +000073CR = to_bytes([13])
74LF = to_bytes([10])
75
cliechtia3a811f2009-07-29 21:59:03 +000076
cliechti0d6029a2008-06-21 01:28:46 +000077PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
cliechti58b481c2009-02-16 20:42:32 +000078STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
cliechti14b274a2009-02-07 00:27:05 +000079FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
cliechtid6bf52c2003-10-01 02:28:12 +000080
81PARITY_NAMES = {
Chris Liechti033f17c2015-08-30 21:28:04 +020082 PARITY_NONE: 'None',
83 PARITY_EVEN: 'Even',
84 PARITY_ODD: 'Odd',
85 PARITY_MARK: 'Mark',
cliechti4a567a02009-07-27 22:09:31 +000086 PARITY_SPACE: 'Space',
cliechtid6bf52c2003-10-01 02:28:12 +000087}
88
cliechti1dbe4b62002-02-14 02:49:25 +000089
cliechti4a567a02009-07-27 22:09:31 +000090class SerialException(IOError):
cliechtid6bf52c2003-10-01 02:28:12 +000091 """Base class for serial port related exceptions."""
cliechti7fe54d52002-03-03 20:11:47 +000092
cliechtid6bf52c2003-10-01 02:28:12 +000093
cliechti62611612004-04-20 01:55:43 +000094class SerialTimeoutException(SerialException):
95 """Write timeouts give an exception"""
96
cliechti4a567a02009-07-27 22:09:31 +000097
cliechti4b20ec62012-08-16 01:04:44 +000098writeTimeoutError = SerialTimeoutException('Write timeout')
99portNotOpenError = SerialException('Attempting to use a port that is not open')
cliechti62611612004-04-20 01:55:43 +0000100
cliechtif81362e2009-07-25 03:44:33 +0000101
Chris Liechtief6b7b42015-08-06 22:19:26 +0200102class SerialBase(io.RawIOBase):
cliechti7d448562014-08-03 21:57:45 +0000103 """\
104 Serial port base class. Provides __init__ function and properties to
105 get/set port settings.
106 """
cliechti14b274a2009-02-07 00:27:05 +0000107
cliechtidfec0c82009-07-21 01:35:41 +0000108 # default values, may be overridden in subclasses that do not support all values
cliechtif81362e2009-07-25 03:44:33 +0000109 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
110 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
111 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
112 3000000, 3500000, 4000000)
cliechtid6bf52c2003-10-01 02:28:12 +0000113 BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
Chris Liechticf29a352015-10-23 22:03:40 +0200114 PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
115 STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
cliechti14b274a2009-02-07 00:27:05 +0000116
cliechtid6bf52c2003-10-01 02:28:12 +0000117 def __init__(self,
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100118 port=None,
119 baudrate=9600,
120 bytesize=EIGHTBITS,
121 parity=PARITY_NONE,
122 stopbits=STOPBITS_ONE,
123 timeout=None,
124 xonxoff=False,
125 rtscts=False,
126 write_timeout=None,
127 dsrdtr=False,
128 inter_byte_timeout=None,
Chris Liechtic14bba82016-01-02 23:23:11 +0100129 **kwargs
cliechtid6bf52c2003-10-01 02:28:12 +0000130 ):
cliechti7d448562014-08-03 21:57:45 +0000131 """\
Chris Liechtid6bcaaf2016-02-01 22:55:26 +0100132 Initialize comm port object. If a "port" is given, then the port will be
cliechti7d448562014-08-03 21:57:45 +0000133 opened immediately. Otherwise a Serial port object in closed state
134 is returned.
135 """
cliechtid6bf52c2003-10-01 02:28:12 +0000136
Chris Liechti033f17c2015-08-30 21:28:04 +0200137 self.is_open = False
Chris Liechtic14bba82016-01-02 23:23:11 +0100138 # correct values are assigned below through properties
139 self._port = None
140 self._baudrate = None
141 self._bytesize = None
142 self._parity = None
143 self._stopbits = None
144 self._timeout = None
145 self._write_timeout = None
146 self._xonxoff = None
147 self._rtscts = None
148 self._dsrdtr = None
149 self._inter_byte_timeout = None
Chris Liechti033f17c2015-08-30 21:28:04 +0200150 self._rs485_mode = None # disabled by default
Chris Liechti4cf65392016-01-21 23:57:02 +0100151 self._rts_state = None
152 self._dtr_state = None
Chris Liechtief1fe252015-08-27 23:25:21 +0200153 self._break_state = False
cliechti14b274a2009-02-07 00:27:05 +0000154
155 # assign values using get/set methods using the properties feature
Chris Liechti033f17c2015-08-30 21:28:04 +0200156 self.port = port
cliechtid6bf52c2003-10-01 02:28:12 +0000157 self.baudrate = baudrate
158 self.bytesize = bytesize
Chris Liechti033f17c2015-08-30 21:28:04 +0200159 self.parity = parity
cliechtid6bf52c2003-10-01 02:28:12 +0000160 self.stopbits = stopbits
Chris Liechti033f17c2015-08-30 21:28:04 +0200161 self.timeout = timeout
Chris Liechti518b0d32015-08-30 02:20:39 +0200162 self.write_timeout = write_timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200163 self.xonxoff = xonxoff
164 self.rtscts = rtscts
165 self.dsrdtr = dsrdtr
Chris Liechtib5331752015-10-24 01:34:11 +0200166 self.inter_byte_timeout = inter_byte_timeout
Chris Liechtic14bba82016-01-02 23:23:11 +0100167 # watch for backward compatible kwargs
168 if 'writeTimeout' in kwargs:
169 self.write_timeout = kwargs.pop('writeTimeout')
170 if 'interCharTimeout' in kwargs:
171 self.inter_byte_timeout = kwargs.pop('interCharTimeout')
172 if kwargs:
173 raise ValueError('unexpected keyword arguments: %r' % (kwargs,))
cliechti14b274a2009-02-07 00:27:05 +0000174
cliechtid6bf52c2003-10-01 02:28:12 +0000175 if port is not None:
176 self.open()
177
cliechtid6bf52c2003-10-01 02:28:12 +0000178 # - - - - - - - - - - - - - - - - - - - - - - - -
179
Chris Liechtia51b0bc2015-12-10 21:14:45 +0100180 # to be implemented by subclasses:
181 # def open(self):
182 # def close(self):
Chris Liechti5e763ca2015-12-09 13:01:26 +0100183
184 # - - - - - - - - - - - - - - - - - - - - - - - -
185
Chris Liechti779b1a22015-08-04 14:54:22 +0200186 @property
187 def port(self):
188 """\
189 Get the current port setting. The value that was passed on init or using
190 setPort() is passed back. See also the attribute portstr which contains
191 the name of the port as a string.
192 """
193 return self._port
194
195 @port.setter
196 def port(self, port):
cliechti7d448562014-08-03 21:57:45 +0000197 """\
198 Change the port. The attribute portstr is set to a string that
199 contains the name of the port.
200 """
cliechti14b274a2009-02-07 00:27:05 +0000201
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200202 was_open = self.is_open
203 if was_open:
204 self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200205 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000206 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000207 self.name = self.portstr
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200208 if was_open:
209 self.open()
cliechti14b274a2009-02-07 00:27:05 +0000210
Chris Liechti779b1a22015-08-04 14:54:22 +0200211 @property
212 def baudrate(self):
213 """Get the current baud rate setting."""
214 return self._baudrate
cliechtid6bf52c2003-10-01 02:28:12 +0000215
Chris Liechti779b1a22015-08-04 14:54:22 +0200216 @baudrate.setter
217 def baudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000218 """\
219 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000220 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000221 accepted and the exception is raised when the port is opened.
222 """
cliechti107db8d2004-01-15 01:20:23 +0000223 try:
cliechtie30868d2013-10-16 15:35:11 +0000224 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000225 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000226 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000227 else:
cliechtie30868d2013-10-16 15:35:11 +0000228 if b <= 0:
229 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
230 self._baudrate = b
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200231 if self.is_open:
232 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000233
Chris Liechti779b1a22015-08-04 14:54:22 +0200234 @property
235 def bytesize(self):
236 """Get the current byte size setting."""
237 return self._bytesize
cliechtid6bf52c2003-10-01 02:28:12 +0000238
Chris Liechti779b1a22015-08-04 14:54:22 +0200239 @bytesize.setter
240 def bytesize(self, bytesize):
cliechtid6bf52c2003-10-01 02:28:12 +0000241 """Change byte size."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200242 if bytesize not in self.BYTESIZES:
243 raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000244 self._bytesize = bytesize
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200245 if self.is_open:
246 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000247
Chris Liechti779b1a22015-08-04 14:54:22 +0200248 @property
249 def parity(self):
250 """Get the current parity setting."""
251 return self._parity
252
253 @parity.setter
254 def parity(self, parity):
cliechtid6bf52c2003-10-01 02:28:12 +0000255 """Change parity setting."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200256 if parity not in self.PARITIES:
257 raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000258 self._parity = parity
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200259 if self.is_open:
260 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000261
Chris Liechti779b1a22015-08-04 14:54:22 +0200262 @property
263 def stopbits(self):
264 """Get the current stop bits setting."""
265 return self._stopbits
266
267 @stopbits.setter
268 def stopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000269 """Change stop bits size."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200270 if stopbits not in self.STOPBITS:
271 raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000272 self._stopbits = stopbits
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200273 if self.is_open:
274 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000275
Chris Liechti779b1a22015-08-04 14:54:22 +0200276 @property
277 def timeout(self):
278 """Get the current timeout setting."""
279 return self._timeout
cliechtid6bf52c2003-10-01 02:28:12 +0000280
Chris Liechti779b1a22015-08-04 14:54:22 +0200281 @timeout.setter
282 def timeout(self, timeout):
cliechtid6bf52c2003-10-01 02:28:12 +0000283 """Change timeout setting."""
284 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000285 try:
cliechti14b274a2009-02-07 00:27:05 +0000286 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000287 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000288 raise ValueError("Not a valid timeout: %r" % (timeout,))
Chris Liechticf29a352015-10-23 22:03:40 +0200289 if timeout < 0:
290 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000291 self._timeout = timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200292 if self.is_open:
293 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000294
Chris Liechti779b1a22015-08-04 14:54:22 +0200295 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200296 def write_timeout(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000297 """Get the current timeout setting."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200298 return self._write_timeout
cliechti14b274a2009-02-07 00:27:05 +0000299
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200300 @write_timeout.setter
301 def write_timeout(self, timeout):
cliechti62611612004-04-20 01:55:43 +0000302 """Change timeout setting."""
303 if timeout is not None:
Chris Liechti033f17c2015-08-30 21:28:04 +0200304 if timeout < 0:
305 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000306 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200307 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti62611612004-04-20 01:55:43 +0000308 except TypeError:
309 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000310
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200311 self._write_timeout = timeout
312 if self.is_open:
313 self._reconfigure_port()
314
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200315 @property
Chris Liechti518b0d32015-08-30 02:20:39 +0200316 def inter_byte_timeout(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200317 """Get the current inter-character timeout setting."""
Chris Liechti96242372015-09-02 02:49:49 +0200318 return self._inter_byte_timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200319
Chris Liechti518b0d32015-08-30 02:20:39 +0200320 @inter_byte_timeout.setter
321 def inter_byte_timeout(self, ic_timeout):
322 """Change inter-byte timeout setting."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200323 if ic_timeout is not None:
Chris Liechti033f17c2015-08-30 21:28:04 +0200324 if ic_timeout < 0:
325 raise ValueError("Not a valid timeout: %r" % ic_timeout)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200326 try:
327 ic_timeout + 1 # test if it's a number, will throw a TypeError if not...
328 except TypeError:
329 raise ValueError("Not a valid timeout: %r" % ic_timeout)
330
Chris Liechti518b0d32015-08-30 02:20:39 +0200331 self._inter_byte_timeout = ic_timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200332 if self.is_open:
333 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000334
Chris Liechti779b1a22015-08-04 14:54:22 +0200335 @property
336 def xonxoff(self):
337 """Get the current XON/XOFF setting."""
338 return self._xonxoff
cliechtid6bf52c2003-10-01 02:28:12 +0000339
Chris Liechti779b1a22015-08-04 14:54:22 +0200340 @xonxoff.setter
341 def xonxoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000342 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000343 self._xonxoff = xonxoff
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200344 if self.is_open:
345 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000346
Chris Liechti779b1a22015-08-04 14:54:22 +0200347 @property
348 def rtscts(self):
349 """Get the current RTS/CTS flow control setting."""
350 return self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000351
Chris Liechti779b1a22015-08-04 14:54:22 +0200352 @rtscts.setter
353 def rtscts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000354 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000355 self._rtscts = rtscts
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200356 if self.is_open:
357 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000358
Chris Liechti779b1a22015-08-04 14:54:22 +0200359 @property
360 def dsrdtr(self):
361 """Get the current DSR/DTR flow control setting."""
362 return self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000363
Chris Liechti779b1a22015-08-04 14:54:22 +0200364 @dsrdtr.setter
365 def dsrdtr(self, dsrdtr=None):
cliechtif46e0a82005-05-19 15:24:57 +0000366 """Change DsrDtr flow control setting."""
367 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000368 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000369 self._dsrdtr = self._rtscts
370 else:
cliechti14b274a2009-02-07 00:27:05 +0000371 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000372 self._dsrdtr = dsrdtr
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200373 if self.is_open:
374 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000375
Chris Liechti779b1a22015-08-04 14:54:22 +0200376 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200377 def rts(self):
378 return self._rts_state
cliechti679bfa62008-06-20 23:58:15 +0000379
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200380 @rts.setter
381 def rts(self, value):
382 self._rts_state = value
383 if self.is_open:
384 self._update_rts_state()
cliechti14b274a2009-02-07 00:27:05 +0000385
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200386 @property
387 def dtr(self):
388 return self._dtr_state
cliechti14b274a2009-02-07 00:27:05 +0000389
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200390 @dtr.setter
391 def dtr(self, value):
392 self._dtr_state = value
393 if self.is_open:
394 self._update_dtr_state()
395
396 @property
397 def break_condition(self):
398 return self._break_state
399
400 @break_condition.setter
401 def break_condition(self, value):
402 self._break_state = value
403 if self.is_open:
404 self._update_break_state()
cliechti679bfa62008-06-20 23:58:15 +0000405
cliechti4065dce2009-08-10 00:55:46 +0000406 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti33f0ec52015-08-06 16:37:21 +0200407 # functions useful for RS-485 adapters
408
409 @property
410 def rs485_mode(self):
411 """\
412 Enable RS485 mode and apply new settings, set to None to disable.
413 See serial.rs485.RS485Settings for more info about the value.
414 """
415 return self._rs485_mode
416
417 @rs485_mode.setter
418 def rs485_mode(self, rs485_settings):
419 self._rs485_mode = rs485_settings
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200420 if self.is_open:
421 self._reconfigure_port()
Chris Liechti33f0ec52015-08-06 16:37:21 +0200422
423 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti4065dce2009-08-10 00:55:46 +0000424
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200425 _SAVED_SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
Chris Liechti033f17c2015-08-30 21:28:04 +0200426 'dsrdtr', 'rtscts', 'timeout', 'write_timeout',
Chris Liechti1c3249f2015-09-01 02:31:36 +0200427 'inter_byte_timeout')
cliechti4065dce2009-08-10 00:55:46 +0000428
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200429 def get_settings(self):
cliechti7d448562014-08-03 21:57:45 +0000430 """\
431 Get current port settings as a dictionary. For use with
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200432 apply_settings().
cliechti7d448562014-08-03 21:57:45 +0000433 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200434 return dict([(key, getattr(self, '_' + key)) for key in self._SAVED_SETTINGS])
cliechti4065dce2009-08-10 00:55:46 +0000435
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200436 def apply_settings(self, d):
cliechti7d448562014-08-03 21:57:45 +0000437 """\
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200438 Apply stored settings from a dictionary returned from
439 get_settings(). It's allowed to delete keys from the dictionary. These
cliechti7d448562014-08-03 21:57:45 +0000440 values will simply left unchanged.
441 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200442 for key in self._SAVED_SETTINGS:
Chris Liechti033f17c2015-08-30 21:28:04 +0200443 if key in d and d[key] != getattr(self, '_' + key): # check against internal "_" value
cliechti4065dce2009-08-10 00:55:46 +0000444 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000445
cliechtid6bf52c2003-10-01 02:28:12 +0000446 # - - - - - - - - - - - - - - - - - - - - - - - -
447
448 def __repr__(self):
449 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000450 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)" % (
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200451 self.__class__.__name__,
452 id(self),
453 self.is_open,
454 self.portstr,
455 self.baudrate,
456 self.bytesize,
457 self.parity,
458 self.stopbits,
459 self.timeout,
460 self.xonxoff,
461 self.rtscts,
462 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000463 )
464
cliechti4a567a02009-07-27 22:09:31 +0000465 # - - - - - - - - - - - - - - - - - - - - - - - -
466 # compatibility with io library
467
Chris Liechti033f17c2015-08-30 21:28:04 +0200468 def readable(self):
469 return True
470
471 def writable(self):
472 return True
473
474 def seekable(self):
475 return False
476
cliechti4a567a02009-07-27 22:09:31 +0000477 def readinto(self, b):
478 data = self.read(len(b))
479 n = len(data)
480 try:
481 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200482 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000483 import array
484 if not isinstance(b, array.array):
485 raise err
486 b[:n] = array.array('b', data)
487 return n
cliechtif81362e2009-07-25 03:44:33 +0000488
Chris Liechti70b89232015-08-04 03:00:52 +0200489 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti779b1a22015-08-04 14:54:22 +0200490 # context manager
491
492 def __enter__(self):
493 return self
494
495 def __exit__(self, *args, **kwargs):
496 self.close()
497
498 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechtief1fe252015-08-27 23:25:21 +0200499
500 def send_break(self, duration=0.25):
501 """\
502 Send break condition. Timed, returns to idle state after given
503 duration.
504 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200505 if not self.is_open:
506 raise portNotOpenError
Chris Liechtief1fe252015-08-27 23:25:21 +0200507 self.break_condition = True
508 time.sleep(duration)
509 self.break_condition = False
510
511 # - - - - - - - - - - - - - - - - - - - - - - - -
512 # backwards compatibility / deprecated functions
513
514 def flushInput(self):
515 self.reset_input_buffer()
516
517 def flushOutput(self):
518 self.reset_output_buffer()
519
520 def inWaiting(self):
521 return self.in_waiting
522
523 def sendBreak(self, duration=0.25):
524 self.send_break(duration)
525
526 def setRTS(self, value=1):
527 self.rts = value
528
529 def setDTR(self, value=1):
530 self.dtr = value
531
532 def getCTS(self):
533 return self.cts
534
535 def getDSR(self):
536 return self.dsr
537
538 def getRI(self):
539 return self.ri
540
541 def getCD(self):
542 return self.cd
543
544 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200545 def writeTimeout(self):
546 return self.write_timeout
547
548 @writeTimeout.setter
549 def writeTimeout(self, timeout):
550 self.write_timeout = timeout
Chris Liechtief1fe252015-08-27 23:25:21 +0200551
552 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200553 def interCharTimeout(self):
Chris Liechti96242372015-09-02 02:49:49 +0200554 return self.inter_byte_timeout
Chris Liechtief1fe252015-08-27 23:25:21 +0200555
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200556 @interCharTimeout.setter
557 def interCharTimeout(self, interCharTimeout):
Chris Liechti96242372015-09-02 02:49:49 +0200558 self.inter_byte_timeout = interCharTimeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200559
560 def getSettingsDict(self):
561 return self.get_settings()
562
563 def applySettingsDict(self, d):
564 self.apply_settings(d)
565
566 def isOpen(self):
Chris Liechti16843852015-09-22 23:24:35 +0200567 return self.is_open
Chris Liechtief1fe252015-08-27 23:25:21 +0200568
569 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti70b89232015-08-04 03:00:52 +0200570 # additional functionality
571
David Howlett240f8fc2015-10-28 12:32:09 +0000572 def read_all(self):
Chris Liechti03cb8ed2015-10-30 23:37:24 +0100573 """\
574 Read all bytes currently available in the buffer of the OS.
575 """
David Howlett240f8fc2015-10-28 12:32:09 +0000576 return self.read(self.in_waiting)
577
Chris Liechti70b89232015-08-04 03:00:52 +0200578 def read_until(self, terminator=LF, size=None):
579 """\
580 Read until a termination sequence is found ('\n' by default), the size
581 is exceeded or until timeout occurs.
582 """
583 lenterm = len(terminator)
584 line = bytearray()
585 while True:
586 c = self.read(1)
587 if c:
588 line += c
589 if line[-lenterm:] == terminator:
590 break
591 if size is not None and len(line) >= size:
592 break
593 else:
594 break
595 return bytes(line)
596
Chris Liechti70b89232015-08-04 03:00:52 +0200597 def iread_until(self, *args, **kwargs):
598 """\
599 Read lines, implemented as generator. It will raise StopIteration on
600 timeout (empty read).
601 """
602 while True:
603 line = self.read_until(*args, **kwargs)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200604 if not line:
605 break
Chris Liechti70b89232015-08-04 03:00:52 +0200606 yield line
cliechtif81362e2009-07-25 03:44:33 +0000607
Chris Liechti779b1a22015-08-04 14:54:22 +0200608
609# - - - - - - - - - - - - - - - - - - - - - - - - -
cliechtid6bf52c2003-10-01 02:28:12 +0000610if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000611 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000612 s = SerialBase()
Chris Liechti779b1a22015-08-04 14:54:22 +0200613 sys.stdout.write('port name: %s\n' % s.name)
614 sys.stdout.write('baud rates: %s\n' % s.BAUDRATES)
615 sys.stdout.write('byte sizes: %s\n' % s.BYTESIZES)
616 sys.stdout.write('parities: %s\n' % s.PARITIES)
617 sys.stdout.write('stop bits: %s\n' % s.STOPBITS)
cliechtif81362e2009-07-25 03:44:33 +0000618 sys.stdout.write('%s\n' % s)