Exemple #1
0
    def _check_communication(self) -> bool:
        """ Send a "sendme" command and synchronously wait for a response. NOT to be used when an event loop is running.
        """
        command = SendmeCommand()
        communication_ok = False
        while True:
            # Depending on Nextion status we may have some stale data lingering
            # because we have sent stuff with wrong baudrate and Nextion is answering
            # with an "Invalid Variable" event or something like that.
            # So we keep sending "sendme" until we get a proper response.
            command.send(self.transport)
            timeout = Timeout(0.2)  # 200ms should be WAY MORE than enough
            while not timeout.expired():
                data = self.transport.read_next()
                if data:
                    try:
                        data_event = MsgEvent.parse(data)
                    except NexMessageException:
                        pass
                    else:
                        communication_ok = isinstance(data_event,
                                                      CurrentPageIDHeadEvent)
                    break

            if timeout.expired() or communication_ok:
                break

        return communication_ok
Exemple #2
0
def read_until(port, terminators=None, size=None):
    """\
    Read until any of the termination sequences is found ('\n' by default), the size
    is exceeded or until timeout occurs.
    """
    if not terminators:
        terminators = ['\n']
    terms = map(lambda t: (t, len(t)), terminators)
    line = bytearray()
    timeout = Timeout(port._timeout)
    while True:
        c = port.read(1)
        if c:
            line += c
            for (terminator, lenterm) in terms:
                if line[-lenterm:] == terminator:
                    # break does not work here because it will only step out of for
                    return bytes(line)
            if size is not None and len(line) >= size:
                break
        else:
            break
        if timeout.expired():
            break
    return bytes(line)
