blob: 969467c6c3e1ec9ce12690a7b0b397195d415433 [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#
cliechti14b274a2009-02-07 00:27:05 +00005# (C) 2001-2009 Chris Liechti <cliechti@gmx.net>
cliechtid6bf52c2003-10-01 02:28:12 +00006# this is distributed under a free software license, see license.txt
7
cliechti58a2aee2010-05-20 23:37:57 +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)
22 # append automatically converts integers to characters
23 def append(self, item):
24 if isinstance(item, str):
25 list.append(self, item)
26 else:
27 list.append(self, chr(item))
cliechti1de32cd2009-08-07 19:05:09 +000028 # +=
29 def __iadd__(self, other):
30 for byte in other:
31 self.append(byte)
32 return self
cliechti0bbebbf2009-07-30 17:23:42 +000033
cliechti0bbebbf2009-07-30 17:23:42 +000034# all Python versions prior 3.x convert str([17]) to '[17]' instead of '\x11'
cliechti32c10332009-08-05 13:23:43 +000035# so a simple bytes(sequence) doesn't work for all versions
36def to_bytes(seq):
37 """convert a sequence to a bytes type"""
38 b = bytearray()
39 for item in seq:
40 b.append(item) # this one handles int and str
41 return bytes(b)
42
43# create control bytes
44XON = to_bytes([17])
45XOFF = to_bytes([19])
cliechti4a567a02009-07-27 22:09:31 +000046
cliechtia3a811f2009-07-29 21:59:03 +000047
cliechti0d6029a2008-06-21 01:28:46 +000048PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
cliechti58b481c2009-02-16 20:42:32 +000049STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
cliechti14b274a2009-02-07 00:27:05 +000050FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
cliechtid6bf52c2003-10-01 02:28:12 +000051
52PARITY_NAMES = {
cliechti4a567a02009-07-27 22:09:31 +000053 PARITY_NONE: 'None',
54 PARITY_EVEN: 'Even',
55 PARITY_ODD: 'Odd',
56 PARITY_MARK: 'Mark',
57 PARITY_SPACE: 'Space',
cliechtid6bf52c2003-10-01 02:28:12 +000058}
59
cliechti1dbe4b62002-02-14 02:49:25 +000060
cliechti4a567a02009-07-27 22:09:31 +000061class SerialException(IOError):
cliechtid6bf52c2003-10-01 02:28:12 +000062 """Base class for serial port related exceptions."""
cliechti7fe54d52002-03-03 20:11:47 +000063
cliechtid6bf52c2003-10-01 02:28:12 +000064
cliechti62611612004-04-20 01:55:43 +000065class SerialTimeoutException(SerialException):
66 """Write timeouts give an exception"""
67
cliechti4a567a02009-07-27 22:09:31 +000068
cliechti62611612004-04-20 01:55:43 +000069writeTimeoutError = SerialTimeoutException("Write timeout")
cliechti4a567a02009-07-27 22:09:31 +000070portNotOpenError = ValueError('Attempting to use a port that is not open')
cliechti62611612004-04-20 01:55:43 +000071
cliechtif81362e2009-07-25 03:44:33 +000072
cliechtid6bf52c2003-10-01 02:28:12 +000073class FileLike(object):
cliechti1dbe4b62002-02-14 02:49:25 +000074 """An abstract file like class.
cliechti14b274a2009-02-07 00:27:05 +000075
cliechti1dbe4b62002-02-14 02:49:25 +000076 This class implements readline and readlines based on read and
77 writelines based on write.
78 This class is used to provide the above functions for to Serial
79 port objects.
cliechti14b274a2009-02-07 00:27:05 +000080
cliechti1dbe4b62002-02-14 02:49:25 +000081 Note that when the serial port was opened with _NO_ timeout that
82 readline blocks until it sees a newline (or the specified size is
83 reached) and that readlines would never return and therefore
84 refuses to work (it raises an exception in this case)!
85 """
86
cliechtif81362e2009-07-25 03:44:33 +000087 def __init__(self):
88 self.closed = True
89
90 def close(self):
91 self.closed = True
92
93 # so that ports are closed when objects are discarded
94 def __del__(self):
95 """Destructor. Calls close()."""
96 # The try/except block is in case this is called at program
97 # exit time, when it's possible that globals have already been
98 # deleted, and then the close() call might fail. Since
99 # there's nothing we can do about such failures and they annoy
100 # the end users, we suppress the traceback.
101 try:
102 self.close()
103 except:
104 pass
105
cliechti1dbe4b62002-02-14 02:49:25 +0000106 def writelines(self, sequence):
107 for line in sequence:
108 self.write(line)
109
110 def flush(self):
cliechti1bb1bb22002-08-18 00:43:58 +0000111 """flush of file like objects"""
112 pass
cliechti1dbe4b62002-02-14 02:49:25 +0000113
cliechti980e4b02005-12-20 23:19:58 +0000114 # iterator for e.g. "for line in Serial(0): ..." usage
115 def next(self):
116 line = self.readline()
117 if not line: raise StopIteration
118 return line
119
120 def __iter__(self):
121 return self
122
cliechtif81362e2009-07-25 03:44:33 +0000123 # other functions of file-likes - not used by pySerial
cliechti980e4b02005-12-20 23:19:58 +0000124
cliechtif81362e2009-07-25 03:44:33 +0000125 #~ readinto(b)
126
127 def seek(self, pos, whence=0):
128 raise IOError("file is not seekable")
129
130 def tell(self):
131 raise IOError("file is not seekable")
132
133 def truncate(self, n=None):
134 raise IOError("file is not seekable")
135
136 def isatty(self):
137 return False
138
139
140class SerialBase(object):
cliechtid6bf52c2003-10-01 02:28:12 +0000141 """Serial port base class. Provides __init__ function and properties to
142 get/set port settings."""
cliechti14b274a2009-02-07 00:27:05 +0000143
cliechtidfec0c82009-07-21 01:35:41 +0000144 # default values, may be overridden in subclasses that do not support all values
cliechtif81362e2009-07-25 03:44:33 +0000145 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
146 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
147 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
148 3000000, 3500000, 4000000)
cliechtid6bf52c2003-10-01 02:28:12 +0000149 BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
cliechti14b274a2009-02-07 00:27:05 +0000150 PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
cliechti6ffdb8f2009-07-22 00:48:57 +0000151 STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
cliechti14b274a2009-02-07 00:27:05 +0000152
cliechtid6bf52c2003-10-01 02:28:12 +0000153 def __init__(self,
cliechti14b274a2009-02-07 00:27:05 +0000154 port = None, # number of device, numbering starts at
155 # zero. if everything fails, the user
156 # can specify a device string, note
157 # that this isn't portable anymore
158 # port will be opened if one is specified
cliechtidfec0c82009-07-21 01:35:41 +0000159 baudrate=9600, # baud rate
160 bytesize=EIGHTBITS, # number of data bits
cliechti14b274a2009-02-07 00:27:05 +0000161 parity=PARITY_NONE, # enable parity checking
cliechtidfec0c82009-07-21 01:35:41 +0000162 stopbits=STOPBITS_ONE, # number of stop bits
cliechti14b274a2009-02-07 00:27:05 +0000163 timeout=None, # set a timeout value, None to wait forever
cliechti74308e42010-07-21 14:03:59 +0000164 xonxoff=False, # enable software flow control
165 rtscts=False, # enable RTS/CTS flow control
cliechti14b274a2009-02-07 00:27:05 +0000166 writeTimeout=None, # set a timeout for writes
cliechti58a2aee2010-05-20 23:37:57 +0000167 dsrdtr=False, # None: use rtscts setting, dsrdtr override if True or False
cliechti14b274a2009-02-07 00:27:05 +0000168 interCharTimeout=None # Inter-character timeout, None to disable
cliechtid6bf52c2003-10-01 02:28:12 +0000169 ):
170 """Initialize comm port object. If a port is given, then the port will be
cliechti02f7c992004-02-02 19:48:27 +0000171 opened immediately. Otherwise a Serial port object in closed state
cliechtid6bf52c2003-10-01 02:28:12 +0000172 is returned."""
173
174 self._isOpen = False
cliechti4a567a02009-07-27 22:09:31 +0000175 self._port = None # correct value is assigned below through properties
176 self._baudrate = None # correct value is assigned below through properties
177 self._bytesize = None # correct value is assigned below through properties
178 self._parity = None # correct value is assigned below through properties
179 self._stopbits = None # correct value is assigned below through properties
180 self._timeout = None # correct value is assigned below through properties
181 self._writeTimeout = None # correct value is assigned below through properties
182 self._xonxoff = None # correct value is assigned below through properties
183 self._rtscts = None # correct value is assigned below through properties
184 self._dsrdtr = None # correct value is assigned below through properties
185 self._interCharTimeout = None # correct value is assigned below through properties
cliechti14b274a2009-02-07 00:27:05 +0000186
187 # assign values using get/set methods using the properties feature
cliechtid6bf52c2003-10-01 02:28:12 +0000188 self.port = port
189 self.baudrate = baudrate
190 self.bytesize = bytesize
191 self.parity = parity
192 self.stopbits = stopbits
193 self.timeout = timeout
cliechti62611612004-04-20 01:55:43 +0000194 self.writeTimeout = writeTimeout
cliechtid6bf52c2003-10-01 02:28:12 +0000195 self.xonxoff = xonxoff
196 self.rtscts = rtscts
cliechtif46e0a82005-05-19 15:24:57 +0000197 self.dsrdtr = dsrdtr
cliechti679bfa62008-06-20 23:58:15 +0000198 self.interCharTimeout = interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000199
cliechtid6bf52c2003-10-01 02:28:12 +0000200 if port is not None:
201 self.open()
202
203 def isOpen(self):
204 """Check if the port is opened."""
205 return self._isOpen
206
207 # - - - - - - - - - - - - - - - - - - - - - - - -
208
cliechti9147c442009-07-21 22:12:16 +0000209 # TODO: these are not really needed as the is the BAUDRATES etc. attribute...
cliechti14b274a2009-02-07 00:27:05 +0000210 # maybe i remove them before the final release...
211
cliechtid6bf52c2003-10-01 02:28:12 +0000212 def getSupportedBaudrates(self):
213 return [(str(b), b) for b in self.BAUDRATES]
214
215 def getSupportedByteSizes(self):
216 return [(str(b), b) for b in self.BYTESIZES]
cliechti14b274a2009-02-07 00:27:05 +0000217
cliechtid6bf52c2003-10-01 02:28:12 +0000218 def getSupportedStopbits(self):
219 return [(str(b), b) for b in self.STOPBITS]
220
221 def getSupportedParities(self):
222 return [(PARITY_NAMES[b], b) for b in self.PARITIES]
223
224 # - - - - - - - - - - - - - - - - - - - - - - - -
225
226 def setPort(self, port):
227 """Change the port. The attribute portstr is set to a string that
228 contains the name of the port."""
cliechti14b274a2009-02-07 00:27:05 +0000229
cliechtid6bf52c2003-10-01 02:28:12 +0000230 was_open = self._isOpen
231 if was_open: self.close()
232 if port is not None:
cliechtif81362e2009-07-25 03:44:33 +0000233 if isinstance(port, basestring):
cliechtid6bf52c2003-10-01 02:28:12 +0000234 self.portstr = port
235 else:
236 self.portstr = self.makeDeviceName(port)
237 else:
238 self.portstr = None
239 self._port = port
cliechtif81362e2009-07-25 03:44:33 +0000240 self.name = self.portstr
cliechtid6bf52c2003-10-01 02:28:12 +0000241 if was_open: self.open()
cliechti14b274a2009-02-07 00:27:05 +0000242
cliechtid6bf52c2003-10-01 02:28:12 +0000243 def getPort(self):
cliechti107db8d2004-01-15 01:20:23 +0000244 """Get the current port setting. The value that was passed on init or using
cliechtid6bf52c2003-10-01 02:28:12 +0000245 setPort() is passed back. See also the attribute portstr which contains
246 the name of the port as a string."""
247 return self._port
248
cliechti0276f5e2004-11-13 03:14:11 +0000249 port = property(getPort, setPort, doc="Port setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000250
251
252 def setBaudrate(self, baudrate):
cliechti4a567a02009-07-27 22:09:31 +0000253 """Change baud rate. It raises a ValueError if the port is open and the
cliechti2750b832009-07-28 00:13:52 +0000254 baud rate is not possible. If the port is closed, then the value is
cliechti107db8d2004-01-15 01:20:23 +0000255 accepted and the exception is raised when the port is opened."""
cliechti107db8d2004-01-15 01:20:23 +0000256 try:
257 self._baudrate = int(baudrate)
258 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000259 raise ValueError("Not a valid baudrate: %r" % (baudrate,))
cliechti107db8d2004-01-15 01:20:23 +0000260 else:
261 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000262
cliechtid6bf52c2003-10-01 02:28:12 +0000263 def getBaudrate(self):
cliechti4a567a02009-07-27 22:09:31 +0000264 """Get the current baud rate setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000265 return self._baudrate
cliechti14b274a2009-02-07 00:27:05 +0000266
cliechti4a567a02009-07-27 22:09:31 +0000267 baudrate = property(getBaudrate, setBaudrate, doc="Baud rate setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000268
269
270 def setByteSize(self, bytesize):
271 """Change byte size."""
cliechti93db61b2006-08-26 19:16:18 +0000272 if bytesize not in self.BYTESIZES: raise ValueError("Not a valid byte size: %r" % (bytesize,))
cliechtid6bf52c2003-10-01 02:28:12 +0000273 self._bytesize = bytesize
274 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000275
cliechtid6bf52c2003-10-01 02:28:12 +0000276 def getByteSize(self):
277 """Get the current byte size setting."""
278 return self._bytesize
cliechti14b274a2009-02-07 00:27:05 +0000279
cliechti0276f5e2004-11-13 03:14:11 +0000280 bytesize = property(getByteSize, setByteSize, doc="Byte size setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000281
282
283 def setParity(self, parity):
284 """Change parity setting."""
cliechti93db61b2006-08-26 19:16:18 +0000285 if parity not in self.PARITIES: raise ValueError("Not a valid parity: %r" % (parity,))
cliechtid6bf52c2003-10-01 02:28:12 +0000286 self._parity = parity
287 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000288
cliechtid6bf52c2003-10-01 02:28:12 +0000289 def getParity(self):
290 """Get the current parity setting."""
291 return self._parity
cliechti14b274a2009-02-07 00:27:05 +0000292
cliechti0276f5e2004-11-13 03:14:11 +0000293 parity = property(getParity, setParity, doc="Parity setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000294
295
296 def setStopbits(self, stopbits):
cliechti4a567a02009-07-27 22:09:31 +0000297 """Change stop bits size."""
298 if stopbits not in self.STOPBITS: raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
cliechtid6bf52c2003-10-01 02:28:12 +0000299 self._stopbits = stopbits
300 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000301
cliechtid6bf52c2003-10-01 02:28:12 +0000302 def getStopbits(self):
cliechti4a567a02009-07-27 22:09:31 +0000303 """Get the current stop bits setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000304 return self._stopbits
cliechti14b274a2009-02-07 00:27:05 +0000305
cliechti4a567a02009-07-27 22:09:31 +0000306 stopbits = property(getStopbits, setStopbits, doc="Stop bits setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000307
308
309 def setTimeout(self, timeout):
310 """Change timeout setting."""
311 if timeout is not None:
cliechtid6bf52c2003-10-01 02:28:12 +0000312 try:
cliechti14b274a2009-02-07 00:27:05 +0000313 timeout + 1 # test if it's a number, will throw a TypeError if not...
cliechtid6bf52c2003-10-01 02:28:12 +0000314 except TypeError:
cliechti93db61b2006-08-26 19:16:18 +0000315 raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti2750b832009-07-28 00:13:52 +0000316 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechtid6bf52c2003-10-01 02:28:12 +0000317 self._timeout = timeout
318 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000319
cliechtid6bf52c2003-10-01 02:28:12 +0000320 def getTimeout(self):
321 """Get the current timeout setting."""
322 return self._timeout
cliechti14b274a2009-02-07 00:27:05 +0000323
cliechti0276f5e2004-11-13 03:14:11 +0000324 timeout = property(getTimeout, setTimeout, doc="Timeout setting for read()")
cliechti62611612004-04-20 01:55:43 +0000325
326
327 def setWriteTimeout(self, timeout):
328 """Change timeout setting."""
329 if timeout is not None:
cliechti93db61b2006-08-26 19:16:18 +0000330 if timeout < 0: raise ValueError("Not a valid timeout: %r" % (timeout,))
cliechti62611612004-04-20 01:55:43 +0000331 try:
332 timeout + 1 #test if it's a number, will throw a TypeError if not...
333 except TypeError:
334 raise ValueError("Not a valid timeout: %r" % timeout)
cliechti14b274a2009-02-07 00:27:05 +0000335
cliechti62611612004-04-20 01:55:43 +0000336 self._writeTimeout = timeout
337 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000338
cliechti62611612004-04-20 01:55:43 +0000339 def getWriteTimeout(self):
340 """Get the current timeout setting."""
341 return self._writeTimeout
cliechti14b274a2009-02-07 00:27:05 +0000342
cliechti0276f5e2004-11-13 03:14:11 +0000343 writeTimeout = property(getWriteTimeout, setWriteTimeout, doc="Timeout setting for write()")
cliechtid6bf52c2003-10-01 02:28:12 +0000344
345
346 def setXonXoff(self, xonxoff):
cliechti4a567a02009-07-27 22:09:31 +0000347 """Change XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000348 self._xonxoff = xonxoff
349 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000350
cliechtid6bf52c2003-10-01 02:28:12 +0000351 def getXonXoff(self):
cliechti4a567a02009-07-27 22:09:31 +0000352 """Get the current XON/XOFF setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000353 return self._xonxoff
cliechti14b274a2009-02-07 00:27:05 +0000354
cliechti4a567a02009-07-27 22:09:31 +0000355 xonxoff = property(getXonXoff, setXonXoff, doc="XON/XOFF setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000356
357 def setRtsCts(self, rtscts):
cliechti4a567a02009-07-27 22:09:31 +0000358 """Change RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000359 self._rtscts = rtscts
360 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000361
cliechtid6bf52c2003-10-01 02:28:12 +0000362 def getRtsCts(self):
cliechti4a567a02009-07-27 22:09:31 +0000363 """Get the current RTS/CTS flow control setting."""
cliechtid6bf52c2003-10-01 02:28:12 +0000364 return self._rtscts
cliechti14b274a2009-02-07 00:27:05 +0000365
cliechtif46e0a82005-05-19 15:24:57 +0000366 rtscts = property(getRtsCts, setRtsCts, doc="RTS/CTS flow control setting")
cliechtid6bf52c2003-10-01 02:28:12 +0000367
cliechtif46e0a82005-05-19 15:24:57 +0000368 def setDsrDtr(self, dsrdtr=None):
369 """Change DsrDtr flow control setting."""
370 if dsrdtr is None:
cliechti14b274a2009-02-07 00:27:05 +0000371 # if not set, keep backwards compatibility and follow rtscts setting
cliechtif46e0a82005-05-19 15:24:57 +0000372 self._dsrdtr = self._rtscts
373 else:
cliechti14b274a2009-02-07 00:27:05 +0000374 # if defined independently, follow its value
cliechtif46e0a82005-05-19 15:24:57 +0000375 self._dsrdtr = dsrdtr
376 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000377
cliechtif46e0a82005-05-19 15:24:57 +0000378 def getDsrDtr(self):
cliechti4a567a02009-07-27 22:09:31 +0000379 """Get the current DSR/DTR flow control setting."""
cliechtif46e0a82005-05-19 15:24:57 +0000380 return self._dsrdtr
cliechti14b274a2009-02-07 00:27:05 +0000381
cliechtif46e0a82005-05-19 15:24:57 +0000382 dsrdtr = property(getDsrDtr, setDsrDtr, "DSR/DTR flow control setting")
cliechti679bfa62008-06-20 23:58:15 +0000383
384 def setInterCharTimeout(self, interCharTimeout):
385 """Change inter-character timeout setting."""
386 if interCharTimeout is not None:
387 if interCharTimeout < 0: raise ValueError("Not a valid timeout: %r" % interCharTimeout)
388 try:
cliechti14b274a2009-02-07 00:27:05 +0000389 interCharTimeout + 1 # test if it's a number, will throw a TypeError if not...
cliechti679bfa62008-06-20 23:58:15 +0000390 except TypeError:
391 raise ValueError("Not a valid timeout: %r" % interCharTimeout)
cliechti14b274a2009-02-07 00:27:05 +0000392
cliechti679bfa62008-06-20 23:58:15 +0000393 self._interCharTimeout = interCharTimeout
394 if self._isOpen: self._reconfigurePort()
cliechti14b274a2009-02-07 00:27:05 +0000395
cliechti679bfa62008-06-20 23:58:15 +0000396 def getInterCharTimeout(self):
397 """Get the current inter-character timeout setting."""
398 return self._interCharTimeout
cliechti14b274a2009-02-07 00:27:05 +0000399
cliechti679bfa62008-06-20 23:58:15 +0000400 interCharTimeout = property(getInterCharTimeout, setInterCharTimeout, doc="Inter-character timeout setting for read()")
401
cliechti4065dce2009-08-10 00:55:46 +0000402 # - - - - - - - - - - - - - - - - - - - - - - - -
403
404 _SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
405 'dsrdtr', 'rtscts', 'timeout', 'writeTimeout', 'interCharTimeout')
406
407 def getSettingsDict(self):
408 """Get current port settings as a dictionary. For use with
409 applySettingsDict"""
410 return dict([(key, getattr(self, '_'+key)) for key in self._SETTINGS])
411
412 def applySettingsDict(self, d):
413 """apply stored settings from a dictionary returned from
414 getSettingsDict. it's allowed to delete keys from the dictionary. these
415 values will simply left unchanged."""
416 for key in self._SETTINGS:
417 if d[key] != getattr(self, '_'+key): # check against internal "_" value
418 setattr(self, key, d[key]) # set non "_" value to use properties write function
cliechti679bfa62008-06-20 23:58:15 +0000419
cliechtid6bf52c2003-10-01 02:28:12 +0000420 # - - - - - - - - - - - - - - - - - - - - - - - -
421
422 def __repr__(self):
423 """String representation of the current port settings and its state."""
cliechtif46e0a82005-05-19 15:24:57 +0000424 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 +0000425 self.__class__.__name__,
426 id(self),
427 self._isOpen,
428 self.portstr,
429 self.baudrate,
430 self.bytesize,
431 self.parity,
432 self.stopbits,
433 self.timeout,
434 self.xonxoff,
435 self.rtscts,
cliechtif46e0a82005-05-19 15:24:57 +0000436 self.dsrdtr,
cliechtid6bf52c2003-10-01 02:28:12 +0000437 )
438
cliechti4a567a02009-07-27 22:09:31 +0000439 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechtif81362e2009-07-25 03:44:33 +0000440
cliechti4a567a02009-07-27 22:09:31 +0000441 def readline(self, size=None, eol='\n'):
442 """read a line which is terminated with end-of-line (eol) character
cliechti81167532010-07-21 01:12:22 +0000443 ('\n' by default) or until timeout."""
cliechti04ca5372010-07-21 00:07:22 +0000444 line = bytearray()
cliechti4a567a02009-07-27 22:09:31 +0000445 while 1:
446 c = self.read(1)
447 if c:
cliechti04ca5372010-07-21 00:07:22 +0000448 line += c
cliechti4a567a02009-07-27 22:09:31 +0000449 if c == eol:
450 break
451 if size is not None and len(line) >= size:
452 break
453 else:
454 break
455 return bytes(line)
cliechtif81362e2009-07-25 03:44:33 +0000456
cliechti4a567a02009-07-27 22:09:31 +0000457 def readlines(self, sizehint=None, eol='\n'):
cliechti81167532010-07-21 01:12:22 +0000458 """read a list of lines, until timeout.
459 sizehint is ignored."""
cliechti4a567a02009-07-27 22:09:31 +0000460 if self.timeout is None:
461 raise ValueError("Serial port MUST have enabled timeout for this function!")
462 lines = []
463 while 1:
464 line = self.readline(eol=eol)
465 if line:
466 lines.append(line)
467 if line[-1] != eol: # was the line received with a timeout?
468 break
469 else:
470 break
471 return lines
cliechtif81362e2009-07-25 03:44:33 +0000472
cliechti4a567a02009-07-27 22:09:31 +0000473 def xreadlines(self, sizehint=None):
cliechti81167532010-07-21 01:12:22 +0000474 """Read lines, implemented as generator. It will raise StopIteration on
475 timeout (empty read). sizehint is ignored."""
476 while True:
477 line = self.readline()
478 if not line: break
479 yield line
cliechti4a567a02009-07-27 22:09:31 +0000480
481 # - - - - - - - - - - - - - - - - - - - - - - - -
482 # compatibility with io library
483
484 def readable(self): return True
485 def writable(self): return True
486 def seekable(self): return False
487 def readinto(self, b):
488 data = self.read(len(b))
489 n = len(data)
490 try:
491 b[:n] = data
492 except TypeError, err:
493 import array
494 if not isinstance(b, array.array):
495 raise err
496 b[:n] = array.array('b', data)
497 return n
cliechtif81362e2009-07-25 03:44:33 +0000498
499
cliechtid6bf52c2003-10-01 02:28:12 +0000500if __name__ == '__main__':
cliechtif81362e2009-07-25 03:44:33 +0000501 import sys
cliechtid6bf52c2003-10-01 02:28:12 +0000502 s = SerialBase()
cliechtif81362e2009-07-25 03:44:33 +0000503 sys.stdout.write('port name: %s\n' % s.portstr)
504 sys.stdout.write('baud rates: %s\n' % s.getSupportedBaudrates())
505 sys.stdout.write('byte sizes: %s\n' % s.getSupportedByteSizes())
506 sys.stdout.write('parities: %s\n' % s.getSupportedParities())
507 sys.stdout.write('stop bits: %s\n' % s.getSupportedStopbits())
508 sys.stdout.write('%s\n' % s)