Example #1
0
    def _open_port(device, baudrate, logfile=False, debug=False):
        """Open the serial communication port"""
        try:
            from serial.serialutil import SerialException
        except ImportError:
            raise ImportError("Python serial module not installed")
        try:
            from serial import serial_for_url, VERSION as serialver

            versions = [int(x) for x in serialver.split(".", 1)]
            if (versions[0] < 2) or (versions[1] < 6):
                raise ValueError
        except (ValueError, IndexError, ImportError):
            raise ImportError("pyserial 2.6+ is required")
        import pyftdi.serialext

        try:
            port = serial_for_url(device, baudrate=baudrate, timeout=0)
            if logfile:
                port.set_logger(logfile)
            if not port.isOpen():
                port.open()
            if not port.isOpen():
                raise AssertionError('Cannot open port "%s"' % device)
            if debug:
                print "Using serial backend '%s'" % port.BACKEND
            return port
        except SerialException, e:
            raise AssertionError(str(e))
Example #2
0
 def _open_port(device, baudrate, logfile=False, debug=False):
     """Open the serial communication port"""
     try:
         from serial.serialutil import SerialException
     except ImportError:
         raise ImportError("Python serial module not installed")
     try:
         from serial import serial_for_url, VERSION as serialver
         versions = [int(x) for x in serialver.split('.', 1)]
         if (versions[0] < 2) or (versions[1] < 6):
             raise ValueError
     except (ValueError, IndexError, ImportError):
         raise ImportError("pyserial 2.6+ is required")
     import pyftdi.serialext
     try:
         port = serial_for_url(device, baudrate=baudrate, timeout=0)
         if logfile:
             port.set_logger(logfile)
         if not port.isOpen():
             port.open()
         if not port.isOpen():
             raise AssertionError('Cannot open port "%s"' % device)
         if debug:
             print "Using serial backend '%s'" % port.BACKEND
         return port
     except SerialException, e:
         raise AssertionError(str(e))
Example #3
0
 def _open_port(device, baudrate, logfile=False, debug=False):
     """Open the serial communication port"""
     try:
         from serial.serialutil import SerialException
     except ImportError:
         raise ImportError("Python serial module not installed")
     try:
         from serial import serial_for_url, VERSION as serialver
         version = tuple([int(x) for x in serialver.split('.')])
         if version < (2,6):
             raise ValueError
     except (ValueError, IndexError, ImportError):
         raise ImportError("pyserial 2.6+ is required")
     # the following import enables serial protocol extensions
     import pyftdi.serialext
     try:
         port = serial_for_url(device,
                               baudrate=baudrate,
                               timeout=0)
         if logfile:
             port.set_logger(logfile)
         if not port.isOpen():
             port.open()
         if not port.isOpen():
             raise IOError('Cannot open port "%s"' % device)
         if debug:
             print_("Using serial backend '%s'" % port.BACKEND)
         return port
     except SerialException as e:
         raise IOError(str(e))
Example #4
0
 def _open_port(device, baudrate, logfile=False, debug=False):
     """Open the serial communication port"""
     try:
         from serial.serialutil import SerialException
     except ImportError:
         raise ImportError("Python serial module not installed")
     try:
         from serial import serial_for_url, VERSION as serialver
         version = tuple([int(x) for x in serialver.split('.')])
         if version < (2, 6):
             raise ValueError
     except (ValueError, IndexError, ImportError):
         raise ImportError("pyserial 2.6+ is required")
     # the following import enables serial protocol extensions
     import pyftdi.serialext
     try:
         port = serial_for_url(device, baudrate=baudrate, timeout=0)
         if logfile:
             port.set_logger(logfile)
         if not port.isOpen():
             port.open()
         if not port.isOpen():
             raise IOError('Cannot open port "%s"' % device)
         if debug:
             print_("Using serial backend '%s'" % port.BACKEND)
         return port
     except SerialException as e:
         raise IOError(str(e))
def is_correct_pyserial_version():
    """Returns whether the pyserial version is supported"""
    version_tags = [int(version_tag)
                    for version_tag in PYSERIAL_VERSION.split('.')]
    if version_tags[0] >= 3:
        if version_tags[0] == 3 and version_tags[1] <= 3:
            warn("PySerial out of date, please update to v3.4 if possible", stacklevel=0)
        return True
    return False
