using mainapp.py
import sys
from PySide6 import QtWidgets
from utils import resource_path
from MainWindow import Ui_MainWindow  # Import the generated UI
from start_up import start_up  # Import the function to initialize UI components
from comms import list_open_com_ports, send_string_to_ports, send_mdf_and_check  # Import functions from comms.py

class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()

        self.setupUi(self)  # Setup the UI from the Ui_MainWindow class

        # Initialize all necessary UI components and populate them
        start_up(
            self.LblStatusVersionNo, 
            self.BtnStartTest, 
            self.ComboBoxLang, 
            self.ComboBoxMaxSwl, 
            self.FldJtfDeviceModelNo, 
            self.FldJtfDeviceSerialNo, 
            self.FldJtfDeviceManufacturer, 
            self.FldJtfDeviceMaxCapacitySwl, 
            self.FldTestDataToleranceThreshold, 
            self.FldTestDataTestCycleTime, 
            self.FldTestConductedByCompany, 
            self.FldTestConductedByPlace, 
            self.FldTestDataDateOfTest,
            self.FldTestDataNextTestDue
        )

        # Connect the existing BtnInitialize to the on_initialize_clicked method
        self.BtnInitialize.clicked.connect(self.on_initialize_clicked)

    def on_initialize_clicked(self):
        """Event handler for BtnInitialize click."""
        # List all open COM ports
        available_ports = list_open_com_ports()
        if available_ports:
            print("Available COM ports:", available_ports)
            # Send the string "wei.zrp" to each open port and check responses
            responding_port, received_data = send_string_to_ports(available_ports, "wei.zrp")
            if responding_port is not None:
                self.LblStatusComPort.setText(responding_port)  # Set the label to the port name
                self.CbStatusPortOPen.setChecked(True)  # Set the checkbox to True

                # Now send 'wei.mdf' if the valid return was received
                live_data = send_mdf_and_check([responding_port], "wei.mdf")
                if live_data is not None:
                    self.LblStatusLiveData.setText(live_data)  # Set the label to the received live data
            else:
                self.LblStatusComPort.setText("--")  # Set label to "--" if no responding port
                self.CbStatusPortOPen.setChecked(False)  # Set checkbox to False if no responding port

# Start the application
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())
and comms.py
# comms.py
import serial
import serial.tools.list_ports
import time

def list_open_com_ports():
    """List all open COM ports."""
    ports = serial.tools.list_ports.comports()
    open_ports = [port.device for port in ports]
    print("Open COM ports:", open_ports)
    return open_ports

def send_string_to_ports(ports, message):
    """Send the specified string to each port and print the received data.
       Also returns the port name if the response starts with 'wei.zrp' and contains 'wei.zrp'."""
    # Append CRLF to the message
    message_with_termination = message + "\r\n"
    
    for port in ports:
        try:
            # Create a serial connection
            with serial.Serial(port, baudrate=57600, bytesize=8, parity=serial.PARITY_NONE,
                               stopbits=serial.STOPBITS_ONE, timeout=1) as ser:
                print(f"Sending data to {port}...")
                ser.write(message_with_termination.encode('utf-8'))  # Send the message as bytes

                # Wait for a response (adjust time as necessary)
                time.sleep(1)  # Delay to ensure the device has time to respond

                # Read received data, expecting it to be terminated by CRLF
                received_data = ser.read_until(b'\r\n')  # Read until CRLF
                decoded_data = received_data.decode('utf-8', errors='ignore').strip()
                
                print(f"Received from {port}: {decoded_data}")

                # Check for the expected response conditions
                if decoded_data.startswith("wei.zrp") and "wei.zrp" in decoded_data:
                    return port, decoded_data  # Return the port name and data

        except Exception as e:
            print(f"Error communicating with {port}: {e}")

    return None, None  # Return None if no port met the requirements

def send_mdf_and_check(ports, message):
    """Send 'wei.mdf' and check if the response starts with 'wei.mdf'."""
    # Append CRLF to the message
    message_with_termination = message + "\r\n"
    
    for port in ports:
        try:
            # Create a serial connection to send 'wei.mdf'
            with serial.Serial(port, baudrate=57600, bytesize=8, parity=serial.PARITY_NONE,
                               stopbits=serial.STOPBITS_ONE, timeout=1) as ser:
                print(f"Sending data to {port}...")
                ser.write(message_with_termination.encode('utf-8'))  # Send the message as bytes

                # Wait for a response
                time.sleep(1)  # Delay for response

                # Read received data, expecting it to be terminated by CRLF
                received_data = ser.read_until(b'\r\n')  # Read until CRLF
                decoded_data = received_data.decode('utf-8', errors='ignore').strip()
                
                print(f"Received from {port}: {decoded_data}")

                # Check if the response starts with "wei.mdf"
                if decoded_data.startswith("wei.mdf") and "wei.zrp" in decoded_data:
                    return decoded_data  # Return the received data if it starts with wei.mdf

        except Exception as e:
            print(f"Error communicating with {port}: {e}")

    return None  # Return None if no valid response

when sending the second string, send 'wei.mdf' does a new serial connection have to be opened as the second send only occurs if a valid reponse is received from the first send, send 'wei.zrp', the port is already open