blob: e9ac19bfef1cc5882551a4f588d3074f258ddd78 [file] [log] [blame]
cliechtie8f75f92002-02-14 01:33:33 +00001#!jython
cliechti89b4af12002-02-12 23:24:41 +00002#
Chris Liechti3e02f702015-12-16 23:06:04 +01003# Backend Jython with JavaComm
cliechti809b82e2008-06-22 22:45:04 +00004#
Chris Liechti3e02f702015-12-16 23:06:04 +01005# This file is part of pySerial. https://github.com/pyserial/pyserial
Chris Liechti2cda7e62015-09-19 22:08:54 +02006# (C) 2002-2015 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02007#
8# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +00009
cliechti39cfb7b2011-08-22 00:30:07 +000010from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000011
Chris Liechti2cda7e62015-09-19 22:08:54 +020012
cliechti809b82e2008-06-22 22:45:04 +000013def my_import(name):
14 mod = __import__(name)
15 components = name.split('.')
16 for comp in components[1:]:
17 mod = getattr(mod, comp)
18 return mod
19
cliechti4a567a02009-07-27 22:09:31 +000020
cliechti809b82e2008-06-22 22:45:04 +000021def detect_java_comm(names):
22 """try given list of modules and return that imports"""
23 for name in names:
24 try:
25 mod = my_import(name)
26 mod.SerialPort
27 return mod
28 except (ImportError, AttributeError):
29 pass
30 raise ImportError("No Java Communications API implementation found")
31
cliechti4a567a02009-07-27 22:09:31 +000032
cliechti809b82e2008-06-22 22:45:04 +000033# Java Communications API implementations
34# http://mho.republika.pl/java/comm/
35
36comm = detect_java_comm([
Chris Liechti2cda7e62015-09-19 22:08:54 +020037 'javax.comm', # Sun/IBM
38 'gnu.io', # RXTX
cliechti809b82e2008-06-22 22:45:04 +000039])
cliechti89b4af12002-02-12 23:24:41 +000040
cliechti89b4af12002-02-12 23:24:41 +000041
42def device(portnumber):
cliechtid6bf52c2003-10-01 02:28:12 +000043 """Turn a port number into a device name"""
cliechti809b82e2008-06-22 22:45:04 +000044 enum = comm.CommPortIdentifier.getPortIdentifiers()
cliechti89b4af12002-02-12 23:24:41 +000045 ports = []
46 while enum.hasMoreElements():
47 el = enum.nextElement()
cliechti809b82e2008-06-22 22:45:04 +000048 if el.getPortType() == comm.CommPortIdentifier.PORT_SERIAL:
cliechti89b4af12002-02-12 23:24:41 +000049 ports.append(el)
cliechtid6bf52c2003-10-01 02:28:12 +000050 return ports[portnumber].getName()
cliechti89b4af12002-02-12 23:24:41 +000051
cliechtif81362e2009-07-25 03:44:33 +000052
Chris Liechtief6b7b42015-08-06 22:19:26 +020053class Serial(SerialBase):
cliechti7d448562014-08-03 21:57:45 +000054 """\
55 Serial port class, implemented with Java Communications API and
56 thus usable with jython and the appropriate java extension.
57 """
cliechti58b481c2009-02-16 20:42:32 +000058
cliechtid6bf52c2003-10-01 02:28:12 +000059 def open(self):
cliechti7d448562014-08-03 21:57:45 +000060 """\
61 Open port with current settings. This may throw a SerialException
62 if the port cannot be opened.
63 """
cliechtid6bf52c2003-10-01 02:28:12 +000064 if self._port is None:
65 raise SerialException("Port must be configured before it can be used.")
Chris Liechti2cda7e62015-09-19 22:08:54 +020066 if self.is_open:
cliechti8f69e702011-03-19 00:22:32 +000067 raise SerialException("Port is already open.")
cliechti4a567a02009-07-27 22:09:31 +000068 if type(self._port) == type(''): # strings are taken directly
cliechti809b82e2008-06-22 22:45:04 +000069 portId = comm.CommPortIdentifier.getPortIdentifier(self._port)
cliechti89b4af12002-02-12 23:24:41 +000070 else:
cliechti4a567a02009-07-27 22:09:31 +000071 portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) # numbers are transformed to a comport id obj
cliechti4616bf12002-04-08 23:13:14 +000072 try:
73 self.sPort = portId.open("python serial module", 10)
Chris Liechti2cda7e62015-09-19 22:08:54 +020074 except Exception as msg:
cliechti4616bf12002-04-08 23:13:14 +000075 self.sPort = None
cliechtid6bf52c2003-10-01 02:28:12 +000076 raise SerialException("Could not open port: %s" % msg)
77 self._reconfigurePort()
78 self._instream = self.sPort.getInputStream()
79 self._outstream = self.sPort.getOutputStream()
Chris Liechti2cda7e62015-09-19 22:08:54 +020080 self.is_open = True
cliechti89b4af12002-02-12 23:24:41 +000081
cliechtid6bf52c2003-10-01 02:28:12 +000082 def _reconfigurePort(self):
cliechti4a567a02009-07-27 22:09:31 +000083 """Set communication parameters on opened port."""
cliechtid6bf52c2003-10-01 02:28:12 +000084 if not self.sPort:
85 raise SerialException("Can only operate on a valid port handle")
cliechti58b481c2009-02-16 20:42:32 +000086
cliechtid6bf52c2003-10-01 02:28:12 +000087 self.sPort.enableReceiveTimeout(30)
88 if self._bytesize == FIVEBITS:
cliechti809b82e2008-06-22 22:45:04 +000089 jdatabits = comm.SerialPort.DATABITS_5
cliechtid6bf52c2003-10-01 02:28:12 +000090 elif self._bytesize == SIXBITS:
cliechti809b82e2008-06-22 22:45:04 +000091 jdatabits = comm.SerialPort.DATABITS_6
cliechtid6bf52c2003-10-01 02:28:12 +000092 elif self._bytesize == SEVENBITS:
cliechti809b82e2008-06-22 22:45:04 +000093 jdatabits = comm.SerialPort.DATABITS_7
cliechtid6bf52c2003-10-01 02:28:12 +000094 elif self._bytesize == EIGHTBITS:
cliechti809b82e2008-06-22 22:45:04 +000095 jdatabits = comm.SerialPort.DATABITS_8
cliechti89b4af12002-02-12 23:24:41 +000096 else:
cliechtid6bf52c2003-10-01 02:28:12 +000097 raise ValueError("unsupported bytesize: %r" % self._bytesize)
cliechti58b481c2009-02-16 20:42:32 +000098
cliechtid6bf52c2003-10-01 02:28:12 +000099 if self._stopbits == STOPBITS_ONE:
cliechti809b82e2008-06-22 22:45:04 +0000100 jstopbits = comm.SerialPort.STOPBITS_1
cliechtic5aed012014-08-01 02:34:22 +0000101 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
102 jstopbits = comm.SerialPort.STOPBITS_1_5
cliechtid6bf52c2003-10-01 02:28:12 +0000103 elif self._stopbits == STOPBITS_TWO:
cliechti809b82e2008-06-22 22:45:04 +0000104 jstopbits = comm.SerialPort.STOPBITS_2
cliechtid6bf52c2003-10-01 02:28:12 +0000105 else:
106 raise ValueError("unsupported number of stopbits: %r" % self._stopbits)
107
108 if self._parity == PARITY_NONE:
cliechti809b82e2008-06-22 22:45:04 +0000109 jparity = comm.SerialPort.PARITY_NONE
cliechtid6bf52c2003-10-01 02:28:12 +0000110 elif self._parity == PARITY_EVEN:
cliechti809b82e2008-06-22 22:45:04 +0000111 jparity = comm.SerialPort.PARITY_EVEN
cliechtid6bf52c2003-10-01 02:28:12 +0000112 elif self._parity == PARITY_ODD:
cliechti809b82e2008-06-22 22:45:04 +0000113 jparity = comm.SerialPort.PARITY_ODD
114 elif self._parity == PARITY_MARK:
115 jparity = comm.SerialPort.PARITY_MARK
116 elif self._parity == PARITY_SPACE:
117 jparity = comm.SerialPort.PARITY_SPACE
cliechtid6bf52c2003-10-01 02:28:12 +0000118 else:
119 raise ValueError("unsupported parity type: %r" % self._parity)
cliechti89b4af12002-02-12 23:24:41 +0000120
121 jflowin = jflowout = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000122 if self._rtscts:
Chris Liechti2cda7e62015-09-19 22:08:54 +0200123 jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN
124 jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT
cliechtid6bf52c2003-10-01 02:28:12 +0000125 if self._xonxoff:
Chris Liechti2cda7e62015-09-19 22:08:54 +0200126 jflowin |= comm.SerialPort.FLOWCONTROL_XONXOFF_IN
127 jflowout |= comm.SerialPort.FLOWCONTROL_XONXOFF_OUT
cliechti58b481c2009-02-16 20:42:32 +0000128
cliechti6670f732009-07-25 23:49:26 +0000129 self.sPort.setSerialPortParams(self._baudrate, jdatabits, jstopbits, jparity)
cliechti89b4af12002-02-12 23:24:41 +0000130 self.sPort.setFlowControlMode(jflowin | jflowout)
cliechti58b481c2009-02-16 20:42:32 +0000131
cliechtid6bf52c2003-10-01 02:28:12 +0000132 if self._timeout >= 0:
cliechtic5aed012014-08-01 02:34:22 +0000133 self.sPort.enableReceiveTimeout(int(self._timeout*1000))
cliechti89b4af12002-02-12 23:24:41 +0000134 else:
135 self.sPort.disableReceiveTimeout()
136
cliechti89b4af12002-02-12 23:24:41 +0000137 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000138 """Close port"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200139 if self.is_open:
cliechtid6bf52c2003-10-01 02:28:12 +0000140 if self.sPort:
141 self._instream.close()
142 self._outstream.close()
143 self.sPort.close()
144 self.sPort = None
Chris Liechti2cda7e62015-09-19 22:08:54 +0200145 self.is_open = False
cliechti95c62212002-03-04 22:17:53 +0000146
cliechtid6bf52c2003-10-01 02:28:12 +0000147 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000148
Chris Liechti2cda7e62015-09-19 22:08:54 +0200149 @property
150 def in_waiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000151 """Return the number of characters currently in the input buffer."""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200152 if not self.sPort:
153 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000154 return self._instream.available()
cliechti89b4af12002-02-12 23:24:41 +0000155
cliechti4a567a02009-07-27 22:09:31 +0000156 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +0000157 """\
158 Read size bytes from the serial port. If a timeout is set it may
159 return less characters as requested. With no timeout it will block
160 until the requested number of bytes is read.
161 """
Chris Liechti2cda7e62015-09-19 22:08:54 +0200162 if not self.sPort:
163 raise portNotOpenError
cliechti4a567a02009-07-27 22:09:31 +0000164 read = bytearray()
cliechtia9e4e952002-05-26 01:20:22 +0000165 if size > 0:
166 while len(read) < size:
cliechtid6bf52c2003-10-01 02:28:12 +0000167 x = self._instream.read()
cliechtia9e4e952002-05-26 01:20:22 +0000168 if x == -1:
169 if self.timeout >= 0:
170 break
171 else:
cliechti4a567a02009-07-27 22:09:31 +0000172 read.append(x)
173 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000174
cliechti4a567a02009-07-27 22:09:31 +0000175 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000176 """Output the given string over the serial port."""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200177 if not self.sPort:
178 raise portNotOpenError
cliechtiddd78132009-07-28 01:13:28 +0000179 if not isinstance(data, (bytes, bytearray)):
180 raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
cliechtid6bf52c2003-10-01 02:28:12 +0000181 self._outstream.write(data)
cliechtif81362e2009-07-25 03:44:33 +0000182 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000183
Chris Liechti2cda7e62015-09-19 22:08:54 +0200184 def reset_input_buffer(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000185 """Clear input buffer, discarding all that is in the buffer."""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200186 if not self.sPort:
187 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000188 self._instream.skip(self._instream.available())
cliechti89b4af12002-02-12 23:24:41 +0000189
Chris Liechti2cda7e62015-09-19 22:08:54 +0200190 def reset_output_buffer(self):
cliechti7d448562014-08-03 21:57:45 +0000191 """\
192 Clear output buffer, aborting the current output and
193 discarding all that is in the buffer.
194 """
Chris Liechti2cda7e62015-09-19 22:08:54 +0200195 if not self.sPort:
196 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000197 self._outstream.flush()
cliechti89b4af12002-02-12 23:24:41 +0000198
Chris Liechti2cda7e62015-09-19 22:08:54 +0200199 def send_break(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000200 """Send break condition. Timed, returns to idle state after given duration."""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200201 if not self.sPort:
202 raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000203 self.sPort.sendBreak(duration*1000.0)
cliechti89b4af12002-02-12 23:24:41 +0000204
Chris Liechti2cda7e62015-09-19 22:08:54 +0200205 def _update_break_state(self):
cliechti997b63c2008-06-21 00:09:31 +0000206 """Set break: Controls TXD. When active, to transmitting is possible."""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200207 if self.fd is None:
208 raise portNotOpenError
209 raise SerialException("The _update_break_state function is not implemented in java.")
cliechti997b63c2008-06-21 00:09:31 +0000210
Chris Liechti2cda7e62015-09-19 22:08:54 +0200211 def _update_rts_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000212 """Set terminal status line: Request To Send"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200213 if not self.sPort:
214 raise portNotOpenError
215 self.sPort.setRTS(self._rts_state)
cliechtif81362e2009-07-25 03:44:33 +0000216
Chris Liechti2cda7e62015-09-19 22:08:54 +0200217 def _update_dtr_state(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000218 """Set terminal status line: Data Terminal Ready"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200219 if not self.sPort:
220 raise portNotOpenError
221 self.sPort.setDTR(self._dtr_state)
cliechti89b4af12002-02-12 23:24:41 +0000222
Chris Liechti2cda7e62015-09-19 22:08:54 +0200223 @property
224 def cts(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000225 """Read terminal status line: Clear To Send"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200226 if not self.sPort:
227 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000228 self.sPort.isCTS()
229
Chris Liechti2cda7e62015-09-19 22:08:54 +0200230 @property
231 def dsr(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000232 """Read terminal status line: Data Set Ready"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200233 if not self.sPort:
234 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000235 self.sPort.isDSR()
236
Chris Liechti2cda7e62015-09-19 22:08:54 +0200237 @property
238 def ri(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000239 """Read terminal status line: Ring Indicator"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200240 if not self.sPort:
241 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000242 self.sPort.isRI()
243
Chris Liechti2cda7e62015-09-19 22:08:54 +0200244 @property
245 def cd(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000246 """Read terminal status line: Carrier Detect"""
Chris Liechti2cda7e62015-09-19 22:08:54 +0200247 if not self.sPort:
248 raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000249 self.sPort.isCD()
250
251
cliechti89b4af12002-02-12 23:24:41 +0000252if __name__ == '__main__':
253 s = Serial(0,
cliechti4a567a02009-07-27 22:09:31 +0000254 baudrate=19200, # baudrate
255 bytesize=EIGHTBITS, # number of databits
256 parity=PARITY_EVEN, # enable parity checking
257 stopbits=STOPBITS_ONE, # number of stopbits
258 timeout=3, # set a timeout value, None for waiting forever
259 xonxoff=0, # enable software flow control
260 rtscts=0, # enable RTS/CTS flow control
261 )
cliechti89b4af12002-02-12 23:24:41 +0000262 s.setRTS(1)
263 s.setDTR(1)
Chris Liechti2cda7e62015-09-19 22:08:54 +0200264 s.reset_input_buffer()
265 s.reset_output_buffer()
cliechti89b4af12002-02-12 23:24:41 +0000266 s.write('hello')
cliechti7aaead32009-07-23 14:02:41 +0000267 sys.stdio.write('%r\n' % s.read(5))
Chris Liechti2cda7e62015-09-19 22:08:54 +0200268 sys.stdio.write('%s\n' % s.in_waiting())
cliechti89b4af12002-02-12 23:24:41 +0000269 del s
270