serialjava.py 9.1 KB

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