Exemple #3
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 not self.is_open:
         raise PortNotOpenError()
     read = bytearray()
     timeout = Timeout(self._timeout)
     poll = select.poll()
     poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
     poll.register(self.pipe_abort_read_r, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
     if size > 0:
         while len(read) < size:
             # print "\tread(): size",size, "have", len(read)    #debug
             # wait until device becomes ready to read (or something fails)
             for fd, event in poll.poll(None if timeout.is_infinite else (timeout.time_left() * 1000)):
                 if fd == self.pipe_abort_read_r:
                     break
                 if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
                     raise SerialException('device reports error (poll)')
                 #  we don't care if it is select.POLLIN or timeout, that's
                 #  handled below
             if fd == self.pipe_abort_read_r:
                 os.read(self.pipe_abort_read_r, 1000)
                 break
             buf = os.read(self.fd, size - len(read))
             read.extend(buf)
             if timeout.expired() \
                     or (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0) and not buf:
                 break   # early abort on timeout
     return bytes(read)
Exemple #4
0
    def init(self):
        """ Set the device to always send responses and select page 0. To be called in single-threaded environment
            WITHOUT any poller running
        """
        self._logger.info("Initializing Nextion device")
        # Flush incoming data
        while True:
            if not self.transport.read_all():
                break

        # First check if the transport has the correct baudrate
        if not self._check_communication():
            raise NexCommandFailure(
                "Could not initialize Nextion device communication with current transport settings"
            )

        if self._force_baudrate and self._force_baudrate != self.transport.baudrate:
            command = BaudCommand(self._force_baudrate)
            command.send(self.transport)
            self._logger.info("Changing baudrate to {}", self._force_baudrate)
            self.transport.baudrate = self._force_baudrate
            timeout = Timeout(0.1)  # 100ms should be WAY MORE than enough
            while not timeout.expired():
                # We may have a Command Succeeded if we are in bkcmd=3 mode
                self.transport.read_all()

            if not self._check_communication():
                raise NexCommandFailure(
                    "Could not change device baudrate to {}".format(
                        self._force_baudrate))
            self._logger.info("Changed baudrate to %d", self._force_baudrate)

        # mode = Return.Mode.NO_RETURN
        # mode = Return.Mode.SUCCESS_ONLY  # production setting
        # mode = Return.Mode.FAIL_ONLY  # default screen setting
        mode = Return.Mode.ALWAYS

        self._commands.extendleft((
            Command("bkcmd=%d" % mode.value
                    ),  # This must come first as is the first to be executed
        ))
        while self._commands:
            self.poll()

        for page_id, page in self._pages_by_id.items():
            self.select_page(page_id)
            while self._commands:
                self.poll()

            page.onetime_refresh()
            while self._commands:
                self.poll()

        self.select_page(0)
        while self._commands:
            self.poll()

        self._initialized = True
        self._logger.info("Nextion device initialized")
    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 not self.is_open:
            raise PortNotOpenError()
        read = bytearray()
        timeout = Timeout(self._timeout)
        while len(read) < size:
            try:
                ready, _, _ = select.select([self.fd, self.pipe_abort_read_r],
                                            [], [], timeout.time_left())
                if self.pipe_abort_read_r in ready:
                    os.read(self.pipe_abort_read_r, 1000)
                    break
                # If select was used with a timeout, and the timeout occurs, it
                # returns with empty lists -> thus abort read operation.
                # For timeout == 0 (non-blocking operation) also abort when
                # there is nothing to read.
                if not ready:
                    break  # timeout
                buf = os.read(self.fd, size - len(read))
            except OSError as e:
                # this is for Python 3.x where select.error is a subclass of
                # OSError ignore BlockingIOErrors and EINTR. other errors are shown
                # https://www.python.org/dev/peps/pep-0475.
                if e.errno not in (errno.EAGAIN, errno.EALREADY,
                                   errno.EWOULDBLOCK, errno.EINPROGRESS,
                                   errno.EINTR):
                    raise SerialException('read failed: {}'.format(e))
            except select.error as e:
                # this is for Python 2.x
                # ignore BlockingIOErrors and EINTR. all errors are shown
                # see also http://www.python.org/dev/peps/pep-3151/#select
                if e[0] not in (errno.EAGAIN, errno.EALREADY,
                                errno.EWOULDBLOCK, errno.EINPROGRESS,
                                errno.EINTR):
                    raise SerialException('read failed: {}'.format(e))
            else:
                # read should always return some data as select reported it was
                # ready to read when we get to this point.
                if not buf:
                    # Disconnected devices, at least on Linux, show the
                    # behavior that they are always ready to read immediately
                    # but reading returns nothing.
                    raise SerialException(
                        'device reports readiness to read but returned no data '
                        '(device disconnected or multiple access on port?)')
                read.extend(buf)

            if timeout.expired():
                break
        return bytes(read)
Exemple #6
0
 def write(self, data):
     """Output the given byte string over the serial port."""
     if not self.is_open:
         raise portNotOpenError
     d = to_bytes(data)
     tx_len = length = len(d)
     timeout = Timeout(self._write_timeout)
     while tx_len > 0:
         try:
             n = os.write(self.fd, d)
             if timeout.is_non_blocking:
                 # Zero timeout indicates non-blocking - simply return the
                 # number of bytes of data actually written
                 return n
             elif not timeout.is_infinite:
                 # when timeout is set, use select to wait for being ready
                 # with the time left as timeout
                 if timeout.expired():
                     raise writeTimeoutError
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
                 if abort:
                     os.read(self.pipe_abort_write_r, 1000)
                     break
                 if not ready:
                     raise writeTimeoutError
             else:
                 assert timeout.time_left() is None
                 # wait for write operation
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
                 if abort:
                     os.read(self.pipe_abort_write_r, 1)
                     break
                 if not ready:
                     raise SerialException('write failed (select)')
             d = d[n:]
             tx_len -= n
         except SerialException:
             raise
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('write failed: {}'.format(e))
         except select.error as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('write failed: {}'.format(e))
         if not timeout.is_non_blocking and timeout.expired():
             raise writeTimeoutError
     return length - len(d)
 def write(self, data):
     """Output the given byte string over the serial port."""
     if not self.is_open:
         raise portNotOpenError
     d = to_bytes(data)
     tx_len = length = len(d)
     timeout = Timeout(self._write_timeout)
     while tx_len > 0:
         try:
             n = os.write(self.fd, d)
             if timeout.is_non_blocking:
                 # Zero timeout indicates non-blocking - simply return the
                 # number of bytes of data actually written
                 return n
             elif not timeout.is_infinite:
                 # when timeout is set, use select to wait for being ready
                 # with the time left as timeout
                 if timeout.expired():
                     raise writeTimeoutError
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
                 if abort:
                     os.read(self.pipe_abort_write_r, 1000)
                     break
                 if not ready:
                     raise writeTimeoutError
             else:
                 assert timeout.time_left() is None
                 # wait for write operation
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
                 if abort:
                     os.read(self.pipe_abort_write_r, 1)
                     break
                 if not ready:
                     raise SerialException('write failed (select)')
             d = d[n:]
             tx_len -= n
         except SerialException:
             raise
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('write failed: {}'.format(e))
         except select.error as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('write failed: {}'.format(e))
         if not timeout.is_non_blocking and timeout.expired():
             raise writeTimeoutError
     return length - len(d)
 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 not self.is_open:
         raise portNotOpenError
     read = bytearray()
     timeout = Timeout(self._timeout)
     while len(read) < size:
         try:
             ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout.time_left())
             if self.pipe_abort_read_r in ready:
                 os.read(self.pipe_abort_read_r, 1000)
                 break
             # If select was used with a timeout, and the timeout occurs, it
             # returns with empty lists -> thus abort read operation.
             # For timeout == 0 (non-blocking operation) also abort when
             # there is nothing to read.
             if not ready:
                 break   # timeout
             buf = os.read(self.fd, size - len(read))
             # read should always return some data as select reported it was
             # ready to read when we get to this point.
             if not buf:
                 # Disconnected devices, at least on Linux, show the
                 # behavior that they are always ready to read immediately
                 # but reading returns nothing.
                 raise SerialException(
                     'device reports readiness to read but returned no data '
                     '(device disconnected or multiple access on port?)')
             read.extend(buf)
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         except select.error as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         if timeout.expired():
             break
     return bytes(read)
    def _wait_for_response(self, command, timeout=None):
        timeout = Timeout(timeout or self._timeout)

        def read(size=1):
            self._serial.timeout = timeout.time_left()
            data = self._serial.read(size)
            if len(data) != size:
                raise TimeoutError()
            return data

        while True:
            data = []
            data += read(1)
            if data[-1] != 0x55:
                LOGGER.error(
                    'Got unexpected octet while waiting for response header: %02x',
                    data[-1])
                continue
            data += read(1)
            if data[-1] != 0x55:
                LOGGER.error(
                    'Got unexpected octet while waiting for response header: %02x',
                    data[-1])
                continue
            data += read(2)
            length = data[2]
            cmd = data[3]

            data += read(length - 2) if length > 2 else []
            params = data[4:]

            LOGGER.debug('Got command %s response: %s', cmd, hex_data(data))
            self._responses.append([cmd] + params)

            return params