Example #6
0
 def _open_port(device, baudrate, parity, rtscts, debug=False):
     """Open the serial communication port"""
     try:
         from serial.serialutil import SerialException
         from serial import PARITY_NONE
     except ImportError:
         raise ImportError("Python serial module not installed")
     try:
         from serial import serial_for_url, VERSION as serialver
         version = tuple([int(x) for x in serialver.split('.')])
         if version < (2, 6):
             raise ValueError
     except (ValueError, IndexError, ImportError):
         raise ImportError("pyserial 2.6+ is required")
     # the following import enables serial protocol extensions
     if device.startswith('ftdi:'):
         try:
             from pyftdi import serialext
             serialext.touch()
         except ImportError:
             raise ImportError("PyFTDI module not installed")
     try:
         port = serial_for_url(device,
                               baudrate=baudrate,
                               parity=parity or PARITY_NONE,
                               rtscts=rtscts,
                               timeout=0)
         if not port.is_open:
             port.open()
         if not port.is_open:
             raise IOError('Cannot open port "%s"' % device)
         if debug:
             backend = port.BACKEND if hasattr(port, 'BACKEND') else '?'
             print("Using serial backend '%s'" % backend)
         return port
     except SerialException as exc:
         raise IOError(str(exc))
Example #7
0
 def _open_port(device, baudrate, parity, rtscts, debug=False):
     """Open the serial communication port"""
     try:
         from serial.serialutil import SerialException
         from serial import PARITY_NONE
     except ImportError:
         raise ImportError("Python serial module not installed")
     try:
         from serial import serial_for_url, VERSION as serialver
         version = tuple([int(x) for x in serialver.split('.')])
         if version < (2, 6):
             raise ValueError
     except (ValueError, IndexError, ImportError):
         raise ImportError("pyserial 2.6+ is required")
     # the following import enables serial protocol extensions
     if device.startswith('ftdi:'):
         try:
             from pyftdi import serialext
             serialext.touch()
         except ImportError:
             raise ImportError("PyFTDI module not installed")
     try:
         port = serial_for_url(device,
                               baudrate=baudrate,
                               parity=parity or PARITY_NONE,
                               rtscts=rtscts,
                               timeout=0)
         if not port.is_open:
             port.open()
         if not port.is_open:
             raise IOError('Cannot open port "%s"' % device)
         if debug:
             backend = hasattr(port, 'BACKEND') and port.BACKEND or '?'
             print("Using serial backend '%s'" % backend)
         return port
     except SerialException as e:
         raise IOError(str(e))
Example #8
0
# Copyright (c) 2010-2016 Emmanuel Blot <*****@*****.**>
# Copyright (c) 2008-2015, Neotion
# All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
"""Serial modules compliant with pyserial APIs
"""

try:
    from serial.serialutil import SerialException
except ImportError as exc:
    raise ImportError("Python serial module not installed") from exc
try:
    from serial import VERSION, serial_for_url as serial4url
    version = tuple([int(x) for x in VERSION.split('.')])
    if version < (3, 0):
        raise ValueError
except (ValueError, IndexError, ImportError) as exc:
    raise ImportError("pyserial 3.0+ is required") from exc
try:
    from serial import protocol_handler_packages
    protocol_handler_packages.append('pyftdi.serialext')
except ImportError as exc:
    raise SerialException('Cannot register pyftdi extensions') from exc

serial_for_url = serial4url


