You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
8.3KB

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