serialjava.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #!jython
  2. #
  3. # Backend Jython with JavaComm
  4. #
  5. # This file is part of pySerial. https://github.com/pyserial/pyserial
  6. # (C) 2002-2015 Chris Liechti <cliechti@gmx.net>
  7. #
  8. # SPDX-License-Identifier: BSD-3-Clause
  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 Serial(SerialBase):
  42. """\
  43. Serial port class, implemented with Java Communications API and
  44. thus usable with jython and the appropriate java extension.
  45. """
  46. def open(self):
  47. """\
  48. Open port with current settings. This may throw a SerialException
  49. if the port cannot be opened.
  50. """
  51. if self._port is None:
  52. raise SerialException("Port must be configured before it can be used.")
  53. if self.is_open:
  54. raise SerialException("Port is already open.")
  55. if type(self._port) == type(''): # strings are taken directly
  56. portId = comm.CommPortIdentifier.getPortIdentifier(self._port)
  57. else:
  58. portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) # numbers are transformed to a comport id obj
  59. try:
  60. self.sPort = portId.open("python serial module", 10)
  61. except Exception as msg:
  62. self.sPort = None
  63. raise SerialException("Could not open port: %s" % msg)
  64. self._reconfigurePort()
  65. self._instream = self.sPort.getInputStream()
  66. self._outstream = self.sPort.getOutputStream()
  67. self.is_open = True
  68. def _reconfigurePort(self):
  69. """Set communication parameters on opened port."""
  70. if not self.sPort:
  71. raise SerialException("Can only operate on a valid port handle")
  72. self.sPort.enableReceiveTimeout(30)
  73. if self._bytesize == FIVEBITS:
  74. jdatabits = comm.SerialPort.DATABITS_5
  75. elif self._bytesize == SIXBITS:
  76. jdatabits = comm.SerialPort.DATABITS_6
  77. elif self._bytesize == SEVENBITS:
  78. jdatabits = comm.SerialPort.DATABITS_7
  79. elif self._bytesize == EIGHTBITS:
  80. jdatabits = comm.SerialPort.DATABITS_8
  81. else:
  82. raise ValueError("unsupported bytesize: %r" % self._bytesize)
  83. if self._stopbits == STOPBITS_ONE:
  84. jstopbits = comm.SerialPort.STOPBITS_1
  85. elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
  86. jstopbits = comm.SerialPort.STOPBITS_1_5
  87. elif self._stopbits == STOPBITS_TWO:
  88. jstopbits = comm.SerialPort.STOPBITS_2
  89. else:
  90. raise ValueError("unsupported number of stopbits: %r" % self._stopbits)
  91. if self._parity == PARITY_NONE:
  92. jparity = comm.SerialPort.PARITY_NONE
  93. elif self._parity == PARITY_EVEN:
  94. jparity = comm.SerialPort.PARITY_EVEN
  95. elif self._parity == PARITY_ODD:
  96. jparity = comm.SerialPort.PARITY_ODD
  97. elif self._parity == PARITY_MARK:
  98. jparity = comm.SerialPort.PARITY_MARK
  99. elif self._parity == PARITY_SPACE:
  100. jparity = comm.SerialPort.PARITY_SPACE
  101. else:
  102. raise ValueError("unsupported parity type: %r" % self._parity)
  103. jflowin = jflowout = 0
  104. if self._rtscts:
  105. jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN
  106. jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT
  107. if self._xonxoff:
  108. jflowin |= comm.SerialPort.FLOWCONTROL_XONXOFF_IN
  109. jflowout |= comm.SerialPort.FLOWCONTROL_XONXOFF_OUT
  110. self.sPort.setSerialPortParams(self._baudrate, jdatabits, jstopbits, jparity)
  111. self.sPort.setFlowControlMode(jflowin | jflowout)
  112. if self._timeout >= 0:
  113. self.sPort.enableReceiveTimeout(int(self._timeout*1000))
  114. else:
  115. self.sPort.disableReceiveTimeout()
  116. def close(self):
  117. """Close port"""
  118. if self.is_open:
  119. if self.sPort:
  120. self._instream.close()
  121. self._outstream.close()
  122. self.sPort.close()
  123. self.sPort = None
  124. self.is_open = False
  125. # - - - - - - - - - - - - - - - - - - - - - - - -
  126. @property
  127. def in_waiting(self):
  128. """Return the number of characters currently in the input buffer."""
  129. if not self.sPort:
  130. raise portNotOpenError
  131. return self._instream.available()
  132. def read(self, size=1):
  133. """\
  134. Read size bytes from the serial port. If a timeout is set it may
  135. return less characters as requested. With no timeout it will block
  136. until the requested number of bytes is read.
  137. """
  138. if not self.sPort:
  139. raise portNotOpenError
  140. read = bytearray()
  141. if size > 0:
  142. while len(read) < size:
  143. x = self._instream.read()
  144. if x == -1:
  145. if self.timeout >= 0:
  146. break
  147. else:
  148. read.append(x)
  149. return bytes(read)
  150. def write(self, data):
  151. """Output the given string over the serial port."""
  152. if not self.sPort:
  153. raise portNotOpenError
  154. if not isinstance(data, (bytes, bytearray)):
  155. raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
  156. self._outstream.write(data)
  157. return len(data)
  158. def reset_input_buffer(self):
  159. """Clear input buffer, discarding all that is in the buffer."""
  160. if not self.sPort:
  161. raise portNotOpenError
  162. self._instream.skip(self._instream.available())
  163. def reset_output_buffer(self):
  164. """\
  165. Clear output buffer, aborting the current output and
  166. discarding all that is in the buffer.
  167. """
  168. if not self.sPort:
  169. raise portNotOpenError
  170. self._outstream.flush()
  171. def send_break(self, duration=0.25):
  172. """Send break condition. Timed, returns to idle state after given duration."""
  173. if not self.sPort:
  174. raise portNotOpenError
  175. self.sPort.sendBreak(duration*1000.0)
  176. def _update_break_state(self):
  177. """Set break: Controls TXD. When active, to transmitting is possible."""
  178. if self.fd is None:
  179. raise portNotOpenError
  180. raise SerialException("The _update_break_state function is not implemented in java.")
  181. def _update_rts_state(self):
  182. """Set terminal status line: Request To Send"""
  183. if not self.sPort:
  184. raise portNotOpenError
  185. self.sPort.setRTS(self._rts_state)
  186. def _update_dtr_state(self):
  187. """Set terminal status line: Data Terminal Ready"""
  188. if not self.sPort:
  189. raise portNotOpenError
  190. self.sPort.setDTR(self._dtr_state)
  191. @property
  192. def cts(self):
  193. """Read terminal status line: Clear To Send"""
  194. if not self.sPort:
  195. raise portNotOpenError
  196. self.sPort.isCTS()
  197. @property
  198. def dsr(self):
  199. """Read terminal status line: Data Set Ready"""
  200. if not self.sPort:
  201. raise portNotOpenError
  202. self.sPort.isDSR()
  203. @property
  204. def ri(self):
  205. """Read terminal status line: Ring Indicator"""
  206. if not self.sPort:
  207. raise portNotOpenError
  208. self.sPort.isRI()
  209. @property
  210. def cd(self):
  211. """Read terminal status line: Carrier Detect"""
  212. if not self.sPort:
  213. raise portNotOpenError
  214. self.sPort.isCD()