def touch():
    """Do nothing, only for static checkers than do not like module import
       with no module references
Example #9
0
class FtdiSerial(SerialBase):
    """Base class for Serial port implementation compatible with pyserial API
       using a USB device.
    """

    BAUDRATES = sorted([9600 * (x+1) for x in range(6)] +
                       list(range(115200, 1000000, 115200)) +
                       list(range(1000000, 13000000, 100000)))

    PYSERIAL_VERSION = tuple([int(x) for x in pyserialver.split('.')])

    def open(self):
        """Open the initialized serial port"""
        if self.port is None:
            raise SerialException("Port must be configured before use.")
        try:
            device = Ftdi.create_from_url(self.port)
        except (UsbToolsError, IOError) as ex:
            raise SerialException('Unable to open USB port %s: %s' %
                                  (self.portstr, str(ex)))
        self.udev = device
        self._set_open_state(True)
        self._reconfigure_port()

    def close(self):
        """Close the open port"""
        self._set_open_state(False)
        if self.udev:
            self.udev.close()
            self.udev = None

    def read(self, size=1):
        """Read size bytes from the serial port. If a timeout is set it may
           return less characters as requested. With no timeout it will block
           until the requested number of bytes is read."""
        data = bytearray()
        start = now()
        while True:
            buf = self.udev.read_data(size)
            data.extend(buf)
            size -= len(buf)
            if size <= 0:
                break
            if self._timeout is not None:
                if buf:
                    break
                ms = now()-start
                if ms > self._timeout:
                    break
            sleep(0.01)
        return bytes(data)

    def write(self, data):
        """Output the given string over the serial port."""
        return self.udev.write_data(data)

    def flush(self):
        """Flush of file like objects. In this case, wait until all data
           is written."""
        pass

    def reset_input_buffer(self):
        """Clear input buffer, discarding all that is in the buffer."""
        self.udev.purge_rx_buffer()

    def reset_output_buffer(self):
        """Clear output buffer, aborting the current output and
        discarding all that is in the buffer."""
        self.udev.purge_tx_buffer()

    def send_break(self, duration=0.25):
        """Send break condition."""
        self.udev.set_break(True)
        sleep(duration)
        self.udev.set_break(False)

    def _update_break_state(self):
        """Send break condition. Not supported"""
        self.udev.set_break(self._break_state)

    def _update_rts_state(self):
        """Set terminal status line: Request To Send"""
        self.udev.set_rts(self._rts_state)

    def _update_dtr_state(self):
        """Set terminal status line: Data Terminal Ready"""
        self.udev.set_dtr(self._dtr_state)

    @property
    def usb_path(self):
        """Return the physical location as a triplet, only for debugging
           purposes.
             * bus is the USB bus
             * address is the address on the USB bus
             * interface is the interface number on the FTDI debice

           :return: (bus, address, interface)
           :rtype: tuple(int)
        """
        return (self.udev.usb_dev.bus, self.udev.usb_dev.address,
                self.udev.interface.bInterfaceNumber)

    @property
    def cts(self):
        """Read terminal status line: Clear To Send"""
        return self.udev.get_cts()

    @property
    def dsr(self):
        """Read terminal status line: Data Set Ready"""
        return self.udev.get_dsr()

    @property
    def ri(self):
        """Read terminal status line: Ring Indicator"""
        return self.udev.get_ri()

    @property
    def cd(self):
        """Read terminal status line: Carrier Detect"""
        return self.udev.get_cd()

    @property
    def in_waiting(self):
        """Return the number of characters currently in the input buffer."""
        # not implemented
        return 0

    @property
    def out_waiting(self):
        """Return the number of bytes currently in the output buffer."""
        return 0

    @property
    def fifoSizes(self):
        """Return the (TX, RX) tupple of hardware FIFO sizes"""
        return self.udev.fifo_sizes

    def _reconfigure_port(self):
        try:
            self.udev.set_baudrate(self._baudrate)
            self._baudrate = self.udev.baudrate
            self.udev.set_line_property(self._bytesize,
                                        self._stopbits,
                                        self._parity)
            if self._rtscts:
                self.udev.set_flowctrl('hw')
            elif self._xonxoff:
                self.udev.set_flowctrl('sw')
            else:
                self.udev.set_flowctrl('')
            try:
                self.udev.set_dynamic_latency(12, 200, 50)
            except AttributeError:
                # backend does not support this feature
                pass
        except IOError as e:
            err = self.udev.get_error_string()
            raise SerialException("%s (%s)" % (str(e), err))

    def _set_open_state(self, open_):
        self.is_open = bool(open_)
Example #10
0
class SocketSerial(SerialBase):
    """Fake serial port redirected to a Unix socket.

       This is basically a copy of the serialposix serial port implementation
       with redefined IO for a Unix socket"""

    BACKEND = 'socket'
    VIRTUAL_DEVICE = True

    PYSERIAL_VERSION = tuple([int(x) for x in pyserialver.split('.')])

    def _reconfigure_port(self):
        pass

    def makeDeviceName(self, port):
        return port

    def open(self):
        """Open the initialized serial port"""
        if self._port is None:
            raise SerialException("Port must be configured before use.")
        if self.isOpen():
            raise SerialException("Port is already open.")
        self._dump = False
        self.sock = None
        try:
            self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
            filename = self.portstr[self.portstr.index('://')+3:]
            if filename.startswith('~/'):
                home = os.getenv('HOME')
                if home:
                    filename = os.path.join(home, filename[2:])
            self._filename = filename
            self.sock.connect(self._filename)
        except Exception as e:
            self.close()
            msg = "Could not open port: %s" % (str(e),)
            if isinstance(e, socket.error):
                raise SerialExceptionWithErrno(msg, e.errno)
            else:
                raise SerialException(msg)
        self._set_open_state(True)
        self._lastdtr = None

    def close(self):
        if self.sock:
            try:
                self.sock.shutdown(socket.SHUT_RDWR)
            except Exception:
                pass
            try:
                self.sock.close()
            except Exception:
                pass
            self.sock = None
        self._set_open_state(False)

    def in_waiting(self):
        """Return the number of characters currently in the input buffer."""
        return 0

    def read(self, size=1):
        """Read size bytes from the serial port. If a timeout is set it may
           return less characters as requested. With no timeout it will block
           until the requested number of bytes is read."""
        if self.sock is None:
            raise portNotOpenError
        read = bytearray()
        if size > 0:
            while len(read) < size:
                ready, _, _ = select.select([self.sock], [], [], self._timeout)
                if not ready:
                    break   # timeout
                buf = self.sock.recv(size-len(read))
                if not len(buf):
                    # Some character is ready, but none can be read
                    # it is a marker for a disconnected peer
                    raise portNotOpenError
                read += buf
                if self._timeout >= 0 and not buf:
                    break  # early abort on timeout
        return read

    def write(self, data):
        """Output the given string over the serial port."""
        if self.sock is None:
            raise portNotOpenError
        t = len(data)
        d = data
        while t > 0:
            try:
                if self._writeTimeout is not None and self._writeTimeout > 0:
                    _, ready, _ = select.select([], [self.sock], [],
                                                self._writeTimeout)
                    if not ready:
                        raise writeTimeoutError
                n = self.sock.send(d)
                if self._dump:
                    print(hexdump(d[:n]))
                if self._writeTimeout is not None and self._writeTimeout > 0:
                    _, ready, _ = select.select([], [self.sock], [],
                                                self._writeTimeout)
                    if not ready:
                        raise writeTimeoutError
                d = d[n:]
                t = t - n
            except OSError as e:
                if e.errno != errno.EAGAIN:
                    raise

    def flush(self):
        """Flush of file like objects. In this case, wait until all data
           is written."""
        pass

    def reset_input_buffer(self):
        """Clear input buffer, discarding all that is in the buffer."""
        pass

    def reset_output_buffer(self):
        """Clear output buffer, aborting the current output and
        discarding all that is in the buffer."""
        pass

    def send_break(self, duration=0.25):
        """Send break condition. Not supported"""

    def _update_break_state(self):
        """Send break condition. Not supported"""
        pass

    def _update_rts_state(self):
        """Set terminal status line: Request To Send"""
        pass

    def _update_dtr_state(self):
        """Set terminal status line: Data Terminal Ready"""
        pass

    def setDTR(self, on=1):
        """Set terminal status line: Data Terminal Ready"""
        pass

    @property
    def cts(self):
        """Read terminal status line: Clear To Send"""
        return True

    @property
    def dsr(self):
        """Read terminal status line: Data Set Ready"""
        return True

    @property
    def ri(self):
        """Read terminal status line: Ring Indicator"""
        return False

    @property
    def cd(self):
        """Read terminal status line: Carrier Detect"""
        return False

    # - - platform specific - - - -

    def nonblocking(self):
        """internal - not portable!"""
        if self.sock is None:
            raise portNotOpenError
        self.sock.setblocking(0)

    def dump(self, enable):
        self._dump = enable

    # - - Helpers - -

    def _set_open_state(self, open_):
        if self.PYSERIAL_VERSION < (3, 0):
            self._isOpen = bool(open_)
        else:
            self.is_open = bool(open_)
Example #11
0
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Serial modules compliant with pyserial APIs
"""

