blob: d9ee5159ab34d741835a5e45d6a98bd2826794f6 [file] [log] [blame]
cliechtie8f75f92002-02-14 01:33:33 +00001#!jython
cliechti89b4af12002-02-12 23:24:41 +00002#
cliechti809b82e2008-06-22 22:45:04 +00003# Python Serial Port Extension for Win32, Linux, BSD, Jython
4# module for serial IO for Jython and JavaComm
5# see __init__.py
6#
7# (C) 2002-2008 Chris Liechti <cliechti@gmx.net>
Chris Liechtifbdd8a02015-08-09 02:37:45 +02008#
9# SPDX-License-Identifier: BSD-3-Clause
cliechti89b4af12002-02-12 23:24:41 +000010
cliechti39cfb7b2011-08-22 00:30:07 +000011from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000012
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([
37 'javax.comm', # Sun/IBM
38 'gnu.io', # RXTX
39])
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.")
cliechti8f69e702011-03-19 00:22:32 +000066 if self._isOpen:
67 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)
74 except Exception, msg:
75 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()
80 self._isOpen = 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:
cliechti809b82e2008-06-22 22:45:04 +0000123 jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN
124 jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT
cliechtid6bf52c2003-10-01 02:28:12 +0000125 if self._xonxoff:
cliechti809b82e2008-06-22 22:45:04 +0000126 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"""
139 if self._isOpen:
140 if self.sPort:
141 self._instream.close()
142 self._outstream.close()
143 self.sPort.close()
144 self.sPort = None
145 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000146
cliechtid6bf52c2003-10-01 02:28:12 +0000147 def makeDeviceName(self, port):
148 return device(port)
cliechti95c62212002-03-04 22:17:53 +0000149
cliechtid6bf52c2003-10-01 02:28:12 +0000150 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000151
cliechti89b4af12002-02-12 23:24:41 +0000152 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000153 """Return the number of characters currently in the input buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000154 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000155 return self._instream.available()
cliechti89b4af12002-02-12 23:24:41 +0000156
cliechti4a567a02009-07-27 22:09:31 +0000157 def read(self, size=1):
cliechti7d448562014-08-03 21:57:45 +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 """
cliechti89b4af12002-02-12 23:24:41 +0000163 if not self.sPort: 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."""
cliechti89b4af12002-02-12 23:24:41 +0000177 if not self.sPort: raise portNotOpenError
cliechtiddd78132009-07-28 01:13:28 +0000178 if not isinstance(data, (bytes, bytearray)):
179 raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
cliechtid6bf52c2003-10-01 02:28:12 +0000180 self._outstream.write(data)
cliechtif81362e2009-07-25 03:44:33 +0000181 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000182
183 def flushInput(self):
184 """Clear input buffer, discarding all that is in the buffer."""
185 if not self.sPort: raise portNotOpenError
186 self._instream.skip(self._instream.available())
cliechti89b4af12002-02-12 23:24:41 +0000187
188 def flushOutput(self):
cliechti7d448562014-08-03 21:57:45 +0000189 """\
190 Clear output buffer, aborting the current output and
191 discarding all that is in the buffer.
192 """
cliechti89b4af12002-02-12 23:24:41 +0000193 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000194 self._outstream.flush()
cliechti89b4af12002-02-12 23:24:41 +0000195
cliechtiaaa04602006-02-05 23:02:46 +0000196 def sendBreak(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000197 """Send break condition. Timed, returns to idle state after given duration."""
cliechti89b4af12002-02-12 23:24:41 +0000198 if not self.sPort: raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000199 self.sPort.sendBreak(duration*1000.0)
cliechti89b4af12002-02-12 23:24:41 +0000200
cliechti997b63c2008-06-21 00:09:31 +0000201 def setBreak(self, level=1):
202 """Set break: Controls TXD. When active, to transmitting is possible."""
203 if self.fd is None: raise portNotOpenError
204 raise SerialException("The setBreak function is not implemented in java.")
205
cliechti4569bac2007-11-08 21:57:19 +0000206 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000207 """Set terminal status line: Request To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000208 if not self.sPort: raise portNotOpenError
cliechti4569bac2007-11-08 21:57:19 +0000209 self.sPort.setRTS(level)
cliechtif81362e2009-07-25 03:44:33 +0000210
cliechti4569bac2007-11-08 21:57:19 +0000211 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000212 """Set terminal status line: Data Terminal Ready"""
cliechti89b4af12002-02-12 23:24:41 +0000213 if not self.sPort: raise portNotOpenError
cliechti4569bac2007-11-08 21:57:19 +0000214 self.sPort.setDTR(level)
cliechti89b4af12002-02-12 23:24:41 +0000215
cliechtid6bf52c2003-10-01 02:28:12 +0000216 def getCTS(self):
217 """Read terminal status line: Clear To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000218 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000219 self.sPort.isCTS()
220
221 def getDSR(self):
222 """Read terminal status line: Data Set Ready"""
223 if not self.sPort: raise portNotOpenError
224 self.sPort.isDSR()
225
226 def getRI(self):
227 """Read terminal status line: Ring Indicator"""
228 if not self.sPort: raise portNotOpenError
229 self.sPort.isRI()
230
231 def getCD(self):
232 """Read terminal status line: Carrier Detect"""
233 if not self.sPort: raise portNotOpenError
234 self.sPort.isCD()
235
236
cliechti89b4af12002-02-12 23:24:41 +0000237if __name__ == '__main__':
238 s = Serial(0,
cliechti4a567a02009-07-27 22:09:31 +0000239 baudrate=19200, # baudrate
240 bytesize=EIGHTBITS, # number of databits
241 parity=PARITY_EVEN, # enable parity checking
242 stopbits=STOPBITS_ONE, # number of stopbits
243 timeout=3, # set a timeout value, None for waiting forever
244 xonxoff=0, # enable software flow control
245 rtscts=0, # enable RTS/CTS flow control
246 )
cliechti89b4af12002-02-12 23:24:41 +0000247 s.setRTS(1)
248 s.setDTR(1)
249 s.flushInput()
250 s.flushOutput()
251 s.write('hello')
cliechti7aaead32009-07-23 14:02:41 +0000252 sys.stdio.write('%r\n' % s.read(5))
253 sys.stdio.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000254 del s
255
256