blob: d360d9cb23cebd7eb7febcab4577056f58f38a1c [file] [log] [blame]
cliechti89b4af12002-02-12 23:24:41 +00001#! python
cliechtic54b2c82008-06-21 01:59:08 +00002# Python Serial Port Extension for Win32, Linux, BSD, Jython
3# serial driver for win32
4# see __init__.py
cliechti89b4af12002-02-12 23:24:41 +00005#
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
cliechti183d4ae2009-07-23 22:03:51 +00009#
10# Initial patch to use ctypes by Giovanni Bajo <rasky@develer.com>
cliechti89b4af12002-02-12 23:24:41 +000011
cliechti183d4ae2009-07-23 22:03:51 +000012import ctypes
Chris Liechtid240cf52015-08-05 02:57:03 +020013import time
cliechti39cfb7b2011-08-22 00:30:07 +000014from serial import win32
cliechti183d4ae2009-07-23 22:03:51 +000015
cliechti39cfb7b2011-08-22 00:30:07 +000016from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000017
cliechti4a567a02009-07-27 22:09:31 +000018
cliechti4e838702003-08-28 22:18:02 +000019def device(portnum):
cliechtid6bf52c2003-10-01 02:28:12 +000020 """Turn a port number into a device name"""
cliechti4a567a02009-07-27 22:09:31 +000021 return 'COM%d' % (portnum+1) # numbers are transformed to a string
22
cliechti4e838702003-08-28 22:18:02 +000023
Chris Liechtief6b7b42015-08-06 22:19:26 +020024class Serial(SerialBase):
cliechti1e2a6df2009-07-24 02:00:50 +000025 """Serial port implementation for Win32 based on ctypes."""
cliechti89b4af12002-02-12 23:24:41 +000026
cliechti4a567a02009-07-27 22:09:31 +000027 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
28 9600, 19200, 38400, 57600, 115200)
cliechti80a0ed12003-10-03 23:53:42 +000029
cliechti5735a072009-10-26 23:57:48 +000030 def __init__(self, *args, **kwargs):
31 self.hComPort = None
cliechti1ae5ab02013-10-11 01:08:02 +000032 self._overlappedRead = None
33 self._overlappedWrite = None
cliechti1f89a0a2011-08-05 02:53:24 +000034 self._rtsToggle = False
cliechti22175a72011-12-29 00:17:53 +000035
36 self._rtsState = win32.RTS_CONTROL_ENABLE
37 self._dtrState = win32.DTR_CONTROL_ENABLE
38
cliechti1ae5ab02013-10-11 01:08:02 +000039
cliechti5735a072009-10-26 23:57:48 +000040 SerialBase.__init__(self, *args, **kwargs)
41
cliechtid6bf52c2003-10-01 02:28:12 +000042 def open(self):
cliechti7d448562014-08-03 21:57:45 +000043 """\
44 Open port with current settings. This may throw a SerialException
45 if the port cannot be opened.
46 """
cliechtid6bf52c2003-10-01 02:28:12 +000047 if self._port is None:
48 raise SerialException("Port must be configured before it can be used.")
cliechti8f69e702011-03-19 00:22:32 +000049 if self._isOpen:
50 raise SerialException("Port is already open.")
cliechti8b7cff02008-06-24 12:11:57 +000051 # the "\\.\COMx" format is required for devices other than COM1-COM8
52 # not all versions of windows seem to support this properly
53 # so that the first few ports are used with the DOS device name
54 port = self.portstr
cliechti4a567a02009-07-27 22:09:31 +000055 try:
56 if port.upper().startswith('COM') and int(port[3:]) > 8:
57 port = '\\\\.\\' + port
58 except ValueError:
59 # for like COMnotanumber
60 pass
cliechtie37b6a82009-07-24 12:19:50 +000061 self.hComPort = win32.CreateFile(port,
62 win32.GENERIC_READ | win32.GENERIC_WRITE,
63 0, # exclusive access
64 None, # no security
65 win32.OPEN_EXISTING,
66 win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
67 0)
68 if self.hComPort == win32.INVALID_HANDLE_VALUE:
cliechti4a567a02009-07-27 22:09:31 +000069 self.hComPort = None # 'cause __del__ is called anyway
cliechti1083be72011-12-28 20:45:30 +000070 raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))
cliechtie37b6a82009-07-24 12:19:50 +000071
cliechti1ae5ab02013-10-11 01:08:02 +000072 try:
73 self._overlappedRead = win32.OVERLAPPED()
74 self._overlappedRead.hEvent = win32.CreateEvent(None, 1, 0, None)
75 self._overlappedWrite = win32.OVERLAPPED()
76 #~ self._overlappedWrite.hEvent = win32.CreateEvent(None, 1, 0, None)
77 self._overlappedWrite.hEvent = win32.CreateEvent(None, 0, 0, None)
cliechti89b4af12002-02-12 23:24:41 +000078
cliechti1ae5ab02013-10-11 01:08:02 +000079 # Setup a 4k buffer
80 win32.SetupComm(self.hComPort, 4096, 4096)
cliechti89b4af12002-02-12 23:24:41 +000081
cliechti1ae5ab02013-10-11 01:08:02 +000082 # Save original timeout values:
83 self._orgTimeouts = win32.COMMTIMEOUTS()
84 win32.GetCommTimeouts(self.hComPort, ctypes.byref(self._orgTimeouts))
cliechtiedfba4e2009-02-07 00:29:47 +000085
cliechti1ae5ab02013-10-11 01:08:02 +000086 self._reconfigurePort()
cliechti89b4af12002-02-12 23:24:41 +000087
cliechti1ae5ab02013-10-11 01:08:02 +000088 # Clear buffers:
89 # Remove anything that was there
90 win32.PurgeComm(self.hComPort,
91 win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
92 win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
93 except:
94 try:
95 self._close()
96 except:
97 # ignore any exception when closing the port
98 # also to keep original exception that happened when setting up
99 pass
100 self.hComPort = None
101 raise
102 else:
103 self._isOpen = True
104
cliechti89b4af12002-02-12 23:24:41 +0000105
cliechtid6bf52c2003-10-01 02:28:12 +0000106 def _reconfigurePort(self):
cliechticc8d9d22008-07-06 22:42:44 +0000107 """Set communication parameters on opened port."""
cliechtid6bf52c2003-10-01 02:28:12 +0000108 if not self.hComPort:
109 raise SerialException("Can only operate on a valid port handle")
cliechtiedfba4e2009-02-07 00:29:47 +0000110
111 # Set Windows timeout values
112 # timeouts is a tuple with the following items:
113 # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
114 # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
115 # WriteTotalTimeoutConstant)
cliechtid6bf52c2003-10-01 02:28:12 +0000116 if self._timeout is None:
117 timeouts = (0, 0, 0, 0, 0)
118 elif self._timeout == 0:
cliechti183d4ae2009-07-23 22:03:51 +0000119 timeouts = (win32.MAXDWORD, 0, 0, 0, 0)
cliechtid6bf52c2003-10-01 02:28:12 +0000120 else:
121 timeouts = (0, 0, int(self._timeout*1000), 0, 0)
cliechti679bfa62008-06-20 23:58:15 +0000122 if self._timeout != 0 and self._interCharTimeout is not None:
123 timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
cliechtiedfba4e2009-02-07 00:29:47 +0000124
cliechti62611612004-04-20 01:55:43 +0000125 if self._writeTimeout is None:
126 pass
127 elif self._writeTimeout == 0:
cliechti183d4ae2009-07-23 22:03:51 +0000128 timeouts = timeouts[:-2] + (0, win32.MAXDWORD)
cliechti62611612004-04-20 01:55:43 +0000129 else:
130 timeouts = timeouts[:-2] + (0, int(self._writeTimeout*1000))
cliechti183d4ae2009-07-23 22:03:51 +0000131 win32.SetCommTimeouts(self.hComPort, ctypes.byref(win32.COMMTIMEOUTS(*timeouts)))
cliechti89b4af12002-02-12 23:24:41 +0000132
cliechti183d4ae2009-07-23 22:03:51 +0000133 win32.SetCommMask(self.hComPort, win32.EV_ERR)
cliechti89b4af12002-02-12 23:24:41 +0000134
cliechti95c62212002-03-04 22:17:53 +0000135 # Setup the connection info.
136 # Get state and modify it:
cliechti183d4ae2009-07-23 22:03:51 +0000137 comDCB = win32.DCB()
138 win32.GetCommState(self.hComPort, ctypes.byref(comDCB))
cliechtid6bf52c2003-10-01 02:28:12 +0000139 comDCB.BaudRate = self._baudrate
140
141 if self._bytesize == FIVEBITS:
142 comDCB.ByteSize = 5
143 elif self._bytesize == SIXBITS:
144 comDCB.ByteSize = 6
145 elif self._bytesize == SEVENBITS:
146 comDCB.ByteSize = 7
147 elif self._bytesize == EIGHTBITS:
148 comDCB.ByteSize = 8
149 else:
150 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
151
152 if self._parity == PARITY_NONE:
cliechti183d4ae2009-07-23 22:03:51 +0000153 comDCB.Parity = win32.NOPARITY
154 comDCB.fParity = 0 # Disable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000155 elif self._parity == PARITY_EVEN:
cliechti183d4ae2009-07-23 22:03:51 +0000156 comDCB.Parity = win32.EVENPARITY
157 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000158 elif self._parity == PARITY_ODD:
cliechti183d4ae2009-07-23 22:03:51 +0000159 comDCB.Parity = win32.ODDPARITY
160 comDCB.fParity = 1 # Enable Parity Check
cliechtic54b2c82008-06-21 01:59:08 +0000161 elif self._parity == PARITY_MARK:
cliechti183d4ae2009-07-23 22:03:51 +0000162 comDCB.Parity = win32.MARKPARITY
163 comDCB.fParity = 1 # Enable Parity Check
cliechtic54b2c82008-06-21 01:59:08 +0000164 elif self._parity == PARITY_SPACE:
cliechti183d4ae2009-07-23 22:03:51 +0000165 comDCB.Parity = win32.SPACEPARITY
166 comDCB.fParity = 1 # Enable Parity Check
cliechtid6bf52c2003-10-01 02:28:12 +0000167 else:
168 raise ValueError("Unsupported parity mode: %r" % self._parity)
169
170 if self._stopbits == STOPBITS_ONE:
cliechti183d4ae2009-07-23 22:03:51 +0000171 comDCB.StopBits = win32.ONESTOPBIT
cliechti58b481c2009-02-16 20:42:32 +0000172 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
cliechti183d4ae2009-07-23 22:03:51 +0000173 comDCB.StopBits = win32.ONE5STOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000174 elif self._stopbits == STOPBITS_TWO:
cliechti183d4ae2009-07-23 22:03:51 +0000175 comDCB.StopBits = win32.TWOSTOPBITS
cliechtid6bf52c2003-10-01 02:28:12 +0000176 else:
177 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
cliechtiedfba4e2009-02-07 00:29:47 +0000178
cliechtid6bf52c2003-10-01 02:28:12 +0000179 comDCB.fBinary = 1 # Enable Binary Transmission
180 # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
Chris Liechti33f0ec52015-08-06 16:37:21 +0200181 if self._rs485_mode is None:
182 if self._rtscts:
183 comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE
184 else:
185 comDCB.fRtsControl = self._rtsState
186 comDCB.fOutxCtsFlow = self._rtscts
cliechtid6bf52c2003-10-01 02:28:12 +0000187 else:
Chris Liechti33f0ec52015-08-06 16:37:21 +0200188 # checks for unsupported settings
189 # XXX verify if platform really does not have a setting for those
190 if not self._rs485_mode.rts_level_for_tx:
191 raise ValueError(
192 'Unsupported value for RS485Settings.rts_level_for_tx: %r' % (
193 self._rs485_mode.rts_level_for_tx,))
194 if self._rs485_mode.rts_level_for_rx:
195 raise ValueError(
196 'Unsupported value for RS485Settings.rts_level_for_rx: %r' % (
197 self._rs485_mode.rts_level_for_rx,))
198 if self._rs485_mode.delay_before_tx is not None:
199 raise ValueError(
200 'Unsupported value for RS485Settings.delay_before_tx: %r' % (
201 self._rs485_mode.delay_before_tx,))
202 if self._rs485_mode.delay_before_rx is not None:
203 raise ValueError(
204 'Unsupported value for RS485Settings.delay_before_rx: %r' % (
205 self._rs485_mode.delay_before_rx,))
206 if self._rs485_mode.loopback:
207 raise ValueError(
208 'Unsupported value for RS485Settings.loopback: %r' % (
209 self._rs485_mode.loopback,))
210 comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE
211 comDCB.fOutxCtsFlow = 0
212
cliechtif46e0a82005-05-19 15:24:57 +0000213 if self._dsrdtr:
cliechti183d4ae2009-07-23 22:03:51 +0000214 comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE
cliechtif46e0a82005-05-19 15:24:57 +0000215 else:
cliechti7ffcfef2004-07-28 01:08:25 +0000216 comDCB.fDtrControl = self._dtrState
cliechtif46e0a82005-05-19 15:24:57 +0000217 comDCB.fOutxDsrFlow = self._dsrdtr
cliechtid6bf52c2003-10-01 02:28:12 +0000218 comDCB.fOutX = self._xonxoff
219 comDCB.fInX = self._xonxoff
220 comDCB.fNull = 0
221 comDCB.fErrorChar = 0
222 comDCB.fAbortOnError = 0
cliechti62611612004-04-20 01:55:43 +0000223 comDCB.XonChar = XON
224 comDCB.XoffChar = XOFF
cliechtid6bf52c2003-10-01 02:28:12 +0000225
cliechti183d4ae2009-07-23 22:03:51 +0000226 if not win32.SetCommState(self.hComPort, ctypes.byref(comDCB)):
cliechti1083be72011-12-28 20:45:30 +0000227 raise ValueError("Cannot configure port, some setting was wrong. Original message: %r" % ctypes.WinError())
cliechti95c62212002-03-04 22:17:53 +0000228
cliechtid6bf52c2003-10-01 02:28:12 +0000229 #~ def __del__(self):
230 #~ self.close()
231
cliechti1ae5ab02013-10-11 01:08:02 +0000232
233 def _close(self):
234 """internal close port helper"""
235 if self.hComPort:
236 # Restore original timeout values:
237 win32.SetCommTimeouts(self.hComPort, self._orgTimeouts)
238 # Close COM-Port:
239 win32.CloseHandle(self.hComPort)
240 if self._overlappedRead is not None:
241 win32.CloseHandle(self._overlappedRead.hEvent)
242 self._overlappedRead = None
243 if self._overlappedWrite is not None:
244 win32.CloseHandle(self._overlappedWrite.hEvent)
245 self._overlappedWrite = None
246 self.hComPort = None
247
cliechtid6bf52c2003-10-01 02:28:12 +0000248 def close(self):
249 """Close port"""
250 if self._isOpen:
cliechti1ae5ab02013-10-11 01:08:02 +0000251 self._close()
cliechtid6bf52c2003-10-01 02:28:12 +0000252 self._isOpen = False
253
254 def makeDeviceName(self, port):
cliechti8b7cff02008-06-24 12:11:57 +0000255 return device(port)
cliechtid6bf52c2003-10-01 02:28:12 +0000256
257 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechtiedfba4e2009-02-07 00:29:47 +0000258
cliechti89b4af12002-02-12 23:24:41 +0000259 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000260 """Return the number of characters currently in the input buffer."""
cliechti183d4ae2009-07-23 22:03:51 +0000261 flags = win32.DWORD()
262 comstat = win32.COMSTAT()
263 if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
264 raise SerialException('call to ClearCommError failed')
cliechti89b4af12002-02-12 23:24:41 +0000265 return comstat.cbInQue
266
cliechti4a567a02009-07-27 22:09:31 +0000267 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000268 """\
269 Read size bytes from the serial port. If a timeout is set it may
270 return less characters as requested. With no timeout it will block
271 until the requested number of bytes is read."""
cliechti89b4af12002-02-12 23:24:41 +0000272 if not self.hComPort: raise portNotOpenError
cliechti89b4af12002-02-12 23:24:41 +0000273 if size > 0:
cliechti183d4ae2009-07-23 22:03:51 +0000274 win32.ResetEvent(self._overlappedRead.hEvent)
275 flags = win32.DWORD()
276 comstat = win32.COMSTAT()
277 if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
278 raise SerialException('call to ClearCommError failed')
cliechti5c39e702002-06-04 14:56:34 +0000279 if self.timeout == 0:
cliechti17f177f2002-06-07 22:33:37 +0000280 n = min(comstat.cbInQue, size)
281 if n > 0:
cliechti183d4ae2009-07-23 22:03:51 +0000282 buf = ctypes.create_string_buffer(n)
283 rc = win32.DWORD()
cliechti14213e12010-05-20 22:31:18 +0000284 err = win32.ReadFile(self.hComPort, buf, n, ctypes.byref(rc), ctypes.byref(self._overlappedRead))
cliechti183d4ae2009-07-23 22:03:51 +0000285 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000286 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
cliechti183d4ae2009-07-23 22:03:51 +0000287 err = win32.WaitForSingleObject(self._overlappedRead.hEvent, win32.INFINITE)
288 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000289 else:
cliechti4a567a02009-07-27 22:09:31 +0000290 read = bytes()
cliechti5c39e702002-06-04 14:56:34 +0000291 else:
cliechti183d4ae2009-07-23 22:03:51 +0000292 buf = ctypes.create_string_buffer(size)
293 rc = win32.DWORD()
294 err = win32.ReadFile(self.hComPort, buf, size, ctypes.byref(rc), ctypes.byref(self._overlappedRead))
295 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000296 raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
cliechti183d4ae2009-07-23 22:03:51 +0000297 err = win32.GetOverlappedResult(self.hComPort, ctypes.byref(self._overlappedRead), ctypes.byref(rc), True)
298 read = buf.raw[:rc.value]
cliechtif622faf2003-07-12 23:41:43 +0000299 else:
cliechti4a567a02009-07-27 22:09:31 +0000300 read = bytes()
301 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000302
cliechti4a567a02009-07-27 22:09:31 +0000303 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000304 """Output the given string over the serial port."""
cliechti89b4af12002-02-12 23:24:41 +0000305 if not self.hComPort: raise portNotOpenError
cliechti23dc2a02009-07-30 17:25:09 +0000306 #~ if not isinstance(data, (bytes, bytearray)):
307 #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
308 # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
cliechti38077122013-10-16 02:57:27 +0000309 data = to_bytes(data)
cliechtib2f5fc82006-10-20 00:09:07 +0000310 if data:
cliechti107db8d2004-01-15 01:20:23 +0000311 #~ win32event.ResetEvent(self._overlappedWrite.hEvent)
cliechti183d4ae2009-07-23 22:03:51 +0000312 n = win32.DWORD()
cliechtie37b6a82009-07-24 12:19:50 +0000313 err = win32.WriteFile(self.hComPort, data, len(data), ctypes.byref(n), self._overlappedWrite)
cliechti183d4ae2009-07-23 22:03:51 +0000314 if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
cliechti1083be72011-12-28 20:45:30 +0000315 raise SerialException("WriteFile failed (%r)" % ctypes.WinError())
cliechti31000fc2011-08-05 01:47:26 +0000316 if self._writeTimeout != 0: # if blocking (None) or w/ write timeout (>0)
317 # Wait for the write to complete.
318 #~ win32.WaitForSingleObject(self._overlappedWrite.hEvent, win32.INFINITE)
319 err = win32.GetOverlappedResult(self.hComPort, self._overlappedWrite, ctypes.byref(n), True)
320 if n.value != len(data):
321 raise writeTimeoutError
cliechti23dc2a02009-07-30 17:25:09 +0000322 return n.value
323 else:
324 return 0
cliechtiedfba4e2009-02-07 00:29:47 +0000325
cliechti26409782013-05-31 00:47:16 +0000326 def flush(self):
cliechti7d448562014-08-03 21:57:45 +0000327 """\
328 Flush of file like objects. In this case, wait until all data
329 is written.
330 """
cliechti26409782013-05-31 00:47:16 +0000331 while self.outWaiting():
332 time.sleep(0.05)
333 # XXX could also use WaitCommEvent with mask EV_TXEMPTY, but it would
334 # require overlapped IO and its also only possible to set a single mask
335 # on the port---
cliechti89b4af12002-02-12 23:24:41 +0000336
337 def flushInput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000338 """Clear input buffer, discarding all that is in the buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000339 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000340 win32.PurgeComm(self.hComPort, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000341
342 def flushOutput(self):
cliechti7d448562014-08-03 21:57:45 +0000343 """\
344 Clear output buffer, aborting the current output and discarding all
345 that is in the buffer.
346 """
cliechti89b4af12002-02-12 23:24:41 +0000347 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000348 win32.PurgeComm(self.hComPort, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT)
cliechti89b4af12002-02-12 23:24:41 +0000349
cliechtiaaa04602006-02-05 23:02:46 +0000350 def sendBreak(self, duration=0.25):
cliechti7d448562014-08-03 21:57:45 +0000351 """\
352 Send break condition. Timed, returns to idle state after given duration.
353 """
cliechti89b4af12002-02-12 23:24:41 +0000354 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000355 win32.SetCommBreak(self.hComPort)
cliechtiaaa04602006-02-05 23:02:46 +0000356 time.sleep(duration)
cliechti183d4ae2009-07-23 22:03:51 +0000357 win32.ClearCommBreak(self.hComPort)
cliechti89b4af12002-02-12 23:24:41 +0000358
cliechti997b63c2008-06-21 00:09:31 +0000359 def setBreak(self, level=1):
360 """Set break: Controls TXD. When active, to transmitting is possible."""
361 if not self.hComPort: raise portNotOpenError
362 if level:
cliechti183d4ae2009-07-23 22:03:51 +0000363 win32.SetCommBreak(self.hComPort)
cliechti997b63c2008-06-21 00:09:31 +0000364 else:
cliechti183d4ae2009-07-23 22:03:51 +0000365 win32.ClearCommBreak(self.hComPort)
cliechti997b63c2008-06-21 00:09:31 +0000366
cliechti93db61b2006-08-26 19:16:18 +0000367 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000368 """Set terminal status line: Request To Send"""
cliechti22175a72011-12-29 00:17:53 +0000369 # remember level for reconfigure
cliechti89b4af12002-02-12 23:24:41 +0000370 if level:
cliechtie37b6a82009-07-24 12:19:50 +0000371 self._rtsState = win32.RTS_CONTROL_ENABLE
cliechti89b4af12002-02-12 23:24:41 +0000372 else:
cliechtie37b6a82009-07-24 12:19:50 +0000373 self._rtsState = win32.RTS_CONTROL_DISABLE
cliechti22175a72011-12-29 00:17:53 +0000374 # also apply now if port is open
375 if self.hComPort:
376 if level:
377 win32.EscapeCommFunction(self.hComPort, win32.SETRTS)
378 else:
379 win32.EscapeCommFunction(self.hComPort, win32.CLRRTS)
cliechti89b4af12002-02-12 23:24:41 +0000380
cliechti93db61b2006-08-26 19:16:18 +0000381 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000382 """Set terminal status line: Data Terminal Ready"""
cliechti22175a72011-12-29 00:17:53 +0000383 # remember level for reconfigure
cliechti89b4af12002-02-12 23:24:41 +0000384 if level:
cliechtie37b6a82009-07-24 12:19:50 +0000385 self._dtrState = win32.DTR_CONTROL_ENABLE
cliechti89b4af12002-02-12 23:24:41 +0000386 else:
cliechtie37b6a82009-07-24 12:19:50 +0000387 self._dtrState = win32.DTR_CONTROL_DISABLE
cliechti22175a72011-12-29 00:17:53 +0000388 # also apply now if port is open
389 if self.hComPort:
390 if level:
391 win32.EscapeCommFunction(self.hComPort, win32.SETDTR)
392 else:
393 win32.EscapeCommFunction(self.hComPort, win32.CLRDTR)
cliechti183d4ae2009-07-23 22:03:51 +0000394
395 def _GetCommModemStatus(self):
396 stat = win32.DWORD()
397 win32.GetCommModemStatus(self.hComPort, ctypes.byref(stat))
398 return stat.value
cliechti89b4af12002-02-12 23:24:41 +0000399
400 def getCTS(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000401 """Read terminal status line: Clear To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000402 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000403 return win32.MS_CTS_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000404
405 def getDSR(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000406 """Read terminal status line: Data Set Ready"""
cliechti89b4af12002-02-12 23:24:41 +0000407 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000408 return win32.MS_DSR_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000409
cliechtid0b8b272002-02-14 01:33:08 +0000410 def getRI(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000411 """Read terminal status line: Ring Indicator"""
cliechtid0b8b272002-02-14 01:33:08 +0000412 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000413 return win32.MS_RING_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000414
cliechtid0b8b272002-02-14 01:33:08 +0000415 def getCD(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000416 """Read terminal status line: Carrier Detect"""
cliechtid0b8b272002-02-14 01:33:08 +0000417 if not self.hComPort: raise portNotOpenError
cliechti183d4ae2009-07-23 22:03:51 +0000418 return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0
cliechti89b4af12002-02-12 23:24:41 +0000419
cliechtia30a8a02003-10-05 12:28:13 +0000420 # - - platform specific - - - -
421
cliechti59199642011-12-28 20:54:30 +0000422 def setBufferSize(self, rx_size=4096, tx_size=None):
423 """\
424 Recommend a buffer size to the driver (device driver can ignore this
425 vlaue). Must be called before the port is opended.
426 """
427 if tx_size is None: tx_size = rx_size
428 win32.SetupComm(self.hComPort, rx_size, tx_size)
429
cliechtia30a8a02003-10-05 12:28:13 +0000430 def setXON(self, level=True):
cliechti2f0f8a32011-12-28 22:10:00 +0000431 """\
432 Manually control flow - when software flow control is enabled.
433 This will send XON (true) and XOFF (false) to the other device.
434 WARNING: this function is not portable to different platforms!
435 """
cliechtia30a8a02003-10-05 12:28:13 +0000436 if not self.hComPort: raise portNotOpenError
437 if level:
cliechti183d4ae2009-07-23 22:03:51 +0000438 win32.EscapeCommFunction(self.hComPort, win32.SETXON)
cliechtia30a8a02003-10-05 12:28:13 +0000439 else:
cliechti183d4ae2009-07-23 22:03:51 +0000440 win32.EscapeCommFunction(self.hComPort, win32.SETXOFF)
cliechtia30a8a02003-10-05 12:28:13 +0000441
cliechtic8e83d82009-07-21 21:34:05 +0000442 def outWaiting(self):
cliechti7d448562014-08-03 21:57:45 +0000443 """Return how many characters the in the outgoing buffer"""
cliechti183d4ae2009-07-23 22:03:51 +0000444 flags = win32.DWORD()
445 comstat = win32.COMSTAT()
446 if not win32.ClearCommError(self.hComPort, ctypes.byref(flags), ctypes.byref(comstat)):
447 raise SerialException('call to ClearCommError failed')
cliechtic8e83d82009-07-21 21:34:05 +0000448 return comstat.cbOutQue
449
cliechti1f89a0a2011-08-05 02:53:24 +0000450 # functions useful for RS-485 adapters
Chris Liechti33f0ec52015-08-06 16:37:21 +0200451 @property
452 def rs485_mode(self):
453 """\
454 enable RS485 mode and apply new settings, set to None to disable.
455 see serial.rs485 for more info about the value.
456 """
457 return self.rs485_settings
458
459 @rs485_mode.setter
460 def rs485_mode(self, rs485_settings):
461 self.rs485_settings = rs485_settings
462 self._rtsToggle = rs485_settings is not None
cliechti1f89a0a2011-08-05 02:53:24 +0000463 if self._isOpen: self._reconfigurePort()
464
cliechtif81362e2009-07-25 03:44:33 +0000465
Chris Liechtiaf6d0462015-08-03 17:21:14 +0200466t
cliechtiedfba4e2009-02-07 00:29:47 +0000467# Nur Testfunktion!!
cliechti89b4af12002-02-12 23:24:41 +0000468if __name__ == '__main__':
cliechti93db61b2006-08-26 19:16:18 +0000469 s = Serial(0)
cliechti7aaead32009-07-23 14:02:41 +0000470 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000471
cliechtid6bf52c2003-10-01 02:28:12 +0000472 s = Serial()
cliechti7aaead32009-07-23 14:02:41 +0000473 sys.stdout.write("%s\n" % s)
cliechtiedfba4e2009-02-07 00:29:47 +0000474
cliechtid6bf52c2003-10-01 02:28:12 +0000475 s.baudrate = 19200
476 s.databits = 7
477 s.close()
cliechti93db61b2006-08-26 19:16:18 +0000478 s.port = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000479 s.open()
cliechti7aaead32009-07-23 14:02:41 +0000480 sys.stdout.write("%s\n" % s)
cliechti89b4af12002-02-12 23:24:41 +0000481