blob: 2dbaad6975f4bc1ced1d7ee3159139ab5c06b80a [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
cliechtid6bf52c2003-10-01 02:28:12 +000010from 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
19def detect_java_comm(names):
20 """try given list of modules and return that imports"""
21 for name in names:
22 try:
23 mod = my_import(name)
24 mod.SerialPort
25 return mod
26 except (ImportError, AttributeError):
27 pass
28 raise ImportError("No Java Communications API implementation found")
29
30# Java Communications API implementations
31# http://mho.republika.pl/java/comm/
32
33comm = detect_java_comm([
34 'javax.comm', # Sun/IBM
35 'gnu.io', # RXTX
36])
cliechti89b4af12002-02-12 23:24:41 +000037
cliechti89b4af12002-02-12 23:24:41 +000038
39def device(portnumber):
cliechtid6bf52c2003-10-01 02:28:12 +000040 """Turn a port number into a device name"""
cliechti809b82e2008-06-22 22:45:04 +000041 enum = comm.CommPortIdentifier.getPortIdentifiers()
cliechti89b4af12002-02-12 23:24:41 +000042 ports = []
43 while enum.hasMoreElements():
44 el = enum.nextElement()
cliechti809b82e2008-06-22 22:45:04 +000045 if el.getPortType() == comm.CommPortIdentifier.PORT_SERIAL:
cliechti89b4af12002-02-12 23:24:41 +000046 ports.append(el)
cliechtid6bf52c2003-10-01 02:28:12 +000047 return ports[portnumber].getName()
cliechti89b4af12002-02-12 23:24:41 +000048
cliechtid6bf52c2003-10-01 02:28:12 +000049class Serial(SerialBase):
cliechti809b82e2008-06-22 22:45:04 +000050 """Serial port class, implemented with Java Communications API and
51 thus usable with jython and the appropriate java extension."""
cliechti58b481c2009-02-16 20:42:32 +000052
cliechtid6bf52c2003-10-01 02:28:12 +000053 def open(self):
54 """Open port with current settings. This may throw a SerialException
55 if the port cannot be opened."""
56 if self._port is None:
57 raise SerialException("Port must be configured before it can be used.")
58 if type(self._port) == type(''): #strings are taken directly
cliechti809b82e2008-06-22 22:45:04 +000059 portId = comm.CommPortIdentifier.getPortIdentifier(self._port)
cliechti89b4af12002-02-12 23:24:41 +000060 else:
cliechti809b82e2008-06-22 22:45:04 +000061 portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) #numbers are transformed to a comportid obj
cliechti4616bf12002-04-08 23:13:14 +000062 try:
63 self.sPort = portId.open("python serial module", 10)
64 except Exception, msg:
65 self.sPort = None
cliechtid6bf52c2003-10-01 02:28:12 +000066 raise SerialException("Could not open port: %s" % msg)
67 self._reconfigurePort()
68 self._instream = self.sPort.getInputStream()
69 self._outstream = self.sPort.getOutputStream()
70 self._isOpen = True
cliechti89b4af12002-02-12 23:24:41 +000071
cliechtid6bf52c2003-10-01 02:28:12 +000072 def _reconfigurePort(self):
73 """Set commuication parameters on opened port."""
74 if not self.sPort:
75 raise SerialException("Can only operate on a valid port handle")
cliechti58b481c2009-02-16 20:42:32 +000076
cliechtid6bf52c2003-10-01 02:28:12 +000077 self.sPort.enableReceiveTimeout(30)
78 if self._bytesize == FIVEBITS:
cliechti809b82e2008-06-22 22:45:04 +000079 jdatabits = comm.SerialPort.DATABITS_5
cliechtid6bf52c2003-10-01 02:28:12 +000080 elif self._bytesize == SIXBITS:
cliechti809b82e2008-06-22 22:45:04 +000081 jdatabits = comm.SerialPort.DATABITS_6
cliechtid6bf52c2003-10-01 02:28:12 +000082 elif self._bytesize == SEVENBITS:
cliechti809b82e2008-06-22 22:45:04 +000083 jdatabits = comm.SerialPort.DATABITS_7
cliechtid6bf52c2003-10-01 02:28:12 +000084 elif self._bytesize == EIGHTBITS:
cliechti809b82e2008-06-22 22:45:04 +000085 jdatabits = comm.SerialPort.DATABITS_8
cliechti89b4af12002-02-12 23:24:41 +000086 else:
cliechtid6bf52c2003-10-01 02:28:12 +000087 raise ValueError("unsupported bytesize: %r" % self._bytesize)
cliechti58b481c2009-02-16 20:42:32 +000088
cliechtid6bf52c2003-10-01 02:28:12 +000089 if self._stopbits == STOPBITS_ONE:
cliechti809b82e2008-06-22 22:45:04 +000090 jstopbits = comm.SerialPort.STOPBITS_1
cliechti58b481c2009-02-16 20:42:32 +000091 elif stopbits == STOPBITS_ONE_POINT_FIVE:
cliechti809b82e2008-06-22 22:45:04 +000092 self._jstopbits = comm.SerialPort.STOPBITS_1_5
cliechtid6bf52c2003-10-01 02:28:12 +000093 elif self._stopbits == STOPBITS_TWO:
cliechti809b82e2008-06-22 22:45:04 +000094 jstopbits = comm.SerialPort.STOPBITS_2
cliechtid6bf52c2003-10-01 02:28:12 +000095 else:
96 raise ValueError("unsupported number of stopbits: %r" % self._stopbits)
97
98 if self._parity == PARITY_NONE:
cliechti809b82e2008-06-22 22:45:04 +000099 jparity = comm.SerialPort.PARITY_NONE
cliechtid6bf52c2003-10-01 02:28:12 +0000100 elif self._parity == PARITY_EVEN:
cliechti809b82e2008-06-22 22:45:04 +0000101 jparity = comm.SerialPort.PARITY_EVEN
cliechtid6bf52c2003-10-01 02:28:12 +0000102 elif self._parity == PARITY_ODD:
cliechti809b82e2008-06-22 22:45:04 +0000103 jparity = comm.SerialPort.PARITY_ODD
104 elif self._parity == PARITY_MARK:
105 jparity = comm.SerialPort.PARITY_MARK
106 elif self._parity == PARITY_SPACE:
107 jparity = comm.SerialPort.PARITY_SPACE
cliechtid6bf52c2003-10-01 02:28:12 +0000108 else:
109 raise ValueError("unsupported parity type: %r" % self._parity)
cliechti89b4af12002-02-12 23:24:41 +0000110
111 jflowin = jflowout = 0
cliechtid6bf52c2003-10-01 02:28:12 +0000112 if self._rtscts:
cliechti809b82e2008-06-22 22:45:04 +0000113 jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN
114 jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT
cliechtid6bf52c2003-10-01 02:28:12 +0000115 if self._xonxoff:
cliechti809b82e2008-06-22 22:45:04 +0000116 jflowin |= comm.SerialPort.FLOWCONTROL_XONXOFF_IN
117 jflowout |= comm.SerialPort.FLOWCONTROL_XONXOFF_OUT
cliechti58b481c2009-02-16 20:42:32 +0000118
cliechtid6bf52c2003-10-01 02:28:12 +0000119 self.sPort.setSerialPortParams(baudrate, jdatabits, jstopbits, jparity)
cliechti89b4af12002-02-12 23:24:41 +0000120 self.sPort.setFlowControlMode(jflowin | jflowout)
cliechti58b481c2009-02-16 20:42:32 +0000121
cliechtid6bf52c2003-10-01 02:28:12 +0000122 if self._timeout >= 0:
123 self.sPort.enableReceiveTimeout(self._timeout*1000)
cliechti89b4af12002-02-12 23:24:41 +0000124 else:
125 self.sPort.disableReceiveTimeout()
126
cliechti89b4af12002-02-12 23:24:41 +0000127 def close(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000128 """Close port"""
129 if self._isOpen:
130 if self.sPort:
131 self._instream.close()
132 self._outstream.close()
133 self.sPort.close()
134 self.sPort = None
135 self._isOpen = False
cliechti89b4af12002-02-12 23:24:41 +0000136
cliechtid6bf52c2003-10-01 02:28:12 +0000137 def makeDeviceName(self, port):
138 return device(port)
cliechti95c62212002-03-04 22:17:53 +0000139
cliechtid6bf52c2003-10-01 02:28:12 +0000140 # - - - - - - - - - - - - - - - - - - - - - - - -
cliechti95c62212002-03-04 22:17:53 +0000141
cliechti89b4af12002-02-12 23:24:41 +0000142 def inWaiting(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000143 """Return the number of characters currently in the input buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000144 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000145 return self._instream.available()
cliechti89b4af12002-02-12 23:24:41 +0000146
147 def read(self, size=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000148 """Read size bytes from the serial port. If a timeout is set it may
149 return less characters as requested. With no timeout it will block
150 until the requested number of bytes is read."""
cliechti89b4af12002-02-12 23:24:41 +0000151 if not self.sPort: raise portNotOpenError
cliechtia9e4e952002-05-26 01:20:22 +0000152 read = ''
153 if size > 0:
154 while len(read) < size:
cliechtid6bf52c2003-10-01 02:28:12 +0000155 x = self._instream.read()
cliechtia9e4e952002-05-26 01:20:22 +0000156 if x == -1:
157 if self.timeout >= 0:
158 break
159 else:
160 read = read + chr(x)
161 return read
cliechti89b4af12002-02-12 23:24:41 +0000162
cliechtid6bf52c2003-10-01 02:28:12 +0000163 def write(self, data):
164 """Output the given string over the serial port."""
cliechti89b4af12002-02-12 23:24:41 +0000165 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000166 self._outstream.write(data)
167
168 def flushInput(self):
169 """Clear input buffer, discarding all that is in the buffer."""
170 if not self.sPort: raise portNotOpenError
171 self._instream.skip(self._instream.available())
cliechti89b4af12002-02-12 23:24:41 +0000172
173 def flushOutput(self):
cliechtid6bf52c2003-10-01 02:28:12 +0000174 """Clear output buffer, aborting the current output and
175 discarding all that is in the buffer."""
cliechti89b4af12002-02-12 23:24:41 +0000176 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000177 self._outstream.flush()
cliechti89b4af12002-02-12 23:24:41 +0000178
cliechtiaaa04602006-02-05 23:02:46 +0000179 def sendBreak(self, duration=0.25):
cliechti997b63c2008-06-21 00:09:31 +0000180 """Send break condition. Timed, returns to idle state after given duration."""
cliechti89b4af12002-02-12 23:24:41 +0000181 if not self.sPort: raise portNotOpenError
cliechtiaaa04602006-02-05 23:02:46 +0000182 self.sPort.sendBreak(duration*1000.0)
cliechti89b4af12002-02-12 23:24:41 +0000183
cliechti997b63c2008-06-21 00:09:31 +0000184 def setBreak(self, level=1):
185 """Set break: Controls TXD. When active, to transmitting is possible."""
186 if self.fd is None: raise portNotOpenError
187 raise SerialException("The setBreak function is not implemented in java.")
188
cliechti4569bac2007-11-08 21:57:19 +0000189 def setRTS(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000190 """Set terminal status line: Request To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000191 if not self.sPort: raise portNotOpenError
cliechti4569bac2007-11-08 21:57:19 +0000192 self.sPort.setRTS(level)
cliechtid6bf52c2003-10-01 02:28:12 +0000193
cliechti4569bac2007-11-08 21:57:19 +0000194 def setDTR(self, level=1):
cliechtid6bf52c2003-10-01 02:28:12 +0000195 """Set terminal status line: Data Terminal Ready"""
cliechti89b4af12002-02-12 23:24:41 +0000196 if not self.sPort: raise portNotOpenError
cliechti4569bac2007-11-08 21:57:19 +0000197 self.sPort.setDTR(level)
cliechti89b4af12002-02-12 23:24:41 +0000198
cliechtid6bf52c2003-10-01 02:28:12 +0000199 def getCTS(self):
200 """Read terminal status line: Clear To Send"""
cliechti89b4af12002-02-12 23:24:41 +0000201 if not self.sPort: raise portNotOpenError
cliechtid6bf52c2003-10-01 02:28:12 +0000202 self.sPort.isCTS()
203
204 def getDSR(self):
205 """Read terminal status line: Data Set Ready"""
206 if not self.sPort: raise portNotOpenError
207 self.sPort.isDSR()
208
209 def getRI(self):
210 """Read terminal status line: Ring Indicator"""
211 if not self.sPort: raise portNotOpenError
212 self.sPort.isRI()
213
214 def getCD(self):
215 """Read terminal status line: Carrier Detect"""
216 if not self.sPort: raise portNotOpenError
217 self.sPort.isCD()
218
219
cliechti89b4af12002-02-12 23:24:41 +0000220
221if __name__ == '__main__':
222 s = Serial(0,
223 baudrate=19200, #baudrate
224 bytesize=EIGHTBITS, #number of databits
225 parity=PARITY_EVEN, #enable parity checking
226 stopbits=STOPBITS_ONE, #number of stopbits
227 timeout=3, #set a timeout value, None for waiting forever
228 xonxoff=0, #enable software flow control
229 rtscts=0, #enable RTS/CTS flow control
230 )
231 s.setRTS(1)
232 s.setDTR(1)
233 s.flushInput()
234 s.flushOutput()
235 s.write('hello')
cliechti7aaead32009-07-23 14:02:41 +0000236 sys.stdio.write('%r\n' % s.read(5))
237 sys.stdio.write('%s\n' % s.inWaiting())
cliechti89b4af12002-02-12 23:24:41 +0000238 del s
239
240