blob: e36ecf56a951ddd7131137187e35e7e147445d7a [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>
cliechti89b4af12002-02-12 23:24:41 +00008# this is distributed under a free software license, see license.txt
9
cliechti39cfb7b2011-08-22 00:30:07 +000010from serial.serialutil import *
cliechti89b4af12002-02-12 23:24:41 +000011
cliechti809b82e2008-06-22 22:45:04 +000012def my_import(name):
13 mod = __import__(name)
14 components = name.split('.')
15 for comp in components[1:]:
16 mod = getattr(mod, comp)
17 return mod
18
cliechti4a567a02009-07-27 22:09:31 +000019
cliechti809b82e2008-06-22 22:45:04 +000020def detect_java_comm(names):
21 """try given list of modules and return that imports"""
22 for name in names:
23 try:
24 mod = my_import(name)
25 mod.SerialPort
26 return mod
27 except (ImportError, AttributeError):
28 pass
29 raise ImportError("No Java Communications API implementation found")
30
cliechti4a567a02009-07-27 22:09:31 +000031
cliechti809b82e2008-06-22 22:45:04 +000032# Java Communications API implementations
33# http://mho.republika.pl/java/comm/
34
35comm = detect_java_comm([
36 'javax.comm', # Sun/IBM
37 'gnu.io', # RXTX
38])
cliechti89b4af12002-02-12 23:24:41 +000039
cliechti89b4af12002-02-12 23:24:41 +000040
41def device(portnumber):
cliechtid6bf52c2003-10-01 02:28:12 +000042 """Turn a port number into a device name"""
cliechti809b82e2008-06-22 22:45:04 +000043 enum = comm.CommPortIdentifier.getPortIdentifiers()
cliechti89b4af12002-02-12 23:24:41 +000044 ports = []
45 while enum.hasMoreElements():
46 el = enum.nextElement()
cliechti809b82e2008-06-22 22:45:04 +000047 if el.getPortType() == comm.CommPortIdentifier.PORT_SERIAL:
cliechti89b4af12002-02-12 23:24:41 +000048 ports.append(el)
cliechtid6bf52c2003-10-01 02:28:12 +000049 return ports[portnumber].getName()
cliechti89b4af12002-02-12 23:24:41 +000050
cliechtif81362e2009-07-25 03:44:33 +000051
Chris Liechtief6b7b42015-08-06 22:19:26 +020052class Serial(SerialBase):
cliechti7d448562014-08-03 21:57:45 +000053 """\
54 Serial port class, implemented with Java Communications API and
55 thus usable with jython and the appropriate java extension.
56 """
cliechti58b481c2009-02-16 20:42:32 +000057
cliechtid6bf52c2003-10-01 02:28:12 +000058 def open(self):
cliechti7d448562014-08-03 21:57:45 +000059 """\
60 Open port with current settings. This may throw a SerialException
61 if the port cannot be opened.
62 """
cliechtid6bf52c2003-10-01 02:28:12 +000063 if self._port is None:
64 raise SerialException("Port must be configured before it can be used.")
cliechti8f69e702011-03-19 00:22:32 +000065 if self._isOpen:
66 raise SerialException("Port is already open.")
cliechti4a567a02009-07-27 22:09:31 +000067 if type(self._port) == type(''): # strings are taken directly
cliechti809b82e2008-06-22 22:45:04 +000068 portId = comm.CommPortIdentifier.getPortIdentifier(self._port)
cliechti89b4af12002-02-12 23:24:41 +000069 else:
cliechti4a567a02009-07-27 22:09:31 +000070 portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) # numbers are transformed to a comport id obj
cliechti4616bf12002-04-08 23:13:14 +000071 try:
72 self.sPort = portId.open("python serial module", 10)
73 except Exception, msg:
74 self.sPort = None
cliechtid6bf52c2003-10-01 02:28:12 +000075 raise SerialException("Could not open port: %s" % msg)
76 self._reconfigurePort()
77 self._instream = self.sPort.getInputStream()
78 self._outstream = self.sPort.getOutputStream()
79 self._isOpen = True
cliechti89b4af12002-02-12 23:24:41 +000080
cliechtid6bf52c2003-10-01 02:28:12 +000081 def _reconfigurePort(self):
cliechti4a567a02009-07-27 22:09:31 +000082 """Set communication parameters on opened port."""
cliechtid6bf52c2003-10-01 02:28:12 +000083 if not self.sPort:
84 raise SerialException("Can only operate on a valid port handle")
cliechti58b481c2009-02-16 20:42:32 +000085
cliechtid6bf52c2003-10-01 02:28:12 +000086 self.sPort.enableReceiveTimeout(30)
87 if self._bytesize == FIVEBITS:
cliechti809b82e2008-06-22 22:45:04 +000088 jdatabits = comm.SerialPort.DATABITS_5
cliechtid6bf52c2003-10-01 02:28:12 +000089 elif self._bytesize == SIXBITS:
cliechti809b82e2008-06-22 22:45:04 +000090 jdatabits = comm.SerialPort.DATABITS_6
cliechtid6bf52c2003-10-01 02:28:12 +000091 elif self._bytesize == SEVENBITS:
cliechti809b82e2008-06-22 22:45:04 +000092 jdatabits = comm.SerialPort.DATABITS_7
cliechtid6bf52c2003-10-01 02:28:12 +000093 elif self._bytesize == EIGHTBITS:
cliechti809b82e2008-06-22 22:45:04 +000094 jdatabits = comm.SerialPort.DATABITS_8
cliechti89b4af12002-02-12 23:24:41 +000095 else:
cliechtid6bf52c2003-10-01 02:28:12 +000096 raise ValueError("unsupported bytesize: %r" % self._bytesize)
cliechti58b481c2009-02-16 20:42:32 +000097
cliechtid6bf52c2003-10-01 02:28:12 +000098 if self._stopbits == STOPBITS_ONE:
cliechti809b82e2008-06-22 22:45:04 +000099 jstopbits = comm.SerialPort.STOPBITS_1
cliechtic5aed012014-08-01 02:34:22 +0000100 elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
101 jstopbits = comm.SerialPort.STOPBITS_1_5
cliechtid6bf52c2003-10-01 02:28:12 +0000102 elif self._stopbits == STOPBITS_TWO:
cliechti809b82e2008-06-22 22:45:04 +0000103 jstopbits = comm.SerialPort.STOPBITS_2
cliechtid6bf52c2003-10-01 02:28:12 +0000104 else:
105 raise ValueError("unsupported number of stopbits: %r" % self._stopbits)
106
107 if self._parity == PARITY_NONE:
cliechti809b82e2008-06-22 22:45:04 +0000108 jparity = comm.SerialPort.PARITY_NONE
cliechtid6bf52c2003-10-01 02:28:12 +0000109 elif self._parity == PARITY_EVEN:
cliechti809b82e2008-06-22 22:45:04 +0000110 jparity = comm.SerialPort.PARITY_EVEN
cliechtid6bf52c2003-10-01 02:28:12 +0000111 elif self._parity == PARITY_ODD:
cliechti809b82e2008-06-22 22:45:04 +0000112 jparity = comm.SerialPort.PARITY_ODD
113 elif self._parity == PARITY_MARK:
114 jparity = comm.SerialPort.PARITY_MARK
115 elif self._parity == PARITY_SPACE:
116 jparity = comm.SerialPort.PARITY_SPACE
cliechtid6bf52c2003-10-01 02:28:12 +0000117 else:
118 raise ValueError("unsupported parity type: %r" % self._parity)
cliechti89b4af12002-02-12 23:24:41 +0000119
120 jflowin = jflowout = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000121 if self._rtscts:
cliechti809b82e2008-06-22 22:45:04 +0000122 jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN
123 jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT
cliechtid6bf52c2003-10-01 02:28:12 +0000124 if self._xonxoff:
cliechti809b82e2008-06-22 22:45:04 +0000125 jflowin |= comm.SerialPort.FLOWCONTROL_XONXOFF_IN
126 jflowout |= comm.SerialPort.FLOWCONTROL_XONXOFF_OUT
cliechti58b481c2009-02-16 20:42:32 +0000127
cliechti6670f732009-07-25 23:49:26 +0000128 self.sPort.setSerialPortParams(self._baudrate, jdatabits, jstopbits, jparity)
cliechti89b4af12002-02-12 23:24:41 +0000129 self.sPort.setFlowControlMode(jflowin | jflowout)
cliechti58b481c2009-02-16 20:42:32 +0000130
cliechtid6bf52c2003-10-01 02:28:12 +0000131 if self._timeout >= 0:
cliechtic5aed012014-08-01 02:34:22 +0000132 self.sPort.enableReceiveTimeout(int(self._timeout*1000))
cliechti89b4af12002-02-12 23:24:41 +0000133 else:
134 self.sPort.disableReceiveTimeout()
135
cliechti89b4af12002-02-12 23:24:41 +0000136 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000137 """Close port"""
138 if self._isOpen:
139 if self.sPort:
140 self._instream.close()
141 self._outstream.close()
142 self.sPort.close()
143 self.sPort = None
144 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000145
cliechtid6bf52c2003-10-01 02:28:12 +0000146 def makeDeviceName(self, port):
147 return device(port)
cliechti95c62212002-03-04 22:17:53 +0000148
cliechtid6bf52c2003-10-01 02:28:12 +0000149 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000150
cliechti89b4af12002-02-12 23:24:41 +0000151 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000152 """Return the number of characters currently in the input buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000153 if not self.sPort: 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 """
cliechti89b4af12002-02-12 23:24:41 +0000162 if not self.sPort: raise portNotOpenError
cliechti4a567a02009-07-27 22:09:31 +0000163 read = bytearray()
cliechtia9e4e952002-05-26 01:20:22 +0000164 if size > 0:
165 while len(read) < size:
cliechtid6bf52c2003-10-01 02:28:12 +0000166 x = self._instream.read()
cliechtia9e4e952002-05-26 01:20:22 +0000167 if x == -1:
168 if self.timeout >= 0:
169 break
170 else:
cliechti4a567a02009-07-27 22:09:31 +0000171 read.append(x)
172 return bytes(read)
cliechti89b4af12002-02-12 23:24:41 +0000173
cliechti4a567a02009-07-27 22:09:31 +0000174 def write(self, data):
cliechtid6bf52c2003-10-01 02:28:12 +0000175 """Output the given string over the serial port."""
cliechti89b4af12002-02-12 23:24:41 +0000176 if not self.sPort: raise portNotOpenError
cliechtiddd78132009-07-28 01:13:28 +0000177 if not isinstance(data, (bytes, bytearray)):
178 raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
cliechtid6bf52c2003-10-01 02:28:12 +0000179 self._outstream.write(data)
cliechtif81362e2009-07-25 03:44:33 +0000180 return len(data)
cliechtid6bf52c2003-10-01 02:28:12 +0000181
182 def flushInput(self):
183 """Clear input buffer, discarding all that is in the buffer."""
184 if not self.sPort: raise portNotOpenError
185 self._instream.skip(self._instream.available())
cliechti89b4af12002-02-12 23:24:41 +0000186
187 def flushOutput(self):
cliechti7d448562014-08-03 21:57:45 +0000188 """\
189 Clear output buffer, aborting the current output and
190 discarding all that is in the buffer.
191 """
cliechti89b4af12002-02-12 23:24:41 +0000192 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000193 self._outstream.flush()
cliechti89b4af12002-02-12 23:24:41 +0000194
cliechtiaaa04602006-02-05 23:02:46 +0000195 def sendBreak(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000196 """Send break condition. Timed, returns to idle state after given duration."""
cliechti89b4af12002-02-12 23:24:41 +0000197 if not self.sPort: raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000198 self.sPort.sendBreak(duration*1000.0)
cliechti89b4af12002-02-12 23:24:41 +0000199
cliechti997b63c2008-06-21 00:09:31 +0000200 def setBreak(self, level=1):
201 """Set break: Controls TXD. When active, to transmitting is possible."""
202 if self.fd is None: raise portNotOpenError
203 raise SerialException("The setBreak function is not implemented in java.")
204
cliechti4569bac2007-11-08 21:57:19 +0000205 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000206 """Set terminal status line: Request To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000207 if not self.sPort: raise portNotOpenError
cliechti4569bac2007-11-08 21:57:19 +0000208 self.sPort.setRTS(level)
cliechtif81362e2009-07-25 03:44:33 +0000209
cliechti4569bac2007-11-08 21:57:19 +0000210 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000211 """Set terminal status line: Data Terminal Ready"""
cliechti89b4af12002-02-12 23:24:41 +0000212 if not self.sPort: raise portNotOpenError
cliechti4569bac2007-11-08 21:57:19 +0000213 self.sPort.setDTR(level)
cliechti89b4af12002-02-12 23:24:41 +0000214
cliechtid6bf52c2003-10-01 02:28:12 +0000215 def getCTS(self):
216 """Read terminal status line: Clear To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000217 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000218 self.sPort.isCTS()
219
220 def getDSR(self):
221 """Read terminal status line: Data Set Ready"""
222 if not self.sPort: raise portNotOpenError
223 self.sPort.isDSR()
224
225 def getRI(self):
226 """Read terminal status line: Ring Indicator"""
227 if not self.sPort: raise portNotOpenError
228 self.sPort.isRI()
229
230 def getCD(self):
231 """Read terminal status line: Carrier Detect"""
232 if not self.sPort: raise portNotOpenError
233 self.sPort.isCD()
234
235
cliechti89b4af12002-02-12 23:24:41 +0000236if __name__ == '__main__':
237 s = Serial(0,
cliechti4a567a02009-07-27 22:09:31 +0000238 baudrate=19200, # baudrate
239 bytesize=EIGHTBITS, # number of databits
240 parity=PARITY_EVEN, # enable parity checking
241 stopbits=STOPBITS_ONE, # number of stopbits
242 timeout=3, # set a timeout value, None for waiting forever
243 xonxoff=0, # enable software flow control
244 rtscts=0, # enable RTS/CTS flow control
245 )
cliechti89b4af12002-02-12 23:24:41 +0000246 s.setRTS(1)
247 s.setDTR(1)
248 s.flushInput()
249 s.flushOutput()
250 s.write('hello')
cliechti7aaead32009-07-23 14:02:41 +0000251 sys.stdio.write('%r\n' % s.read(5))
252 sys.stdio.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000253 del s
254
255