def test_hooked_io(handler): protocol_hooked.Serial = HookedSerialHandler ser = rs232.SerialData(port='hooked://', open_delay=0) # Peek inside, it should have a PySerial instance as member ser. assert ser.ser assert ser.ser.__class__.__name__ == 'HookedSerialHandler' print(str(ser.ser)) # Open is automatically called by SerialData. assert ser.is_connected # Can read many identical lines from ser. first_line = None for n in range(20): line = ser.read(retry_delay=10, retry_limit=20) if first_line: assert line == first_line else: first_line = line assert 'message' in line reading = ser.get_reading() assert reading[1] == line # Can write to the "device" many times. line = 'abcdefghijklmnop' * 30 line = line + '\r\n' for n in range(20): assert len(line) == ser.write(line) ser.disconnect() assert not ser.is_connected
def __init__(self, *args, **kwargs): """Initialize an AbstractSerialDome. Creates a serial connection to the port indicated in the config. """ super().__init__(*args, **kwargs) # Get config info, e.g. which port (e.g. /dev/ttyUSB123) should we use? # TODO(jamessynge): Switch to passing configuration of serial port in as a sub-section # of the dome config in the YAML. That way we don't intermingle serial settings and # any other settings required. cfg = self._dome_config self._port = cfg.get('port') if not self._port: msg = 'No port specified in the config for dome: {}'.format(cfg) self.logger.error(msg) raise error.DomeNotFound(msg=msg) baudrate = int(cfg.get('baudrate', 9600)) # Setup our serial connection to the given port. self.serial = None try: self.serial = rs232.SerialData(port=self._port, baudrate=baudrate) except Exception as err: raise error.DomeNotFound(err)
def test_detect_bogus_scheme(handler): """When our handlers are installed, will still detect unknown scheme.""" with pytest.raises(ValueError) as excinfo: # The scheme (the part before the ://) must be a Python module name, so use # a string that can't be a module name. rs232.SerialData(port='# bogus #://') assert '# bogus #' in repr(excinfo.value)
def test_basic_io(handler): protocol_buffers.ResetBuffers(b'abc\r\ndef\n') ser = rs232.SerialData(port='buffers://', open_delay=0.01, retry_delay=0.01, retry_limit=2) # Peek inside, it should have a BuffersSerial instance as member ser. assert isinstance(ser.ser, protocol_buffers.BuffersSerial) # Can read two lines. Read the first as a sensor reading: (ts, line) = ser.get_reading() assert 'abc\r\n' == line # Read the second line from the read buffer. assert 'def\n' == ser.read(retry_delay=0.1, retry_limit=10) # Another read will fail, having exhausted the contents of the read buffer. assert '' == ser.read() # Can write to the "device", the handler will accumulate the results. assert 5 == ser.write('def\r\n') assert 6 == ser.write('done\r\n') assert b'def\r\ndone\r\n' == protocol_buffers.GetWBufferValue() # If we add more to the read buffer, we can read again. protocol_buffers.SetRBufferValue(b'line1\r\nline2\r\ndangle') assert 'line1\r\n' == ser.read(retry_delay=10, retry_limit=20) assert 'line2\r\n' == ser.read(retry_delay=10, retry_limit=20) assert 'dangle' == ser.read(retry_delay=10, retry_limit=20) ser.disconnect() assert not ser.is_connected
def test_detect_uninstalled_scheme(): """If our handlers aren't installed, will detect unknown scheme.""" # See https://pythonhosted.org/pyserial/url_handlers.html#urls for info on the # standard schemes that are supported by PySerial. with pytest.raises(ValueError): # The no_op scheme references one of our test handlers, but it shouldn't be # accessible unless we've added our package to the list to be searched. rs232.SerialData(port='no_op://')
def test_non_existent_device(): """Doesn't complain if it can't find the device.""" port = '/dev/tty12345698765' ser = rs232.SerialData(port=port) assert not ser.is_connected assert port == ser.name # Can't connect to that device. with pytest.raises(error.BadSerialConnection): ser.connect() assert not ser.is_connected
def __init__(self, *args, **kwargs): """Initialize an AbstractSerialMount for the port defined in the config. Opens a connection to the serial device, if it is valid. """ super().__init__(*args, **kwargs) # Setup our serial connection at the given port try: serial_config = self.get_config('mount.serial') self.serial = rs232.SerialData(**serial_config) if self.serial.is_connected is False: raise error.MountNotFound("Can't open mount") except KeyError: self.logger.critical( 'No serial config specified, cannot create mount {}', self.get_config('mount')) except Exception as e: self.logger.critical(e)
def test_basic_no_op(handler): # Confirm we can create the SerialData object. ser = rs232.SerialData(port='no_op://', name='a name', open_delay=0) assert ser.name == 'a name' # Peek inside, it should have a NoOpSerial instance as member ser. assert ser.ser assert isinstance(ser.ser, NoOpSerial) # Open is automatically called by SerialData. assert ser.is_connected # connect() is idempotent. ser.connect() assert ser.is_connected # Several passes of reading, writing, disconnecting and connecting. for _ in range(3): # no_op handler doesn't do any reading, analogous to /dev/null, which # never produces any output. assert '' == ser.read(retry_delay=0.01, retry_limit=2) assert b'' == ser.read_bytes(size=1) assert 0 == ser.write('abcdef') ser.reset_input_buffer() # Disconnect from the serial port. assert ser.is_connected ser.disconnect() assert not ser.is_connected # Should no longer be able to read or write. with pytest.raises(AssertionError): ser.read(retry_delay=0.01, retry_limit=1) with pytest.raises(AssertionError): ser.read_bytes(size=1) with pytest.raises(AssertionError): ser.write('a') ser.reset_input_buffer() # And we should be able to reconnect. assert not ser.is_connected ser.connect() assert ser.is_connected
def test_missing_port(): with pytest.raises(ValueError): rs232.SerialData()
def test_custom_logger(handler, fake_logger): s0 = rs232.SerialData(port='no_op://', logger=fake_logger) s0.logger.debug('Testing logger')