blob: 3070948341570f2e0eaf8cf8c437840ec762f1e3 [file] [log] [blame]
cliechti0d6029a2008-06-21 01:28:46 +00001#! python
cliechti0d6029a2008-06-21 01:28:46 +00002#
Chris Liechti3e02f702015-12-16 23:06:04 +01003# Backend for .NET/Mono (IronPython), .NET >= 2
4#
5# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechtic2b26792015-09-22 23:16:07 +02006# (C) 2008-2015 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
Chris Liechti6ed12e02015-09-18 21:23:42 +020016#~ def device(portnum):
17 #~ """Turn a port number into a device name"""
18 #~ return System.IO.Ports.SerialPort.GetPortNames()[portnum]
cliechti0d6029a2008-06-21 01:28:46 +000019
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.")
Chris Liechti6ed12e02015-09-18 21:23:42 +020040 if self.is_open:
cliechti8f69e702011-03-19 00:22:32 +000041 raise SerialException("Port is already open.")
cliechti0d6029a2008-06-21 01:28:46 +000042 try:
43 self._port_handle = System.IO.Ports.SerialPort(self.portstr)
Chris Liechti6ed12e02015-09-18 21:23:42 +020044 except Exception as 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
Chris Liechtifc3b4992016-01-22 02:19:59 +010048 # if RTS and/or DTR are not set before open, they default to True
49 if self._rts_state is None:
50 self._rts_state = True
51 if self._dtr_state is None:
52 self._dtr_state = True
53
cliechti0d6029a2008-06-21 01:28:46 +000054 self._reconfigurePort()
55 self._port_handle.Open()
Chris Liechti6ed12e02015-09-18 21:23:42 +020056 self.is_open = True
57 if not self._dsrdtr:
58 self._update_dtr_state()
cliechti761fd6e2008-06-24 11:32:43 +000059 if not self._rtscts:
Chris Liechti6ed12e02015-09-18 21:23:42 +020060 self._update_rts_state()
61 self.reset_input_buffer()
cliechti0d6029a2008-06-21 01:28:46 +000062
63 def _reconfigurePort(self):
cliechtiff0c3792008-06-22 01:01:21 +000064 """Set communication parameters on opened port."""
cliechti0d6029a2008-06-21 01:28:46 +000065 if not self._port_handle:
66 raise SerialException("Can only operate on a valid port handle")
cliechti58b481c2009-02-16 20:42:32 +000067
cliechtiedfba4e2009-02-07 00:29:47 +000068 #~ self._port_handle.ReceivedBytesThreshold = 1
cliechti58b481c2009-02-16 20:42:32 +000069
cliechti0d6029a2008-06-21 01:28:46 +000070 if self._timeout is None:
71 self._port_handle.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
72 else:
73 self._port_handle.ReadTimeout = int(self._timeout*1000)
cliechti58b481c2009-02-16 20:42:32 +000074
cliechti0d6029a2008-06-21 01:28:46 +000075 # if self._timeout != 0 and self._interCharTimeout is not None:
76 # timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
cliechti58b481c2009-02-16 20:42:32 +000077
Chris Liechti6ed12e02015-09-18 21:23:42 +020078 if self._write_timeout is None:
cliechtiff0c3792008-06-22 01:01:21 +000079 self._port_handle.WriteTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
cliechti0d6029a2008-06-21 01:28:46 +000080 else:
Chris Liechti6ed12e02015-09-18 21:23:42 +020081 self._port_handle.WriteTimeout = int(self._write_timeout*1000)
cliechti0d6029a2008-06-21 01:28:46 +000082
83
84 # Setup the connection info.
cliechtic53a8ca2008-06-24 11:57:32 +000085 try:
86 self._port_handle.BaudRate = self._baudrate
Chris Liechti6ed12e02015-09-18 21:23:42 +020087 except IOError as e:
cliechtic53a8ca2008-06-24 11:57:32 +000088 # catch errors from illegal baudrate settings
89 raise ValueError(str(e))
cliechti0d6029a2008-06-21 01:28:46 +000090
91 if self._bytesize == FIVEBITS:
92 self._port_handle.DataBits = 5
93 elif self._bytesize == SIXBITS:
94 self._port_handle.DataBits = 6
95 elif self._bytesize == SEVENBITS:
96 self._port_handle.DataBits = 7
97 elif self._bytesize == EIGHTBITS:
98 self._port_handle.DataBits = 8
99 else:
100 raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
101
102 if self._parity == PARITY_NONE:
cliechti91d247d2009-07-25 00:42:57 +0000103 self._port_handle.Parity = getattr(System.IO.Ports.Parity, 'None') # reserved keyword in Py3k
cliechti0d6029a2008-06-21 01:28:46 +0000104 elif self._parity == PARITY_EVEN:
105 self._port_handle.Parity = System.IO.Ports.Parity.Even
106 elif self._parity == PARITY_ODD:
107 self._port_handle.Parity = System.IO.Ports.Parity.Odd
108 elif self._parity == PARITY_MARK:
109 self._port_handle.Parity = System.IO.Ports.Parity.Mark
110 elif self._parity == PARITY_SPACE:
111 self._port_handle.Parity = System.IO.Ports.Parity.Space
112 else:
113 raise ValueError("Unsupported parity mode: %r" % self._parity)
114
115 if self._stopbits == STOPBITS_ONE:
116 self._port_handle.StopBits = System.IO.Ports.StopBits.One
cliechti58b481c2009-02-16 20:42:32 +0000117 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
118 self._port_handle.StopBits = System.IO.Ports.StopBits.OnePointFive
cliechti0d6029a2008-06-21 01:28:46 +0000119 elif self._stopbits == STOPBITS_TWO:
120 self._port_handle.StopBits = System.IO.Ports.StopBits.Two
121 else:
122 raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
cliechti58b481c2009-02-16 20:42:32 +0000123
cliechti0d6029a2008-06-21 01:28:46 +0000124 if self._rtscts and self._xonxoff:
125 self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSendXOnXOff
126 elif self._rtscts:
127 self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSend
128 elif self._xonxoff:
129 self._port_handle.Handshake = System.IO.Ports.Handshake.XOnXOff
130 else:
cliechti91d247d2009-07-25 00:42:57 +0000131 self._port_handle.Handshake = getattr(System.IO.Ports.Handshake, 'None') # reserved keyword in Py3k
cliechti0d6029a2008-06-21 01:28:46 +0000132
133 #~ def __del__(self):
134 #~ self.close()
135
136 def close(self):
137 """Close port"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200138 if self.is_open:
cliechti0d6029a2008-06-21 01:28:46 +0000139 if self._port_handle:
140 try:
cliechtiff0c3792008-06-22 01:01:21 +0000141 self._port_handle.Close()
cliechti0d6029a2008-06-21 01:28:46 +0000142 except System.IO.Ports.InvalidOperationException:
143 # ignore errors. can happen for unplugged USB serial devices
144 pass
145 self._port_handle = None
Chris Liechti6ed12e02015-09-18 21:23:42 +0200146 self.is_open = False
cliechti0d6029a2008-06-21 01:28:46 +0000147
148 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti58b481c2009-02-16 20:42:32 +0000149
Chris Liechti6ed12e02015-09-18 21:23:42 +0200150 @property
151 def in_waiting(self):
cliechti0d6029a2008-06-21 01:28:46 +0000152 """Return the number of characters currently in the input buffer."""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200153 if not self._port_handle:
154 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000155 return self._port_handle.BytesToRead
156
cliechti4a567a02009-07-27 22:09:31 +0000157 def read(self, size=1):
cliechti00df9702014-08-04 10:12:48 +0000158 """\
159 Read size bytes from the serial port. If a timeout is set it may
160 return less characters as requested. With no timeout it will block
161 until the requested number of bytes is read.
162 """
Chris Liechti6ed12e02015-09-18 21:23:42 +0200163 if not self._port_handle:
164 raise portNotOpenError
cliechti4a567a02009-07-27 22:09:31 +0000165 # must use single byte reads as this is the only way to read
166 # without applying encodings
167 data = bytearray()
cliechti0d6029a2008-06-21 01:28:46 +0000168 while size:
cliechtiff0c3792008-06-22 01:01:21 +0000169 try:
cliechti4a567a02009-07-27 22:09:31 +0000170 data.append(self._port_handle.ReadByte())
Chris Liechti6ed12e02015-09-18 21:23:42 +0200171 except System.TimeoutException as e:
cliechtiff0c3792008-06-22 01:01:21 +0000172 break
173 else:
174 size -= 1
cliechti4a567a02009-07-27 22:09:31 +0000175 return bytes(data)
cliechti0d6029a2008-06-21 01:28:46 +0000176
cliechti4a567a02009-07-27 22:09:31 +0000177 def write(self, data):
cliechti0d6029a2008-06-21 01:28:46 +0000178 """Output the given string over the serial port."""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200179 if not self._port_handle:
180 raise portNotOpenError
cliechti00df9702014-08-04 10:12:48 +0000181 #~ if not isinstance(data, (bytes, bytearray)):
182 #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
cliechtiff0c3792008-06-22 01:01:21 +0000183 try:
cliechti761fd6e2008-06-24 11:32:43 +0000184 # must call overloaded method with byte array argument
185 # as this is the only one not applying encodings
186 self._port_handle.Write(as_byte_array(data), 0, len(data))
Chris Liechti6ed12e02015-09-18 21:23:42 +0200187 except System.TimeoutException as e:
cliechtiff0c3792008-06-22 01:01:21 +0000188 raise writeTimeoutError
cliechtif81362e2009-07-25 03:44:33 +0000189 return len(data)
cliechti0d6029a2008-06-21 01:28:46 +0000190
Chris Liechti6ed12e02015-09-18 21:23:42 +0200191 def reset_input_buffer(self):
cliechti0d6029a2008-06-21 01:28:46 +0000192 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200193 if not self._port_handle:
194 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000195 self._port_handle.DiscardInBuffer()
196
Chris Liechti6ed12e02015-09-18 21:23:42 +0200197 def reset_output_buffer(self):
cliechti00df9702014-08-04 10:12:48 +0000198 """\
199 Clear output buffer, aborting the current output and
200 discarding all that is in the buffer.
201 """
Chris Liechti6ed12e02015-09-18 21:23:42 +0200202 if not self._port_handle:
203 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000204 self._port_handle.DiscardOutBuffer()
205
Chris Liechti6ed12e02015-09-18 21:23:42 +0200206 def _update_break_state(self):
cliechti00df9702014-08-04 10:12:48 +0000207 """
208 Set break: Controls TXD. When active, to transmitting is possible.
209 """
Chris Liechti6ed12e02015-09-18 21:23:42 +0200210 if not self._port_handle:
211 raise portNotOpenError
212 self._port_handle.BreakState = bool(self._break_state)
cliechti0d6029a2008-06-21 01:28:46 +0000213
Chris Liechti6ed12e02015-09-18 21:23:42 +0200214 def _update_rts_state(self):
cliechti0d6029a2008-06-21 01:28:46 +0000215 """Set terminal status line: Request To Send"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200216 if not self._port_handle:
217 raise portNotOpenError
218 self._port_handle.RtsEnable = bool(self._rts_state)
cliechti0d6029a2008-06-21 01:28:46 +0000219
Chris Liechti6ed12e02015-09-18 21:23:42 +0200220 def _update_dtr_state(self):
cliechti0d6029a2008-06-21 01:28:46 +0000221 """Set terminal status line: Data Terminal Ready"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200222 if not self._port_handle:
223 raise portNotOpenError
224 self._port_handle.DtrEnable = bool(self._dtr_state)
cliechti0d6029a2008-06-21 01:28:46 +0000225
Chris Liechti6ed12e02015-09-18 21:23:42 +0200226 @property
227 def cts(self):
cliechti0d6029a2008-06-21 01:28:46 +0000228 """Read terminal status line: Clear To Send"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200229 if not self._port_handle:
230 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000231 return self._port_handle.CtsHolding
232
Chris Liechti6ed12e02015-09-18 21:23:42 +0200233 @property
234 def dsr(self):
cliechti0d6029a2008-06-21 01:28:46 +0000235 """Read terminal status line: Data Set Ready"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200236 if not self._port_handle:
237 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000238 return self._port_handle.DsrHolding
239
Chris Liechti6ed12e02015-09-18 21:23:42 +0200240 @property
241 def ri(self):
cliechtiff0c3792008-06-22 01:01:21 +0000242 """Read terminal status line: Ring Indicator"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200243 if not self._port_handle:
244 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000245 #~ return self._port_handle.XXX
cliechtiff0c3792008-06-22 01:01:21 +0000246 return False #XXX an error would be better
cliechti0d6029a2008-06-21 01:28:46 +0000247
Chris Liechti6ed12e02015-09-18 21:23:42 +0200248 @property
249 def cd(self):
cliechti0d6029a2008-06-21 01:28:46 +0000250 """Read terminal status line: Carrier Detect"""
Chris Liechti6ed12e02015-09-18 21:23:42 +0200251 if not self._port_handle:
252 raise portNotOpenError
cliechti0d6029a2008-06-21 01:28:46 +0000253 return self._port_handle.CDHolding
254
255 # - - platform specific - - - -
cliechtif81362e2009-07-25 03:44:33 +0000256 # none
257
258
cliechti4a567a02009-07-27 22:09:31 +0000259# Nur Testfunktion!!
cliechti0d6029a2008-06-21 01:28:46 +0000260if __name__ == '__main__':
cliechti7aaead32009-07-23 14:02:41 +0000261 import sys
262
cliechti0d6029a2008-06-21 01:28:46 +0000263 s = Serial(0)
cliechti7aaead32009-07-23 14:02:41 +0000264 sys.stdio.write('%s\n' % s)
265
cliechti0d6029a2008-06-21 01:28:46 +0000266 s = Serial()
cliechti7aaead32009-07-23 14:02:41 +0000267 sys.stdio.write('%s\n' % s)
268
269
cliechti0d6029a2008-06-21 01:28:46 +0000270 s.baudrate = 19200
271 s.databits = 7
272 s.close()
273 s.port = 0
274 s.open()
cliechti7aaead32009-07-23 14:02:41 +0000275 sys.stdio.write('%s\n' % s)
cliechti0d6029a2008-06-21 01:28:46 +0000276