blob: bc3c893fe1c58f9817ed77c3740af395f6da7f0a [file] [log] [blame]
cliechti0d6029a2008-06-21 01:28:46 +00001#! python
cliechtiff0c3792008-06-22 01:01:21 +00002# Python Serial Port Extension for Win32, Linux, BSD, Jython and .NET/Mono
3# serial driver for .NET/Mono (IronPython), .NET >= 2
4# see __init__.py
cliechti0d6029a2008-06-21 01:28:46 +00005#
cliechtiff0c3792008-06-22 01:01:21 +00006# (C) 2008 Chris Liechti <cliechti@gmx.net>
cliechti0d6029a2008-06-21 01:28:46 +00007# this is distributed under a free software license, see license.txt
8
cliechti761fd6e2008-06-24 11:32:43 +00009import clr
10import System
cliechti0d6029a2008-06-21 01:28:46 +000011import System.IO.Ports
12from serialutil import *
13
14def device(portnum):
15 """Turn a port number into a device name"""
16 return System.IO.Ports.SerialPort.GetPortNames()[portnum]
17
cliechti761fd6e2008-06-24 11:32:43 +000018# must invoke function with byte array, make a helper to convert strings
19# to byte arrays
20sab = System.Array[System.Byte]
21def as_byte_array(string):
22 return sab([ord(x) for x in string])
23
cliechti0d6029a2008-06-21 01:28:46 +000024class Serial(SerialBase):
25 """Serial port implemenation for .NET/Mono."""
26
27 BAUDRATES = (50,75,110,134,150,200,300,600,1200,1800,2400,4800,9600,
28 19200,38400,57600,115200)
29
30 def open(self):
31 """Open port with current settings. This may throw a SerialException
32 if the port cannot be opened."""
33 if self._port is None:
34 raise SerialException("Port must be configured before it can be used.")
cliechti0d6029a2008-06-21 01:28:46 +000035 try:
36 self._port_handle = System.IO.Ports.SerialPort(self.portstr)
37 except Exception, msg:
cliechtiff0c3792008-06-22 01:01:21 +000038 self._port_handle = None
cliechti0d6029a2008-06-21 01:28:46 +000039 raise SerialException("could not open port %s: %s" % (self.portstr, msg))
40
41 self._reconfigurePort()
42 self._port_handle.Open()
43 self._isOpen = True
cliechti761fd6e2008-06-24 11:32:43 +000044 if not self._rtscts:
45 self.setRTS(True)
46 self.setDTR(True)
cliechtiff0c3792008-06-22 01:01:21 +000047 self.flushInput()
48 self.flushOutput()
cliechti0d6029a2008-06-21 01:28:46 +000049
50 def _reconfigurePort(self):
cliechtiff0c3792008-06-22 01:01:21 +000051 """Set communication parameters on opened port."""
cliechti0d6029a2008-06-21 01:28:46 +000052 if not self._port_handle:
53 raise SerialException("Can only operate on a valid port handle")
54
cliechtiedfba4e2009-02-07 00:29:47 +000055 #~ self._port_handle.ReceivedBytesThreshold = 1
cliechti0d6029a2008-06-21 01:28:46 +000056
57 if self._timeout is None:
58 self._port_handle.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
59 else:
60 self._port_handle.ReadTimeout = int(self._timeout*1000)
61
62 # if self._timeout != 0 and self._interCharTimeout is not None:
63 # timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
64
65 if self._writeTimeout is None:
cliechtiff0c3792008-06-22 01:01:21 +000066 self._port_handle.WriteTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
cliechti0d6029a2008-06-21 01:28:46 +000067 else:
68 self._port_handle.WriteTimeout = int(self._writeTimeout*1000)
69
70
71 # Setup the connection info.
cliechtic53a8ca2008-06-24 11:57:32 +000072 try:
73 self._port_handle.BaudRate = self._baudrate
74 except IOError, e:
75 # catch errors from illegal baudrate settings
76 raise ValueError(str(e))
cliechti0d6029a2008-06-21 01:28:46 +000077
78 if self._bytesize == FIVEBITS:
79 self._port_handle.DataBits = 5
80 elif self._bytesize == SIXBITS:
81 self._port_handle.DataBits = 6
82 elif self._bytesize == SEVENBITS:
83 self._port_handle.DataBits = 7
84 elif self._bytesize == EIGHTBITS:
85 self._port_handle.DataBits = 8
86 else:
87 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
88
89 if self._parity == PARITY_NONE:
90 self._port_handle.Parity = System.IO.Ports.Parity.None
91 elif self._parity == PARITY_EVEN:
92 self._port_handle.Parity = System.IO.Ports.Parity.Even
93 elif self._parity == PARITY_ODD:
94 self._port_handle.Parity = System.IO.Ports.Parity.Odd
95 elif self._parity == PARITY_MARK:
96 self._port_handle.Parity = System.IO.Ports.Parity.Mark
97 elif self._parity == PARITY_SPACE:
98 self._port_handle.Parity = System.IO.Ports.Parity.Space
99 else:
100 raise ValueError("Unsupported parity mode: %r" % self._parity)
101
102 if self._stopbits == STOPBITS_ONE:
103 self._port_handle.StopBits = System.IO.Ports.StopBits.One
104 elif self._stopbits == STOPBITS_TWO:
105 self._port_handle.StopBits = System.IO.Ports.StopBits.Two
106 else:
107 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
108
109 if self._rtscts and self._xonxoff:
110 self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSendXOnXOff
111 elif self._rtscts:
112 self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSend
113 elif self._xonxoff:
114 self._port_handle.Handshake = System.IO.Ports.Handshake.XOnXOff
115 else:
116 self._port_handle.Handshake = System.IO.Ports.Handshake.None
117
118 #~ def __del__(self):
119 #~ self.close()
120
121 def close(self):
122 """Close port"""
123 if self._isOpen:
124 if self._port_handle:
125 try:
cliechtiff0c3792008-06-22 01:01:21 +0000126 self._port_handle.Close()
cliechti0d6029a2008-06-21 01:28:46 +0000127 except System.IO.Ports.InvalidOperationException:
128 # ignore errors. can happen for unplugged USB serial devices
129 pass
130 self._port_handle = None
131 self._isOpen = False
132
133 def makeDeviceName(self, port):
cliechtic53a8ca2008-06-24 11:57:32 +0000134 try:
135 return device(port)
136 except TypeError, e:
137 raise SerialException(str(e))
cliechti0d6029a2008-06-21 01:28:46 +0000138
139 # - - - - - - - - - - - - - - - - - - - - - - - -
140
141 def inWaiting(self):
142 """Return the number of characters currently in the input buffer."""
143 if not self._port_handle: raise portNotOpenError
144 return self._port_handle.BytesToRead
145
146 def read(self, size=1):
147 """Read size bytes from the serial port. If a timeout is set it may
148 return less characters as requested. With no timeout it will block
149 until the requested number of bytes is read."""
150 if not self._port_handle: raise portNotOpenError
cliechti761fd6e2008-06-24 11:32:43 +0000151 # must use single byte reads as this is the only way to read
152 # without applying encodings
cliechti0d6029a2008-06-21 01:28:46 +0000153 data = []
154 while size:
cliechtiff0c3792008-06-22 01:01:21 +0000155 try:
cliechti95e7d842008-06-24 10:05:42 +0000156 data.append(chr(self._port_handle.ReadByte()))
cliechtiff0c3792008-06-22 01:01:21 +0000157 except System.TimeoutException, e:
158 break
159 else:
160 size -= 1
cliechti0d6029a2008-06-21 01:28:46 +0000161 return ''.join(data)
162
163 def write(self, data):
164 """Output the given string over the serial port."""
165 if not self._port_handle: raise portNotOpenError
166 if not isinstance(data, str):
167 raise TypeError('expected str, got %s' % type(data))
cliechtiff0c3792008-06-22 01:01:21 +0000168 try:
cliechti761fd6e2008-06-24 11:32:43 +0000169 # must call overloaded method with byte array argument
170 # as this is the only one not applying encodings
171 self._port_handle.Write(as_byte_array(data), 0, len(data))
cliechtiff0c3792008-06-22 01:01:21 +0000172 except System.TimeoutException, e:
173 raise writeTimeoutError
cliechti0d6029a2008-06-21 01:28:46 +0000174
175 def flushInput(self):
176 """Clear input buffer, discarding all that is in the buffer."""
177 if not self._port_handle: raise portNotOpenError
178 self._port_handle.DiscardInBuffer()
179
180 def flushOutput(self):
181 """Clear output buffer, aborting the current output and
182 discarding all that is in the buffer."""
183 if not self._port_handle: raise portNotOpenError
184 self._port_handle.DiscardOutBuffer()
185
186 def sendBreak(self, duration=0.25):
187 """Send break condition. Timed, returns to idle state after given duration."""
188 if not self._port_handle: raise portNotOpenError
189 import time
190 self._port_handle.BreakState = True
191 time.sleep(duration)
192 self._port_handle.BreakState = False
193
cliechtiff0c3792008-06-22 01:01:21 +0000194 def setBreak(self, level=True):
cliechti0d6029a2008-06-21 01:28:46 +0000195 """Set break: Controls TXD. When active, to transmitting is possible."""
196 if not self._port_handle: raise portNotOpenError
cliechtiff0c3792008-06-22 01:01:21 +0000197 self._port_handle.BreakState = bool(level)
cliechti0d6029a2008-06-21 01:28:46 +0000198
cliechtiff0c3792008-06-22 01:01:21 +0000199 def setRTS(self, level=True):
cliechti0d6029a2008-06-21 01:28:46 +0000200 """Set terminal status line: Request To Send"""
201 if not self._port_handle: raise portNotOpenError
cliechtiff0c3792008-06-22 01:01:21 +0000202 self._port_handle.RtsEnable = bool(level)
cliechti0d6029a2008-06-21 01:28:46 +0000203
cliechtiff0c3792008-06-22 01:01:21 +0000204 def setDTR(self, level=True):
cliechti0d6029a2008-06-21 01:28:46 +0000205 """Set terminal status line: Data Terminal Ready"""
206 if not self._port_handle: raise portNotOpenError
cliechtiff0c3792008-06-22 01:01:21 +0000207 self._port_handle.DtrEnable = bool(level)
cliechti0d6029a2008-06-21 01:28:46 +0000208
209 def getCTS(self):
210 """Read terminal status line: Clear To Send"""
211 if not self._port_handle: raise portNotOpenError
212 return self._port_handle.CtsHolding
213
214 def getDSR(self):
215 """Read terminal status line: Data Set Ready"""
216 if not self._port_handle: raise portNotOpenError
217 return self._port_handle.DsrHolding
218
cliechtiff0c3792008-06-22 01:01:21 +0000219 def getRI(self):
220 """Read terminal status line: Ring Indicator"""
221 if not self._port_handle: raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000222 #~ return self._port_handle.XXX
cliechtiff0c3792008-06-22 01:01:21 +0000223 return False #XXX an error would be better
cliechti0d6029a2008-06-21 01:28:46 +0000224
225 def getCD(self):
226 """Read terminal status line: Carrier Detect"""
227 if not self._port_handle: raise portNotOpenError
228 return self._port_handle.CDHolding
229
230 # - - platform specific - - - -
231
232#Nur Testfunktion!!
233if __name__ == '__main__':
234 s = Serial(0)
235 print s
236
237 s = Serial()
238 print s
239
240
241 s.baudrate = 19200
242 s.databits = 7
243 s.close()
244 s.port = 0
245 s.open()
246 print s
247