Exemple #10
0
    def send_message(self, data, timeout=DEFAULT_SEND_TIMEOUT):

        self.urc_state = Modem.SOCKET_INIT

        self.write_socket(data)

        loop_timeout = Timeout(timeout)
        while self.urc_state != Modem.SOCKET_SEND_READ:
            self.checkURC()
            if self.urc_state != Modem.SOCKET_SEND_READ:
                if loop_timeout.expired():
                    raise SerialError('Timeout occurred waiting for message status')
                time.sleep(self._RETRY_DELAY)
            elif self.urc_state == Modem.SOCKET_CLOSED:
                return '[1,0]' #this is connection closed for hologram cloud response

        return self.read_socket()
 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 not self.is_open:
         raise PortNotOpenError()
     read = bytearray()
     timeout = Timeout(self._timeout)
     while len(read) < size:
         try:
             ready, _, _ = select.select([self._socket], [], [],
                                         timeout.time_left())
             # If select was used with a timeout, and the timeout occurs, it
             # returns with empty lists -> thus abort read operation.
             # For timeout == 0 (non-blocking operation) also abort when
             # there is nothing to read.
             if not ready:
                 break  # timeout
             buf = self._socket.recv(size - len(read))
             # read should always return some data as select reported it was
             # ready to read when we get to this point, unless it is EOF
             if not buf:
                 raise SerialException('socket disconnected')
             read.extend(buf)
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY,
                                errno.EWOULDBLOCK, errno.EINPROGRESS,
                                errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         except (select.error, socket.error) as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY,
                             errno.EWOULDBLOCK, errno.EINPROGRESS,
                             errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         if timeout.expired():
             break
     return bytes(read)
