Home | History | Annotate | Download | only in serial
      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