blob: 617c6868ce5790cd142ab736e8041cf5a7600c06 [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 Liechti033f17c2015-08-30 21:28:04 +0200126 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 Liechti033f17c2015-08-30 21:28:04 +0200132 inter_byte_timeout=None # Inter-character timeout, None to disable
cliechtid6bf52c2003-10-01 02:28:12 +0000133 ):
cliechti7d448562014-08-03 21:57:45 +0000134 """\
135 Initialize comm port object. If a port is given, then the port will be
136 opened immediately. Otherwise a Serial port object in closed state
137 is returned.
138 """
cliechtid6bf52c2003-10-01 02:28:12 +0000139
Chris Liechti033f17c2015-08-30 21:28:04 +0200140 self.is_open = False
141 self._port = None # correct value is assigned below through properties
142 self._baudrate = None # correct value is assigned below through properties
143 self._bytesize = None # correct value is assigned below through properties
Chris Liechticf29a352015-10-23 22:03:40 +0200144 self._parity = None # correct value is assigned below through properties
Chris Liechti033f17c2015-08-30 21:28:04 +0200145 self._stopbits = None # correct value is assigned below through properties
146 self._timeout = None # correct value is assigned below through properties
147 self._write_timeout = None # correct value is assigned below through properties
148 self._xonxoff = None # correct value is assigned below through properties
149 self._rtscts = None # correct value is assigned below through properties
150 self._dsrdtr = None # correct value is assigned below through properties
151 self._inter_byte_timeout = None # correct value is assigned below through properties
152 self._rs485_mode = None # disabled by default
Chris Liechtief1fe252015-08-27 23:25:21 +0200153 self._rts_state = True
154 self._dtr_state = True
155 self._break_state = False
cliechti14b274a2009-02-07 00:27:05 +0000156
157 # assign values using get/set methods using the properties feature
Chris Liechti033f17c2015-08-30 21:28:04 +0200158 self.port = port
cliechtid6bf52c2003-10-01 02:28:12 +0000159 self.baudrate = baudrate
160 self.bytesize = bytesize
Chris Liechti033f17c2015-08-30 21:28:04 +0200161 self.parity = parity
cliechtid6bf52c2003-10-01 02:28:12 +0000162 self.stopbits = stopbits
Chris Liechti033f17c2015-08-30 21:28:04 +0200163 self.timeout = timeout
Chris Liechti518b0d32015-08-30 02:20:39 +0200164 self.write_timeout = write_timeout
Chris Liechti033f17c2015-08-30 21:28:04 +0200165 self.xonxoff = xonxoff
166 self.rtscts = rtscts
167 self.dsrdtr = dsrdtr
Chris Liechtib5331752015-10-24 01:34:11 +0200168 self.inter_byte_timeout = inter_byte_timeout
cliechti14b274a2009-02-07 00:27:05 +0000169
cliechtid6bf52c2003-10-01 02:28:12 +0000170 if port is not None:
171 self.open()
172
cliechtid6bf52c2003-10-01 02:28:12 +0000173 # - - - - - - - - - - - - - - - - - - - - - - - -
174
Chris Liechtia51b0bc2015-12-10 21:14:45 +0100175 # to be implemented by subclasses:
176 # def open(self):
177 # def close(self):
Chris Liechti5e763ca2015-12-09 13:01:26 +0100178
179 # - - - - - - - - - - - - - - - - - - - - - - - -
180
Chris Liechti779b1a22015-08-04 14:54:22 +0200181 @property
182 def port(self):
183 """\
184 Get the current port setting. The value that was passed on init or using
185 setPort() is passed back. See also the attribute portstr which contains
186 the name of the port as a string.
187 """
188 return self._port
189
190 @port.setter
191 def port(self, port):
cliechti7d448562014-08-03 21:57:45 +0000192 """\
193 Change the port. The attribute portstr is set to a string that
194 contains the name of the port.
195 """
cliechti14b274a2009-02-07 00:27:05 +0000196
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200197 was_open = self.is_open
198 if was_open:
199 self.close()
Chris Liechti68340d72015-08-03 14:15:48 +0200200 self.portstr = port
cliechtid6bf52c2003-10-01 02:28:12 +0000201 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000202 self.name = self.portstr
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200203 if was_open:
204 self.open()
cliechti14b274a2009-02-07 00:27:05 +0000205
cliechtid6bf52c2003-10-01 02:28:12 +0000206
Chris Liechti779b1a22015-08-04 14:54:22 +0200207 @property
208 def baudrate(self):
209 """Get the current baud rate setting."""
210 return self._baudrate
cliechtid6bf52c2003-10-01 02:28:12 +0000211
Chris Liechti779b1a22015-08-04 14:54:22 +0200212 @baudrate.setter
213 def baudrate(self, baudrate):
cliechti7d448562014-08-03 21:57:45 +0000214 """\
215 Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000216 baud rate is not possible. If the port is closed, then the value is
cliechti7d448562014-08-03 21:57:45 +0000217 accepted and the exception is raised when the port is opened.
218 """
cliechti107db8d2004-01-15 01:20:23 +0000219 try:
cliechtie30868d2013-10-16 15:35:11 +0000220 b = int(baudrate)
cliechti107db8d2004-01-15 01:20:23 +0000221 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000222 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000223 else:
cliechtie30868d2013-10-16 15:35:11 +0000224 if b <= 0:
225 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
226 self._baudrate = b
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200227 if self.is_open:
228 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000229
cliechti14b274a2009-02-07 00:27:05 +0000230
Chris Liechti779b1a22015-08-04 14:54:22 +0200231 @property
232 def bytesize(self):
233 """Get the current byte size setting."""
234 return self._bytesize
cliechtid6bf52c2003-10-01 02:28:12 +0000235
Chris Liechti779b1a22015-08-04 14:54:22 +0200236 @bytesize.setter
237 def bytesize(self, bytesize):
cliechtid6bf52c2003-10-01 02:28:12 +0000238 """Change byte size."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200239 if bytesize not in self.BYTESIZES:
240 raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000241 self._bytesize = bytesize
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200242 if self.is_open:
243 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000244
cliechtid6bf52c2003-10-01 02:28:12 +0000245
246
Chris Liechti779b1a22015-08-04 14:54:22 +0200247 @property
248 def parity(self):
249 """Get the current parity setting."""
250 return self._parity
251
252 @parity.setter
253 def parity(self, parity):
cliechtid6bf52c2003-10-01 02:28:12 +0000254 """Change parity setting."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200255 if parity not in self.PARITIES:
256 raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000257 self._parity = parity
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200258 if self.is_open:
259 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000260
cliechtid6bf52c2003-10-01 02:28:12 +0000261
262
Chris Liechti779b1a22015-08-04 14:54:22 +0200263 @property
264 def stopbits(self):
265 """Get the current stop bits setting."""
266 return self._stopbits
267
268 @stopbits.setter
269 def stopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000270 """Change stop bits size."""
Chris Liechti033f17c2015-08-30 21:28:04 +0200271 if stopbits not in self.STOPBITS:
272 raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000273 self._stopbits = stopbits
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200274 if self.is_open:
275 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000276
cliechti14b274a2009-02-07 00:27:05 +0000277
Chris Liechti779b1a22015-08-04 14:54:22 +0200278 @property
279 def timeout(self):
280 """Get the current timeout setting."""
281 return self._timeout
cliechtid6bf52c2003-10-01 02:28:12 +0000282
Chris Liechti779b1a22015-08-04 14:54:22 +0200283 @timeout.setter
284 def timeout(self, timeout):
cliechtid6bf52c2003-10-01 02:28:12 +0000285 """Change timeout setting."""
286 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000287 try:
cliechti14b274a2009-02-07 00:27:05 +0000288 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000289 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000290 raise ValueError("Not a valid timeout: %r" % (timeout,))
Chris Liechticf29a352015-10-23 22:03:40 +0200291 if timeout < 0:
292 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000293 self._timeout = timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200294 if self.is_open:
295 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000296
Chris Liechti779b1a22015-08-04 14:54:22 +0200297
298 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200299 def write_timeout(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000300 """Get the current timeout setting."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200301 return self._write_timeout
cliechti14b274a2009-02-07 00:27:05 +0000302
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200303 @write_timeout.setter
304 def write_timeout(self, timeout):
cliechti62611612004-04-20 01:55:43 +0000305 """Change timeout setting."""
306 if timeout is not None:
Chris Liechti033f17c2015-08-30 21:28:04 +0200307 if timeout < 0:
308 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000309 try:
Chris Liechti033f17c2015-08-30 21:28:04 +0200310 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti62611612004-04-20 01:55:43 +0000311 except TypeError:
312 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000313
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200314 self._write_timeout = timeout
315 if self.is_open:
316 self._reconfigure_port()
317
318
319 @property
Chris Liechti518b0d32015-08-30 02:20:39 +0200320 def inter_byte_timeout(self):
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200321 """Get the current inter-character timeout setting."""
Chris Liechti96242372015-09-02 02:49:49 +0200322 return self._inter_byte_timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200323
Chris Liechti518b0d32015-08-30 02:20:39 +0200324 @inter_byte_timeout.setter
325 def inter_byte_timeout(self, ic_timeout):
326 """Change inter-byte timeout setting."""
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200327 if ic_timeout is not None:
Chris Liechti033f17c2015-08-30 21:28:04 +0200328 if ic_timeout < 0:
329 raise ValueError("Not a valid timeout: %r" % ic_timeout)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200330 try:
331 ic_timeout + 1 # test if it's a number, will throw a TypeError if not...
332 except TypeError:
333 raise ValueError("Not a valid timeout: %r" % ic_timeout)
334
Chris Liechti518b0d32015-08-30 02:20:39 +0200335 self._inter_byte_timeout = ic_timeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200336 if self.is_open:
337 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000338
cliechti14b274a2009-02-07 00:27:05 +0000339
Chris Liechti779b1a22015-08-04 14:54:22 +0200340 @property
341 def xonxoff(self):
342 """Get the current XON/XOFF setting."""
343 return self._xonxoff
cliechtid6bf52c2003-10-01 02:28:12 +0000344
Chris Liechti779b1a22015-08-04 14:54:22 +0200345 @xonxoff.setter
346 def xonxoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000347 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000348 self._xonxoff = xonxoff
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200349 if self.is_open:
350 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000351
cliechti14b274a2009-02-07 00:27:05 +0000352
Chris Liechti779b1a22015-08-04 14:54:22 +0200353 @property
354 def rtscts(self):
355 """Get the current RTS/CTS flow control setting."""
356 return self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000357
Chris Liechti779b1a22015-08-04 14:54:22 +0200358 @rtscts.setter
359 def rtscts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000360 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000361 self._rtscts = rtscts
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200362 if self.is_open:
363 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000364
cliechti14b274a2009-02-07 00:27:05 +0000365
Chris Liechti779b1a22015-08-04 14:54:22 +0200366 @property
367 def dsrdtr(self):
368 """Get the current DSR/DTR flow control setting."""
369 return self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000370
Chris Liechti779b1a22015-08-04 14:54:22 +0200371 @dsrdtr.setter
372 def dsrdtr(self, dsrdtr=None):
cliechtif46e0a82005-05-19 15:24:57 +0000373 """Change DsrDtr flow control setting."""
374 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000375 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000376 self._dsrdtr = self._rtscts
377 else:
cliechti14b274a2009-02-07 00:27:05 +0000378 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000379 self._dsrdtr = dsrdtr
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200380 if self.is_open:
381 self._reconfigure_port()
cliechti14b274a2009-02-07 00:27:05 +0000382
cliechti14b274a2009-02-07 00:27:05 +0000383
Chris Liechti779b1a22015-08-04 14:54:22 +0200384 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200385 def rts(self):
386 return self._rts_state
cliechti679bfa62008-06-20 23:58:15 +0000387
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200388 @rts.setter
389 def rts(self, value):
390 self._rts_state = value
391 if self.is_open:
392 self._update_rts_state()
cliechti14b274a2009-02-07 00:27:05 +0000393
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200394 @property
395 def dtr(self):
396 return self._dtr_state
cliechti14b274a2009-02-07 00:27:05 +0000397
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200398 @dtr.setter
399 def dtr(self, value):
400 self._dtr_state = value
401 if self.is_open:
402 self._update_dtr_state()
403
404 @property
405 def break_condition(self):
406 return self._break_state
407
408 @break_condition.setter
409 def break_condition(self, value):
410 self._break_state = value
411 if self.is_open:
412 self._update_break_state()
cliechti679bfa62008-06-20 23:58:15 +0000413
cliechti4065dce2009-08-10 00:55:46 +0000414 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti33f0ec52015-08-06 16:37:21 +0200415 # functions useful for RS-485 adapters
416
417 @property
418 def rs485_mode(self):
419 """\
420 Enable RS485 mode and apply new settings, set to None to disable.
421 See serial.rs485.RS485Settings for more info about the value.
422 """
423 return self._rs485_mode
424
425 @rs485_mode.setter
426 def rs485_mode(self, rs485_settings):
427 self._rs485_mode = rs485_settings
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200428 if self.is_open:
429 self._reconfigure_port()
Chris Liechti33f0ec52015-08-06 16:37:21 +0200430
431 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti4065dce2009-08-10 00:55:46 +0000432
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200433 _SAVED_SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
Chris Liechti033f17c2015-08-30 21:28:04 +0200434 'dsrdtr', 'rtscts', 'timeout', 'write_timeout',
Chris Liechti1c3249f2015-09-01 02:31:36 +0200435 'inter_byte_timeout')
cliechti4065dce2009-08-10 00:55:46 +0000436
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200437 def get_settings(self):
cliechti7d448562014-08-03 21:57:45 +0000438 """\
439 Get current port settings as a dictionary. For use with
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200440 apply_settings().
cliechti7d448562014-08-03 21:57:45 +0000441 """
Chris Liechti033f17c2015-08-30 21:28:04 +0200442 return dict([(key, getattr(self, '_' + key)) for key in self._SAVED_SETTINGS])
cliechti4065dce2009-08-10 00:55:46 +0000443
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200444 def apply_settings(self, d):
cliechti7d448562014-08-03 21:57:45 +0000445 """\
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200446 Apply stored settings from a dictionary returned from
447 get_settings(). It's allowed to delete keys from the dictionary. These
cliechti7d448562014-08-03 21:57:45 +0000448 values will simply left unchanged.
449 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200450 for key in self._SAVED_SETTINGS:
Chris Liechti033f17c2015-08-30 21:28:04 +0200451 if key in d and d[key] != getattr(self, '_' + key): # check against internal "_" value
cliechti4065dce2009-08-10 00:55:46 +0000452 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000453
cliechtid6bf52c2003-10-01 02:28:12 +0000454 # - - - - - - - - - - - - - - - - - - - - - - - -
455
456 def __repr__(self):
457 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000458 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 +0200459 self.__class__.__name__,
460 id(self),
461 self.is_open,
462 self.portstr,
463 self.baudrate,
464 self.bytesize,
465 self.parity,
466 self.stopbits,
467 self.timeout,
468 self.xonxoff,
469 self.rtscts,
470 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000471 )
472
cliechti4a567a02009-07-27 22:09:31 +0000473 # - - - - - - - - - - - - - - - - - - - - - - - -
474 # compatibility with io library
475
Chris Liechti033f17c2015-08-30 21:28:04 +0200476 def readable(self):
477 return True
478
479 def writable(self):
480 return True
481
482 def seekable(self):
483 return False
484
cliechti4a567a02009-07-27 22:09:31 +0000485 def readinto(self, b):
486 data = self.read(len(b))
487 n = len(data)
488 try:
489 b[:n] = data
Chris Liechti68340d72015-08-03 14:15:48 +0200490 except TypeError as err:
cliechti4a567a02009-07-27 22:09:31 +0000491 import array
492 if not isinstance(b, array.array):
493 raise err
494 b[:n] = array.array('b', data)
495 return n
cliechtif81362e2009-07-25 03:44:33 +0000496
Chris Liechti70b89232015-08-04 03:00:52 +0200497 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti779b1a22015-08-04 14:54:22 +0200498 # context manager
499
500 def __enter__(self):
501 return self
502
503 def __exit__(self, *args, **kwargs):
504 self.close()
505
506 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechtief1fe252015-08-27 23:25:21 +0200507
508 def send_break(self, duration=0.25):
509 """\
510 Send break condition. Timed, returns to idle state after given
511 duration.
512 """
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200513 if not self.is_open:
514 raise portNotOpenError
Chris Liechtief1fe252015-08-27 23:25:21 +0200515 self.break_condition = True
516 time.sleep(duration)
517 self.break_condition = False
518
519 # - - - - - - - - - - - - - - - - - - - - - - - -
520 # backwards compatibility / deprecated functions
521
522 def flushInput(self):
523 self.reset_input_buffer()
524
525 def flushOutput(self):
526 self.reset_output_buffer()
527
528 def inWaiting(self):
529 return self.in_waiting
530
531 def sendBreak(self, duration=0.25):
532 self.send_break(duration)
533
534 def setRTS(self, value=1):
535 self.rts = value
536
537 def setDTR(self, value=1):
538 self.dtr = value
539
540 def getCTS(self):
541 return self.cts
542
543 def getDSR(self):
544 return self.dsr
545
546 def getRI(self):
547 return self.ri
548
549 def getCD(self):
550 return self.cd
551
552 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200553 def writeTimeout(self):
554 return self.write_timeout
555
556 @writeTimeout.setter
557 def writeTimeout(self, timeout):
558 self.write_timeout = timeout
Chris Liechtief1fe252015-08-27 23:25:21 +0200559
560 @property
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200561 def interCharTimeout(self):
Chris Liechti96242372015-09-02 02:49:49 +0200562 return self.inter_byte_timeout
Chris Liechtief1fe252015-08-27 23:25:21 +0200563
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200564 @interCharTimeout.setter
565 def interCharTimeout(self, interCharTimeout):
Chris Liechti96242372015-09-02 02:49:49 +0200566 self.inter_byte_timeout = interCharTimeout
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200567
568 def getSettingsDict(self):
569 return self.get_settings()
570
571 def applySettingsDict(self, d):
572 self.apply_settings(d)
573
574 def isOpen(self):
Chris Liechti16843852015-09-22 23:24:35 +0200575 return self.is_open
Chris Liechtief1fe252015-08-27 23:25:21 +0200576
577 # - - - - - - - - - - - - - - - - - - - - - - - -
Chris Liechti70b89232015-08-04 03:00:52 +0200578 # additional functionality
579
David Howlett240f8fc2015-10-28 12:32:09 +0000580 def read_all(self):
Chris Liechti03cb8ed2015-10-30 23:37:24 +0100581 """\
582 Read all bytes currently available in the buffer of the OS.
583 """
David Howlett240f8fc2015-10-28 12:32:09 +0000584 return self.read(self.in_waiting)
585
Chris Liechti70b89232015-08-04 03:00:52 +0200586 def read_until(self, terminator=LF, size=None):
587 """\
588 Read until a termination sequence is found ('\n' by default), the size
589 is exceeded or until timeout occurs.
590 """
591 lenterm = len(terminator)
592 line = bytearray()
593 while True:
594 c = self.read(1)
595 if c:
596 line += c
597 if line[-lenterm:] == terminator:
598 break
599 if size is not None and len(line) >= size:
600 break
601 else:
602 break
603 return bytes(line)
604
Chris Liechti70b89232015-08-04 03:00:52 +0200605 def iread_until(self, *args, **kwargs):
606 """\
607 Read lines, implemented as generator. It will raise StopIteration on
608 timeout (empty read).
609 """
610 while True:
611 line = self.read_until(*args, **kwargs)
Chris Liechti3ad62fb2015-08-29 21:53:32 +0200612 if not line:
613 break
Chris Liechti70b89232015-08-04 03:00:52 +0200614 yield line
cliechtif81362e2009-07-25 03:44:33 +0000615
Chris Liechti779b1a22015-08-04 14:54:22 +0200616
617# - - - - - - - - - - - - - - - - - - - - - - - - -
cliechtid6bf52c2003-10-01 02:28:12 +0000618if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000619 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000620 s = SerialBase()
Chris Liechti779b1a22015-08-04 14:54:22 +0200621 sys.stdout.write('port name: %s\n' % s.name)
622 sys.stdout.write('baud rates: %s\n' % s.BAUDRATES)
623 sys.stdout.write('byte sizes: %s\n' % s.BYTESIZES)
624 sys.stdout.write('parities: %s\n' % s.PARITIES)
625 sys.stdout.write('stop bits: %s\n' % s.STOPBITS)
cliechtif81362e2009-07-25 03:44:33 +0000626 sys.stdout.write('%s\n' % s)