Exemple #12
0
 def write(self, data):
     """Output the given byte string over the serial port."""
     if not self.is_open:
         raise portNotOpenError
     d = to_bytes(data)
     tx_len = len(d)
     timeout = Timeout(self._write_timeout)
     while tx_len > 0:
         try:
             n = os.write(self.fd, d)
             if timeout.is_non_blocking:
                 # Zero timeout indicates non-blocking - simply return the
                 # number of bytes of data actually written
                 return n
             elif not timeout.is_infinite:
                 # when timeout is set, use select to wait for being ready
                 # with the time left as timeout
                 if timeout.expired():
                     raise writeTimeoutError
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
                 if abort:
                     os.read(self.pipe_abort_write_r, 1000)
                     break
                 if not ready:
                     raise writeTimeoutError
             else:
                 assert timeout.time_left() is None
                 # wait for write operation
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
                 if abort:
                     os.read(self.pipe_abort_write_r, 1)
                     break
                 if not ready:
                     raise SerialException('write failed (select)')
             d = d[n:]
             tx_len -= n
         except SerialException:
             raise
         except OSError as v:
             if v.errno != errno.EAGAIN:
                 raise SerialException('write failed: {}'.format(v))
             # still calculate and check timeout
             if timeout.expired():
                 raise writeTimeoutError
     return len(data)
 def write(self, data):
     """Output the given byte string over the serial port."""
     if not self.is_open:
         raise portNotOpenError
     d = to_bytes(data)
     tx_len = len(d)
     timeout = Timeout(self._write_timeout)
     while tx_len > 0:
         try:
             n = os.write(self.fd, d)
             if timeout.is_non_blocking:
                 # Zero timeout indicates non-blocking - simply return the
                 # number of bytes of data actually written
                 return n
             elif not timeout.is_infinite:
                 # when timeout is set, use select to wait for being ready
                 # with the time left as timeout
                 if timeout.expired():
                     raise writeTimeoutError
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeout.time_left())
                 if abort:
                     os.read(self.pipe_abort_write_r, 1000)
                     break
                 if not ready:
                     raise writeTimeoutError
             else:
                 assert timeout.time_left() is None
                 # wait for write operation
                 abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], None)
                 if abort:
                     os.read(self.pipe_abort_write_r, 1)
                     break
                 if not ready:
                     raise SerialException('write failed (select)')
             d = d[n:]
             tx_len -= n
         except SerialException:
             raise
         except OSError as v:
             if v.errno != errno.EAGAIN:
                 raise SerialException('write failed: {}'.format(v))
             # still calculate and check timeout
             if timeout.expired():
                 raise writeTimeoutError
     return len(data)
Exemple #14
0
    def read(self, size=1):
        if not self.is_open:
            raise portNotOpenError

        data = bytearray()
        try:
            timeout = Timeout(self._timeout)
            while len(data) < size:
                if self._thread is None:
                    raise SerialException(
                        'connection failed (reader thread died)')
                buf = self._read_buffer.get(True, timeout.time_left())
                if buf is None:
                    return bytes(data)
                data += buf
                if timeout.expired():
                    break
        except Queue.Empty:  # -> timeout
            pass
        return bytes(data)
 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 not self.is_open:
         raise portNotOpenError
     read = bytearray()
     timeout = Timeout(self._timeout)
     while len(read) < size:
         try:
             ready, _, _ = select.select([self._socket], [], [], timeout.time_left())
             # If select was used with a timeout, and the timeout occurs, it
             # returns with empty lists -> thus abort read operation.
             # For timeout == 0 (non-blocking operation) also abort when
             # there is nothing to read.
             if not ready:
                 break   # timeout
             buf = self._socket.recv(size - len(read))
             # read should always return some data as select reported it was
             # ready to read when we get to this point, unless it is EOF
             if not buf:
                 raise SerialException('socket disconnected')
             read.extend(buf)
         except OSError as e:
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             if e.errno not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         except (select.error, socket.error) as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY, errno.EWOULDBLOCK, errno.EINPROGRESS, errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         if timeout.expired():
             break
     return bytes(read)
