blob: eb83b670654f3d9a16df55956ce4e2e1df76cf09 [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 Liechti033f17c2015-08-30 21:28:04 +0200118 port=None, # number of device, numbering starts at
cliechti14b274a2009-02-07 00:27:05 +0000119 # zero. if everything fails, the user
120 # can specify a device string, note
121 # that this isn't portable anymore
122 # port will be opened if one is specified
cliechtidfec0c82009-07-21 01:35:41 +0000123 baudrate=9600, # baud rate
124 bytesize=EIGHTBITS, # number of data bits
cliechti14b274a2009-02-07 00:27:05 +0000125 parity=PARITY_NONE, # enable parity checking
Chris Liechtic14bba82016-01-02 23:23:11 +0100126 stopbits=STOPBITS_ONE, # number of stop bits
cliechti14b274a2009-02-07 00:27:05 +0000127 timeout=None, # set a timeout value, None to wait forever
cliechti74308e42010-07-21 14:03:59 +0000128 xonxoff=False, # enable software flow control
129 rtscts=False, # enable RTS/CTS flow control
Chris Liechti518b0d32015-08-30 02:20:39 +0200130 write_timeout=None, # set a timeout for writes
cliechti58a2aee2010-05-20 23:37:57 +0000131 dsrdtr=False, # None: use rtscts setting, dsrdtr override if True or False
Chris Liechtic14bba82016-01-02 23:23:11 +0100132 inter_byte_timeout=None, # Inter-character timeout, None to disable
133 **kwargs
cliechtid6bf52c2003-10-01 02:28:12 +0000134 ):
cliechti7d448562014-08-03 21:57:45 +0000135 """\
136 Initialize comm port object. If a port is given, then the port will be
137 opened immediately. Otherwise a Serial port object in closed state
138 is returned.
139 """
cliechtid6bf52c2003-10-01 02:28:12 +0000140
Chris Liechti033f17c2015-08-30 21:28:04 +0200141 self.is_open = False
Chris Liechtic14bba82016-01-02 23:23:11 +0100142 # correct values are assigned below through properties
143 self._port = None
144 self._baudrate = None
145 self._bytesize = None
146 self._parity = None
147 self._stopbits = None
148 self._timeout = None
149 self._write_timeout = None
150 self._xonxoff = None
151 self._rtscts = None
152 self._dsrdtr = None
153 self._inter_byte_timeout = None
Chris Liechti033f17c2015-08-30 21:28:04 +0200154 self._rs485_mode = None # disabled by default
Chris Liechti4cf65392016-01-21 23:57:02 +0100155 self._rts_state = None
156 self._dtr_state = None
Chris Liechtief1fe252015-08-27 23:25:21 +0200157 self._break_state = False
cliechti14b274a2009-02-07 00:27:05 +0000158
159 # assign values using get/set methods using the properties feature
Chris Liechti033f17c2015-08-30 21:28:04 +0200160 self.port = port
cliechtid6bf52c2003-10-01 02:28:12 +0000161 self.baudrate = baudrate
162 self.bytesize = bytesize
Chris Liechti033f17c2015-08-30 21:28:04 +0200163 self.parity = parity
cliechtid6bf52c2003-10-01 02:28:12 +0000164 self.stopbits = stopbits
Chris Liechti033f17c2015-08-30 21:28:04 +0200165 self.timeout = timeout
Chris Liechti518b0d32015-08-30 02:20:39 +0200166 self.write_timeout = write_timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200167 self.xonxoff = xonxoff
168 self.rtscts = rtscts
169 self.dsrdtr = dsrdtr
Chris Liechtib5331752015-10-24 01:34:11 +0200170 self.inter_byte_timeout = inter_byte_timeout
Chris Liechtic14bba82016-01-02 23:23:11 +0100171 # watch for backward compatible kwargs
172 if 'writeTimeout' in kwargs:
173 self.write_timeout = kwargs.pop('writeTimeout')
174 if 'interCharTimeout' in kwargs:
175 self.inter_byte_timeout = kwargs.pop('interCharTimeout')
176 if kwargs:
177 raise ValueError('unexpected keyword arguments: %r' % (kwargs,))
cliechti14b274a2009-02-07 00:27:05 +0000178
cliechtid6bf52c2003-10-01 02:28:12 +0000179 if port is not None:
180 self.open()
181
cliechtid6bf52c2003-10-01 02:28:12 +0000182 # - - - - - - - - - - - - - - - - - - - - - - - -
183
Chris Liechtia51b0bc2015-12-10 21:14:45 +0100184 # to be implemented by subclasses:
185 # def open(self):
186 # def close(self):
Chris Liechti5e763ca2015-12-09 13:01:26 +0100187
188 # - - - - - - - - - - - - - - - - - - - - - - - -
189
Chris Liechti779b1a22015-08-04 14:54:22 +0200190 @property
191 def port(self):
192 """\
193 Get the current port setting. The value that was passed on init or using
194 setPort() is passed back. See also the attribute portstr which contains
195 the name of the port as a string.
196 """
197 return self._port
198
199 @port.setter
200 def port(self, port):
cliechti7d448562014-08-03 21:57:45 +0000201 """\
202 Change the port. The attribute portstr is set to a string that
203 contains the name of the port.
204 """
cliechti14b274a2009-02-07 00:27:05 +0000205
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200206 was_open = self.is_open
207 if was_open:
208 self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200209 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000210 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000211 self.name = self.portstr
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200212 if was_open:
213 self.open()
cliechti14b274a2009-02-07 00:27:05 +0000214
cliechtid6bf52c2003-10-01 02:28:12 +0000215
Chris Liechti779b1a22015-08-04 14:54:22 +0200216 @property
217 def baudrate(self):
218 """Get the current baud rate setting."""
219 return self._baudrate
cliechtid6bf52c2003-10-01 02:28:12 +0000220
Chris Liechti779b1a22015-08-04 14:54:22 +0200221 @baudrate.setter
222 def baudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000223 """\
224 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000225 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000226 accepted and the exception is raised when the port is opened.
227 """
cliechti107db8d2004-01-15 01:20:23 +0000228 try:
cliechtie30868d2013-10-16 15:35:11 +0000229 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000230 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000231 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000232 else:
cliechtie30868d2013-10-16 15:35:11 +0000233 if b <= 0:
234 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
235 self._baudrate = b
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200236 if self.is_open:
237 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000238
cliechti14b274a2009-02-07 00:27:05 +0000239
Chris Liechti779b1a22015-08-04 14:54:22 +0200240 @property
241 def bytesize(self):
242 """Get the current byte size setting."""
243 return self._bytesize
cliechtid6bf52c2003-10-01 02:28:12 +0000244
Chris Liechti779b1a22015-08-04 14:54:22 +0200245 @bytesize.setter
246 def bytesize(self, bytesize):
cliechtid6bf52c2003-10-01 02:28:12 +0000247 """Change byte size."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200248 if bytesize not in self.BYTESIZES:
249 raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000250 self._bytesize = bytesize
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200251 if self.is_open:
252 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000253
cliechtid6bf52c2003-10-01 02:28:12 +0000254
255
Chris Liechti779b1a22015-08-04 14:54:22 +0200256 @property
257 def parity(self):
258 """Get the current parity setting."""
259 return self._parity
260
261 @parity.setter
262 def parity(self, parity):
cliechtid6bf52c2003-10-01 02:28:12 +0000263 """Change parity setting."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200264 if parity not in self.PARITIES:
265 raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000266 self._parity = parity
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200267 if self.is_open:
268 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000269
cliechtid6bf52c2003-10-01 02:28:12 +0000270
271
Chris Liechti779b1a22015-08-04 14:54:22 +0200272 @property
273 def stopbits(self):
274 """Get the current stop bits setting."""
275 return self._stopbits
276
277 @stopbits.setter
278 def stopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000279 """Change stop bits size."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200280 if stopbits not in self.STOPBITS:
281 raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000282 self._stopbits = stopbits
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200283 if self.is_open:
284 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000285
cliechti14b274a2009-02-07 00:27:05 +0000286
Chris Liechti779b1a22015-08-04 14:54:22 +0200287 @property
288 def timeout(self):
289 """Get the current timeout setting."""
290 return self._timeout
cliechtid6bf52c2003-10-01 02:28:12 +0000291
Chris Liechti779b1a22015-08-04 14:54:22 +0200292 @timeout.setter
293 def timeout(self, timeout):
cliechtid6bf52c2003-10-01 02:28:12 +0000294 """Change timeout setting."""
295 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000296 try:
cliechti14b274a2009-02-07 00:27:05 +0000297 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000298 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000299 raise ValueError("Not a valid timeout: %r" % (timeout,))
Chris Liechticf29a352015-10-23 22:03:40 +0200300 if timeout < 0:
301 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000302 self._timeout = timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200303 if self.is_open:
304 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000305
Chris Liechti779b1a22015-08-04 14:54:22 +0200306
307 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200308 def write_timeout(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000309 """Get the current timeout setting."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200310 return self._write_timeout
cliechti14b274a2009-02-07 00:27:05 +0000311
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200312 @write_timeout.setter
313 def write_timeout(self, timeout):
cliechti62611612004-04-20 01:55:43 +0000314 """Change timeout setting."""
315 if timeout is not None:
Chris Liechti033f17c2015-08-30 21:28:04 +0200316 if timeout < 0:
317 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000318 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200319 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti62611612004-04-20 01:55:43 +0000320 except TypeError:
321 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000322
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200323 self._write_timeout = timeout
324 if self.is_open:
325 self._reconfigure_port()
326
327
328 @property
Chris Liechti518b0d32015-08-30 02:20:39 +0200329 def inter_byte_timeout(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200330 """Get the current inter-character timeout setting."""
Chris Liechti96242372015-09-02 02:49:49 +0200331 return self._inter_byte_timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200332
Chris Liechti518b0d32015-08-30 02:20:39 +0200333 @inter_byte_timeout.setter
334 def inter_byte_timeout(self, ic_timeout):
335 """Change inter-byte timeout setting."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200336 if ic_timeout is not None:
Chris Liechti033f17c2015-08-30 21:28:04 +0200337 if ic_timeout < 0:
338 raise ValueError("Not a valid timeout: %r" % ic_timeout)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200339 try:
340 ic_timeout + 1 # test if it's a number, will throw a TypeError if not...
341 except TypeError:
342 raise ValueError("Not a valid timeout: %r" % ic_timeout)
343
Chris Liechti518b0d32015-08-30 02:20:39 +0200344 self._inter_byte_timeout = ic_timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200345 if self.is_open:
346 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000347
cliechti14b274a2009-02-07 00:27:05 +0000348
Chris Liechti779b1a22015-08-04 14:54:22 +0200349 @property
350 def xonxoff(self):
351 """Get the current XON/XOFF setting."""
352 return self._xonxoff
cliechtid6bf52c2003-10-01 02:28:12 +0000353
Chris Liechti779b1a22015-08-04 14:54:22 +0200354 @xonxoff.setter
355 def xonxoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000356 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000357 self._xonxoff = xonxoff
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200358 if self.is_open:
359 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000360
cliechti14b274a2009-02-07 00:27:05 +0000361
Chris Liechti779b1a22015-08-04 14:54:22 +0200362 @property
363 def rtscts(self):
364 """Get the current RTS/CTS flow control setting."""
365 return self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000366
Chris Liechti779b1a22015-08-04 14:54:22 +0200367 @rtscts.setter
368 def rtscts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000369 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000370 self._rtscts = rtscts
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200371 if self.is_open:
372 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000373
cliechti14b274a2009-02-07 00:27:05 +0000374
Chris Liechti779b1a22015-08-04 14:54:22 +0200375 @property
376 def dsrdtr(self):
377 """Get the current DSR/DTR flow control setting."""
378 return self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000379
Chris Liechti779b1a22015-08-04 14:54:22 +0200380 @dsrdtr.setter
381 def dsrdtr(self, dsrdtr=None):
cliechtif46e0a82005-05-19 15:24:57 +0000382 """Change DsrDtr flow control setting."""
383 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000384 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000385 self._dsrdtr = self._rtscts
386 else:
cliechti14b274a2009-02-07 00:27:05 +0000387 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000388 self._dsrdtr = dsrdtr
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200389 if self.is_open:
390 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000391
cliechti14b274a2009-02-07 00:27:05 +0000392
Chris Liechti779b1a22015-08-04 14:54:22 +0200393 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200394 def rts(self):
395 return self._rts_state
cliechti679bfa62008-06-20 23:58:15 +0000396
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200397 @rts.setter
398 def rts(self, value):
399 self._rts_state = value
400 if self.is_open:
401 self._update_rts_state()
cliechti14b274a2009-02-07 00:27:05 +0000402
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200403 @property
404 def dtr(self):
405 return self._dtr_state
cliechti14b274a2009-02-07 00:27:05 +0000406
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200407 @dtr.setter
408 def dtr(self, value):
409 self._dtr_state = value
410 if self.is_open:
411 self._update_dtr_state()
412
413 @property
414 def break_condition(self):
415 return self._break_state
416
417 @break_condition.setter
418 def break_condition(self, value):
419 self._break_state = value
420 if self.is_open:
421 self._update_break_state()
cliechti679bfa62008-06-20 23:58:15 +0000422
cliechti4065dce2009-08-10 00:55:46 +0000423 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti33f0ec52015-08-06 16:37:21 +0200424 # functions useful for RS-485 adapters
425
426 @property
427 def rs485_mode(self):
428 """\
429 Enable RS485 mode and apply new settings, set to None to disable.
430 See serial.rs485.RS485Settings for more info about the value.
431 """
432 return self._rs485_mode
433
434 @rs485_mode.setter
435 def rs485_mode(self, rs485_settings):
436 self._rs485_mode = rs485_settings
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200437 if self.is_open:
438 self._reconfigure_port()
Chris Liechti33f0ec52015-08-06 16:37:21 +0200439
440 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti4065dce2009-08-10 00:55:46 +0000441
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200442 _SAVED_SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
Chris Liechti033f17c2015-08-30 21:28:04 +0200443 'dsrdtr', 'rtscts', 'timeout', 'write_timeout',
Chris Liechti1c3249f2015-09-01 02:31:36 +0200444 'inter_byte_timeout')
cliechti4065dce2009-08-10 00:55:46 +0000445
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200446 def get_settings(self):
cliechti7d448562014-08-03 21:57:45 +0000447 """\
448 Get current port settings as a dictionary. For use with
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200449 apply_settings().
cliechti7d448562014-08-03 21:57:45 +0000450 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200451 return dict([(key, getattr(self, '_' + key)) for key in self._SAVED_SETTINGS])
cliechti4065dce2009-08-10 00:55:46 +0000452
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200453 def apply_settings(self, d):
cliechti7d448562014-08-03 21:57:45 +0000454 """\
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200455 Apply stored settings from a dictionary returned from
456 get_settings(). It's allowed to delete keys from the dictionary. These
cliechti7d448562014-08-03 21:57:45 +0000457 values will simply left unchanged.
458 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200459 for key in self._SAVED_SETTINGS:
Chris Liechti033f17c2015-08-30 21:28:04 +0200460 if key in d and d[key] != getattr(self, '_' + key): # check against internal "_" value
cliechti4065dce2009-08-10 00:55:46 +0000461 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000462
cliechtid6bf52c2003-10-01 02:28:12 +0000463 # - - - - - - - - - - - - - - - - - - - - - - - -
464
465 def __repr__(self):
466 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000467 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 +0200468 self.__class__.__name__,
469 id(self),
470 self.is_open,
471 self.portstr,
472 self.baudrate,
473 self.bytesize,
474 self.parity,
475 self.stopbits,
476 self.timeout,
477 self.xonxoff,
478 self.rtscts,
479 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000480 )
481
cliechti4a567a02009-07-27 22:09:31 +0000482 # - - - - - - - - - - - - - - - - - - - - - - - -
483 # compatibility with io library
484
Chris Liechti033f17c2015-08-30 21:28:04 +0200485 def readable(self):
486 return True
487
488 def writable(self):
489 return True
490
491 def seekable(self):
492 return False
493
cliechti4a567a02009-07-27 22:09:31 +0000494 def readinto(self, b):
495 data = self.read(len(b))
496 n = len(data)
497 try:
498 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200499 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000500 import array
501 if not isinstance(b, array.array):
502 raise err
503 b[:n] = array.array('b', data)
504 return n
cliechtif81362e2009-07-25 03:44:33 +0000505
Chris Liechti70b89232015-08-04 03:00:52 +0200506 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti779b1a22015-08-04 14:54:22 +0200507 # context manager
508
509 def __enter__(self):
510 return self
511
512 def __exit__(self, *args, **kwargs):
513 self.close()
514
515 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechtief1fe252015-08-27 23:25:21 +0200516
517 def send_break(self, duration=0.25):
518 """\
519 Send break condition. Timed, returns to idle state after given
520 duration.
521 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200522 if not self.is_open:
523 raise portNotOpenError
Chris Liechtief1fe252015-08-27 23:25:21 +0200524 self.break_condition = True
525 time.sleep(duration)
526 self.break_condition = False
527
528 # - - - - - - - - - - - - - - - - - - - - - - - -
529 # backwards compatibility / deprecated functions
530
531 def flushInput(self):
532 self.reset_input_buffer()
533
534 def flushOutput(self):
535 self.reset_output_buffer()
536
537 def inWaiting(self):
538 return self.in_waiting
539
540 def sendBreak(self, duration=0.25):
541 self.send_break(duration)
542
543 def setRTS(self, value=1):
544 self.rts = value
545
546 def setDTR(self, value=1):
547 self.dtr = value
548
549 def getCTS(self):
550 return self.cts
551
552 def getDSR(self):
553 return self.dsr
554
555 def getRI(self):
556 return self.ri
557
558 def getCD(self):
559 return self.cd
560
561 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200562 def writeTimeout(self):
563 return self.write_timeout
564
565 @writeTimeout.setter
566 def writeTimeout(self, timeout):
567 self.write_timeout = timeout
Chris Liechtief1fe252015-08-27 23:25:21 +0200568
569 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200570 def interCharTimeout(self):
Chris Liechti96242372015-09-02 02:49:49 +0200571 return self.inter_byte_timeout
Chris Liechtief1fe252015-08-27 23:25:21 +0200572
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200573 @interCharTimeout.setter
574 def interCharTimeout(self, interCharTimeout):
Chris Liechti96242372015-09-02 02:49:49 +0200575 self.inter_byte_timeout = interCharTimeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200576
577 def getSettingsDict(self):
578 return self.get_settings()
579
580 def applySettingsDict(self, d):
581 self.apply_settings(d)
582
583 def isOpen(self):
Chris Liechti16843852015-09-22 23:24:35 +0200584 return self.is_open
Chris Liechtief1fe252015-08-27 23:25:21 +0200585
586 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti70b89232015-08-04 03:00:52 +0200587 # additional functionality
588
David Howlett240f8fc2015-10-28 12:32:09 +0000589 def read_all(self):
Chris Liechti03cb8ed2015-10-30 23:37:24 +0100590 """\
591 Read all bytes currently available in the buffer of the OS.
592 """
David Howlett240f8fc2015-10-28 12:32:09 +0000593 return self.read(self.in_waiting)
594
Chris Liechti70b89232015-08-04 03:00:52 +0200595 def read_until(self, terminator=LF, size=None):
596 """\
597 Read until a termination sequence is found ('\n' by default), the size
598 is exceeded or until timeout occurs.
599 """
600 lenterm = len(terminator)
601 line = bytearray()
602 while True:
603 c = self.read(1)
604 if c:
605 line += c
606 if line[-lenterm:] == terminator:
607 break
608 if size is not None and len(line) >= size:
609 break
610 else:
611 break
612 return bytes(line)
613
Chris Liechti70b89232015-08-04 03:00:52 +0200614 def iread_until(self, *args, **kwargs):
615 """\
616 Read lines, implemented as generator. It will raise StopIteration on
617 timeout (empty read).
618 """
619 while True:
620 line = self.read_until(*args, **kwargs)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200621 if not line:
622 break
Chris Liechti70b89232015-08-04 03:00:52 +0200623 yield line
cliechtif81362e2009-07-25 03:44:33 +0000624
Chris Liechti779b1a22015-08-04 14:54:22 +0200625
626# - - - - - - - - - - - - - - - - - - - - - - - - -
cliechtid6bf52c2003-10-01 02:28:12 +0000627if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000628 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000629 s = SerialBase()
Chris Liechti779b1a22015-08-04 14:54:22 +0200630 sys.stdout.write('port name: %s\n' % s.name)
631 sys.stdout.write('baud rates: %s\n' % s.BAUDRATES)
632 sys.stdout.write('byte sizes: %s\n' % s.BYTESIZES)
633 sys.stdout.write('parities: %s\n' % s.PARITIES)
634 sys.stdout.write('stop bits: %s\n' % s.STOPBITS)
cliechtif81362e2009-07-25 03:44:33 +0000635 sys.stdout.write('%s\n' % s)