try:
    from serial.serialutil import SerialException
except ImportError:
    raise ImportError("Python serial module not installed")
try:
    from serial import VERSION, serial_for_url as serial4url
    version = tuple([int(x) for x in VERSION.split('.')])
    if version < (3, 0):
        raise ValueError
except (ValueError, IndexError, ImportError):
    raise ImportError("pyserial 3.0+ is required")
try:
    from serial import protocol_handler_packages
    protocol_handler_packages.append('pyftdi.serialext')
except ImportError:
    raise SerialException('Cannot register pyftdi extensions')

serial_for_url = serial4url


def touch():
    """Do nothing, only for static checkers than do not like module import
Example #12
0
class UsbSerial(SerialBase):
    """Base class for Serial port implementation compatible with pyserial API
       using a USB device.
    """

    BAUDRATES = sorted([9600 * (x+1) for x in range(6)] +
                       list(range(115200, 1000000, 115200)) +
                       list(range(1000000, 13000000, 100000)))

    PYSERIAL_VERSION = tuple([int(x) for x in pyserialver.split('.')])

    def makeDeviceName(self, port):
        return port

    def open(self, devclass, scheme, vdict, pdict, default_vendor):
        """Open the initialized serial port"""
        from serial import SerialException
        if self._port is None:
            raise SerialException("Port must be configured before use.")
        try:
            vendor, product, interface, sernum, ix = UsbTools.parse_url(
                self.portstr, devclass, scheme, vdict, pdict, default_vendor)
        except UsbToolsError as e:
            raise SerialException(str(e))
        try:
            self.udev = devclass()
            self.udev.open(vendor, product, interface, ix, sernum)
            self.flushOutput()
            self.flushInput()
        except IOError:
            raise SerialException('Unable to open USB port %s' % self.portstr)
        self._set_open_state(True)
        self._reconfigurePort()
        self._product = product

    def close(self):
        """Close the open port"""
        self._set_open_state(False)
        self.udev.close()
        self.udev = None

    def read(self, size=1):
        """Read size bytes from the serial port. If a timeout is set it may
           return less characters as requested. With no timeout it will block
           until the requested number of bytes is read."""
        data = bytearray()
        start = time.time()
        while size > 0:
            buf = self.udev.read_data(size)
            data += buf
            size -= len(buf)
            if self._timeout > 0:
                if buf:
                    break
                ms = time.time()-start
                if ms > self._timeout:
                    break
            time.sleep(0.01)
        return data

    def write(self, data):
        """Output the given string over the serial port."""
        self.udev.write_data(data)

    def flush(self):
        """Flush of file like objects. In this case, wait until all data
           is written."""
        # do nothing

    def flushInput(self):
        """Clear input buffer, discarding all that is in the buffer."""
        self.udev.purge_rx_buffer()

    def flushOutput(self):
        """Clear output buffer, aborting the current output and
        discarding all that is in the buffer."""
        self.udev.purge_tx_buffer()

    def sendBreak(self):
        """Send break condition."""
        # Not supported
        pass

    def setRTS(self, level=True):
        """Set terminal status line: Request To Send"""
        self.udev.set_rts(level)

    def setDTR(self, level=True):
        """Set terminal status line: Data Terminal Ready"""
        self.udev.set_dtr(level)

    def getCTS(self):
        """Read terminal status line: Clear To Send"""
        return self.udev.get_cts()

    def getDSR(self):
        """Read terminal status line: Data Set Ready"""
        return self.udev.get_dsr()

    def getRI(self):
        """Read terminal status line: Ring Indicator"""
        return self.udev.get_ri()

    def getCD(self):
        """Read terminal status line: Carrier Detect"""
        return self.udev.get_cd()

    def inWaiting(self):
        """Return the number of characters currently in the input buffer."""
        # not implemented
        return 0

    @property
    def fifoSizes(self):
        """Return the (TX, RX) tupple of hardware FIFO sizes"""
        return self.udev.fifo_sizes

    def _reconfigurePort(self):
        try:
            self.udev.set_baudrate(self._baudrate)
            self.udev.set_line_property(self._bytesize,
                                        self._stopbits,
                                        self._parity)
            if self._rtscts:
                self.udev.set_flowctrl('hw')
            elif self._xonxoff:
                self.udev.set_flowctrl('sw')
            else:
                self.udev.set_flowctrl('')
            try:
                self.udev.set_dynamic_latency(2, 200, 400)
            except AttributeError:
                # backend does not support this feature
                pass
        except IOError as e:
            from serial import SerialException
            err = self.udev.get_error_string()
            raise SerialException("%s (%s)" % (str(e), err))

    _reconfigure_port = _reconfigurePort

    def _set_open_state(self, open_):
        if self.PYSERIAL_VERSION < (3, 0):
            self._isOpen = bool(open_)
        else:
            self.is_open = bool(open_)