Exemple #16
0
    def read(self, size=1):
        '''Read data from the serial port.
        
        Parameters:
            size (int): the number of data bytes to read.
    
        Returns:
            read (bytes): data bytes read from the serial port. 
        '''
        read = bytearray()
        timeout = Timeout(self.timeout)

        # If there is enough data in the buffer, do not bother to read.
        if len(self._read_buffer) < size:
            # Keep reading until there is enough data or timeout.
            while self.in_waiting < size:
                if timeout.expired():
                    break

        # Get data from read buffer.
        read = self._read_buffer[:size]
        self._read_buffer = self._read_buffer[size:]

        return bytes(read)
Exemple #17
0
    def _wait_for_response(self, servo_id, command, timeout=None):
        timeout = Timeout(timeout or self._timeout)

        def read(size=1):
            self._serial.timeout = timeout.time_left()
            data = self._serial.read(size)
            if len(data) != size:
                raise TimeoutError()
            return data

        while True:
            data = []
            data += read(1)
            if data[-1] != 0x55:
                continue
            data += read(1)
            if data[-1] != 0x55:
                continue
            data += read(3)
            sid = data[2]
            length = data[3]
            cmd = data[4]
            if length > 7:
                print('Invalid length for packet %s', list(data), flush=True)
                continue

            data += read(length - 3) if length > 3 else []
            params = data[5:]
            data += read(1)
            checksum = data[-1]
            if 255 - (sid + length + cmd + sum(params)) % 256 != checksum:
                print('Invalid checksum for packet %s', list(data), flush=True)
                continue

            if cmd != command:
                print('Got unexpected command %s response %s',
                      cmd,
                      list(data),
                      flush=True)
                continue

            if servo_id != SERVO_ID_ALL and sid != servo_id:
                print('Got command response from unexpected servo %s',
                      sid,
                      flush=True)
                continue
            break
        return [sid, cmd, *params]
    def _wait_for_response(self, servo_id, command, timeout=None):
        timeout = Timeout(timeout or self._timeout)

        # As Tx and Rx are tied together, clear the receive buffer to get rid of our last outbound packet.
        self._serial.flushInput()
        
        def read(size=1):
            self._serial.timeout = timeout.time_left()
            data = self._serial.read(size)
            if len(data) != size:
                raise TimeoutError()
            return data

        while True:
            data = []
            data += read(1)
            if data[-1] != 0x55:
                continue
            data += read(1)
            if data[-1] != 0x55:
                continue
            data += read(3)
            sid = data[2]
            length = data[3]
            cmd = data[4]
            if length > 7:
                LOGGER.error('Invalid length for packet %s', list(data))
                continue

            data += read(length-3) if length > 3 else []
            params = data[5:]
            data += read(1)
            checksum = data[-1]
            if 255-(sid + length + cmd + sum(params)) % 256 != checksum:
                LOGGER.error('Invalid checksum for packet %s', list(data))
                continue

            if cmd != command:
                LOGGER.warning('Got unexpected command %s response %s',
                               cmd, list(data))
                continue

            if servo_id != SERVO_ID_ALL and sid != servo_id:
                LOGGER.warning('Got command response from unexpected servo %s', sid)
                continue
            return [sid, cmd, *params]
