diff options
author | cliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a> | 2004-04-20 01:55:43 +0000 |
---|---|---|
committer | cliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a> | 2004-04-20 01:55:43 +0000 |
commit | 626116161311f6ade383f4f603c8250e12cc8321 (patch) | |
tree | 5bd1d3e86abc7aed0e87f20237db31cdaeccc9cc /pyserial | |
parent | 6ac115b52dfbc2bc71538445b9d1c11fad7251c4 (diff) | |
download | pyserial-git-626116161311f6ade383f4f603c8250e12cc8321.tar.gz |
- implement write timeouts + tests
- added XON/XOFF constants
Diffstat (limited to 'pyserial')
-rw-r--r-- | pyserial/CHANGES.txt | 8 | ||||
-rw-r--r-- | pyserial/examples/test.py | 26 | ||||
-rw-r--r-- | pyserial/examples/test_advanced.py | 3 | ||||
-rw-r--r-- | pyserial/serial/.cvsignore | 1 | ||||
-rw-r--r-- | pyserial/serial/serialposix.py | 19 | ||||
-rw-r--r-- | pyserial/serial/serialutil.py | 34 | ||||
-rw-r--r-- | pyserial/serial/serialwin32.py | 16 |
7 files changed, 91 insertions, 16 deletions
diff --git a/pyserial/CHANGES.txt b/pyserial/CHANGES.txt index 3b8c4b1..fa8c257 100644 --- a/pyserial/CHANGES.txt +++ b/pyserial/CHANGES.txt @@ -28,8 +28,8 @@ Version 1.13 09 Apr 2002 If port opening fails, a SerialException is raised on all platforms Version 1.14 29 May 2002 - added examples to archive - added non-blocking mode for timeout=0 (tnx Mat Martineau) + Added examples to archive + Added non-blocking mode for timeout=0 (tnx Mat Martineau) Bugfixes: - win32 does now return the remaining characters on timeout @@ -137,4 +137,6 @@ Version 2.0 6 Nov 2003 Version 2.1 XXXXXXXXXXX Bugfixes (posix): - - fd == 0 fix from Vsevolod Lobko + - fd == 0 fix from Vsevolod Lobko + New Features: + - implement write timeouts ('writeTimeout' parameter) diff --git a/pyserial/examples/test.py b/pyserial/examples/test.py index 9713145..96bd3ee 100644 --- a/pyserial/examples/test.py +++ b/pyserial/examples/test.py @@ -95,7 +95,7 @@ class Test1_Forever(unittest.TestCase): character is sent after some time to stop the test, this is done through the SendEvent class and the Loopback HW.""" def setUp(self): - self.s = serial.Serial(PORT,timeout=None) + self.s = serial.Serial(PORT, timeout=None) self.event = SendEvent(self.s) def tearDown(self): self.event.stop() @@ -105,7 +105,7 @@ class Test1_Forever(unittest.TestCase): """no timeout: after port open, the input buffer must be empty (read). a character is sent after some time to terminate the test (SendEvent).""" c = self.s.read(1) - if not (self.event.isSet() and c =='E'): + if not (self.event.isSet() and c == 'E'): self.fail("expected marker") class Test2_Forever(unittest.TestCase): @@ -155,6 +155,28 @@ class Test0_DataWires(unittest.TestCase): """Test RI""" self.failUnless(self.s.getRI()==0, "RI -> 0") +class Test_MoreTimeouts(unittest.TestCase): + """Test with timeouts""" + def setUp(self): + self.s = serial.Serial() #create an closed serial port + + def tearDown(self): + self.s.close() + + def test_WriteTimeout(self): + """Test write() timeout.""" + #use xonxoff setting and the loopback adapter to switch traffic on hold + self.s.port = PORT + self.s.writeTimeout = 1 + self.s.xonxoff = 1 + self.s.open() + self.s.write(serial.XOFF) + time.sleep(0.1) #some systems need a little delay so that they can react on XOFF + t1 = time.time() + self.failUnlessRaises(serial.SerialTimeoutException, self.s.write, "timeout please"*100) + t2 = time.time() + self.failUnless( 1 <= (t2-t1) < 2, "Timeout not in the given intervall (%s)" % (t2-t1)) + if __name__ == '__main__': import sys print __doc__ diff --git a/pyserial/examples/test_advanced.py b/pyserial/examples/test_advanced.py index 8d65b16..a966c2f 100644 --- a/pyserial/examples/test_advanced.py +++ b/pyserial/examples/test_advanced.py @@ -67,7 +67,7 @@ class Test_ChangeAttributes(unittest.TestCase): #test internals self.failUnlessEqual(self.s._baudrate, baudrate) #test illegal values - for illegal_value in (-300, -1, 0, 'a', None): + for illegal_value in (-300, -1, 'a', None): self.failUnlessRaises(ValueError, self.s.setBaudrate, illegal_value) def test_BaudrateSetting2(self): @@ -155,7 +155,6 @@ class Test_ChangeAttributes(unittest.TestCase): self.s.close() self.failUnless(not self.s.isOpen()) - if __name__ == '__main__': import sys print __doc__ diff --git a/pyserial/serial/.cvsignore b/pyserial/serial/.cvsignore new file mode 100644 index 0000000..7e99e36 --- /dev/null +++ b/pyserial/serial/.cvsignore @@ -0,0 +1 @@ +*.pyc
\ No newline at end of file diff --git a/pyserial/serial/serialposix.py b/pyserial/serial/serialposix.py index 30e1eab..a03622e 100644 --- a/pyserial/serial/serialposix.py +++ b/pyserial/serial/serialposix.py @@ -13,7 +13,7 @@ import sys, os, fcntl, termios, struct, select from serialutil import * -VERSION = "$Revision: 1.20 $".split()[1] #extract CVS version +VERSION = "$Revision: 1.21 $".split()[1] #extract CVS version #Do check the Python version as some constants have moved. if (sys.hexversion < 0x020100f0): @@ -144,10 +144,11 @@ class Serial(SerialBase): except Exception, msg: self.fd = None raise SerialException("Could not open port: %s" % msg) - fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) #set blocking + #~ fcntl.fcntl(self.fd, FCNTL.F_SETFL, 0) #set blocking self._reconfigurePort() self._isOpen = True + #~ self.flushInput() def _reconfigurePort(self): @@ -208,7 +209,7 @@ class Serial(SerialBase): #xonxoff if hasattr(TERMIOS, 'IXANY'): if self._xonxoff: - iflag |= (TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY) + iflag |= (TERMIOS.IXON|TERMIOS.IXOFF) #|TERMIOS.IXANY) else: iflag &= ~(TERMIOS.IXON|TERMIOS.IXOFF|TERMIOS.IXANY) else: @@ -270,12 +271,12 @@ class Serial(SerialBase): if size > 0: while len(read) < size: #print "\tread(): size",size, "have", len(read) #debug - ready,_,_ = select.select([self.fd],[],[], self.timeout) + ready,_,_ = select.select([self.fd],[],[], self._timeout) if not ready: break #timeout buf = os.read(self.fd, size-len(read)) read = read + buf - if self.timeout >= 0 and not buf: + if self._timeout >= 0 and not buf: break #early abort on timeout return read @@ -285,7 +286,15 @@ class Serial(SerialBase): t = len(data) d = data while t > 0: + if self._writeTimeout is not None and self._writeTimeout > 0: + _,ready,_ = select.select([],[self.fd],[], self._writeTimeout) + if not ready: + raise writeTimeoutError n = os.write(self.fd, d) + if self._writeTimeout is not None and self._writeTimeout > 0: + _,ready,_ = select.select([],[self.fd],[], self._writeTimeout) + if not ready: + raise writeTimeoutError d = d[n:] t = t - n diff --git a/pyserial/serial/serialutil.py b/pyserial/serial/serialutil.py index c503568..0d4883b 100644 --- a/pyserial/serial/serialutil.py +++ b/pyserial/serial/serialutil.py @@ -15,6 +15,9 @@ PARITY_NAMES = { PARITY_ODD: 'Odd', } +XON = chr(16) +XOFF = chr(18) + #Python < 2.2.3 compatibility try: True @@ -27,6 +30,11 @@ class SerialException(Exception): portNotOpenError = SerialException('Port not open') +class SerialTimeoutException(SerialException): + """Write timeouts give an exception""" + +writeTimeoutError = SerialTimeoutException("Write timeout") + class FileLike(object): """An abstract file like class. @@ -113,6 +121,7 @@ class SerialBase(FileLike): timeout=None, #set a timeout value, None to wait forever xonxoff=0, #enable software flow control rtscts=0, #enable RTS/CTS flow control + writeTimeout=None, #set a timeout for writes ): """Initialize comm port object. If a port is given, then the port will be opened immediately. Otherwise a Serial port object in closed state @@ -125,16 +134,18 @@ class SerialBase(FileLike): self._parity = None #correct value is assigned below trough properties self._stopbits = None #correct value is assigned below trough properties self._timeout = None #correct value is assigned below trough properties + self._writeTimeout = None #correct value is assigned below trough properties self._xonxoff = None #correct value is assigned below trough properties self._rtscts = None #correct value is assigned below trough properties - #assign values using get/set methods using the properties featrure + #assign values using get/set methods using the properties feature self.port = port self.baudrate = baudrate self.bytesize = bytesize self.parity = parity self.stopbits = stopbits self.timeout = timeout + self.writeTimeout = writeTimeout self.xonxoff = xonxoff self.rtscts = rtscts @@ -263,7 +274,26 @@ class SerialBase(FileLike): """Get the current timeout setting.""" return self._timeout - timeout = property(getTimeout, setTimeout, "Timeout setting") + timeout = property(getTimeout, setTimeout, "Timeout setting for read()") + + + def setWriteTimeout(self, timeout): + """Change timeout setting.""" + if timeout is not None: + if timeout < 0: raise ValueError("Not a valid timeout: %r" % timeout) + try: + timeout + 1 #test if it's a number, will throw a TypeError if not... + except TypeError: + raise ValueError("Not a valid timeout: %r" % timeout) + + self._writeTimeout = timeout + if self._isOpen: self._reconfigurePort() + + def getWriteTimeout(self): + """Get the current timeout setting.""" + return self._writeTimeout + + writeTimeout = property(getWriteTimeout, setWriteTimeout, "Timeout setting for write()") def setXonXoff(self, xonxoff): diff --git a/pyserial/serial/serialwin32.py b/pyserial/serial/serialwin32.py index fa04029..5a22efd 100644 --- a/pyserial/serial/serialwin32.py +++ b/pyserial/serial/serialwin32.py @@ -11,7 +11,7 @@ import win32event # We use events and the WaitFor[Single|Multiple]Objects functi import win32con # constants. from serialutil import * -VERSION = "$Revision: 1.28 $".split()[1] #extract CVS version +VERSION = "$Revision: 1.29 $".split()[1] #extract CVS version #from winbase.h. these should realy be in win32con MS_CTS_ON = 16 @@ -90,6 +90,12 @@ class Serial(SerialBase): timeouts = (win32con.MAXDWORD, 0, 0, 0, 0) else: timeouts = (0, 0, int(self._timeout*1000), 0, 0) + if self._writeTimeout is None: + pass + elif self._writeTimeout == 0: + timeouts = timeouts[:-2] + (0, win32con.MAXDWORD) + else: + timeouts = timeouts[:-2] + (0, int(self._writeTimeout*1000)) win32file.SetCommTimeouts(self.hComPort, timeouts) win32file.SetCommMask(self.hComPort, win32file.EV_ERR) @@ -144,6 +150,8 @@ class Serial(SerialBase): comDCB.fNull = 0 comDCB.fErrorChar = 0 comDCB.fAbortOnError = 0 + comDCB.XonChar = XON + comDCB.XoffChar = XOFF try: win32file.SetCommState(self.hComPort, comDCB) @@ -207,7 +215,11 @@ class Serial(SerialBase): err, n = win32file.WriteFile(self.hComPort, s, self._overlappedWrite) if err: #will be ERROR_IO_PENDING: # Wait for the write to complete. - win32event.WaitForSingleObject(self._overlappedWrite.hEvent, win32event.INFINITE) + #~ win32event.WaitForSingleObject(self._overlappedWrite.hEvent, win32event.INFINITE) + n = win32file.GetOverlappedResult(self.hComPort, self._overlappedWrite, 1) + if n != len(s): + raise writeTimeoutError + def flushInput(self): """Clear input buffer, discarding all that is in the buffer.""" |