blob: 622f7372e695678ddacedb00b75d486aaa0095f2 [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>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti0d6029a2008-06-21 01:28:46 +00009
cliechti761fd6e2008-06-24 11:32:43 +000010import clr
11import System
cliechti0d6029a2008-06-21 01:28:46 +000012import System.IO.Ports
cliechti39cfb7b2011-08-22 00:30:07 +000013from serial.serialutil import *
cliechti0d6029a2008-06-21 01:28:46 +000014
cliechti4a567a02009-07-27 22:09:31 +000015
cliechti0d6029a2008-06-21 01:28:46 +000016def device(portnum):
17 """Turn a port number into a device name"""
18 return System.IO.Ports.SerialPort.GetPortNames()[portnum]
19
cliechti4a567a02009-07-27 22:09:31 +000020
cliechti761fd6e2008-06-24 11:32:43 +000021# must invoke function with byte array, make a helper to convert strings
22# to byte arrays
23sab = System.Array[System.Byte]
24def as_byte_array(string):
cliechti4a567a02009-07-27 22:09:31 +000025 return sab([ord(x) for x in string]) # XXX will require adaption when run with a 3.x compatible IronPython
cliechti761fd6e2008-06-24 11:32:43 +000026
Chris Liechtief6b7b42015-08-06 22:19:26 +020027class Serial(SerialBase):
cliechti771278b2013-10-17 03:19:00 +000028 """Serial port implementation for .NET/Mono."""
cliechti0d6029a2008-06-21 01:28:46 +000029
cliechti4a567a02009-07-27 22:09:31 +000030 BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
31 9600, 19200, 38400, 57600, 115200)
cliechti0d6029a2008-06-21 01:28:46 +000032
33 def open(self):
cliechti00df9702014-08-04 10:12:48 +000034 """\
35 Open port with current settings. This may throw a SerialException
36 if the port cannot be opened.
37 """
cliechti0d6029a2008-06-21 01:28:46 +000038 if self._port is None:
39 raise SerialException("Port must be configured before it can be used.")
cliechti8f69e702011-03-19 00:22:32 +000040 if self._isOpen:
41 raise SerialException("Port is already open.")
cliechti0d6029a2008-06-21 01:28:46 +000042 try:
43 self._port_handle = System.IO.Ports.SerialPort(self.portstr)
44 except Exception, msg:
cliechtiff0c3792008-06-22 01:01:21 +000045 self._port_handle = None
cliechti0d6029a2008-06-21 01:28:46 +000046 raise SerialException("could not open port %s: %s" % (self.portstr, msg))
47
48 self._reconfigurePort()
49 self._port_handle.Open()
50 self._isOpen = True
cliechti761fd6e2008-06-24 11:32:43 +000051 if not self._rtscts:
52 self.setRTS(True)
53 self.setDTR(True)
cliechtiff0c3792008-06-22 01:01:21 +000054 self.flushInput()
55 self.flushOutput()
cliechti0d6029a2008-06-21 01:28:46 +000056
57 def _reconfigurePort(self):
cliechtiff0c3792008-06-22 01:01:21 +000058 """Set communication parameters on opened port."""
cliechti0d6029a2008-06-21 01:28:46 +000059 if not self._port_handle:
60 raise SerialException("Can only operate on a valid port handle")
cliechti58b481c2009-02-16 20:42:32 +000061
cliechtiedfba4e2009-02-07 00:29:47 +000062 #~ self._port_handle.ReceivedBytesThreshold = 1
cliechti58b481c2009-02-16 20:42:32 +000063
cliechti0d6029a2008-06-21 01:28:46 +000064 if self._timeout is None:
65 self._port_handle.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
66 else:
67 self._port_handle.ReadTimeout = int(self._timeout*1000)
cliechti58b481c2009-02-16 20:42:32 +000068
cliechti0d6029a2008-06-21 01:28:46 +000069 # if self._timeout != 0 and self._interCharTimeout is not None:
70 # timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
cliechti58b481c2009-02-16 20:42:32 +000071
cliechti0d6029a2008-06-21 01:28:46 +000072 if self._writeTimeout is None:
cliechtiff0c3792008-06-22 01:01:21 +000073 self._port_handle.WriteTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
cliechti0d6029a2008-06-21 01:28:46 +000074 else:
75 self._port_handle.WriteTimeout = int(self._writeTimeout*1000)
76
77
78 # Setup the connection info.
cliechtic53a8ca2008-06-24 11:57:32 +000079 try:
80 self._port_handle.BaudRate = self._baudrate
81 except IOError, e:
82 # catch errors from illegal baudrate settings
83 raise ValueError(str(e))
cliechti0d6029a2008-06-21 01:28:46 +000084
85 if self._bytesize == FIVEBITS:
86 self._port_handle.DataBits = 5
87 elif self._bytesize == SIXBITS:
88 self._port_handle.DataBits = 6
89 elif self._bytesize == SEVENBITS:
90 self._port_handle.DataBits = 7
91 elif self._bytesize == EIGHTBITS:
92 self._port_handle.DataBits = 8
93 else:
94 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
95
96 if self._parity == PARITY_NONE:
cliechti91d247d2009-07-25 00:42:57 +000097 self._port_handle.Parity = getattr(System.IO.Ports.Parity, 'None') # reserved keyword in Py3k
cliechti0d6029a2008-06-21 01:28:46 +000098 elif self._parity == PARITY_EVEN:
99 self._port_handle.Parity = System.IO.Ports.Parity.Even
100 elif self._parity == PARITY_ODD:
101 self._port_handle.Parity = System.IO.Ports.Parity.Odd
102 elif self._parity == PARITY_MARK:
103 self._port_handle.Parity = System.IO.Ports.Parity.Mark
104 elif self._parity == PARITY_SPACE:
105 self._port_handle.Parity = System.IO.Ports.Parity.Space
106 else:
107 raise ValueError("Unsupported parity mode: %r" % self._parity)
108
109 if self._stopbits == STOPBITS_ONE:
110 self._port_handle.StopBits = System.IO.Ports.StopBits.One
cliechti58b481c2009-02-16 20:42:32 +0000111 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
112 self._port_handle.StopBits = System.IO.Ports.StopBits.OnePointFive
cliechti0d6029a2008-06-21 01:28:46 +0000113 elif self._stopbits == STOPBITS_TWO:
114 self._port_handle.StopBits = System.IO.Ports.StopBits.Two
115 else:
116 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000117
cliechti0d6029a2008-06-21 01:28:46 +0000118 if self._rtscts and self._xonxoff:
119 self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSendXOnXOff
120 elif self._rtscts:
121 self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSend
122 elif self._xonxoff:
123 self._port_handle.Handshake = System.IO.Ports.Handshake.XOnXOff
124 else:
cliechti91d247d2009-07-25 00:42:57 +0000125 self._port_handle.Handshake = getattr(System.IO.Ports.Handshake, 'None') # reserved keyword in Py3k
cliechti0d6029a2008-06-21 01:28:46 +0000126
127 #~ def __del__(self):
128 #~ self.close()
129
130 def close(self):
131 """Close port"""
132 if self._isOpen:
133 if self._port_handle:
134 try:
cliechtiff0c3792008-06-22 01:01:21 +0000135 self._port_handle.Close()
cliechti0d6029a2008-06-21 01:28:46 +0000136 except System.IO.Ports.InvalidOperationException:
137 # ignore errors. can happen for unplugged USB serial devices
138 pass
139 self._port_handle = None
140 self._isOpen = False
141
142 def makeDeviceName(self, port):
cliechtic53a8ca2008-06-24 11:57:32 +0000143 try:
144 return device(port)
145 except TypeError, e:
146 raise SerialException(str(e))
cliechti0d6029a2008-06-21 01:28:46 +0000147
148 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti58b481c2009-02-16 20:42:32 +0000149
cliechti0d6029a2008-06-21 01:28:46 +0000150 def inWaiting(self):
151 """Return the number of characters currently in the input buffer."""
152 if not self._port_handle: raise portNotOpenError
153 return self._port_handle.BytesToRead
154
cliechti4a567a02009-07-27 22:09:31 +0000155 def read(self, size=1):
cliechti00df9702014-08-04 10:12:48 +0000156 """\
157 Read size bytes from the serial port. If a timeout is set it may
158 return less characters as requested. With no timeout it will block
159 until the requested number of bytes is read.
160 """
cliechti0d6029a2008-06-21 01:28:46 +0000161 if not self._port_handle: raise portNotOpenError
cliechti4a567a02009-07-27 22:09:31 +0000162 # must use single byte reads as this is the only way to read
163 # without applying encodings
164 data = bytearray()
cliechti0d6029a2008-06-21 01:28:46 +0000165 while size:
cliechtiff0c3792008-06-22 01:01:21 +0000166 try:
cliechti4a567a02009-07-27 22:09:31 +0000167 data.append(self._port_handle.ReadByte())
cliechtiff0c3792008-06-22 01:01:21 +0000168 except System.TimeoutException, e:
169 break
170 else:
171 size -= 1
cliechti4a567a02009-07-27 22:09:31 +0000172 return bytes(data)
cliechti0d6029a2008-06-21 01:28:46 +0000173
cliechti4a567a02009-07-27 22:09:31 +0000174 def write(self, data):
cliechti0d6029a2008-06-21 01:28:46 +0000175 """Output the given string over the serial port."""
176 if not self._port_handle: raise portNotOpenError
cliechti00df9702014-08-04 10:12:48 +0000177 #~ if not isinstance(data, (bytes, bytearray)):
178 #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
cliechtiff0c3792008-06-22 01:01:21 +0000179 try:
cliechti761fd6e2008-06-24 11:32:43 +0000180 # must call overloaded method with byte array argument
181 # as this is the only one not applying encodings
182 self._port_handle.Write(as_byte_array(data), 0, len(data))
cliechtiff0c3792008-06-22 01:01:21 +0000183 except System.TimeoutException, e:
184 raise writeTimeoutError
cliechtif81362e2009-07-25 03:44:33 +0000185 return len(data)
cliechti0d6029a2008-06-21 01:28:46 +0000186
187 def flushInput(self):
188 """Clear input buffer, discarding all that is in the buffer."""
189 if not self._port_handle: raise portNotOpenError
190 self._port_handle.DiscardInBuffer()
191
192 def flushOutput(self):
cliechti00df9702014-08-04 10:12:48 +0000193 """\
194 Clear output buffer, aborting the current output and
195 discarding all that is in the buffer.
196 """
cliechti0d6029a2008-06-21 01:28:46 +0000197 if not self._port_handle: raise portNotOpenError
198 self._port_handle.DiscardOutBuffer()
199
200 def sendBreak(self, duration=0.25):
cliechti00df9702014-08-04 10:12:48 +0000201 """\
202 Send break condition. Timed, returns to idle state after given
203 duration.
204 """
cliechti0d6029a2008-06-21 01:28:46 +0000205 if not self._port_handle: raise portNotOpenError
206 import time
207 self._port_handle.BreakState = True
208 time.sleep(duration)
209 self._port_handle.BreakState = False
210
cliechtiff0c3792008-06-22 01:01:21 +0000211 def setBreak(self, level=True):
cliechti00df9702014-08-04 10:12:48 +0000212 """
213 Set break: Controls TXD. When active, to transmitting is possible.
214 """
cliechti0d6029a2008-06-21 01:28:46 +0000215 if not self._port_handle: raise portNotOpenError
cliechtiff0c3792008-06-22 01:01:21 +0000216 self._port_handle.BreakState = bool(level)
cliechti0d6029a2008-06-21 01:28:46 +0000217
cliechtiff0c3792008-06-22 01:01:21 +0000218 def setRTS(self, level=True):
cliechti0d6029a2008-06-21 01:28:46 +0000219 """Set terminal status line: Request To Send"""
220 if not self._port_handle: raise portNotOpenError
cliechtiff0c3792008-06-22 01:01:21 +0000221 self._port_handle.RtsEnable = bool(level)
cliechti0d6029a2008-06-21 01:28:46 +0000222
cliechtiff0c3792008-06-22 01:01:21 +0000223 def setDTR(self, level=True):
cliechti0d6029a2008-06-21 01:28:46 +0000224 """Set terminal status line: Data Terminal Ready"""
225 if not self._port_handle: raise portNotOpenError
cliechtiff0c3792008-06-22 01:01:21 +0000226 self._port_handle.DtrEnable = bool(level)
cliechti0d6029a2008-06-21 01:28:46 +0000227
228 def getCTS(self):
229 """Read terminal status line: Clear To Send"""
230 if not self._port_handle: raise portNotOpenError
231 return self._port_handle.CtsHolding
232
233 def getDSR(self):
234 """Read terminal status line: Data Set Ready"""
235 if not self._port_handle: raise portNotOpenError
236 return self._port_handle.DsrHolding
237
cliechtiff0c3792008-06-22 01:01:21 +0000238 def getRI(self):
239 """Read terminal status line: Ring Indicator"""
240 if not self._port_handle: raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000241 #~ return self._port_handle.XXX
cliechtiff0c3792008-06-22 01:01:21 +0000242 return False #XXX an error would be better
cliechti0d6029a2008-06-21 01:28:46 +0000243
244 def getCD(self):
245 """Read terminal status line: Carrier Detect"""
246 if not self._port_handle: raise portNotOpenError
247 return self._port_handle.CDHolding
248
249 # - - platform specific - - - -
cliechtif81362e2009-07-25 03:44:33 +0000250 # none
251
252
cliechti4a567a02009-07-27 22:09:31 +0000253# Nur Testfunktion!!
cliechti0d6029a2008-06-21 01:28:46 +0000254if __name__ == '__main__':
cliechti7aaead32009-07-23 14:02:41 +0000255 import sys
256
cliechti0d6029a2008-06-21 01:28:46 +0000257 s = Serial(0)
cliechti7aaead32009-07-23 14:02:41 +0000258 sys.stdio.write('%s\n' % s)
259
cliechti0d6029a2008-06-21 01:28:46 +0000260 s = Serial()
cliechti7aaead32009-07-23 14:02:41 +0000261 sys.stdio.write('%s\n' % s)
262
263
cliechti0d6029a2008-06-21 01:28:46 +0000264 s.baudrate = 19200
265 s.databits = 7
266 s.close()
267 s.port = 0
268 s.open()
cliechti7aaead32009-07-23 14:02:41 +0000269 sys.stdio.write('%s\n' % s)
cliechti0d6029a2008-06-21 01:28:46 +0000270