Exemple #19
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 not self.is_open:
         raise portNotOpenError
     read = bytearray()
     timeout = Timeout(self._timeout)
     while len(read) < size:
         try:
             ready, _, _ = select.select([self.fd, self.pipe_abort_read_r],
                                         [], [], timeout.time_left())
             if self.pipe_abort_read_r in ready:
                 os.read(self.pipe_abort_read_r, 1000)
                 break
             # If select was used with a timeout, and the timeout occurs, it
             # returns with empty lists -> thus abort read operation.
             # For timeout == 0 (non-blocking operation) also abort when
             # there is nothing to read.
             if not ready:
                 break  # timeout
             buf = os.read(self.fd, size - len(read))
             # read should always return some data as select reported it was
             # ready to read when we get to this point.
             if not buf:
                 # Disconnected devices, at least on Linux, show the
                 # behavior that they are always ready to read immediately
                 # but reading returns nothing.
                 raise SerialException(
                     'device reports readiness to read but returned no data '
                     '(device disconnected or multiple access on port?)')
             read.extend(buf)
         except OSError as e:
             # Devices connecting through a poor USB/Serial cable or an
             # underpowered USB hub can spontaneously disconnect from
             # the OS, and promptly reconnect.  If this happens, attempt
             # to reopen the device and continue the session.
             if e.errno == errno.ENXIO:
                 retryTimeout = Timeout(2)  # Allow for a short grace period
                 sys.stderr.write(
                     'pySerial WARNING: Serial device disappeared! '
                     '...Trying to reconnect...\n')
                 sys.stderr.write(
                     'pySerial WARNING: If this problem is chronic '
                     'replace your cable/powered USB HUB.\n')
                 sys.stderr.flush()
                 self.close()
                 while self.fd == None:
                     try:
                         self.open()
                     except OSError as e:
                         if e.errno != errno.ENOENT or retryTimeout.expired(
                         ):
                             raise SerialException(
                                 'Serial device gone: {}'.format(e))
                 break
             # this is for Python 3.x where select.error is a subclass of
             # OSError ignore BlockingIOErrors and EINTR. other errors are shown
             # https://www.python.org/dev/peps/pep-0475.
             elif e.errno not in (errno.EAGAIN, errno.EALREADY,
                                  errno.EWOULDBLOCK, errno.EINPROGRESS,
                                  errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         except select.error as e:
             # this is for Python 2.x
             # ignore BlockingIOErrors and EINTR. all errors are shown
             # see also http://www.python.org/dev/peps/pep-3151/#select
             if e[0] not in (errno.EAGAIN, errno.EALREADY,
                             errno.EWOULDBLOCK, errno.EINPROGRESS,
                             errno.EINTR):
                 raise SerialException('read failed: {}'.format(e))
         if timeout.expired():
             break
     return bytes(read)
Exemple #20
0
    def GetBufferTillPattern(self, ExpectedPrompt=None, timeOutSeconds=10.0, send_new_line_on_timeout=True):
        """
        this method tries to capture buffer till the termination sequence (prompt) is captured
        or until the timeout has passed, return True if succeeded to capture prompt and False if timeout has passed
        it also flushes its also flushes it self history buffer and fills it with all info for this session
        :param ExpectedPrompt:
        :type ExpectedPrompt: String Or Regex
        :param timeOutSeconds:
        :type timeOutSeconds: float
        :return: bool
        :rtype: bool
        """
        if ExpectedPrompt is None:
            ExpectedPrompt = self.shellPrompt

        result = False
        try:
            getbufferTimeout = self.get_buffer_till_pattern_interval
            self.lastBufferTillPrompt = ""
            # type: (re, float) -> bool ,
            # handle case where expected prompt is str
            res_ExpectedPrompt = None

            if isinstance(ExpectedPrompt, str):
                # if PY3:
                #     res_ExpectedPrompt = re.compile(str(ExpectedPrompt).encode('utf-8'), re.IGNORECASE)
                # else:
                    res_ExpectedPrompt = re.compile(str(ExpectedPrompt), re.IGNORECASE)
            elif type(ExpectedPrompt) == self.reType:
                res_ExpectedPrompt = ExpectedPrompt

            # self.SetShellPrompt("Console#")
            # buff = CommunicationManagement.GetBufferTillPrompt(self.connAlias)
            timeout = Timeout(timeOutSeconds)
            while not result:
                buff = self.GetBuffer(getbufferTimeout)
                if buff is not None and buff != "":
                    self.lastBufferTillPrompt += buff
                    if not self.cli_print_mode:
                        self.LogToTestLogger(buff)
                    if re.search(res_ExpectedPrompt, buff):
                        result = True
                        if self.cli_print_mode:
                            self.LogToTestLogger(self.lastBufferTillPrompt)
                        break

                if timeout.expired():
                    if send_new_line_on_timeout:
                        # send newline char and try 1 final time, if still didn't succeed then give up
                        msg = "timeout expired\nsending newline char and trying 1 last time"
                        self.LogToTestLogger(msg,force_format=True)
                        self.SendCommand(self.newlineChar, AppendNewLine=False)
                        buff = self.GetBuffer(getbufferTimeout)
                        if buff is not None and buff != "":
                            if not self.cli_print_mode:
                                self.LogToTestLogger(buff)
                            self.lastBufferTillPrompt += buff
                            if re.search(res_ExpectedPrompt, self.lastBufferTillPrompt):
                                result = True
                    if self.cli_print_mode:
                        self.LogToTestLogger(self.lastBufferTillPrompt)

                    break

                # TODO:handle event of user prompt - implement login() function
                # got emtpy string
                # if not buff:
                #     self.SendCommand(self.newlineChar)

        except ConnectionLostException as e:
            if self._handle_connection_lost(not self._is_inner_call, e, cmd_str=ExpectedPrompt):
                # If the user handled the event we want to run the cmd again
                return self.GetBufferTillPattern(ExpectedPrompt, timeOutSeconds, send_new_line_on_timeout)
        except Exception as e:
            self.LogToTestLogger(str(e),force_format=True)
            # print str(e)

        finally:
            return result
Exemple #21
0
    def GetAllMatchedPatternsInBuffer(self, patterns_list, timeOutSeconds=10.0, sendNewlineBetweenAttempts=False):
        """
        this method tries to capture buffer till any of the termination sequences(prompts) provided in patterns_list
       or until the timeout has passed, return True if succeeded to capture prompt and False if timeout has passed
       it also flushes its self history buffer and fills it with all info for this session
       :param patterns_list: list of patterns to search in the buffer
       :type patterns_list: list[str]
       :param timeOutSeconds: timeout for search
       :type timeOutSeconds: float
       :param sendNewlineBetweenAttempts: indicate if to send newline between attempts to capture expected pattern
       :type sendNewlineBetweenAttempts: bool
       :return: pattern list of found patterns or None if no pattern was found before timeout
       :rtype: list[str]
       """
        if type(patterns_list) is not list:
            raise TypeError("GetAllMatchedPatternsInBuffer: the type of patterns_list is not list but "
                            "type {}".format(str(type(patterns_list))))
        # inner function to search multiple patterns
        def search_all(listofpatterns, buffer):
            retlist = []
            if buffer:
                for pattern in listofpatterns:
                    if re.search(pattern,buffer):
                        retlist.append(pattern)
            return retlist

        result = None
        found_prompts = None
        try:
            getbufferTimeout = 0.1
            self.lastBufferTillPrompt = ""
            timeout = Timeout(timeOutSeconds)
            while not result:
                if sendNewlineBetweenAttempts:
                    self.SendCommand(self.newlineChar, AppendNewLine=False)
                buff = self.GetBuffer(getbufferTimeout)
                if buff is not None and buff != "":
                    if not self.cli_print_mode:
                        self.LogToTestLogger(buff)
                    self.lastBufferTillPrompt += buff
                    found_prompts = search_all(patterns_list, buff)
                    if found_prompts:
                        if self.cli_print_mode:
                            self.LogToTestLogger(self.lastBufferTillPrompt)
                        result = True
                        break
                if timeout.expired():
                    # send newline char and try 1 final time, if still didn't succeed then give up
                    msg = "timeout expired\nsending newline char and trying 1 last time"
                    self.LogToTestLogger(msg,force_format=True)
                    self.SendCommand(self.newlineChar,AppendNewLine=False)
                    buff = self.GetBuffer(getbufferTimeout)
                    if buff is not None and buff != "":
                        if not self.cli_print_mode:
                            self.LogToTestLogger(buff)
                        self.lastBufferTillPrompt += buff
                        found_prompts = search_all(patterns_list , buff)
                        if not not found_prompts:
                            if self.cli_print_mode:
                                self.LogToTestLogger(self.lastBufferTillPrompt)
                            result = True
                    break

                # got emtpy string
                # if not buff:
                #     self.SendCommand(self.newlineChar)

        except Exception as e:
            self.LogToTestLogger(str(e),force_format=True)
            # print str(e)

        finally:
            return found_prompts