1 #!jython 2 # 3 # 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 (at] gmx.net> 8 # this is distributed under a free software license, see license.txt 9 10 from serial.serialutil import * 11 12 def 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 19 20 def 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 31 32 # Java Communications API implementations 33 # http://mho.republika.pl/java/comm/ 34 35 comm = detect_java_comm([ 36 'javax.comm', # Sun/IBM 37 'gnu.io', # RXTX 38 ]) 39 40 41 def device(portnumber): 42 """Turn a port number into a device name""" 43 enum = comm.CommPortIdentifier.getPortIdentifiers() 44 ports = [] 45 while enum.hasMoreElements(): 46 el = enum.nextElement() 47 if el.getPortType() == comm.CommPortIdentifier.PORT_SERIAL: 48 ports.append(el) 49 return ports[portnumber].getName() 50 51 52 class JavaSerial(SerialBase): 53 """Serial port class, implemented with Java Communications API and 54 thus usable with jython and the appropriate java extension.""" 55 56 def open(self): 57 """Open port with current settings. This may throw a SerialException 58 if the port cannot be opened.""" 59 if self._port is None: 60 raise SerialException("Port must be configured before it can be used.") 61 if self._isOpen: 62 raise SerialException("Port is already open.") 63 if type(self._port) == type(''): # strings are taken directly 64 portId = comm.CommPortIdentifier.getPortIdentifier(self._port) 65 else: 66 portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) # numbers are transformed to a comport id obj 67 try: 68 self.sPort = portId.open("python serial module", 10) 69 except Exception, msg: 70 self.sPort = None 71 raise SerialException("Could not open port: %s" % msg) 72 self._reconfigurePort() 73 self._instream = self.sPort.getInputStream() 74 self._outstream = self.sPort.getOutputStream() 75 self._isOpen = True 76 77 def _reconfigurePort(self): 78 """Set communication parameters on opened port.""" 79 if not self.sPort: 80 raise SerialException("Can only operate on a valid port handle") 81 82 self.sPort.enableReceiveTimeout(30) 83 if self._bytesize == FIVEBITS: 84 jdatabits = comm.SerialPort.DATABITS_5 85 elif self._bytesize == SIXBITS: 86 jdatabits = comm.SerialPort.DATABITS_6 87 elif self._bytesize == SEVENBITS: 88 jdatabits = comm.SerialPort.DATABITS_7 89 elif self._bytesize == EIGHTBITS: 90 jdatabits = comm.SerialPort.DATABITS_8 91 else: 92 raise ValueError("unsupported bytesize: %r" % self._bytesize) 93 94 if self._stopbits == STOPBITS_ONE: 95 jstopbits = comm.SerialPort.STOPBITS_1 96 elif stopbits == STOPBITS_ONE_POINT_FIVE: 97 self._jstopbits = comm.SerialPort.STOPBITS_1_5 98 elif self._stopbits == STOPBITS_TWO: 99 jstopbits = comm.SerialPort.STOPBITS_2 100 else: 101 raise ValueError("unsupported number of stopbits: %r" % self._stopbits) 102 103 if self._parity == PARITY_NONE: 104 jparity = comm.SerialPort.PARITY_NONE 105 elif self._parity == PARITY_EVEN: 106 jparity = comm.SerialPort.PARITY_EVEN 107 elif self._parity == PARITY_ODD: 108 jparity = comm.SerialPort.PARITY_ODD 109 elif self._parity == PARITY_MARK: 110 jparity = comm.SerialPort.PARITY_MARK 111 elif self._parity == PARITY_SPACE: 112 jparity = comm.SerialPort.PARITY_SPACE 113 else: 114 raise ValueError("unsupported parity type: %r" % self._parity) 115 116 jflowin = jflowout = 0 117 if self._rtscts: 118 jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN 119 jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT 120 if self._xonxoff: 121 jflowin |= comm.SerialPort.FLOWCONTROL_XONXOFF_IN 122 jflowout |= comm.SerialPort.FLOWCONTROL_XONXOFF_OUT 123 124 self.sPort.setSerialPortParams(self._baudrate, jdatabits, jstopbits, jparity) 125 self.sPort.setFlowControlMode(jflowin | jflowout) 126 127 if self._timeout >= 0: 128 self.sPort.enableReceiveTimeout(self._timeout*1000) 129 else: 130 self.sPort.disableReceiveTimeout() 131 132 def close(self): 133 """Close port""" 134 if self._isOpen: 135 if self.sPort: 136 self._instream.close() 137 self._outstream.close() 138 self.sPort.close() 139 self.sPort = None 140 self._isOpen = False 141 142 def makeDeviceName(self, port): 143 return device(port) 144 145 # - - - - - - - - - - - - - - - - - - - - - - - - 146 147 def inWaiting(self): 148 """Return the number of characters currently in the input buffer.""" 149 if not self.sPort: raise portNotOpenError 150 return self._instream.available() 151 152 def read(self, size=1): 153 """Read size bytes from the serial port. If a timeout is set it may 154 return less characters as requested. With no timeout it will block 155 until the requested number of bytes is read.""" 156 if not self.sPort: raise portNotOpenError 157 read = bytearray() 158 if size > 0: 159 while len(read) < size: 160 x = self._instream.read() 161 if x == -1: 162 if self.timeout >= 0: 163 break 164 else: 165 read.append(x) 166 return bytes(read) 167 168 def write(self, data): 169 """Output the given string over the serial port.""" 170 if not self.sPort: raise portNotOpenError 171 if not isinstance(data, (bytes, bytearray)): 172 raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) 173 self._outstream.write(data) 174 return len(data) 175 176 def flushInput(self): 177 """Clear input buffer, discarding all that is in the buffer.""" 178 if not self.sPort: raise portNotOpenError 179 self._instream.skip(self._instream.available()) 180 181 def flushOutput(self): 182 """Clear output buffer, aborting the current output and 183 discarding all that is in the buffer.""" 184 if not self.sPort: raise portNotOpenError 185 self._outstream.flush() 186 187 def sendBreak(self, duration=0.25): 188 """Send break condition. Timed, returns to idle state after given duration.""" 189 if not self.sPort: raise portNotOpenError 190 self.sPort.sendBreak(duration*1000.0) 191 192 def setBreak(self, level=1): 193 """Set break: Controls TXD. When active, to transmitting is possible.""" 194 if self.fd is None: raise portNotOpenError 195 raise SerialException("The setBreak function is not implemented in java.") 196 197 def setRTS(self, level=1): 198 """Set terminal status line: Request To Send""" 199 if not self.sPort: raise portNotOpenError 200 self.sPort.setRTS(level) 201 202 def setDTR(self, level=1): 203 """Set terminal status line: Data Terminal Ready""" 204 if not self.sPort: raise portNotOpenError 205 self.sPort.setDTR(level) 206 207 def getCTS(self): 208 """Read terminal status line: Clear To Send""" 209 if not self.sPort: raise portNotOpenError 210 self.sPort.isCTS() 211 212 def getDSR(self): 213 """Read terminal status line: Data Set Ready""" 214 if not self.sPort: raise portNotOpenError 215 self.sPort.isDSR() 216 217 def getRI(self): 218 """Read terminal status line: Ring Indicator""" 219 if not self.sPort: raise portNotOpenError 220 self.sPort.isRI() 221 222 def getCD(self): 223 """Read terminal status line: Carrier Detect""" 224 if not self.sPort: raise portNotOpenError 225 self.sPort.isCD() 226 227 228 # assemble Serial class with the platform specific implementation and the base 229 # for file-like behavior. for Python 2.6 and newer, that provide the new I/O 230 # library, derive from io.RawIOBase 231 try: 232 import io 233 except ImportError: 234 # classic version with our own file-like emulation 235 class Serial(JavaSerial, FileLike): 236 pass 237 else: 238 # io library present 239 class Serial(JavaSerial, io.RawIOBase): 240 pass 241 242 243 if __name__ == '__main__': 244 s = Serial(0, 245 baudrate=19200, # baudrate 246 bytesize=EIGHTBITS, # number of databits 247 parity=PARITY_EVEN, # enable parity checking 248 stopbits=STOPBITS_ONE, # number of stopbits 249 timeout=3, # set a timeout value, None for waiting forever 250 xonxoff=0, # enable software flow control 251 rtscts=0, # enable RTS/CTS flow control 252 ) 253 s.setRTS(1) 254 s.setDTR(1) 255 s.flushInput() 256 s.flushOutput() 257 s.write('hello') 258 sys.stdio.write('%r\n' % s.read(5)) 259 sys.stdio.write('%s\n' % s.inWaiting()) 260 del s 261 262 263