OLD | NEW |
(Empty) | |
| 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@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._stopbi
ts) |
| 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, jpa
rity) |
| 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(da
ta))) |
| 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 durati
on.""" |
| 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 |
OLD | NEW |