def open(self): """\ Open port with current settings. This may throw a SerialException if the port cannot be opened.""" if self._port is None: raise SerialException("Port must be configured before it can be used.") if self.is_open: raise SerialException("Port is already open.") self.fd = None # open try: self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK) except OSError as msg: self.fd = None raise SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg)) #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking try: self._reconfigure_port(force_update=True) except: try: os.close(self.fd) except: # ignore any exception when closing the port # also to keep original exception that happened when setting up pass self.fd = None raise else: self.is_open = True if not self._dsrdtr: self._update_dtr_state() if not self._rtscts: self._update_rts_state() self.reset_input_buffer()
def open(self): """\ Open port with current settings. This may throw a SerialException if the port cannot be opened. """ self.logger = None if self._port is None: raise SerialException("Port must be configured before it can be used.") if self.is_open: raise SerialException("Port is already open.") try: self._socket = socket.create_connection(self.from_url(self.portstr)) except Exception as msg: self._socket = None raise SerialException("Could not open port %s: %s" % (self.portstr, msg)) self._socket.settimeout(POLL_TIMEOUT) # used for write timeout support :/ # not that there anything to configure... self._reconfigure_port() # all things set up get, now a clean start self.is_open = True if not self._dsrdtr: self._update_dtr_state() if not self._rtscts: self._update_rts_state() self.reset_input_buffer() self.reset_output_buffer()
def test_interrupt(self, serial_readline_mock, serial_open_mock): """ Test whether interrupts are handled. """ serial_open_mock.return_value = None # First call raises expected exception, second call should just return data. eintr_error = SerialException( 'read failed: [Errno 4] Interrupted system call') serial_readline_mock.side_effect = [eintr_error ] + self._dsmr_dummy_data() self.assertFalse(DsmrReading.objects.exists()) self._intercept_command_stdout('dsmr_datalogger') self.assertTrue(DsmrReading.objects.exists()) # Everything else should be reraised. serial_readline_mock.side_effect = SerialException( 'Unexpected error from Serial') DsmrReading.objects.all().delete() self.assertFalse(DsmrReading.objects.exists()) with self.assertRaises(SerialException): self._intercept_command_stdout('dsmr_datalogger') self.assertFalse(DsmrReading.objects.exists())
def open(self): """\ Open port with current settings. This may throw a SerialException if the port cannot be opened. """ if self.is_open: raise SerialException("Port is already open.") self.logger = None self.queue = queue.Queue(self.buffer_size) if self._port is None: raise SerialException( "Port must be configured before it can be used.") # not that there is anything to open, but the function applies the # options found in the URL self.from_url(self.port) # not that there anything to configure... self._reconfigure_port() # all things set up get, now a clean start self.is_open = True if not self._dsrdtr: self._update_dtr_state() if not self._rtscts: self._update_rts_state() self.reset_input_buffer() self.reset_output_buffer()
def reset_input_buffer(self): """Clear input buffer, discarding all that is in the buffer.""" if not self.is_open: raise portNotOpenError # just use recv to remove input, while there is some ready = True while ready: ready, _, _ = select.select([self._socket], [], [], 0) try: self._socket.recv(4096) 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))
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) if self._write_timeout is not None and self._write_timeout > 0: timeout = time.time() + self._write_timeout else: timeout = None while tx_len > 0: try: n = os.write(self.fd, d) if timeout: # when timeout is set, use select to wait for being ready # with the time left as timeout timeleft = timeout - time.time() if timeleft < 0: raise writeTimeoutError _, ready, _ = select.select([], [self.fd], [], timeleft) if not ready: raise writeTimeoutError else: # wait for write operation _, ready, _ = select.select([], [self.fd], [], None) 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: %s' % (v,)) return len(data)
def from_url(self, url): """extract host and port from an URL string""" parts = urlparse.urlsplit(url) if parts.scheme != "socket": raise SerialException( 'expected a string in the form ' '"socket://<host>:<port>[?logging={debug|info|warning|error}]": ' 'not starting with socket:// ({!r})'.format(parts.scheme)) try: # process options now, directly altering self for option, values in urlparse.parse_qs(parts.query, True).items(): if option == 'logging': logging.basicConfig() # XXX is that good to call it here? self.logger = logging.getLogger('pySerial.socket') self.logger.setLevel(LOGGER_LEVELS[values[0]]) self.logger.debug('enabled logging') else: raise ValueError('unknown option: {!r}'.format(option)) if not 0 <= parts.port < 65536: raise ValueError("port not in range 0...65535") except ValueError as e: raise SerialException( 'expected a string in the form ' '"socket://<host>:<port>[?logging={debug|info|warning|error}]": {}' .format(e)) return (parts.hostname, parts.port)
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 open(self): if self._port is None: raise SerialException( "Port must be configured before it can be used.") if self.is_open: raise SerialException("Port is already open.") self._read_buffer = Queue.Queue() self._hid_handle = hid.device() try: portpath = self.from_url(self.portstr) self._hid_handle.open_path(portpath) except OSError as msg: raise SerialException( msg.errno, "could not open port {}: {}".format(self._port, msg)) try: self._reconfigure_port() except: try: self._hid_handle.close() except: pass self._hid_handle = None raise else: self.is_open = True self._thread = threading.Thread(target=self._hid_read_loop) self._thread.setDaemon(True) self._thread.setName('pySerial CP2110 reader thread for {}'.format( self._port)) self._thread.start()
def _open_interface(self): device = self._device log.debug("claiming interfaces, count={}".format( device.getInterfaceCount())) self._control_interface = device.getInterface(0) log.debug("Control iface={}".format(self._control_interface)) if not self._connection.claimInterface(self._control_interface, True): raise SerialException("Could not claim control interface") self._control_endpoint = self._control_interface.getEndpoint(0) log.debug("Control endpoint direction: {}".format( self._control_endpoint.getDirection())) log.debug("Claiming data interface.") self._data_interface = device.getInterface(1) log.debug("data iface={}".format(self._data_interface)) if not self._connection.claimInterface(self._data_interface, True): raise SerialException("Could not claim data interface") self._read_endpoint = self._data_interface.getEndpoint(1) log.debug("Read endpoint direction: {}".format( self._read_endpoint.getDirection())) self._write_endpoint = self._data_interface.getEndpoint(0) log.debug("Write endpoint direction: {}".format( self._write_endpoint.getDirection()))
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._port_handle: raise portNotOpenError if size > 0: win32.ResetEvent(self._overlapped_read.hEvent) flags = win32.DWORD() comstat = win32.COMSTAT() if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)): raise SerialException('call to ClearCommError failed') n = min(comstat.cbInQue, size) if self.timeout == 0 else size if n > 0: buf = ctypes.create_string_buffer(n) rc = win32.DWORD() read_ok = win32.ReadFile(self._port_handle, buf, n, ctypes.byref(rc), ctypes.byref(self._overlapped_read)) if not read_ok and win32.GetLastError() not in ( win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING): raise SerialException("ReadFile failed (%r)" % ctypes.WinError()) win32.GetOverlappedResult(self._port_handle, ctypes.byref(self._overlapped_read), ctypes.byref(rc), True) read = buf.raw[:rc.value] else: read = bytes() else: read = bytes() return bytes(read)
def open_conn(self) -> None: """ Open serial port :return: None """ modi_ports = list_modi_ports() if not modi_ports: raise SerialException("No MODI network module is available") if self.__port: if self.__port not in map(lambda info: info.device, modi_ports): raise SerialException(f"{self.__port} is not connected " f"to a MODI network module.") else: try: self._bus = self.__init_serial(self.__port) self._bus.open() return except SerialException: raise SerialException(f"{self.__port} is not available.") for modi_port in modi_ports: self._bus = self.__init_serial(modi_port.device) try: self._bus.open() print(f'Serial is open at "{modi_port}"') return except SerialException: continue raise SerialException("No MODI port is available now")
def open(self): """\ Open port with current settings. This may throw a SerialException if the port cannot be opened. """ self.logger = None if self._port is None: raise SerialException("Port must be configured before it can be used.") if self.is_open: raise SerialException("Port is already open.") try: # timeout is used for write timeout support :/ and to get an initial connection timeout self._socket = socket.create_connection(self.from_url(self.portstr), timeout=POLL_TIMEOUT) except Exception as msg: self._socket = None raise SerialException("Could not open port {}: {}".format(self.portstr, msg)) # after connecting, switch to non-blocking, we're using select self._socket.setblocking(False) # not that there is anything to configure... self._reconfigure_port() # all things set up get, now a clean start self.is_open = True if not self._dsrdtr: self._update_dtr_state() if not self._rtscts: self._update_rts_state() self.reset_input_buffer() self.reset_output_buffer()
def _set_break(self, break_): '''Start or stop a break exception event on the serial line. Parameters: break_ (bool): either start or stop break event. ''' ch34x_break_reg = (self.CH34X_REG_LCR << 8) | self.CH34X_REG_BREAK break_reg = bytearray(2) if self._ctrl_transfer_in(self.CH34X_REQ_READ_REG, ch34x_break_reg, 0, break_reg) < 0: raise SerialException('Unable to read break state!') if break_: break_reg[0] &= (~self.CH34X_NBREAK_BITS) break_reg[1] &= (~self.CH34X_LCR_ENABLE_TX) else: break_reg[0] |= self.CH34X_NBREAK_BITS break_reg[1] |= self.CH34X_LCR_ENABLE_TX #Unpack break_reg into int reg_contents = break_reg[1] * 256 + break_reg[0] if self._ctrl_transfer_out(self.CH34X_REQ_WRITE_REG, ch34x_break_reg, reg_contents) < 0: raise SerialException('Unable to set break state!')
def open(self): '''Open the serial port. When the serial port is instantiated, it will try to open automatically. ''' self.close() device = usb.get_usb_device(self.portstr) if not device: raise SerialException("Device not present {}".format(self.portstr)) if not usb.has_usb_permission(device): usb.request_usb_permission(device) return connection = usb.get_usb_manager().openDevice(device) if not connection: raise SerialException("Failed to open device!") self._device = device self._connection = connection raw_descriptors = self._connection.getRawDescriptors() self._bcd_device = raw_descriptors[12] + raw_descriptors[13] * 256 for i in range(self._device.getInterfaceCount()): if i == 0: self._interface = self._device.getInterface(i) if not self._connection.claimInterface( self._device.getInterface(i), True): raise SerialException( "Could not claim interface {}.".format(i)) self._index = self._interface.getId() + 1 for i in range(self._interface.getEndpointCount()): ep = self._interface.getEndpoint(i) if ( (ep.getDirection() == usb.UsbConstants.USB_DIR_IN) \ and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_INT) ): self._control_endpoint = ep elif ( (ep.getDirection() == usb.UsbConstants.USB_DIR_IN) \ and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK) ): self._read_endpoint = ep elif ( (ep.getDirection() == usb.UsbConstants.USB_DIR_OUT) \ and (ep.getType() == usb.UsbConstants.USB_ENDPOINT_XFER_BULK) ): self._write_endpoint = ep # Check that all endpoints are good if None in [self._write_endpoint, self._read_endpoint]: raise SerialException("Could not establish all endpoints!") self.is_open = True self._reconfigure_port()
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 elif self._inter_byte_timeout is not None and self._inter_byte_timeout > 0: #atleast one char received --> overwrite timeout by setting it to inter_byte_timeout timeout = Timeout(self._inter_byte_timeout) return bytes(read)
def _set_line_property(self, bits, stopbits, parity): '''Set serial port line property. Parameters: bits (int): number of bits in data(5, 6, 7 or 8). stopbits (float): number of stop bits(1, 1.5, 2). parity (str): 'N', 'E', 'O', 'M' or 'S'. ''' lcr = self.CH34X_LCR_ENABLE_RX | self.CH34X_LCR_ENABLE_TX if bits == 5: lcr |= self.CH34X_LCR_CS5 elif bits == 6: lcr |= self.CH34X_LCR_CS6 elif bits == 7: lcr |= self.CH34X_LCR_CS7 elif bits == 8: lcr |= self.CH34X_LCR_CS8 else: raise ValueError('Unknown bits value: {}'.format(bits)) if parity == 'N': pass elif parity == 'O': lcr |= (self.CH34X_LCR_ENABLE_PAR) elif parity == 'E': lcr |= (self.CH34X_LCR_ENABLE_PAR | self.CH34X_LCR_PAR_EVEN) elif parity == 'M': lcr |= (self.CH34X_LCR_ENABLE_PAR | self.CH34X_LCR_MARK_SPACE) elif parity == 'S': lcr |= ( self.CH34X_LCR_ENABLE_PAR \ | self.CH34X_LCR_MARK_SPACE \ | self.CH34X_LCR_PAR_EVEN ) else: raise ValueError('Unknown parity value: {}'.format(parity)) if stopbits == 1: pass elif stopbits == 1.5: pass elif stopbits == 2: lcr |= self.CH34X_LCR_STOP_BITS_2 else: raise ValueError('Unknown stopbits value: {}'.format(stopbits)) if self._ctrl_transfer_out(self.CH34X_REQ_WRITE_REG, 0x2518, lcr) < 0: raise SerialException('Setting line property failed!') self._check_state('Set parity', self.CH34X_REQ_READ_REG, 0x0706, [0x9f, 0xee]) if self._ctrl_transfer_out(self.CH34X_REQ_WRITE_REG, 0x2727, 0) < 0: raise SerialException('Fail to set line property!') self._lineprop = lcr
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 = self._timeout while len(read) < size: try: start_time = time.time() ready, _, _ = select.select([self.fd, self.pipe_abort_read_r], [], [], timeout) 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 EAGAIN errors. all other errors are shown if e.errno != errno.EAGAIN and e.errno != errno.EINTR: raise SerialException('read failed: {}'.format(e)) except select.error as e: # this is for Python 2.x # ignore EAGAIN errors. all other errors are shown # see also http://www.python.org/dev/peps/pep-3151/#select if e[0] != errno.EAGAIN: raise SerialException('read failed: {}'.format(e)) if timeout is not None: timeout -= time.time() - start_time if timeout <= 0: break return bytes(read)
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 = self._write_timeout if timeout and timeout > 0: # Avoid comparing None with zero timeout += time.time() while tx_len > 0: try: n = os.write(self.fd, d) if timeout == 0: # Zero timeout indicates non-blocking - simply return the # number of bytes of data actually written return n elif timeout and timeout > 0: # Avoid comparing None with zero # when timeout is set, use select to wait for being ready # with the time left as timeout timeleft = timeout - time.time() if timeleft < 0: raise writeTimeoutError abort, ready, _ = select.select([self.pipe_abort_write_r], [self.fd], [], timeleft) if abort: os.read(self.pipe_abort_write_r, 1000) break if not ready: raise writeTimeoutError else: assert timeout 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 and timeout - time.time() < 0: raise writeTimeoutError return len(data)
def _init_device(self): if self._ctrl_transfer_out(0xa1, 0xc29c, 0xb2b9) < 0: raise SerialException('Init failed! #1') if self._ctrl_transfer_out(0xa4, 0xdf, 0) < 0: raise SerialException('Init failed! #2') if self._ctrl_transfer_out(0xa4, 0x9f, 0) < 0: raise SerialException('Init failed! #3') self._check_state('Init #4', self.CH34X_REQ_READ_REG, 0x0706, [0x9f, 0xee]) if self._ctrl_transfer_out(0x9a, 0x2727, 0x0000) < 0: raise SerialException('Init failed! #5') if self._ctrl_transfer_out(0x9a, 0x1312, 0xb282) < 0: raise SerialException('Init failed! #6') if self._ctrl_transfer_out(0x9a, 0x0f2c, 0x0008) < 0: raise SerialException('Init failed! #7') if self._ctrl_transfer_out(0x9a, 0x2518, 0x00c3) < 0: raise SerialException('Init failed! #8') self._check_state('Init #9', self.CH34X_REQ_READ_REG, 0x0706, [0x9f, 0xee]) if self._ctrl_transfer_out(0x9a, 0x2727, 0x0000) < 0: raise SerialException('Init failed! #10')
def _set_break(self, break_): '''Start or stop a break exception event on the serial line. Parameters: break_ (bool): either start or stop break event. ''' if break_: if self._ctrl_transfer_out(self.CP210X_SET_BREAK, self.BREAK_ON) < 0: raise SerialException('Unable to start break sequence') else: if self._ctrl_transfer_out(self.CP210X_SET_BREAK, self.BREAK_OFF) < 0: raise SerialException('Unable to stop break sequence')
def _set_break(self, break_): '''Start or stop a break exception event on the serial line. Parameters: break_ (bool): either start or stop break event. ''' if break_: value = self._lineprop | (0x01 << 14) if self._ctrl_transfer_out(self.SIO_SET_DATA, value, self._index): raise SerialException('Unable to start break sequence') else: value = self._lineprop & ~(0x01 << 14) if self._ctrl_transfer_out(self.SIO_SET_DATA, value, self._index): raise SerialException('Unable to stop break sequence') self._lineprop = value
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 = self._timeout while len(read) < size: try: start_time = time.time() ready, _, _ = select.select([self._socket], [], [], timeout) # 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) if timeout is not None: timeout -= time.time() - start_time if timeout <= 0: break except socket.timeout: # timeout is used for write support, just go reading again pass except socket.error as e: # connection fails -> terminate loop raise SerialException('connection failed (%s)' % e) except OSError as e: # this is for Python 3.x where select.error is a subclass of # OSError ignore EAGAIN errors. all other errors are shown if e.errno != errno.EAGAIN: raise SerialException('read failed: %s' % (e, )) except select.error as e: # this is for Python 2.x # ignore EAGAIN errors. all other errors are shown # see also http://www.python.org/dev/peps/pep-3151/#select if e[0] != errno.EAGAIN: raise SerialException('read failed: %s' % (e, )) return bytes(read)
def write(self, data): """Output the given byte string over the serial port.""" if not self.is_open: raise portNotOpenError #~ if not isinstance(data, (bytes, bytearray)): #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data))) # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview data = to_bytes(data) if data: #~ win32event.ResetEvent(self._overlapped_write.hEvent) n = win32.DWORD() err = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write) if not err and win32.GetLastError() != win32.ERROR_IO_PENDING: raise SerialException("WriteFile failed ({!r})".format( ctypes.WinError())) if self._write_timeout != 0: # if blocking (None) or w/ write timeout (>0) # Wait for the write to complete. #~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE) err = win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True) if win32.GetLastError() == win32.ERROR_OPERATION_ABORTED: return n.value # canceled IO is no error if n.value != len(data): raise writeTimeoutError return n.value else: return 0
def _set_baudrate(self, baudrate): '''Change the current UART baudrate. The FTDI device is not able to use an arbitrary baudrate. Its internal dividors are only able to achieve some baudrates. It attemps to find the closest configurable baudrate and if the deviation from the requested baudrate is too high, it rejects the configuration. Parameters: baudrate (int): the new baudrate for the UART. Raises: ValueError: if deviation from selected baudrate is too large. SerialException: if not able to set baudrate. ''' actual, value, index = self._convert_baudrate(baudrate) delta = 100 * abs(float(actual - baudrate)) / baudrate if delta > self.BAUDRATE_TOLERANCE: raise ValueError('Baudrate tolerance exceeded: %.02f%% ' '(wanted %d, achievable %d)' % (delta, baudrate, actual)) result = self._ctrl_transfer_out(self.SIO_SET_BAUDRATE, value, index) if result != 0: raise SerialException('Unable to set baudrate.')
def write(self, data): '''Write data to the serial port. Parameters: data (bytearray): data written to the serial port. Returns: wrote (int): the number of data bytes written. ''' if not self.is_open: return None offset = 0 timeout = int( self._write_timeout * 1000 if self._write_timeout \ else self.USB_WRITE_TIMEOUT_MILLIS ) wrote = 0 while offset < len(data): data_length = min( len(data) - offset, self.DEFAULT_WRITE_BUFFER_SIZE) buf = data[offset:offset + data_length] i = self._connection.bulkTransfer(self._write_endpoint, buf, data_length, timeout) if i <= 0: raise SerialException("Failed to write {}: {}".format(buf, i)) offset += data_length wrote += i return wrote
def reset(self): '''Reset the serial port.''' if self._connection: result = self._ctrl_transfer_out(self.SIO_RESET, self.SIO_RESET_SIO, self._index) if result != 0: raise SerialException("Reset failed: result={}".format(result))
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 data = bytearray() if self._timeout is not None: timeout = time.time() + self._timeout else: timeout = None while len(data) < size: try: # an implementation with internal buffer would be better # performing... block = self._socket.recv(size - len(data)) if block: data.extend(block) else: # no data -> EOF (connection probably closed) break except socket.timeout: # just need to get out of recv from time to time to check if # still alive and timeout did not expire pass except socket.error as e: # connection fails -> terminate loop raise SerialException('connection failed (%s)' % e) if timeout is not None and time.time() > timeout: break return bytes(data)
def out_waiting(self): """Return how many bytes the in the outgoing buffer""" flags = win32.DWORD() comstat = win32.COMSTAT() if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)): raise SerialException('call to ClearCommError failed') return comstat.cbOutQue
def in_waiting(self): """Return the number of bytes currently in the input buffer.""" flags = win32.DWORD() comstat = win32.COMSTAT() if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)): raise SerialException('call to ClearCommError failed') return comstat.cbInQue