def test_detect(self, serial_for_url_mock, list_ports_mock): for simulator_class in self.simulators: with self.subTest("Simulated meter", simulator=simulator_class): # Create serial instances with unmocked import unconnected_serial_instance = serial_for_url("loop://", baudrate=9600, timeout=5) shared_serial_instance = serial_for_url("loop://", baudrate=9600, timeout=5) # Mock serial_for_url to return an unconnected instance and one with the simulator serial_for_url_mock.side_effect = [ shared_serial_instance, unconnected_serial_instance, shared_serial_instance ] # Create a Simulator. The simulator makes the first call to serial_for_url() and receives the shared instance simulator = simulator_class() simulator.start() # Mock available serial ports list_ports_mock.return_value = [ ListPortInfo("/dev/ttyUSB0"), ListPortInfo("/dev/ttyUSB1") ] # Start device detection. This triggers the remaining two calls to serial_for_url() devices = SmlReader("unused://").detect() simulator.stop() self.assertFalse(shared_serial_instance.is_open) self.assertEqual(len(devices), 1) self.assertIn( Device(simulator.get_meter_id(), "/dev/ttyUSB1", "SML", simulator.get_channels()), devices)
def mock_ListPortInfo(found=True, multiple=False): if found: if multiple: yield from [ListPortInfo(device=PORT), ListPortInfo(device=PORT2)] else: yield ListPortInfo(device=PORT) else: return
def test_no_matches(self): """ insure that extra_info returns the empty string if none of the keys match """ port = ListPortInfo() port.foo = "bar" self.assertTrue(extra_info(port) == "")
def test_interface(self): """ insure that the interface is added to the extra_items list if it is present in port """ port = ListPortInfo() port.interface = "123interface" response = extra_info(port) self.assertTrue(port.interface in response)
def test_serial_number(self): """ insure that the serial_number is added to the extra_items list if it is present in port """ port = ListPortInfo() port.serial_number = "123" response = extra_info(port) self.assertTrue(port.serial_number in response)
def test_manufacturer(self): """ insure that the manufacturer is added to the extra_items list if it is present in port """ port = ListPortInfo() port.manufacturer = "Microsoft" response = extra_info(port) self.assertTrue(port.manufacturer in response)
def test_port_vid_empty(self): """ insures that the is_serial_usb function retunrs false if the port.vid param is empty """ port = ListPortInfo() port.vid = None args = Namespace() args.vid = None response = is_usb_serial(port, args) self.assertFalse(response)
def test_args_vid_not_empty(self): """ checks to make sure that the is_serial_usb function exists correctly when the args["vid"] is not empty and port["vid"] doesn't equal args["vid"] """ port = ListPortInfo() port.vid = "foo" args = Namespace() args.vid = "bar" response = is_usb_serial(port, args) self.assertFalse(response)
def fake_comports(): """ Generate a fake list of comports to compare against. """ fake_device = ListPortInfo(device='COM1') fake_device.vid = 0 fake_device.pid = 1000 fake_device.serial_number = 'a1' fake_device2 = ListPortInfo(device='COM2') fake_device2.vid = 1 fake_device2.pid = 1010 fake_device2.serial_number = 'c0' return [fake_device, fake_device2]
def test_is_serial_usb_manufacturer_match(self, mock_port_list, mock_serial): """ Tests the __init__ function where the port manufacturer is not empty and doesn't match the supplied port in RADIO_TRANSMITTER_PORT """ port, port2 = ListPortInfo(), ListPortInfo() port.vid = "foo" port.pid = "bar" port.manufacturer = "Microsoft" port.serial_number = "456" port.interface = "usb" port.device = "usb" port2.vid = "foo" port2.pid = "bar" port2.manufacturer = "Apple" port2.serial_number = "123" port2.interface = "bluetooth" port2.device = "usb2" mock_port_list.return_value = [port, port2] with patch.dict( os.environ, { "LOG_DIRECTORY": self.temp_dir.path, "RADIO_TRANSMITTER_PORT": "usb2", "LOG_FILE": "logger.txt", "TRANSCEIVER_BAUDRATE": "9600", "TRANSCEIVER_TIMEOUT": "1", }, ): transciever = Transceiver(log_file_name="LOG_FILE") self.assertTrue(transciever.logging is not None) self.assertTrue(transciever.logging.name == "LOG_FILE") self.assertIsInstance(transciever.logging, Logger) self.assertTrue(transciever.port == "usb2") self.assertTrue(transciever.port_vid == "foo") self.assertTrue(transciever.port_pid == "bar") self.assertTrue(transciever.port_vendor == "Apple") self.assertTrue(transciever.port_intf == "bluetooth") self.assertTrue(transciever.port_serial_number == "123") mock_serial.assert_called_with( port="usb2", baudrate=self.baudrate, parity=self.parity, stopbits=self.stopbits, bytesize=self.bytesize, timeout=self.timeout, )
def fixture_patch_comports(mocker): comport = "COM1" dummy_port_info = ListPortInfo("") dummy_port_info.vid = STM_VID dummy_port_info.name = comport dummy_port_info.description = f"Device ({comport})" mocked_comports = mocker.patch.object( mc_comm.list_ports, "comports", autospec=True, return_value=[dummy_port_info], ) yield comport, dummy_port_info.description, mocked_comports
def test_instrument_open_serial_by_usb_ids_multiple_matches(_, mock_comports): with pytest.raises(serial.SerialException): fake_device = ListPortInfo(device='COM1') fake_device.vid = 0 fake_device.pid = 1000 fake_device.serial_number = 'a1' fake_device2 = ListPortInfo(device='COM2') fake_device2.vid = 0 fake_device2.pid = 1000 fake_device2.serial_number = 'b2' mock_comports.return_value = [fake_device, fake_device2] _ = ik.Instrument.open_serial(baud=1234, vid=0, pid=1000)
def test_instrument_open_serial_by_usb_ids_multiple_matches(_, mock_comports): fake_device = ListPortInfo() fake_device.vid = 0 fake_device.pid = 1000 fake_device.serial_number = 'a1' fake_device.device = 'COM1' fake_device2 = ListPortInfo() fake_device2.vid = 0 fake_device2.pid = 1000 fake_device2.serial_number = 'b2' fake_device2.device = 'COM2' mock_comports.return_value = [fake_device, fake_device2] _ = ik.Instrument.open_serial(baud=1234, vid=0, pid=1000)
def fake_comports(): """ Generate a fake list of comports to compare against. """ fake_device = ListPortInfo() fake_device.vid = 0 fake_device.pid = 1000 fake_device.serial_number = 'a1' fake_device.device = 'COM1' fake_device2 = ListPortInfo() fake_device2.vid = 1 fake_device2.pid = 1010 fake_device2.serial_number = 'c0' fake_device2.device = 'COM2' return [fake_device, fake_device2]
def _handle_removed_device(self, removed: List[ListPortInfo]) -> None: if any(self._device.serial_number == dev.serial_number for dev in removed): self._wanted_state = PacemakerState.NOT_CONNECTED self.connect_status_change.emit(PacemakerState.NOT_CONNECTED, removed[0].serial_number) self._device = ListPortInfo() self.serial.stop_serial_comm()
def test_args_vendor_not_empty(self): """ checks to make sure that the is_serial_usb function exists correctly when the args["vendor"] is not empty and port["manufacturer"] doesn't start with args["vendor"] """ port, args = ListPortInfo(), Namespace() port.vid = "bar" port.pid = "foo" port.manufacturer = "Apple" args.vid = None args.pid = None args.vendor = "Microsoft" response = is_usb_serial(port, args) self.assertFalse(response)
def get_mocked_com_port_none_types(): """Mock of a serial port with NoneTypes.""" port = ListPortInfo("/dev/ttyUSB1234") port.device = "/dev/ttyUSB1234" port.serial_number = None port.manufacturer = None port.description = "crownstone dongle - crownstone dongle" port.vid = None port.pid = None return port
def get_mocked_com_port(): """Mock of a serial port.""" port = ListPortInfo("/dev/ttyUSB1234") port.device = "/dev/ttyUSB1234" port.serial_number = "1234567" port.manufacturer = "crownstone" port.description = "crownstone dongle - crownstone dongle" port.vid = 1234 port.pid = 5678 return port
def test_get_port_match(self, port_mocks): port = ListPortInfo() port.vid = "vid" port.pid = None port.manufacturer = None port.serial_number = None port.interface = None port.device = "usb" port_mocks.return_value = [port] self.assertTrue("port found" in get_port())
def test_get_port_empty(self, port_mocks): port = ListPortInfo() port.vid = None port.pid = None port.manufacturer = None port.serial_number = None port.interface = None port.device = "usb" port_mocks.return_value = [port] self.assertIsNone(get_port())
def find_vcu118_tty(pretend: bool) -> ListPortInfo: # find the serial port: expected_vendor_id = 0x10c4 expected_product_id = 0xea70 for info in comports(include_links=True): assert isinstance(info, ListPortInfo) if info.pid == expected_product_id and info.vid == expected_vendor_id: return info if pretend: return ListPortInfo("/dev/fakeTTY") raise ValueError("Could not find USB TTY with VID", hex(expected_vendor_id), "PID", hex(expected_product_id))
def comports_from_dicts(info_dicts): ports = [] for info_dict in info_dicts: info = ListPortInfo() for key, value in info_dict.items(): setattr(info, key, value) ports.append(info) return ports
def test_is_wixel_port(): port = ListPortInfo() port.vid = 4321 port.pid = 5678 assert wixel.is_wixel_port(port) == False port.vid = wixel.VID port.pid = wixel.PID assert wixel.is_wixel_port(port) == True
def list_serial_ports(cls): plat = sys.platform.lower() if os.name == 'posix' and plat[:6] == 'darwin': from serial.tools.list_ports_osx import GetIOServicesByType, GetParentDeviceByType, get_string_property from mac_bt import get_bytes_property, IOBluetooth services = GetIOServicesByType('IOSerialBSDClient') ports = [] bt_devices = IOBluetooth.IOBluetoothDevice.pairedDevices() for service in services: tty = get_string_property(service, "IODialinDevice") bt_device = GetParentDeviceByType(service, "IOBluetoothSerialClient") dev_name = tty if bt_device is not None: address_bytes = get_bytes_property(bt_device, "BTAddress") if address_bytes is not None: address = '-'.join(list('%02.x' % b for b in address_bytes)) for dev in bt_devices: if not address.startswith(dev.addressString()): continue disp_name = dev.getDisplayName() name = dev.getName() if disp_name is not None: dev_name = '{0} - {1} ({2})'.format(disp_name, name, tty) else: dev_name = '{0} ({1})'.format(name, tty) print('Device:', tty, 'Address:', address) print('Name:', dev_name) info = ListPortInfo(tty) info.name = dev_name ports.append(info) break return ports else: return list_comports()
def test_is_serial_usb_no_vid(self, mock_port_list, mock_serial): """ Tests the __init__ function where the port vid is empty """ port = ListPortInfo() port.vid = None port.pid = None port.manufacturer = None port.serial_number = None port.interface = None port.device = "usb" mock_port_list.return_value = [port] with patch.dict( os.environ, { "LOG_DIRECTORY": self.temp_dir.path, "RADIO_TRANSMITTER_PORT": "", "LOG_FILE": "logger.txt", "TRANSCEIVER_BAUDRATE": "9600", "TRANSCEIVER_TIMEOUT": "1", }, ): transciever = Transceiver(log_file_name="LOG_FILE") self.assertTrue(transciever.logging is not None) self.assertTrue(transciever.logging.name == "LOG_FILE") self.assertIsInstance(transciever.logging, Logger) self.assertTrue(transciever.port == "") self.assertIsNone(transciever.port_vid) self.assertIsNone(transciever.port_pid) self.assertIsNone(transciever.port_vendor) self.assertIsNone(transciever.port_intf) self.assertIsNone(transciever.port_serial_number) mock_serial.assert_called_with( port="", baudrate=self.baudrate, parity=self.parity, stopbits=self.stopbits, bytesize=self.bytesize, timeout=self.timeout, )
def com_port(): """Mock of a serial port.""" port = ListPortInfo(DEFAULT_PORT) port.serial_number = "1234" port.manufacturer = "Virtual serial port" port.device = DEFAULT_PORT port.description = "Some serial port" return port
def __init__(self): super().__init__() print("Connection handler init") self._running = False self._device = ListPortInfo() self._devices = self._old_devices = [] self._first_serial_num = "" self._current_state = self._prev_state = self._wanted_state = PacemakerState.NOT_CONNECTED # Initialize and start the serial connection handler self.serial = _SerialHandler() self.serial.start()
def mock_comports(): mock_port_attrs = [ { "device": "/dev/ttyS4", }, { # XB112 ~ as given from serial.tools.list_ports.comports "device": "/dev/ttyUSB0", "description": "XB112", "manufacturer": "Acconeer AB", "product": "XB112", "interface": None, }, { # XE132 ~ as given ... "device": "/dev/ttyUSB1", "description": "Acconeer XE132 - Enhanced Com Port", "manufacturer": "Silicon Labs", "product": "Acconeer XE132", "interface": "Enhanced Com Port", }, { # XE132 ~ as given ... "device": "/dev/ttyUSB2", "description": "Acconeer XE132 - Standard Com Port", "manufacturer": "Silicon Labs", "product": "Acconeer XE132", "interface": "Standard Com Port", }, { "device": "/dev/ttyS5", }, { "device": "/dev/ttyS6", }, { "device": "/dev/ttyUSB3", "description": "Linux Foundation 1.1 root hub " }, ] mock_ports = [] for mpp in mock_port_attrs: lpi = ListPortInfo("") for k, v in mpp.items(): setattr(lpi, k, v) mock_ports.append(lpi) return mock_ports
def test_listen_exception(self, mock_port_list, mock_serial, mock_json): """ tests the listen method with invalid input """ port = ListPortInfo() port.vid = "vid" port.pid = "pid" port.manufacturer = "Microsoft" port.serial_number = "456" port.interface = "usb" port.device = "usb" mock_json.side_effect = Exception("ex") mock_port_list.return_value = [port] test_input = "{'value': 'value'}" with patch.dict( os.environ, { "LOG_DIRECTORY": self.temp_dir.path, "RADIO_TRANSMITTER_PORT": "usb", "LOG_FILE": "logger.txt", "TRANSCEIVER_BAUDRATE": "9600", "TRANSCEIVER_TIMEOUT": "1", }, ): with LogCapture() as capture: transceiver = Transceiver(log_file_name="LOG_FILE") mock_receiver = MagicMock() mock_receiver.readline.return_value.decode.return_value = test_input transceiver.serial = mock_receiver with self.assertRaises(Exception): transceiver.listen() capture.check( ("LOG_FILE", "INFO", "Port device found: usb"), ("LOG_FILE", "INFO", "Opening serial on: usb"), ("LOG_FILE", "ERROR", "error occurred: ex"), )
def test_send(self, mock_port_list, mock_serial): """ tests the send method """ port = ListPortInfo() port.vid = "vid" port.pid = "pid" port.manufacturer = "Microsoft" port.serial_number = "456" port.interface = "usb" port.device = "usb" mock_port_list.return_value = [port] test_payload = {"value": "value"} output = get_serial_stream(test_payload) with patch.dict( os.environ, { "LOG_DIRECTORY": self.temp_dir.path, "RADIO_TRANSMITTER_PORT": "usb", "LOG_FILE": "logger.txt", "TRANSCEIVER_BAUDRATE": "9600", "TRANSCEIVER_TIMEOUT": "1", }, ): with LogCapture() as capture: transciever = Transceiver(log_file_name="LOG_FILE") mock_serial_sender = MagicMock() transciever.serial = mock_serial_sender transciever.send(test_payload) mock_serial_sender.write.assert_called_with(output) capture.check( ("LOG_FILE", "INFO", "Port device found: usb"), ("LOG_FILE", "INFO", "Opening serial on: usb"), ("LOG_FILE", "INFO", "sending"), ("LOG_FILE", "INFO", "{'value': 'value'}"), )
def patch_pyserial_if_needed(): """ A workaround for https://github.com/pyserial/pyserial/issues/286 """ try: from serial.tools.list_ports_common import ListPortInfo except ImportError: return try: dummy = ListPortInfo() dummy == None log.debug("pyserial patch not needed") except AttributeError: def __eq__(self, other): return isinstance(other, ListPortInfo) \ and self.device == other.device ListPortInfo.__eq__ = __eq__ log.debug("pyserial patched")
def test_McCommunicationProcess_create_connections_to_all_available_boards__populates_connections_list_with_a_simulator_when_com_port_is_unavailable__and_sends_correct_message_to_main( four_board_mc_comm_process, mocker, patch_comports, patch_serial_connection): _, _, mocked_comports = patch_comports mocked_comports.return_value = [ListPortInfo("")] _, mocked_serial = patch_serial_connection mc_process = four_board_mc_comm_process["mc_process"] board_queues = four_board_mc_comm_process["board_queues"] mocker.patch.object( mc_process, "determine_how_many_boards_are_connected", autospec=True, return_value=1, ) board_idx = 0 actual_connections = mc_process.get_board_connections_list() assert actual_connections == [None] * 4 mc_process.create_connections_to_all_available_boards() confirm_queue_is_eventually_of_size(board_queues[0][1], 1) assert mocked_comports.call_count == 1 assert mocked_serial.call_count == 0 actual_connections = mc_process.get_board_connections_list() assert actual_connections[1:] == [None] * 3 actual_serial_obj = actual_connections[board_idx] assert isinstance(actual_serial_obj, MantarrayMcSimulator) # Tanner (8/25/21): it's important that the simulator is created with no read timeout because the connection to a real instrument will not have one either assert actual_serial_obj.get_read_timeout() == 0 actual_message = board_queues[0][1].get( timeout=QUEUE_CHECK_TIMEOUT_SECONDS) assert actual_message[ "communication_type"] == "board_connection_status_change" assert actual_message["board_index"] == board_idx assert actual_message[ "message"] == "No board detected. Creating simulator." assert actual_message["is_connected"] is False assert actual_message["timestamp"] == "2021-03-15 13:27:31.005000"