import os
import threading
import tkinter as tk
from plyer import notification
from PIL import Image, ImageTk
from integration_test_manager import IntegrationTestManager  # Ensure this is correctly implemented
import queue


class LaveUi:
    def __init__(self, root):
        self.root = root
        self.root.title("LAVU L2 Test Bench")
        self.root.geometry("1080x800")  # Set the size of the window

        # Initialize class variables
        self.enable_full_execution = False
        self.all_app = None
        self.var = None
        self.secure = False
        self.app_set_state = True
        self.init_event = None
        self.checkbox_frame = None
        self.test_handler = None
        self.terminate_thread = False  # Flag to signal thread termination
        self.thread = None
        self.queue = queue.Queue()  # Queue for UI updates

        # User Input Values
        self.ip_address = None
        self.dlt_port = 3490
        self.grpc_port = "8866"
        self.software_ver = None

        # Variable list for checkboxes
        self.check_vars = [tk.BooleanVar() for _ in range(48)]
        self.checkbox_names = [
            "SD11_CleanupRoutines", "SD11_CleanupRoutinesGeneric", "SD12_DiagnosisCaptureImage",
            "SD13_EthernetTest", "SD2_RDIOperation", "SD3_CodingOperation",
            "SD4_IOCTLOperation", "SD5_MeasurementOperation", "SD6_AdaptionOperation",
            "SD7_EthernetFaultDetection", "SD11_DashCamCrashEvent", "SD11_EmergencyBrakeEvent",
            "SD12_DashCamPlayback", "SD14_ExportDashCamRecord",
            "SD13_DeleteDashCamRecord", "SD15_SetAndUnsetDashCamRecordToFavourite",
            "SD21_MemoriesRecordingSaving", "SD21_MemoriesRecordingDiscarding",
            "SD22_MemoriesPlayback", "SD24_ExportMemories", "SD25_SetMemoriesToFavourite",
            "SD23_DeleteMemories", "SD1_TelemetryTrackMapRecordingImproperRequest",
            "SD1_TelemetryTrackMapRecordingProperRequest", "SD211_TelemetrySectorManagementSelectASectorToEdit",
            "SD212_TelemetrySectorManagementAddOrRemoveASector",
            "SD213_TelemetrySectorManagementSaveASectorChanges",
            "SD213_TelemetrySectorManagementDiscardASectorChanges",
            "SD22_TelemetryTrackManagementExportTrackAndSessionsData",
            "SD23_TelemetryTrackManagementSetATrackAsFavorite",
            "SD23_TelemetryTrackManagementUnsetATrackAsFavorite",
            "SD24_ImportTracksAndSessions", "SD31_TelemetrySessionManagementStartSession",
            "SD31_TelemetrySessionManagementStartSessionOutOfTrack",
            "SD32_TelemetrySessionManagementStopSession",
            "SD32_TelemetrySessionManagementStopSessionRaceCanBeSavedFalse",
            "SD33_SetSessionAsFavorite", "SD33_UnsetSessionAsFavorite",
            "SD34_DeleteSessions", "SD4_TelemetrySessionAnalysisSessionLap",
            "SD4_TelemetrySessionAnalysisSessionBest",
            "SD4_TelemetrySessionAnalysisPersonalBest", "SD4_TelemetrySessionAnalysisAbsoluteBest",
            "SD1_IPSec", "SD2_SecureBoot", "SD3_UartAccess", "SD4_mTLS", "SD1_UpdateLAVU"
        ]

        # Animation variables
        self.images = []  # List to hold animation images
        self.image_index = 0
        self.animation_running = True
        self.animation_label = tk.Label(self.root)
        self.animation_label.pack(pady=20)

        self.load_animation_images()
        self.start_boot_animation()

        # Loading text (status label)
        self.loading_label = tk.Label(self.root, text="Setup Input Values", font=("Helvetica", 24), fg="red")
        self.loading_label.pack(pady=15)

        # Exit button
        self.exit_frame = tk.Frame(self.root)  # Create a frame for the exit button
        self.exit_frame.pack(side=tk.BOTTOM, pady=10)  # Pack it to the bottom
        self.exit_button()

        self.get_ui_input()  # Initialize user input fields

        # Start a periodic check for updates in the queue
        self.check_queue()

    def exit_button(self):
        exit_button = tk.Button(self.exit_frame, text="Exit", command=self.exit_ui_application)
        exit_button.pack(pady=10)

    def exit_ui_application(self):
        print("UI Application Exit !!")

        # Set the flag to terminate the thread
        self.terminate_thread = True

        # If there's a thread running, join it
        if self.thread and self.thread.is_alive():
            self.thread.join(timeout=5)  # Wait for the thread to finish

            if self.thread.is_alive():
                print("Thread did not finish in time, proceeding to exit.")

        self.root.quit()

    def initTestManager(self, ip_address, dlt_port, grpc_port, software_ver):
        """ Initialize Integration Test Manager in a separate thread. """
        self.terminate_thread = False
        self.thread = threading.Thread(target=self.run_integration_test_manager,
                                       args=(ip_address, self.dlt_port, grpc_port, software_ver))
        self.thread.start()  # Start the initialization in a separate thread
        self.root.after(100, self.check_init_complete)  # Initial check for completion

    def run_integration_test_manager(self, ip_address, dlt_port, grpc_port, software_ver):
        """ This method will contain the logic for running the integration tests. """
        self.test_handler = IntegrationTestManager(
            d_can_dbc_file_path="./can_database/MLBevo_Gen2_MLBevo_DCAN_KMatrix_V8.24.00F_20220602_VP.dbc",
            p_can_dbc_file_path="./can_database/PCAN_INFOT_Merged_R20.dbc",
            server_ip=ip_address,  # Using the user input IP address
            grpc_port=grpc_port,  # Using the user input gRPC port
            dlt_port=3490,  # Using the integer DLT port
            secure=self.secure  # Using the secure option
        )

        # Simulate long-running task
        while not self.terminate_thread:
            # Here you would typically call methods from the test handler to perform tests.
            pass

        print("IntegrationTestManager thread terminated.")

    def check_init_complete(self):
        """ Check if the initialization thread is complete. """
        if self.thread and self.thread.is_alive():
            if self.test_handler and self.test_handler.init_event:
                self.stop_boot_animation()  # Stop when initialization is complete
            else:
                self.root.after(100, self.check_init_complete)  # Keep checking if still running
        else:
            self.stop_boot_animation()  # Stop the animation when initialization is complete

    def stop_boot_animation(self):
        """ Stop the boot animation. """
        self.animation_running = False
        self.animation_label.config(image='')  # Clear the label when stopping
        self.loading_label.config(text='Initialization Complete')
        self.create_checkbox_list()  # Create checkbox list after boot animation

    def load_animation_images(self):
        """ Load animation images from a directory. """
        directory = "boot_images"  # Directory containing boot images
        for i in range(1, 30):  # Assuming you have images named 1.png to 29.png
            img_path = os.path.join(directory, f'{i}.png')

            # Open the image
            img = Image.open(img_path)

            # Ensure the image has an alpha channel
            img = img.convert("RGBA")  # Convert to RGBA format
            datas = img.getdata()  # Get the pixel data

            new_data = []
            for item in datas:
                # Modify this part to set the specific background color you want to remove
                # For example, remove white background (greater than 240 in RGB)
                if item[0] > 240 and item[1] > 240 and item[2] > 240:
                    new_data.append((255, 255, 255, 0))  # Change to transparent
                else:
                    new_data.append(item)

            img.putdata(new_data)  # Update the image data
            img = img.resize((100, 50), Image.LANCZOS)  # Resize for display
            self.images.append(ImageTk.PhotoImage(img))  # Store the PhotoImage in the list

    def start_boot_animation(self):
        """ Start the boot animation. """
        self.update_animation()
        self.root.after(100)  # Initial delay

    def update_animation(self):
        """ Update the animation label. """
        if self.animation_running:
            # Update the image shown in the label
            self.animation_label.config(image=self.images[self.image_index])
            self.image_index = (self.image_index + 1) % len(self.images)
            self.root.after(100, self.update_animation)  # Change image every 100ms

    def get_ui_input(self):
        """ Create UI elements for user input. """
        input_frame = tk.Frame(self.root)
        input_frame.pack(pady=20)  # Add some vertical padding

        # Labels and Entry for IP Address
        tk.Label(input_frame, text="IP Address").grid(row=0, column=0)
        self.ip_address = tk.Entry(input_frame)
        self.ip_address.grid(row=0, column=1)

        # Labels and Entry for DLT Port
        tk.Label(input_frame, text="DLT Port").grid(row=1, column=0)
        self.dlt_port = tk.Entry(input_frame)
        self.dlt_port.grid(row=1, column=1)

        # Labels and Entry for gRPC Port
        tk.Label(input_frame, text="gRPC Port").grid(row=2, column=0)
        self.grpc_port = tk.Entry(input_frame)
        self.grpc_port.grid(row=2, column=1)

        # Labels and Entry for Software Version
        tk.Label(input_frame, text="Software Version").grid(row=3, column=0)
        self.software_ver = tk.Entry(input_frame)
        self.software_ver.grid(row=3, column=1)

        # Checkbox for secure option
        self.var = tk.BooleanVar()
        tk.Checkbutton(input_frame, text="Secure", variable=self.var, command=self.secure_selection).grid(row=4,
                                                                                                          columnspan=2)

        # Submit button
        self.submit_button = tk.Button(input_frame, text="Submit", command=self.get_user_input)
        self.submit_button.grid(row=5, columnspan=2)

    def secure_selection(self):
        """ Handle the secure checkbox selection. """
        self.secure = self.var.get()

    def get_user_input(self):
        """ Gather user input and start the test manager. """
        if self.app_set_state:
            # Update the loading label
            self.loading_label.config(text="Application Initialization in Progress !!")
            self.app_set_state = False

            # Get user inputs
            ip_address = self.ip_address.get()  # Get the IP address
            # Convert DLT port to an integer, handle potential conversion errors
            try:
                self.dlt_port = int(self.dlt_port.get())  # Convert DLT port to an integer
            except ValueError:
                print("Invalid DLT Port. Please enter a valid integer.")
                return  # Exit if the conversion fails

            grpc_port = self.grpc_port.get()  # Get gRPC port as string directly
            software_ver = self.software_ver.get()  # Get software version as string

            # Print user input for debugging
            print("User input:")
            print("IP Address:", ip_address)
            print("DLT Port:", self.dlt_port)
            print("gRPC Port:", grpc_port)
            print("Software Version:", software_ver)
            print("Secure:", self.secure)

            # Start the test manager with the gathered values
            self.initTestManager(ip_address, self.dlt_port, grpc_port, software_ver)

    def enable_full_execution_test(self):
        if self.all_app.get():
            self.enable_full_execution = True
        else:
            self.enable_full_execution = False

    def create_checkbox_list(self):
        """ Create a list of checkboxes for testing options. """
        self.checkbox_frame = tk.Frame(self.root)
        self.checkbox_frame.pack(pady=20)

        # Checkbox for "All" option
        self.all_app = tk.BooleanVar()
        checkbox_all = tk.Checkbutton(
            self.checkbox_frame,
            text="All",
            variable=self.all_app,
            command=self.enable_full_execution_test
        )
        checkbox_all.grid(row=0, column=0, columnspan=4, sticky='w', padx=10, pady=5)

        # Create Checkboxes in four columns
        for i in range(len(self.checkbox_names)):
            row = (i // 4) + 1
            column = i % 4
            checkbox = tk.Checkbutton(
                self.checkbox_frame,
                text=self.checkbox_names[i],
                variable=self.check_vars[i],
                command=lambda i=i: self.checkbox_toggled(i)  # Pass the index
            )
            checkbox.grid(row=row, column=column, sticky='w', padx=10, pady=5)

        # Configure the grid columns
        for col in range(4):
            self.checkbox_frame.grid_columnconfigure(col, weight=1)

    def checkbox_toggled(self, index):
        """ Handle checkbox toggling event. """
        if self.check_vars[index].get():  # If checkbox is checked
            method_name = self.checkbox_names[index]  # Get the method name

            # Call the corresponding method if it exists
            if self.test_handler:
                method = getattr(self.test_handler, method_name, None)
                if method:
                    method()  # Call the method
                else:
                    self.show_toast()
                    print(f"Method {method_name} is not defined in IntegrationTestManager.")
            else:
                print("Test Application Initialization In Complete..")

    @staticmethod
    def show_toast():
        """ Show a notification to the user. """
        notification.notify(
            title='LAVU L2 Test Bench',
            message='Test Application Not Properly Started..Wait !!',
            app_name='My Application',
            timeout=10  # Duration in seconds
        )

    def check_queue(self):
        """ Check the queue for UI updates. """
        try:
            while True:
                message = self.queue.get_nowait()  # Non-blocking get
                self.loading_label.config(text=message)  # Update the loading label
        except queue.Empty:
            pass

        self.root.after(100, self.check_queue)  # Check the queue every 100ms
Its my Ui.py and below is my integration_test_manager.py
import os
import threading

from grpc import StatusCode
import grpc

from grpc_interface.diagnosis.diagnosis_test import DiagnosisTest
from grpc_interface.dashcam.dashcam_test import DashcamTest
from grpc_interface.filetransfer.filetransfer_test import FiletransferTest
from grpc_interface.gps.gps_test import GpsTest
from grpc_interface.memories.memory_test import MemoryTest
from grpc_interface.network.network_test import NetworkTest
from grpc_interface.system.system_test import SystemTest
from grpc_interface.telemetry import telemetry_pb2
from grpc_interface.connected_services.connectedservices_test import ConnectedServiceTest
from grpc_interface.telemetry.telemetry_test import TelemetryTest
from grpc_interface.security.security_test import SecurityTest
from grpc_interface.update.update_test import UpdateTest
from grpc_manager import GrpcManager
from random import randint

from report.report_manager import ReportManager
from struct_enum.enum_struct import TestSummary, TestResult
from connect_manager import ConnectManager
from utils import *
from multi_can_manager import MultiCanManager
from dlt_manager import *
from grpc_interface.telemetry.telemetry_pb2 import *
from report.report_manager import ReportManager
import os
import time
import random
import string
import inspect
from struct_enum.enum_struct import *
from grpc_interface.gps import gps_pb2
from gpx.gpx_manager import GpxManager
from connect_manager import ConnectManager
from grpc_interface.dashcam import dashcam_pb2
from grpc_interface.memories import memories_pb2
from grpc_interface.telemetry import *
from jira_manager import JiraManager
from time import sleep
import sys

if sys.version_info >= (3, 6):
    import zipfile
else:
    import zipfile36 as zipfile





class IntegrationTestManager:
    # list_test: list[Test]

    def __init__(self, d_can_dbc_file_path: str, p_can_dbc_file_path: str,
                 server_ip="10.0.8.225", grpc_port="8866", dlt_port=3490, secure=False, cycle_id=""):
        # DLT Manager init
        self.dlt_manager = DltManager(server_ip, dlt_port)
        self.dlt_manager.connect_dlt()
        # CAN Manger init
        self.canManager = MultiCanManager(d_can_dbc_file_path, p_can_dbc_file_path, secure)
        self.init_event = False

        # GPRC init
        self.grpc_manager = GrpcManager(server_ip, grpc_port, secure)
        self.grpc_manager.grpc_connect()
        if self.grpc_manager.GetGrpcConnectionChannel() is None:
            return
        self.test_summary_list = []
        self.target_ip = server_ip
        # Report Manager
        self.report_manager = ReportManager()
        # The gRPC clients
        self.diagnosis_test = DiagnosisTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)
        self.dash_cam_test = DashcamTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)
        self.dash_cam_test.SetSignalWatcher('s_DashcamRecordingListUpdated')
        self.memory_test = MemoryTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)
        self.memory_test.SetSignalWatcher('s_MemoriesRecordingListUpdated')
        self.gps_test = GpsTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)
        self.telemetry_test = TelemetryTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)
        self.telemetry_test.SetSignalWatcher('s_TrackListUpdated')
        self.telemetry_test.SetSignalWatcher('s_SessionListUpdated')
        self.update_test = UpdateTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)

        # Track under Test
        self.track_sample = None
        # Dashcam under test
        self.dash_sample = None
        # Memories under test
        self.mem_sample = None
        # Telemetry session under test        
        self.tml_session_sample = None
        try:
            self.canManager.read_dbc()
            self.canManager.setup_can()
            self.canManager.start_key()
        except Exception as e:
            print(str(e))

        self.HardReset()

        time.sleep(10)
        self.connectedService = ConnectedServiceTest(self.grpc_manager.GetGrpcConnectionChannel())
        time.sleep(2)
        self.connectedService.SetTelemetryStatus()
        self.connectedService.SetMemoryStatus()
        self.connectedService.SetDashcamStatus()
        time.sleep(2)

        gpx_manager = GpxManager()
        gpx_manager.read_gpx_file("gpx/Mugello.gpx")
        self.position_data_list = []
        for lat, lon in gpx_manager.get_track_points():
            self.position_data_list.append(gps_pb2.PositionData(iTOW=123456000, fixType=3, numSV=8, lon=int(lon * 1e7),
                                                                lat=int(lat * 1e7), hMSL=50000, hAcc=1500, vAcc=2000,
                                                                gSpeed=3000, headMot=18000000, pDOP=120, sAcc=500,
                                                                headAcc=10000))
        gpx_manager.read_gpx_file("gpx/Parcheggio.gpx")
        self.out_of_track_position_data_list = []
        for lat, lon in gpx_manager.get_track_points():
            self.out_of_track_position_data_list.append(gps_pb2.PositionData(iTOW=123456000, fixType=3, numSV=8,
                                                                             lon=int(lon * 1e7), lat=int(lat * 1e7),
                                                                             hMSL=50000, hAcc=1500, vAcc=2000,
                                                                             gSpeed=3000, headMot=18000000,
                                                                             pDOP=120, sAcc=500, headAcc=10000))
        self.jira_manager = JiraManager()
        # self.jira_manager.connect_jira()
        self.cycle_id = cycle_id
        self.report_manager.create_test_summary_report_excel()
        self.initialize_status()

    def initialize_status(self):
        print("IntegrationTestManager: Initializing complete...")
        self.init_event = True

    @try_catch
    def finish_can_manager(self):
        self.canManager.stop_key()
        self.canManager.stop_can()

    @try_catch
    def FinishGrpcConnection(self):
        if self.grpc_manager.GetGrpcConnectionChannel() is not None:
            self.telemetry_test.StopSignalReceiverThread()
            self.dash_cam_test.StopSignalReceiverThread()
            self.memory_test.StopSignalReceiverThread()
            self.connectedService.StopSignalReceiverThread()
        self.grpc_manager.grpc_connect_close()

    @try_catch
    def telemetry_set_cam_status(self):
        pass
        # EXAMPLE REPORT FOR TEST
        # test = Test()
        # test.test_name = "telemetry_set_cam_status"
        # test.expected_result = "ciao"
        # test.observed_result = "ciao"
        # test.result = TestResult.PASS
        # self.list_tests.append(test)

    @try_catch
    def check_is_present_grpc_response(self, grpc_response_expected: str):
        pass
        # EXAMPLE REPORT FOR TEST2
        # test = Test()
        # test.test_name = "telemetry_set_cam_status2"
        # test.expected_result = "ciao"
        # test.observed_result = "pluto"
        # test.result = TestResult.FAIL
        # self.list_tests.append(test)

    @try_catch
    def check_is_present_dlt(self, dlt_expected: str):
        pass

    @try_catch
    def VerifyDltLogs(self, test_summary: TestSummary, additional_observed=None):
        # Get the list of DLT logs to verify against
        all_dlt_logs = self.dlt_manager.queueDlt.get_list()

        if not all_dlt_logs:
            print(f"No DLT logs have been received as part of the execution of the test: {test_summary.test_name}")
            return

        # Keep track of which logs have been matched
        dlt_log_indices_matched = set()
        # Loop through the expected results and match with DLT logs
        for exp_result_log in test_summary.expected_result:
            # Perform a substring match, ensuring logs haven't been matched yet
            matching_dlt_log = next((curr_log for curr_log_index, curr_log in enumerate(all_dlt_logs)
                                     if
                                     exp_result_log in curr_log.message and curr_log_index not in dlt_log_indices_matched),
                                    None)
            if matching_dlt_log:
                test_summary.observed_result.append(exp_result_log)
                dlt_log_indices_matched.add(all_dlt_logs.index(matching_dlt_log))

        if test_summary.statusCode == "" or test_summary.statusCode == StatusCode.OK:
            # Check for any additional
            if additional_observed is not None:
                for i in additional_observed:
                    test_summary.observed_result.append(i)

            # Check if expected results match observed results exactly (order-sensitive)
            if test_summary.expected_result == test_summary.observed_result:
                test_summary.result = TestResult.PASS

            # Save DLT file
            self.dlt_manager.save_dlt_captured(test_summary.test_name, test_summary.result.name)

            print(f"Test name: {test_summary.test_name}, Test result: {test_summary.result.name}")
            if self.test_summary_list:
                # Save test report to Json file
                print("Adding Result on Json file.")
                self.report_manager.create_single_report_json(self.test_summary_list.pop())

    @try_catch
    def RemoveAllMemoriesRecordings(self, memory_test: MemoryTest):
        # Generate a list of recording IDs as strings from 0 to 100
        recording_id_list = [str(rec_id) for rec_id in range(101)]
        # Delete all memories using the generated list
        memory_test.DeleteMemoriesRequest(item=recording_id_list)
        # Adding necessary time delay for proper processing for the request
        time.sleep(15)

    @try_catch
    def SaveDataToZip(self, zip_name: str):
        with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # Iterate over all files in the current directory
            for file_name in os.listdir('.'):
                # Check if the file is a .dlt or .json file
                if file_name.endswith('.dlt') or file_name.endswith('.json'):
                    try:
                        # Add the file to the zip
                        zipf.write(file_name, arcname=os.path.basename(file_name))

                        # Delete the file after adding it to the ZIP archive
                        os.remove(file_name)

                    except Exception as e:
                        print(f"Failed to process {file_name}: {e}")

    @try_catch
    def RemoveAllDashCamRecordings(self, dash_cam_test: DashcamTest):
        # Generate a list of recording IDs as strings from 0 to 100
        recording_id_list = [str(rec_id) for rec_id in range(101)]
        # Delete all memories using the generated list
        dash_cam_test.DeleteDashcamRequest(element=recording_id_list)
        # Adding necessary time delay for proper processing for the request
        time.sleep(15)

    @try_catch
    def PerformRdiReadOnlyOperation(self, diagnosis_test: DiagnosisTest):
        data_op_read = 0
        for rdi_read_only_id in RdiReadOnlyId:
            print(f"Performing read operation for the read only rdi item: {rdi_read_only_id.name}")
            op_result = diagnosis_test.PerformDataOperation(operation=data_op_read, did=rdi_read_only_id.value,
                                                            length=11,
                                                            databuf=None)
            if op_result.result != 0:
                print(f"Error: Rdi read operation for the read only item: {rdi_read_only_id.name} is failed")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

    @try_catch
    def PerformRdiReadWriteOperation(self, diagnosis_test: DiagnosisTest):
        data_op_read = 0
        rdi_read_write_info = {}
        # Perform read operation for RDI read write type
        for rdi_read_write_id in RdiReadWriteId:
            print(f"Performing read operation for the read and write rdi item: {rdi_read_write_id.name}")
            op_result = diagnosis_test.PerformDataOperation(operation=data_op_read, did=rdi_read_write_id.value,
                                                            length=11, databuf=None)
            if op_result.result == 0:
                rdi_read_write_info[rdi_read_write_id] = op_result.databuf
            else:
                rdi_read_write_info[rdi_read_write_id] = b''
                print(f"Error: Rdi read operation for the read and write item: {rdi_read_write_id.name} is failed")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

        # Perform write operation for RDI read write type
        data_op_write = 1
        for rdi_read_write_id in RdiReadWriteId:
            print(f"Performing write operation for the read and write rdi item: {rdi_read_write_id.name}")
            if not rdi_read_write_info[rdi_read_write_id] == b'':
                diagnosis_test.PerformDataOperation(operation=data_op_write, did=rdi_read_write_id.value,
                                                    length=len(rdi_read_write_info[rdi_read_write_id]),
                                                    databuf=rdi_read_write_info[rdi_read_write_id])
            else:
                print(f"Error: Rdi write operation for the read and write item: {rdi_read_write_id.name} "
                      "is not done as read operation is failed")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

    @try_catch
    def PerformIoctlTurnOffOnOperation(self, diagnosis_test: DiagnosisTest):
        # Perform turn off ioctl operation
        turn_off = bytes([0])
        ioctl_op_return_control_to_ecu = 0
        for ioctl_id in IoctlId:
            print(f"Performing turn off operation for the ioctl item: {ioctl_id.name}")
            op_result = diagnosis_test.PerformIOCtlOperation(operation=ioctl_op_return_control_to_ecu,
                                                             IOid=ioctl_id.value, length=0, testtime=0,
                                                             databuf=turn_off)
            if op_result.result != 0:
                print(f"Error: ioctl turn off operation for the item: {ioctl_id.name} is failed")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

        # Perform turn on ioctl operation
        turn_on = bytes([1])
        ioctl_op_short_term_adjustment = 1
        for ioctl_id in IoctlId:
            print(f"Performing turn on operation for the ioctl item: {ioctl_id.name}")
            op_result = diagnosis_test.PerformIOCtlOperation(operation=ioctl_op_short_term_adjustment,
                                                             IOid=ioctl_id.value, length=0, testtime=0, databuf=turn_on)
            if op_result.result != 0:
                print(f"Error: ioctl turn on operation for the item: {ioctl_id.name} is failed")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

    @try_catch
    def PerformMeasurementReadOperation(self, diagnosis_test: DiagnosisTest):
        data_op_read = 0
        for measurement_id in MeasurementId:
            print(f"Performing read operation for the measurement item: {measurement_id.name}")
            op_result = diagnosis_test.PerformDataOperation(operation=data_op_read, did=measurement_id.value, length=0,
                                                            databuf=None)
            if op_result.result != 0:
                print(f"Error: Measurement read operation for the item: {measurement_id.name} is failed")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

    @try_catch
    def PerformAdaptionReadwriteOperation(self, diagnosis_test: DiagnosisTest):
        data_op_read = 0
        adaption_read_write_info = {}
        # Perform read operation for adaption operation
        for adaption_id in AdaptionId:
            print(f"Performing read operation for the read and write adaption item: {adaption_id.name}")
            op_result = diagnosis_test.PerformDataOperation(operation=data_op_read, did=adaption_id.value, length=11,
                                                            databuf=None)
            if op_result.result == 0:
                adaption_read_write_info[adaption_id] = op_result.databuf
            else:
                adaption_read_write_info[adaption_id] = b''
                print(f"Error: Adaption read operation for the read and write item: {adaption_id.name} is failed")
        # Adding necessary time delay for proper processing for the request
        time.sleep(30)

        # Perform write operation for adaption operation
        data_op_write = 1
        for adaption_id in AdaptionId:
            print(f"Performing write operation for the read and write adaption item: {adaption_id.name}")
            if not adaption_read_write_info[adaption_id] == b'':
                diagnosis_test.PerformDataOperation(operation=data_op_write, did=adaption_id.value,
                                                    length=len(adaption_read_write_info[adaption_id]),
                                                    databuf=adaption_read_write_info[adaption_id])
                # Adding necessary time delay for proper processing for the request
                time.sleep(10)
            else:
                print(f"Error: Adaption write operation for the read and write item: {adaption_id.name} "
                      "is not done as read operation is failed")

    @try_catch
    def GenerateUniqueName(self):
        # Generate random lowercase letters
        random_name = ''.join(random.choices(string.ascii_lowercase, k=12))
        # Capitalize the first letter to mimic a real name
        return random_name.capitalize()

    @try_catch
    def PerformLapOnTheTrack(self, gps_test: GpsTest, move_to_some_pos_on_track: bool = False, no_of_lap=4):
        # Finish first lap
        for position_data in self.position_data_list[1:]:
            gps_test.NewPositionData(position_data=position_data)
            # Adding necessary time delay for proper processing GPS update
            time.sleep(0.01)
        # Continue the race to finish the loop(start to end closed loop for 4 lap)
        for _ in range(no_of_lap):
            for position_data in self.position_data_list:
                gps_test.NewPositionData(position_data=position_data)
                # Adding necessary time delay for proper processing for GPS update
                time.sleep(0.01)
        # Move to some position on the track
        if move_to_some_pos_on_track:
            for position_data in self.position_data_list[:len(self.position_data_list) // 2]:
                gps_test.NewPositionData(position_data=position_data)
                # Adding necessary time delay for proper processing for GPS update
                time.sleep(0.01)
        # Adding necessary time delay for proper processing for the request
        time.sleep(5)

    @try_catch
    def HardReset(self):
        rout_op_start = 0
        self.diagnosis_test.PerformRoutineOperation(operation=rout_op_start, rid=0x322, length=0, databuf=None)

    @retry_tests
    def SD11_CleanupRoutines(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.1.1 - Use case: Deletion of the DLT logs routine")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9081")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0"]
        self.test_summary_list.append(test_summary)

        # Routine identifiers
        delete_logs = 0x328
        rout_op_start = 0
        rout_op_result = 1
        statusCode = StatusCode.OK
        try:
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_start, rid=delete_logs, length=0,
                                                        databuf=None)
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result, rid=delete_logs, length=0,
                                                        databuf=None)
            # Sleep intervals to allow operations to complete
            time.sleep(10)
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result, rid=delete_logs, length=0,
                                                        databuf=None)
        except grpc.RpcError as e:
            statusCode = e.code()

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD11_CleanupRoutinesGeneric(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.1.1 - Use case: Cleanup routines for list of items in GenericCleanupRoutinesId enum class")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "13091")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            # Logs for HARD_FACTORY_RESET
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # Logs for RESET_DEFAULT_VALUES
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # Logs for CUSTOMER_DATA_RESET
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # Logs for CLEAN_MEMORY
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # Logs for CLEAN_MEMORY_PARTITION_B
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # Logs for CLEAN_MEMORY_PARTITION_C
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Routine is completed",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-De-init the routine DELETER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine DELETER_ 0",
            # Logs for CLEAN_RECORDING_BUFFER
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Init and start the routine CLEAN_RECORDING_BUFFER",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine CLEAN_RECORDING_BUFFER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine CLEAN_RECORDING_BUFFER_ 0",
            "TEST STEP: SD.1.1_PerformRoutineOperation_call-Check the status",
            "TEST STEP: SD.1.1_PerformRoutineOperation_return-Init and start the routine CLEAN_RECORDING_BUFFER_ 0"]
        self.test_summary_list.append(test_summary)

        # Routine identifiers
        rout_op_start = 0
        rout_op_result = 1
        statusCode = StatusCode.OK
        try:
            # Perform the diagnostic routine operations for the GenericCleanupRoutinesId items
            for generic_cleanup_routines_id in GenericCleanupRoutinesId:
                print(f"Performing cleanup operation for the item: {generic_cleanup_routines_id.name}")
                self.diagnosis_test.PerformRoutineOperation(operation=rout_op_start,
                                                            rid=generic_cleanup_routines_id.value,
                                                            length=0, databuf=None)
                self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result,
                                                            rid=generic_cleanup_routines_id.value,
                                                            length=0, databuf=None)
                # Sleep intervals to allow operations to complete
                time.sleep(5)
                self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result,
                                                            rid=generic_cleanup_routines_id.value,
                                                            length=0, databuf=None)
                time.sleep(2)  # Give time before next routine
        except grpc.RpcError as e:
            statusCode = e.code()
        # Wait for some time so that the DLT logging is received
        time.sleep(5)

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD12_DiagnosisCaptureImage(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.1.2 - Use case: Capture images from camera")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9092")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.1.2_PerformRoutineOperation_call-Init and start the GStreamerCapture",
            "TEST STEP: SD.1.2_PerformRoutineOperation_return-Init and start the routine GStreamerCapture_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.2_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.2_PerformRoutineOperation_return-Init and start the routine GStreamerCapture_ 0",
            "TEST STEP: SD.1.2_PerformRoutineOperation_call-Routine is complete",
            "TEST STEP: SD.1.2_PerformRoutineOperation_call-De-init the routine REAR_CAPTURE",
            "TEST STEP: SD.1.2_PerformRoutineOperation_return-Init and start the routine GStreamerCapture_ 0"]
        self.test_summary_list.append(test_summary)

        rear_capture = 0x32F
        rout_op_start = 0
        rout_op_result = 1
        statusCode = StatusCode.OK
        try:
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_start, rid=rear_capture, length=0,
                                                        databuf=None)
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result, rid=rear_capture, length=0,
                                                        databuf=None)
            # Sleep intervals to allow operations to complete
            time.sleep(5)
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result, rid=rear_capture, length=0,
                                                        databuf=None)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD13_EthernetTest(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.1.3 - Use case: Performing ethernet test operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "13092")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.1.3_PerformRoutineOperation_call-Init and start the EthernetTest",
            "TEST STEP: SD.1.3_PerformRoutineOperation_return-Init and start the routine TEST_ETHERNET_ 0",
            # When a call to rout_op_result is made, there is a chance that the process has already completed,
            # so the log below may not always appear. For this reason, it has been commented out.
            # "TEST STEP: SD.1.3_PerformRoutineOperation_call-Check the status",
            # "TEST STEP: SD.1.3_PerformRoutineOperation_return-Init and start the routine TEST_ETHERNET_ 0",
            "TEST STEP: SD.1.3_PerformRoutineOperation_call-Routine is complete",
            "TEST STEP: SD.1.3_PerformRoutineOperation_call-De-init the routine EthernetTest",
            "TEST STEP: SD.1.3_PerformRoutineOperation_return-Init and start the routine TEST_ETHERNET_ 0"]
        self.test_summary_list.append(test_summary)

        # Routine identifiers
        test_ethernet = 0x32C
        rout_op_start = 0
        rout_op_result = 1
        statusCode = StatusCode.OK
        try:
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_start, rid=test_ethernet, length=0,
                                                        databuf=None)
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result, rid=test_ethernet, length=0,
                                                        databuf=None)
            # Sleep intervals to allow operations to complete
            time.sleep(10)
            self.diagnosis_test.PerformRoutineOperation(operation=rout_op_result, rid=test_ethernet, length=0,
                                                        databuf=None)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @try_catch
    def SD11_DashCamCrashEvent(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.1.1 - Use case: Detected Dash cam crash event")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9188")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.1.1_SPP_SubscriberMain-call-Dashcam Event",
                                        "TEST STEP: SD1.1_OnEvent_call-StartRecording",
                                        "TEST STEP: SD1.1_OnEvent_call -Stop and SaveCapture",
                                        "TEST STEP: SD1.1_OnRecordingSaved_return-DashcamRecordFinished"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            self.dash_cam_test.SetDashcamSettings()
            time.sleep(60)
            # Send CAN message Airbag_01.AB_Crash_Int with value 7
            self.canManager.send_can_message(message_name="Airbag_01", updated_signal_name="AB_Crash_Int",
                                             updated_value=7)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Wait 1 minute for capturing video
        time.sleep(60)

        # Wait for some time so that the DLT logging is received
        time.sleep(15)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD11_EmergencyBrakeEvent(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.1.1 - Use case: Detected Emergency brake event")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9188")
        time.sleep(2)  # Give some time to gRPC
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.1.1_SPP_SubscriberMain-call-Dashcam Event",
                                        "TEST STEP: SD1.1_OnEvent_call-StartRecording",
                                        "TEST STEP: SD1.1_OnEvent_call -Stop and SaveCapture",
                                        "TEST STEP: SD1.1_OnRecordingSaved_return-DashcamRecordFinished"]
        self.test_summary_list.append(test_summary)
        statusCode = StatusCode.OK
        try:
            self.dash_cam_test.SetDashcamSettings()
            time.sleep(5)
            # Send CAN message ESP_32.ESP_Notbremsanzeige with value 1
            self.canManager.send_can_message(message_name="ESP_32", updated_signal_name="ESP_Notbremsanzeige",
                                             updated_value=1)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait 1 minute for capturing video
        time.sleep(60)

        # Wait for some time so that the DLT logging is received
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD1_UpdateLAVU(self, version: str):
        if version is None or version == "":
            print("Version provided is invalid")
            version = input("Enter the sw version (To skip perss enter): ")
            if version is None or version == '' or version == "":
                print("No SW version provided skipping SD1_UpdateLAVU!!!")
                return -1
        print(f"version : {version}")
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Software+update+functionality")
        print("TESTING: SD.1 - Use case: Pre-Update and Update")

        # Dowloading from the git the version
        v = f"http://gitlab15.local/01061-visionunit/petalinux-dev/lavu-product-petalinux/-/releases/{version}/downloads/binaries/lavu_product_{version}.swu"
        print(f"Downloading {v}")
        ConnectManager.download_file_from_git(v)

        filepath = "./sw_update/lavu_product.swu"
        if not os.path.isfile(filepath):
            print(f"Software update file is not found in the path : {os.path.abspath(filepath)}")
            return

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9107")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.1.1_PrepareUpdate",
                                        "TEST STEP: SD.1.1_PrepareUpdate_retrun- 0 - \"/media/update/lavu_product.swu\"",
                                        "TEST STEP: SD.1.1_CheckUpdate",
                                        "TEST STEP: SD.1.1_CheckUpdate_return-success",
                                        "TEST STEP: SD.1.1_StartUpdate",
                                        "TEST STEP: SD.1.1_StartUpdate_call-swupdate_prepare_req",
                                        "TEST STEP: SD.1.1_write_callback()",
                                        "TEST STEP: SD.1.3_Finish- true",
                                        "TEST STEP: SD.1.2_GetStatus_return- 15",
                                        "TEST STEP: SD.1.4_GetStatus_return- 15"]
        self.test_summary_list.append(test_summary)
        statusCode = StatusCode.OK
        try:
            # Execute test
            preparation_result = self.update_test.PrepareUpdate(size=os.path.getsize(filepath))

            # For UPD_PREPARE_SUCCESS = 0 -> the field preparationStatus.status is {}
            if not preparation_result.status == {}:
                print("Transferring update file to LAVU ...")
                ConnectManager.transfer_file(ip=self.target_ip, port=2223, source_path=filepath,
                                             remote_path="/media/update/lavu_product.swu")  # TODO change with ftp
                # Adding necessary time delay for proper processing for the request
                time.sleep(5)
                print("Transferring update file to LAVU completed")
                print("CheckUpdate started...........")
                self.update_test.CheckUpdate()
                # Adding necessary time delay for proper processing for the request
                time.sleep(1)
                ret, _ = self.update_test.checkUpdateStatus(self.update_test.GetStatus())
                while ret == 1:  # CheckUpdate ongoing
                    # Adding necessary time delay for proper processing for the request
                    time.sleep(5)
                    ret, _ = self.update_test.checkUpdateStatus(self.update_test.GetStatus())

                if ret == 2:  # Check Update success
                    print("CheckUpdate success")
                    print("StartUpdate started...........")
                    self.update_test.StartUpdate()
                    # Adding necessary time delay for proper processing for the request
                    time.sleep(10)
                    ret, _ = self.update_test.checkStartUpdateStatus(self.update_test.GetStatus())
                    while ret == 1:  # StartUpdate ongoing
                        # Adding necessary time delay for proper processing for the request
                        time.sleep(5)
                        try:
                            ret, _ = self.update_test.checkStartUpdateStatus(self.update_test.GetStatus())
                        except Exception as e:
                            print(str(e))
                            break
                    if ret == 2:
                        print("StartUpdate success")
                        time.sleep(2)
                        self.update_test.CommitInstallation()
                        print("CommitInstallation completed")
                    else:
                        print("StartUpdate failed")
                else:
                    print("CheckUpdate failed")
            else:
                print("Failed the update")

            # Wait for some time so that the DLT logging is received
            time.sleep(10)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD12_DashCamPlayback(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.1.2 - Use case: Dash cam playback operation(Play, Pause and Stop)")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12275")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD1.2_DashcamPlayerRequest_call-Play",
                                        "TEST STEP: SD1.2_DashcamPlayerRequest_return-Play_ 1",
                                        "TEST STEP: SD1.2_DashcamPlayerRequest_call-Pause",
                                        "TEST STEP: SD1.2_DashcamPlayerRequest_return-Pause_ 1",
                                        "TEST STEP: SD1.2_DashcamPlayerRequest_call-Stop",
                                        "TEST STEP: SD1.2_DashcamPlayerRequest_return-Stop_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            if self.dash_sample is None:
                self.dash_cam_test.GetDashcamRecordingList()
                time.sleep(2)
                data = self.dash_cam_test.CollectSignals("s_DashcamRecordingListUpdated")[-1]
                for d in data.element:
                    if d.duration > 30:
                        print(f"Performing dashcam request on {d.dashcam_rec_id}")
                        self.dash_sample = d
                        break

            self.dash_cam_test.DashcamPlayerRequest(pb_sts=dashcam_pb2.DashcamPlaybackStatus.DSH_PB_STS_PLAY,
                                                    dashcam_rec_id=self.dash_sample.dashcam_rec_id,
                                                    camera=dashcam_pb2.DashcamCamera.DSH_CAMERA_FRONTAL)
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)
            self.dash_cam_test.DashcamPlayerRequest(pb_sts=dashcam_pb2.DashcamPlaybackStatus.DSH_PB_STS_PAUSE,
                                                    dashcam_rec_id=self.dash_sample.dashcam_rec_id,
                                                    camera=dashcam_pb2.DashcamCamera.DSH_CAMERA_FRONTAL)
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)
            self.dash_cam_test.DashcamPlayerRequest(pb_sts=dashcam_pb2.DashcamPlaybackStatus.DSH_PB_STS_STOP,
                                                    dashcam_rec_id=self.dash_sample.dashcam_rec_id,
                                                    camera=dashcam_pb2.DashcamCamera.DSH_CAMERA_FRONTAL)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD13_DeleteDashCamRecord(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.1.3 - Use case: Dash cam record delete operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9306")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD1.3_DeleteDashcamRequest_call-Delete",
                                        "TEST STEP: SD1.3_DeleteDashcamRequest_return-Delete_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            if self.dash_sample is None:
                self.dash_cam_test.GetDashcamRecordingList()
                time.sleep(2)
                data = self.dash_cam_test.CollectSignals("s_DashcamRecordingListUpdated")[-1]
                for d in data.element:
                    if d.duration > 30:
                        print(f"Performing dashcam request on {d.dashcam_rec_id}")
                        self.dash_sample = d
                        break

            self.dash_cam_test.DeleteDashcamRequest(element=[self.dash_sample.dashcam_rec_id])
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD14_ExportDashCamRecord(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.1.4 - Use case: Dash cam record export operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9420")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD1.4_ExportDashcamRequest_call-Export dashcam records",
            "TEST STEP: SD1.4_ExportDashcamRequest_return-Export dashcam records_DashcamExportList"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            if self.dash_sample is None:
                self.dash_cam_test.GetDashcamRecordingList()
                time.sleep(2)
                data = self.dash_cam_test.CollectSignals("s_DashcamRecordingListUpdated")[-1]
                for d in data.element:
                    if d.duration > 30:
                        print(f"Performing dashcam request on {d.dashcam_rec_id}")
                        self.dash_sample = d
                        break

            self.dash_cam_test.ExportDashcamRequest(element=[self.dash_sample.dashcam_rec_id])
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD15_SetAndUnsetDashCamRecordToFavourite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.1.5 - Use case: Set and Unset Dash cam recording to favourite")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9427")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD1.5_SetDashcamFavourite_call-SetFavorite",
                                        "TEST STEP: SD1.5_SetDashcamFavourite_return-SetFavorite_ 1",
                                        "TEST STEP: SD1.5_UnsetDashcamFavourite_call-SetFavorite",
                                        "TEST STEP: SD1.5_UnsetDashcamFavourite_return-SetFavorite_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            if self.dash_sample is None:
                self.dash_cam_test.GetDashcamRecordingList()
                time.sleep(2)
                data = self.dash_cam_test.CollectSignals("s_DashcamRecordingListUpdated")[-1]
                for d in data.element:
                    if d.duration > 30:
                        print(f"Performing dashcam request on {d.dashcam_rec_id}")
                        self.dash_sample = d
                        break

            # Set favourite
            self.dash_cam_test.SetDashcamFavourite(field=self.dash_sample.dashcam_rec_id)
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)

            # UnSet favourite
            self.dash_cam_test.UnsetDashcamFavourite(field=self.dash_sample.dashcam_rec_id)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD21_MemoriesRecordingSaving(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.1 - Use case: Memories recording Saving")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9884")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.1_NewMemoriesRecordingRequest_call-StartVideoRecording",
                                        "TEST STEP: SD.2.1_NewMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 3",
                                        "TEST STEP: SD.2.1_NewMemoriesRecordingRequest_return-StartVideoRecording_ 0",
                                        "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 4",
                                        "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_call-Stop and Save Video Recording",
                                        "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 5",
                                        "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 1",
                                        "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-Stop and Save Video Recording_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            self.memory_test.NewMemoriesRecordingRequest(
                mem_rec_start_mode=memories_pb2.MemoriesRecordingStartingMode.MEM_REC_START_MODE_IMMEDIATE)
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)
            self.memory_test.StopMemoriesRecordingRequest(
                mem_rec_stop_mode=memories_pb2.MemoriesRecordingStoppingMode.MEM_REC_STOP_MODE_SAVING)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD21_MemoriesRecordingDiscarding(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.1 - Use case: Memories recording Discarding")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9884")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.2.1_NewMemoriesRecordingRequest_call-StartVideoRecording",
            "TEST STEP: SD.2.1_NewMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 3",
            "TEST STEP: SD.2.1_NewMemoriesRecordingRequest_return-StartVideoRecording_ 0",
            "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 6",
            "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 7",
            "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-MemoriesRecordingStatusUpdated_ 1",
            "TEST STEP: SD.2.1_StopMemoriesRecordingRequest_return-Stop and Discard Video Recording_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            self.memory_test.NewMemoriesRecordingRequest(
                mem_rec_start_mode=memories_pb2.MemoriesRecordingStartingMode.MEM_REC_START_MODE_IMMEDIATE)
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)
            self.memory_test.StopMemoriesRecordingRequest(
                mem_rec_stop_mode=memories_pb2.MemoriesRecordingStoppingMode.MEM_REC_STOP_MODE_DISCARDING)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD22_MemoriesPlayback(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.2 - Use case: Memories playback(Play, Pause and Stop)")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9164")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.2_MemoriesPlayerRequest_call-Play",
                                        "TEST STEP: SD.2.2_MemoriesPlayerRequest_return-Play_ 1",
                                        "TEST STEP: SD.2.2_MemoriesPlayerRequest_call-Pause",
                                        "TEST STEP: SD.2.2_MemoriesPlayerRequest_return-Pause_ 1",
                                        "TEST STEP: SD.2.2_MemoriesPlayerRequest_call-Stop",
                                        "TEST STEP: SD.2.2_MemoriesPlayerRequest_return-Stop_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Get list of memories and take first
            if self.mem_sample is None:
                self.memory_test.GetRecordingList()
                time.sleep(2)
                data = self.memory_test.CollectSignals("s_MemoriesRecordingListUpdated")[-1]
                for d in data.item:
                    print(f"Performing dashcam request on {d.memories_rec_id}")
                    self.mem_sample = d
                    break

            self.memory_test.MemoriesPlayerRequest(pb_sts=memories_pb2.MemoriesPlaybackStatus.MEM_PB_STS_PLAY,
                                                   memories_rec_id=self.mem_sample.memories_rec_id,
                                                   camera=memories_pb2.MemoriesCamera.MEM_CAM_FRONTAL)
            self.memory_test.MemoriesPlayerRequest(pb_sts=memories_pb2.MemoriesPlaybackStatus.MEM_PB_STS_PAUSE,
                                                   memories_rec_id=self.mem_sample.memories_rec_id,
                                                   camera=memories_pb2.MemoriesCamera.MEM_CAM_FRONTAL)
            self.memory_test.MemoriesPlayerRequest(pb_sts=memories_pb2.MemoriesPlaybackStatus.MEM_PB_STS_STOP,
                                                   memories_rec_id=self.mem_sample.memories_rec_id,
                                                   camera=memories_pb2.MemoriesCamera.MEM_CAM_FRONTAL)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(20)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD23_DeleteMemories(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.3 - Use case: Delete Memories")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9870")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.3_DeleteMemoriesRequest_call-Delete the recording",
                                        "TEST STEP: SD.2.3_DeleteMemoriesRequest_return-Delete the recording_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Get list of memories and take first
            if self.mem_sample is None:
                self.memory_test.GetRecordingList()
                time.sleep(2)
                data = self.memory_test.CollectSignals("s_MemoriesRecordingListUpdated")[-1]
                for d in data.item:
                    print(f"Performing dashcam request on {d.memories_rec_id}")
                    self.mem_sample = d
                    break

            # Delete the memory
            self.memory_test.DeleteMemoriesRequest(item=[self.mem_sample.memories_rec_id])
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD24_ExportMemories(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.4 - Use case: Export Memories")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9872")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.2.4_ExportMemoriesRequest_call-Export the memories",
            "TEST STEP: SD.2.4_ExportMemoriesRequest_return-Export the memories_ExportMemoriesList"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Get list of memories and take first
            if self.mem_sample is None:
                self.memory_test.GetRecordingList()
                time.sleep(2)
                data = self.memory_test.CollectSignals("s_MemoriesRecordingListUpdated")[-1]
                for d in data.item:
                    print(f"Performing dashcam request on {d.memories_rec_id}")
                    self.mem_sample = d
                    break

            # Export memories
            self.memory_test.ExportMemoriesRequest(item=[self.mem_sample.memories_rec_id])
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD25_SetMemoriesToFavourite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.5 - Use case: Set memories to favourite")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9466")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.2.5_SetMemoriesRecordingFavourite_call-Set memories recording to favorite",
            "TEST STEP: SD.2.5_SetMemoriesRecordingFavourite_return-Set memories recording to favorite_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Get list of memories and take first
            if self.mem_sample is None:
                self.memory_test.GetRecordingList()
                time.sleep(2)
                data = self.memory_test.CollectSignals("s_MemoriesRecordingListUpdated")[-1]
                for d in data.item:
                    print(f"Performing dashcam request on {d.memories_rec_id}")
                    self.mem_sample = d
                    break

            # Set memories to favourite
            self.memory_test.SetMemoriesRecordingFavourite(memories_rec_id=self.mem_sample.memories_rec_id)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD25_UnsetMemoriesToFavourite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/pages/viewpage.action?pageId=279814910")
        print("TESTING: SD.2.5 - Use case: Unset memories to favourite")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9466")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.2.5_SetMemoriesRecordingFavourite_call-remove memories recording from favorite",
            "TEST STEP: SD.2.5_SetMemoriesRecordingFavourite_return-remove memories recording from favorite_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Get list of memories and take first
            if self.mem_sample is None:
                self.memory_test.GetRecordingList()
                time.sleep(2)
                data = self.memory_test.CollectSignals("s_MemoriesRecordingListUpdated")[-1]
                for d in data.item:
                    print(f"Performing dashcam request on {d.memories_rec_id}")
                    self.mem_sample = d
                    break

            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # UnSet memories from favorite
            self.memory_test.SetMemoriesRecordingFavourite(memories_rec_id=self.mem_sample.memories_rec_id,
                                                           favourite=False)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD2_RDIOperation(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.2 - Use case: Read and write operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "8950")
        test_summary.expected_result = [
            # Logs for PROGRAMMING_DATE read only ID
            "TEST STEP: SD.2_PerformDataOperation_call- 20510 - 0",
            "TEST STEP: SD.2_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.2_PerformDataOperation-return_ 0",
            # Logs for SW_VERSION read ID
            "TEST STEP: SD.2_PerformDataOperation_call- 20508 - 0",
            "TEST STEP: SD.2_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.2_PerformDataOperation-return_ 0",
            # Logs for SW_VERSION write ID
            "TEST STEP: SD.2_PerformDataOperation_call- 20508 - 1",
            "TEST STEP: SD.2_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.2_PerformDataOperation-return_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # At present only one read only and one read write operation is added.
            # Perform Rdi read operation
            self.PerformRdiReadOnlyOperation(self.diagnosis_test)

            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

            # Perform Rdi read and write operation
            self.PerformRdiReadWriteOperation(self.diagnosis_test)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Adding necessary time delay to receive DLT logs
        time.sleep(15)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD3_CodingOperation(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.3 - Use case: Coding operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9086")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3_PerformDataOperation_call- 1536 - 1",
                                        "TEST STEP: SD.3_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
                                        "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
                                        "TEST STEP: SD.3_PerformDataOperation-return_ 0",
                                        "TEST STEP: SD.3_PerformDataOperation_call- 1536 - 1",
                                        "TEST STEP: SD.3_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
                                        "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
                                        "TEST STEP: SD.3_PerformDataOperation-return_ 0",
                                        "TEST STEP: SD.3_PerformDataOperation_call- 1536 - 0",
                                        "TEST STEP: SD.3_PerformDataOperation-return_ 1"]
        self.test_summary_list.append(test_summary)

        coding_id = 0x600
        data_op_read = 0
        data_op_write = 1
        statusCode = StatusCode.OK
        try:
            # Perform Disable operation
            # Create a bytearray of size 29, initialized with zeros
            # The first 26 bytes are all 0x00(0 to 25)
            # Byte 26 is 0x00(00000000), Front camera functionality[Bit-7] will not be available with this setting(0x80)
            # Byte 27 is 0x00(00000000)
            # The below functionalities will not be available with this setting(0x00)(00000000)
            # Emotional camera[Bit-0], Rear camera[Bit-1], Offline Telemetry[Bit-2], Offline dash camera[Bit-3],
            # Offline memories recording[Bit-4], Offline augmented reality navigation[Bit-5]
            # Byte 28 is 0x00(00000000), Video output functionality[Bit-4] will not be available with this setting(0x10)
            disable_data_buffer = bytes(bytearray(26) + bytearray([0x00, 0x00, 0x00]))
            self.diagnosis_test.PerformDataOperation(operation=data_op_write, did=coding_id,
                                                     length=len(disable_data_buffer),
                                                     databuf=disable_data_buffer)

            # Adding necessary time delay for proper processing for the request
            time.sleep(30)

            # Perform Enable operation
            # Create a bytearray of size 29, initialized with zeros
            # The first 26 bytes are all 0x00(0 to 25)
            # Byte 26 is 0x80(10000000), Front camera functionality[Bit-7] will be available with this setting(0x80)
            # Byte 27 is 0x3F(00111111)
            # The below functionalities will be available with this setting(0x3F)(00111111)
            # Emotional camera[Bit-0], Rear camera[Bit-1], Offline Telemetry[Bit-2], Offline dash camera[Bit-3],
            # Offline memories recording[Bit-4], Offline augmented reality navigation[Bit-5]
            # Byte 28 is 0x10(00010000), Video output functionality[Bit-4] will be available with this setting(0x10)
            enable_data_buffer = bytes(bytearray(26) + bytearray([0x80, 0x3F, 0x10]))
            self.diagnosis_test.PerformDataOperation(operation=data_op_write, did=coding_id,
                                                     length=len(enable_data_buffer),
                                                     databuf=enable_data_buffer)

            # Adding necessary time delay for proper processing for the request
            time.sleep(20)

            # Perform read operation
            self.diagnosis_test.PerformDataOperation(operation=data_op_read, did=coding_id, length=0, databuf=b'')
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Adding necessary time delay for getting DLT logs
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD4_IOCTLOperation(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.4 - Use case: IO control operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9096")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            # Logs for TURN_ON_FRONT_CAMERA OFF operation
            "TEST STEP: SD.4_PerformIOCtlOperation_call- 1488 - 0",
            "TEST STEP: SD.4_PerformIOCtlOperation_call-Init and start Cameraioctl",
            "TEST STEP: SD.4_PerformIOCtlOperation_return- 0",
            # Logs for TURN_ON_EMOTION_CAMERA OFF operation
            "TEST STEP: SD.4_PerformIOCtlOperation_call- 1489 - 0",
            "TEST STEP: SD.4_PerformIOCtlOperation_call-Init and start Cameraioctl",
            "TEST STEP: SD.4_PerformIOCtlOperation_return- 0",
            # Logs for TURN_ON_REAR_CAMERA OFF operation
            "TEST STEP: SD.4_PerformIOCtlOperation_call- 1490 - 0",
            "TEST STEP: SD.4_PerformIOCtlOperation_call-Init and start Cameraioctl",
            "TEST STEP: SD.4_PerformIOCtlOperation_return- 0",
            # Logs for TURN_ON_FRONT_CAMERA ON operation
            "TEST STEP: SD.4_PerformIOCtlOperation_call- 1488 - 1",
            "TEST STEP: SD.4_PerformIOCtlOperation_return- 0",
            # Logs for TURN_ON_EMOTION_CAMERA ON operation
            "TEST STEP: SD.4_PerformIOCtlOperation_call- 1489 - 1",
            "TEST STEP: SD.4_PerformIOCtlOperation_return- 0",
            # Logs for TURN_ON_REAR_CAMERA ON operation
            "TEST STEP: SD.4_PerformIOCtlOperation_call- 1490 - 1",
            "TEST STEP: SD.4_PerformIOCtlOperation_return- 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            self.PerformIoctlTurnOffOnOperation(self.diagnosis_test)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Adding necessary time delay for getting DLT logs
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD5_MeasurementOperation(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.5 - Use case: Measurement operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9102")
        # Todo: Add logs for verification here. The order should match the execution order.
        test_summary.expected_result = [
            # Logs for TOTAL_OPERATING_TIME read id
            "TEST STEP: SD.5_PerformDataOperation_call- 5536 - 0",
            "TEST STEP: SD.5_TotalSysTimeCommand",
            "TEST STEP: SD.5_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.5_PerformDataOperation-return_ 0",
            # Logs for OPERATING_TIME read id
            "TEST STEP: SD.5_PerformDataOperation_call- 5537 - 0",
            "TEST STEP: SD.5_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.5_PerformDataOperation-return_ 0",
            # Logs for RESET_NUMBER read id
            "TEST STEP: SD.5_PerformDataOperation_call- 5538 - 0",
            "TEST STEP: SD.5_EEpromReadCommand-0",
            "TEST STEP: SD.5_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.5_PerformDataOperation-return_ 0",
            # Logs for POWER_MANAGEMENT_TIMERS read id
            "TEST STEP: SD.5_PerformDataOperation_call- 5539 - 0",
            "TEST STEP: SD.5_GetPwrTimersCommand",
            "TEST STEP: SD.5_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.5_PerformDataOperation-return_ 0",
            # Logs for AUDIO_DELAY read id
            "TEST STEP: SD.5_PerformDataOperation_call- 5540 - 0",
            "TEST STEP: SD.5_EEpromReadCommand-0",
            "TEST STEP: SD.5_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.5_PerformDataOperation-return_ 0",
            # Logs for STORAGE_GLOBAL_STATUS read id
            "TEST STEP: SD.5_PerformDataOperation_call- 5541 - 0",
            "TEST STEP: SD.5_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.5_PerformDataOperation-return_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            self.PerformMeasurementReadOperation(self.diagnosis_test)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Adding necessary time delay for getting DLT logs
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD6_AdaptionOperation(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.6 - Use case: Adaption services command")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9257")
        test_summary.expected_result = [
            # Logs for POWER_MANAGEMENT_TIMERS read id
            "TEST STEP: SD.6_PerformDataOperation_call- 1505 - 0",
            "TEST STEP: SD.6_GetPwrTimersCommand",
            "TEST STEP: SD.6_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.6_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.6_PerformDataOperation-return_ 0",
            # Logs for AUDIO_DELAY read id
            "TEST STEP: SD.6_PerformDataOperation_call- 1506 - 0",
            "TEST STEP: SD.6_EEpromReadCommand-0",
            "TEST STEP: SD.6_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.6_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.6_PerformDataOperation-return_ 0",
            # Logs for POWER_MANAGEMENT_TIMERS write id
            "TEST STEP: SD.6_PerformDataOperation_call- 1505 - 1",
            "TEST STEP: SD.6_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.6_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.6_PerformDataOperation-return_ 0",
            # Logs for AUDIO_DELAY write id
            "TEST STEP: SD.6_PerformDataOperation_call- 1506 - 1",
            "TEST STEP: SD.6_SPP_DoReceiveEvent_call-sends package via ZMQ channel",
            "TEST STEP: SD.6_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
            "TEST STEP: SD.6_PerformDataOperation-return_ 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            self.PerformAdaptionReadwriteOperation(self.diagnosis_test)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Adding necessary time delay for getting DLT logs
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD7_EthernetFaultDetection(self, can_present=True):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Diagnosis+functionality")
        print("TESTING: SD.7 - Use case: Ethernet fault detection")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9163")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.7_Ping()",
                                        "TEST STEP: SD.7_Ping()_return-Pong()",
                                        "TEST STEP: SD.7_EthernetFaultsCommand",
                                        "TEST STEP: SD.7_SPP_DoReceiveEvent_call-sends package via ZMQ channel"]

        statusCode = StatusCode.OK
        try:
            system_test = SystemTest(self.grpc_manager.GetGrpcConnectionChannel())
            time.sleep(2)  # Giving time for gRPC to connect
            # Start the P-CAN message receiver thread so that message can be tracked
            self.canManager.StartCanReceiverThread(message_name="VU_HU_FAULT", signal_name="xD8A900")
            system_test.Ping()
            # Adding necessary time delay for completing P-CAN operation. After 5 seconds we should see the fault
            print("Waiting 20 seconds after last ping issued")
            time.sleep(20)
            # Stop the P-CAN message receiver thread
            self.canManager.StopCanReceiverThread()

            rcv = False
            if can_present:
                # Add P-CAN message expected result
                test_summary.expected_result.append("TEST STEP: SD.7_Ethernet failure P-CAN message received")

                # Check whether P-CAN message received
                if self.canManager.MatchEthFaultCanSignalValue(value_to_match=1):
                    rcv = True
            else:
                print("CAN not available skipping can check")

            self.test_summary_list.append(test_summary)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        if rcv:
            self.VerifyDltLogs(test_summary, ["TEST STEP: SD.7_Ethernet failure P-CAN message received"])
        else:
            self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD1_TelemetryTrackMapRecordingImproperRequest(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.1 - Use case: Telemetry track map recording with improper request")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9601")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.1_StartNewTrackRecord_return-StartNewTrackRecord_ 2"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # TEST CASE SCENARIO START
            # Test Step : Execute improper argument fail test track recording start request
            self.telemetry_test.StartNewTrackRecord(track_name="", driver_name="")
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD1_TelemetryTrackMapRecordingProperRequest(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.1 - Use case: Telemetry track map recording with proper request")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9601")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.1_StartNewTrackRecord_call-initRecordTrack",
            "TEST STEP: SD.1_StartNewTrackRecord_return-StartNewTrackRecord_ 1",
            "TEST STEP: SD.1_OnRecordInited_call-startRecordTrack",
            "TEST STEP: SD.1_OnRecordStarted_call-SetStatus_TelemetryStatus::TLM_STATUS_RECORDING",
            "TEST STEP: SD.1_UpdateTracks_return-TrackListUpdated_TrackDataList",
            "TEST STEP: SD.1_OnClosedTrackFound_call-SetStatus_TelemetryStatus::TLM_STATUS_SAVING_RECORD",
            "TEST STEP: SD.1_OnClosedTrackFound_call-stopRecordTrack",
            "TEST STEP: SD.1_OnClosedTrackFound_call-saveRecordedTrack",
            "TEST STEP: SD.1_OnClosedTrackFound_call-discardRecording",
            "TEST STEP: SD.1_OnTrackSaved_call-setListOfTracks"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # TEST CASE SCENARIO START
            # Test Step : Execute proper argument track recording start
            # We must use at least a naming convention in order to sind out the name of the track for later tests
            tmp = "SWIT_L2_Track_"
            tmp = tmp + self.GenerateUniqueName()
            self.telemetry_test.StartNewTrackRecord(track_name=tmp, driver_name="Test_driver")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)
            # TEST CASE SCENARIO END

            # Continue the race to finish the loop(start to end closed loop)
            # Perform 5 laps also on the track so that the track recording saving is enabled.
            self.PerformLapOnTheTrack(self.gps_test)

            # Adding necessary time delay for proper processing for the request
            time.sleep(10)

            # Finish the track recording by canceling the race so that the race is saved
            # If this is not called then the track recording will not be saved.
            self.telemetry_test.CancelRace()
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD211_TelemetrySectorManagementSelectASectorToEdit(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.1.1 - Use case: Select a sector to edit")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9606")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.1.1_GetSectors_call-UpdateTrackSectors",
                                        "TEST STEP: SD.2.1.1_GetSectors_return-UpdateTrackSectors_ 1",
                                        "TEST STEP: SD.2.1.1_SelectSector_call-setCursorPosition",
                                        "TEST STEP: SD.2.1.1_SelectSector_return-setCursorPosition_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # PRECONDITION START : At least one track recording is happening
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])

            # Start a new track record for telemetry track management testing
            tmp = "SWIT_L2_Track_"
            tmp = tmp + self.GenerateUniqueName()
            self.telemetry_test.StartNewTrackRecord(track_name=tmp, driver_name="Test_driver")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)
            self.telemetry_test.GetSectors(track_id='0')

            # Move to some position on the track in initial lap
            counter = 0
            for position_data in self.position_data_list[1:]:
                self.gps_test.NewPositionData(position_data=position_data)
                # Adding necessary time delay for proper processing GPS position
                time.sleep(0.01)
                counter += 1
                # if randint(0, 10) == 1:
                if counter == 300 or counter == 800:
                    self.telemetry_test.AddSector()
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)
            # PRECONDITION END : track is added with sectors

            self.dlt_manager.queueDlt.clear_queue()
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)

            # TEST CASE SCENARIO START
            # Test Step 1 : Tester opens Track Editor on a selected track
            self.telemetry_test.GetSectors(track_id='0')
            # Test Step 2 : Tester selects a Sector to edit
            self.telemetry_test.SelectSector(sector_index=0)
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Adding necessary time delay for proper processing DLT logs
        time.sleep(20)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)

        # Cleanup : Finish the track recording by canceling the race
        self.telemetry_test.CancelRace()
        return test_summary

    @retry_tests
    def SD212_TelemetrySectorManagementAddOrRemoveASector(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.1.2 - Use case: Add or remove a sector on a track")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12166")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.1.2_AddSector_call-addSplit",
                                        "TEST STEP: SD.2.1.2_AddSector_call-UpdateTrackSectors",
                                        "TEST STEP: SD.2.1.2_AddSector_return-addSplit_ 1",
                                        "TEST STEP: SD.2.1.2_RemoveSector_call-removeSplit",
                                        "TEST STEP: SD.2.1.2_RemoveSector_call-UpdateTrackSectors",
                                        "TEST STEP: SD.2.1.2_RemoveSector_return-addSplit_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # PRECONDITION START : At least one track recording is happening
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])
            # Start a new track record for telemetry track management testing
            tmp = "SWIT_L2_Track_"
            tmp = tmp + self.GenerateUniqueName()
            self.telemetry_test.StartNewTrackRecord(track_name=tmp, driver_name="Test_driver")
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)

            self.telemetry_test.GetSectors(track_id='0')
            # PRECONDITION END : a track recording is in memory

            # TEST CASE SCENARIO START
            # Test Step 1 : Tester adds sector to the track
            counter = 0
            # Move to some position on the track in initial lap
            for position_data in self.position_data_list[1:]:
                self.gps_test.NewPositionData(position_data=position_data)
                # Adding necessary time delay for proper processing GPS position
                time.sleep(0.01)
                counter += 1
                # if randint(0, 10) == 1:
                if counter == 300 or counter == 800:
                    self.telemetry_test.AddSector()
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)
            # Test Step 2 : Tester remove sector from the track
            self.telemetry_test.RemoveSector()
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Adding necessary time delay for proper processing DLT logs
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)

        # Cleanup : Finish the track recording by canceling the race
        self.telemetry_test.CancelRace()
        # Adding necessary time delay for proper processing for the request
        time.sleep(5)
        return test_summary

    @retry_tests
    def SD213_TelemetrySectorManagementSaveASectorChanges(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.1.3 - Use case: Save sector changes")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12170")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.1.3_SaveSectorChanges_call-saveTrackAs",
                                        "TEST STEP: SD.2.1.3_SaveSectorChanges_return-saveTrackAs_ 1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # PRECONDITION START : At least one track recording is happening
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])

            # Start a new track record for telemetry track management testing
            tmp = "SWIT_L2_Track_"
            tmp = tmp + self.GenerateUniqueName()
            self.telemetry_test.StartNewTrackRecord(track_name=tmp, driver_name="Test_driver")
            # Adding necessary time delay for proper processing for the request
            time.sleep(30)
            self.telemetry_test.GetSectors(track_id='0')

            # Move to some position on the track in initial lap
            counter = 0
            for position_data in self.position_data_list[1:]:
                self.gps_test.NewPositionData(position_data=position_data)
                # Adding necessary time delay for proper processing GPS position
                time.sleep(0.01)
                counter += 1
                # if randint(0, 10) == 1:
                if counter == 300 or counter == 800:
                    self.telemetry_test.AddSector()
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)

            self.dlt_manager.queueDlt.clear_queue()
            # Adding necessary time delay for proper processing for the request
            time.sleep(4)
            # PRECONDITION END : A track recording is in memory having sectors

            # TEST CASE SCENARIO START
            # Save the sector with new track name
            self.telemetry_test.SaveSectorsChanges(new_track_name=self.GenerateUniqueName())
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Adding necessary time delay for proper processing DLT logs
        time.sleep(60)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)

        # Cleanup : Finish the race
        self.telemetry_test.CancelRace()
        # Adding necessary time delay for proper processing for the request
        time.sleep(10)
        return test_summary

    @retry_tests
    def SD213_TelemetrySectorManagementDiscardASectorChanges(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.1.3 - Use case: Discard a sector change")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12170")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.1.3_SaveSectorChanges_return-saveTrackAs_ 1"]
        self.test_summary_list.append(test_summary)
        statusCode = StatusCode.OK
        try:
            # PRECONDITION START : At least one track recording is happening
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])

            # Start a new track record for telemetry track management testing
            track_name = self.GenerateUniqueName()
            self.telemetry_test.StartNewTrackRecord(track_name=track_name, driver_name="Test_driver")
            # Adding necessary time delay for proper processing for the request
            time.sleep(60)

            sectors = self.telemetry_test.GetSectors(track_id='0')
            # Move to some position on the track in initial lap
            counter = 0
            for position_data in self.position_data_list[1:]:
                self.gps_test.NewPositionData(position_data=position_data)
                # Adding necessary time delay for proper processing for GPS position
                time.sleep(0.01)
                counter += 1
                # if randint(0, 10) == 1:
                if counter == 300 or counter == 800:
                    self.telemetry_test.AddSector()
            # Adding necessary time delay for proper processing for the request
            time.sleep(10)

            self.dlt_manager.queueDlt.clear_queue()
            # Adding necessary time delay for proper processing for the request
            time.sleep(4)

            self.telemetry_test.SaveSectorsChanges(new_track_name=self.GenerateUniqueName())
            self.dlt_manager.queueDlt.clear_queue()
            # PRECONDITION END : A track recording is in memory having sectors

            # TEST CASE SCENARIO START
            # SD.2.1.3 - Discard a Sector changes
            self.telemetry_test.DiscardSectorsChanges()
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Adding necessary time delay for proper processing for the request
        time.sleep(60)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)

        # Cleanup : Finish the race
        self.telemetry_test.CancelRace()
        # Adding necessary time delay for proper processing for the request
        time.sleep(10)
        return test_summary

    @retry_tests
    def SD22_TelemetryTrackManagementExportTrackAndSessionsData(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.2 - Use case: Export a track and it's session")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12171")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.2_TelemetryExportTrack_call-getTrackName",
                                        "TEST STEP: SD.2.2_TelemetryExportTrack_return-getTrackName_",
                                        "TEST STEP: SD.2.2_TelemetryExportTrack_get_track_files_and_sizes",
                                        "TEST STEP: SD.2.2_TelemetryExportTrack_call-getSessionsFromTrack",
                                        "TEST STEP: SD.2.2_TelemetryExportTrack_return-getSessionsFromTrack"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # TEST CASE SCENARIO START
            # SD.2.2 - Export Track and Sessions data
            self.telemetry_test.TelemetryExportTrack(track_id='0')
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Adding necessary time delay for receiving DLT logs
        time.sleep(5)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD23_TelemetryTrackManagementSetATrackAsFavorite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.3 - Use case: Set a track as favorite")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12271")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.3_SetTrackFavourite_call-getTrackName",
                                        "TEST STEP: SD.2.3_SetTrackFavourite_return-getTrackName_",
                                        "TEST STEP: SD.2.3_SetTrackFavourite_Set_track_to_favourites",
                                        "TEST STEP: SD.2.3_SetTrackFavourite_call-UpdateTracks",
                                        "TEST STEP: SD.1_UpdateTracks_return-TrackListUpdated_TrackDataList"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # TEST CASE SCENARIO START
            # SD.2.3 - Set/Unset a track as favourite
            self.telemetry_test.SetTrackFavourite(field='0')
            # TEST CASE SCENARIO END

            # Adding necessary time delay for receiving DLT logs
            time.sleep(5)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD23_TelemetryTrackManagementUnsetATrackAsFavorite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.3 - Use case: Remove a track from favorites")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12271")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.2.3_UnsetTrackFavourite_call-getTrackName",
                                        "TEST STEP: SD.2.3_UnsetTrackFavourite_return-getTrackName_",
                                        "TEST STEP: SD.2.3_UnsetTrackFavourite_Unset_track_to_favourites",
                                        "TEST STEP: SD.2.3_UnsetTrackFavourite_call-UpdateTracks",
                                        "TEST STEP: SD.1_UpdateTracks_return-TrackListUpdated_TrackDataList"
                                        ]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # TEST CASE SCENARIO START
            # SD.2.3 - Set/Unset a track as favourite
            self.telemetry_test.UnsetTrackFavourite(field='0')
            # TEST CASE SCENARIO END
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Adding necessary time delay for receiving DLT logs
        time.sleep(5)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD24_ImportTracksAndSessions(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.2.4 - Use case: Telemetry Import: PrepareImport and FinalizeImport")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "13514")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.2.4_PrepareImport_call",
            "TEST STEP: SD.2.4_FinalizeImport_return_ 1"
        ]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # Start the test
            print("Calling PrepareImport...")
            s = f"Import_SWIT_L2_{self.GenerateUniqueName()}"
            self.telemetry_test.PrepareImport(msg_sts=telemetry_pb2.TelemetryMsgStatus.TLM_MSG_STS_OK,
                                              datas=s)

            # Wait for 5 seconds
            time.sleep(30)

            print("Calling FinalizeImport...")
            self.telemetry_test.FinalizeImport()
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Allow time for DLT logs to be captured
        time.sleep(30)

        # Verify the DLT logs received from the server against the expected results
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD31_TelemetrySessionManagementStartSession(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.1 - Use case: Start session telemetry Session management")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9660")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3.1_StartRace_call-initRace",
                                        "TEST STEP: SD.3.1_StartRace_return-initRace_ 1",
                                        "TEST STEP: SD.3.1_OnRaceInited_call-startRace",
                                        "TEST STEP: SD.3.1_OnRaceStarted_call-StartVideoRecording",
                                        "TEST STEP: SD.3.1_OnUpdateLapTime",
                                        "TEST STEP: SD.3.1_OnUpdateDiffTime",
                                        "TEST STEP: SD.3.1_OnLapClosed",
                                        "TEST STEP: SD.3.1_OnRaceCanBeSaved",
                                        "TEST STEP: SD.3.1_OnUpdateBestLap",
                                        "TEST STEP: SD.3.1_OnUpdateLaps"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # TEST CASE SCENARIO START
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            if self.track_sample is not None:
                # New session has to be run on Our track
                self.telemetry_test.StartNewSession(track_name=self.track_sample.track_id, driver_name="Test_driver")
                # Adding necessary time delay for proper processing for the request
                time.sleep(5)

                # Continue the race to finish the loop(start to end closed loop)
                self.PerformLapOnTheTrack(self.gps_test)
                # TEST CASE SCENARIO END

                # Adding necessary time delay for proper processing for the request
                time.sleep(10)

                # Finish the track recording by canceling the race
                self.telemetry_test.CancelRace()

                # Adding necessary time delay for proper processing of DLT logs
                time.sleep(10)
            else:
                print("Test precondition NOT met")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD31_TelemetrySessionManagementStartSessionOutOfTrack(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.1 - Use case: Start session telemetry Session management for out of track scenario")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "9660")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3.1_StartRace_call-initRace",
                                        "TEST STEP: SD.3.1_StartRace_return-initRace_ 1",
                                        "TEST STEP: SD.3.1_OnRaceInited_call-startRace",
                                        "TEST STEP: SD.3.1_OnRaceStarted_call-StartVideoRecording",
                                        "TEST STEP: SD.3.1_OnInvalidLap_notify-OutOfTrack"]
        self.test_summary_list.append(test_summary)
        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # TEST CASE SCENARIO START
            # SD.3.1 - Telemetry Session management start session having out of track scenario
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])

            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            if self.track_sample is not None:
                # Start a Session on the last saved track
                self.telemetry_test.StartNewSession(track_name=self.track_sample.track_id, driver_name="Test_driver")
                # Adding necessary time delay for proper processing for the request
                time.sleep(5)
                # perform 5 lap on the track and move to some position on the track
                self.PerformLapOnTheTrack(self.gps_test, True)
                # Adding necessary time delay for proper processing for the request
                time.sleep(15)
                # Race to an out of track path
                for _ in range(4):
                    for out_of_track_position_data in self.out_of_track_position_data_list:
                        self.gps_test.NewPositionData(position_data=out_of_track_position_data)
                        # Adding necessary time delay for proper processing for GPS update
                        time.sleep(0.01)
                # Adding necessary time delay for proper processing for the request
                time.sleep(10)
                # TEST CASE SCENARIO END

                # Cancel the out of track session by canceling the race
                self.telemetry_test.CancelRace()

                # Adding necessary time delay for proper processing  DLT logs
                time.sleep(10)
            else:
                print("Test precondition NOT met")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD32_TelemetrySessionManagementStopSession(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.2 - Use case: Stop session telemetry Session management where RaceCanBeSaved is True")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12272")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3.1_OnRaceCanBeSaved",
                                        "TEST STEP: SD.3.2_OnLogSaved",
                                        "TEST STEP: SD.3.2_OnLogSaved_call-SaveVideoRecording",
                                        "TEST STEP: SD.3.2_CancelRace_call-StopVideoRecording",
                                        "TEST STEP: SD.3.2_CancelRace_call-stopRace",
                                        "TEST STEP: SD.3.2_CancelRace_call-saveRace"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # SD.3.2 - Telemetry Session management Stop session having "RaceCanBeSaved" True scenario
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            if self.track_sample is not None:
                # Start a Session on the last saved track
                self.telemetry_test.StartNewSession(track_name=self.track_sample.track_id, driver_name="Test_driver")
                # Adding necessary time delay for proper processing for the request
                time.sleep(5)
                # Race through the track from start to end(one lap completed and "RaceCanBeSaved" will be True)
                for position_data in self.position_data_list[1:]:
                    self.gps_test.NewPositionData(position_data=position_data)
                    # Adding necessary time delay for proper processing for GPS update
                    time.sleep(0.01)
                for _ in range(4):
                    for position_data in self.position_data_list:
                        self.gps_test.NewPositionData(position_data=position_data)
                        # Adding necessary time delay for proper processing for GPS update
                        time.sleep(0.01)
                # Adding necessary time delay for proper processing for the request
                time.sleep(10)
                # Stop the session by cancelling the race
                self.telemetry_test.CancelRace()
                # Adding necessary time delay for proper processing for the request
                time.sleep(10)
            else:
                print("Test precondition NOT met")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD32_TelemetrySessionManagementStopSessionRaceCanBeSavedFalse(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.2 - Use case: Stop session telemetry Session management where RaceCanBeSaved is False")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12272")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3.2_OnLogDiscarded",
                                        "TEST STEP: SD.3.2_CancelRace_call-quitRace"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # SD.3.2 - Telemetry Session management Stop session having "RaceCanBeSaved" False scenario
            # Set the start position for the race
            self.gps_test.NewPositionData(position_data=self.position_data_list[0])

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            if self.track_sample is not None:
                # Start a Session on the last saved track
                self.telemetry_test.StartNewSession(track_name=self.track_sample.track_id, driver_name="Test_driver")

                # Race through the track for one lap
                for position_data in self.position_data_list[1:]:
                    self.gps_test.NewPositionData(position_data=position_data)
                    # Adding necessary time delay for proper processing for GPS update
                    time.sleep(0.01)
                # Do one more lap on the track so that status is changed to "TLM_STATUS_RACING"
                for _ in range(1):
                    for position_data in self.position_data_list:
                        self.gps_test.NewPositionData(position_data=position_data)
                        # Adding necessary time delay for proper processing for GPS update
                        time.sleep(0.01)
                # Adding necessary time delay for proper processing for the request
                time.sleep(3)
                # Stop the session by cancelling the race
                self.telemetry_test.CancelRace()
                time.sleep(2)
                # Calling again to trigger the usecase
                self.telemetry_test.CancelRace()
                # Adding necessary time delay for proper processing for DLT logs
                time.sleep(10)
            else:
                print("Test precondition NOT met")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD33_SetSessionAsFavorite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.3 - Use case: Set a session as favorite")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12274")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3.3_SetSessionFavourite_call-getSessionsFromTrack",
                                        "TEST STEP: SD.3.3_SetSessionFavourite_return-getSessionsFromTrack_",
                                        "TEST STEP: SD.3.3_SetSessionFavourite_add_session_to_favourites",
                                        "TEST STEP: SD.3.3_SetSessionFavourite_call-UpdateSessions"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            if self.track_sample is not None:
                self.telemetry_test.UnsetSessionFavourite(track_id=self.track_sample.track_id, session_id="0")
                # Adding necessary time delay for proper processing for the request
                time.sleep(4)
                # SD.3.3 - Set/Unset Session as favourite
                self.telemetry_test.SetSessionFavourite(track_id=self.track_sample.track_id, session_id='0')
                # Adding necessary time delay for proper processing for DLT logs
                time.sleep(5)
            else:
                print("Test precondition NOT met")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD33_UnsetSessionAsFavorite(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.3 - Use case: Unset a session as favorite")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12274")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3.3_UnsetSessionFavourite_call-getSessionsFromTrack",
                                        "TEST STEP: SD.3.3_UnsetSessionFavourite_return-getSessionsFromTrack_",
                                        "TEST STEP: SD.3.3_UnsetSessionFavourite_remove_session_to_favourites",
                                        "TEST STEP: SD.3.3_UnsetSessionFavourite_call-UpdateSessions"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            if self.track_sample is not None:
                self.telemetry_test.UnsetSessionFavourite(track_id=self.track_sample.track_id, session_id="0")
                # Adding necessary time delay for proper processing for DLT logs
                time.sleep(5)
            else:
                print("Test precondition NOT met")

        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD34_DeleteSessions(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.3.4 - Use case: delete session")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "13512")
        test_summary.expected_result = [
            "TEST STEP: SD.3.4_DeleteSessions_call",
            "TEST STEP: SD.3.4_DeleteFinished"
        ]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Track {d.track_id}")
                        self.track_sample = d
                        break

            # Getting list of session for such track
            if self.tml_session_sample is None:
                self.telemetry_test.GetSessionList(field=self.track_sample.track_id)
                time.sleep(2)
                ss = self.telemetry_test.CollectSignals("s_SessionListUpdated")[-1]
                for d in ss.element:
                    # Taking first for now
                    self.tml_session_sample = (d.track_id, d.session_id)
                    print(f"Using for test track {self.tml_session_sample[0]} and session {self.tml_session_sample[1]}")
                    break
            # Prepare session IDs to delete
            session_ids = [
                telemetry_pb2.TelemetrySessionId(track_id=self.tml_session_sample[0],
                                                 session_id=self.tml_session_sample[1]),
            ]

            # Start the test
            print("Calling DeleteSessions...")
            response = self.telemetry_test.DeleteSessions(session_ids)

            # Check the response
            if response and response.field == telemetry_pb2.TLM_RET_SUCCESS:
                print("DeleteSessions succeeded.")
            else:
                print("DeleteSessions failed.")

            # Allow time for DLT logs to be captured
            time.sleep(5)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD4_TelemetrySessionAnalysisSessionLap(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.4 - Use case: Telemetry Session Analysis for session lap")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "11820")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.4_RequestAnalysisData_call-getSessionsFromTrack_TLM_QUERY_SESSION_LAP",
            "TEST STEP: SD.4_RequestAnalysisData_return-getSessionsFromTrack_",
            "TEST STEP: SD.4_RequestAnalysisData_call-getLapsFromArchive",
            "TEST STEP: SD.4_RequestAnalysisData_return-getLapsFromArchive_"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            # Getting list of session for such track
            if self.tml_session_sample is None:
                self.telemetry_test.GetSessionList(field=self.track_sample.track_id)
                time.sleep(2)
                ss = self.telemetry_test.CollectSignals("s_SessionListUpdated")[-1]
                for d in ss.element:
                    # Taking first for now
                    self.tml_session_sample = (d.track_id, d.session_id)
                    print(f"Using for test track {self.tml_session_sample[0]} and session {self.tml_session_sample[1]}")
                    break

            if self.track_sample is not None and self.tml_session_sample is not None:
                # Run the test to obtain the session lap data
                self.telemetry_test.RequestAnalysisData(
                    query_type=telemetry_pb2.TelemetryAnalysisQueryType.TLM_QUERY_SESSION_LAP,
                    track_id=self.tml_session_sample[0], session_id=self.tml_session_sample[1])

                # Adding necessary time delay for receiving DLT logs
                time.sleep(30)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD4_TelemetrySessionAnalysisSessionBest(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.4 - Use case: Telemetry Session Analysis for session best")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "11820")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = [
            "TEST STEP: SD.4_RequestAnalysisData_call-getSessionsFromTrack_TLM_QUERY_SESSION_BEST",
            "TEST STEP: SD.4_RequestAnalysisData_return-getSessionsFromTrack"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            # Getting list of session for such track
            if self.tml_session_sample is None:
                self.telemetry_test.GetSessionList(field=self.track_sample.track_id)
                time.sleep(2)
                ss = self.telemetry_test.CollectSignals("s_SessionListUpdated")[-1]
                for d in ss.element:
                    # Taking first for now
                    self.tml_session_sample = (d.track_id, d.session_id)
                    print(f"Using for test track {self.tml_session_sample[0]} and session {self.tml_session_sample[1]}")
                    break

            if self.track_sample is not None and self.tml_session_sample is not None:
                # Run the test to obtain the sessions best
                self.telemetry_test.RequestAnalysisData(
                    query_type=telemetry_pb2.TelemetryAnalysisQueryType.TLM_QUERY_SESSION_BEST,
                    track_id=self.tml_session_sample[0], session_id=self.tml_session_sample[1])

                # Adding necessary time delay for proper processing for the request
                time.sleep(30)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD4_TelemetrySessionAnalysisPersonalBest(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.4 - Use case: Telemetry Session Analysis for personal best")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "11820")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.4_RequestAnalysisData_call-getPersonalBest",
                                        "TEST STEP: SD.4_RequestAnalysisData_return-getPersonalBest -1"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            if self.track_sample is None:
                self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
                time.sleep(2)
                data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
                for d in data.element:
                    if d.name.startswith("SWIT_L2_Track_", 0):
                        print(f"Starting new session on track {d.track_id}")
                        self.track_sample = d
                        break

            # Getting list of session for such track
            if self.tml_session_sample is None:
                self.telemetry_test.GetSessionList(field=self.track_sample.track_id)
                time.sleep(2)
                ss = self.telemetry_test.CollectSignals("s_SessionListUpdated")[-1]
                for d in ss.element:
                    # Taking first for now
                    self.tml_session_sample = (d.track_id, d.session_id)
                    print(f"Using for test track {self.tml_session_sample[0]} and session {self.tml_session_sample[1]}")
                    break

            if self.track_sample is not None and self.tml_session_sample is not None:
                # Run the test to obtain the personal best
                self.telemetry_test.RequestAnalysisData(
                    query_type=telemetry_pb2.TelemetryAnalysisQueryType.TLM_QUERY_PERSONAL_BEST,
                    track_id=self.tml_session_sample[0], session_id=self.tml_session_sample[1],
                    driver_name="Test_driver_A")
                # Adding necessary time delay for receiving DLT logs
                time.sleep(30)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD4_TelemetrySessionAnalysisAbsoluteBest(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Telemetry+functionality")
        print("TESTING: SD.4 - Use case: Telemetry Session Analysis for Absolute best")

        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "11820")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.4_RequestAnalysisData_call-getAbsoluteBest",
                                        "TEST STEP: SD.4_RequestAnalysisData_return-getPersonalBest 0"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Clear the DLT queue before starting the test
            self.dlt_manager.queueDlt.clear_queue()

            # PRECODITION: Get track list name
            self.telemetry_test.GetTrackList()  # This is void, we have to wait for signal
            time.sleep(2)
            data = self.telemetry_test.CollectSignals("s_TrackListUpdated")[-1]
            selected_track: telemetry_pb2.TrackData = 0
            for d in data.element:
                if d.name.startswith("SWIT_L2_Track_", 0):
                    print(f"Starting new session on track {d.track_id}")
                    selected_track = d
                    break

            if selected_track is not None:
                # Run the test to obtain the absolute best
                self.telemetry_test.RequestAnalysisData(
                    query_type=telemetry_pb2.TelemetryAnalysisQueryType.TLM_QUERY_ABSOLUTE_BEST,
                    track_id=selected_track.track_id)
                # Adding necessary time delay for receiving DLT logs
                time.sleep(30)
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD1_IPSec(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Cybersecurity+functionality")
        print("TESTING: SD.1 - Use case: IP security")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12952")
        test_summary.expected_result = ["TEST STEP: SD.1_IPV6 secure connection is established",
                                        "TEST STEP: SD.1_IPV4 insecure connection is not established"]
        self.test_summary_list.append(test_summary)

        statusCode = StatusCode.OK
        try:
            # Test for IPV4 connection
            grpc_manager = GrpcManager("10.0.10.196", "8866")
            grpc_manager.grpc_connect()

            additional_obs = []
            # Check whether IPV6 gRPC connection is success. If so test passed.
            if self.grpc_manager.GetGrpcConnectionChannel() is not None:
                additional_obs.append("TEST STEP: SD.1_IPV6 secure connection is established")
            # Check whether IPV4 gRPC connection is failed. If so test passed.
            if grpc_manager.GetGrpcConnectionChannel() is None:
                additional_obs.append("TEST STEP: SD.1_IPV4 insecure connection is not established")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary, additional_observed=additional_obs)
        return test_summary

    @retry_tests
    def SD2_SecureBoot(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Cybersecurity+functionality")
        print("TESTING: SD.2 - Use case: Secure boot operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name)
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.1.1_PrepareUpdate",
                                        "TEST STEP: SD.1.1_PrepareUpdate_retrun- 0 - \"/media/update/lavu_product.swu\"",
                                        "TEST STEP: SD.1.1_CheckUpdate",
                                        "TEST STEP: SD.1.1_CheckUpdate_return-success",
                                        "TEST STEP: SD.1.1_StartUpdate",
                                        "TEST STEP: SD.1.1_StartUpdate_call-swupdate_prepare_req",
                                        "TEST STEP: SD.1.1_write_callback()",
                                        "TEST STEP: SD.1.3_Finish- true",
                                        "TEST STEP: SD.1.2_GetStatus_return- 15",
                                        "TEST STEP: SD.1.4_GetStatus_return- 15"]
        self.test_summary_list.append(test_summary)

        filepath = "./sw_update/lavu_product.swu"
        if not os.path.isfile(filepath):
            print(f"Software update file is not found in the path : {os.path.abspath(filepath)}")
            return

        statusCode = StatusCode.OK
        try:
            # Create ConnectManager for SSH-FTP connection to transfer update file from client side to LAVU side
            connection_manager = ConnectManager()
            connection_manager.connect_ssh_ftp(ip="fd53:7cb8:0383:0005:0000:0000:0000:0075", port=2223,
                                               username="root", password="art123.2024")
            # Execute test
            preparation_result = self.update_test.PrepareUpdate(size=os.path.getsize(filepath))
            # For UPD_PREPARE_SUCCESS = 0 -> the field preparationStatus.status is {}
            if not preparation_result.status == {}:
                print("Transferring update file to LAVU ...")
                connection_manager.put_ftp_file(source_path=filepath, remote_path="/media/update/lavu_product.swu")
                # Adding necessary time delay for proper processing for the request
                time.sleep(5)
                print("Transferring update file to LAVU completed")
                print("CheckUpdate started...........")
                self.update_test.CheckUpdate()
                # Adding necessary time delay for proper processing for the request
                time.sleep(1)
                ret, _ = self.update_test.checkUpdateStatus(self.update_test.GetStatus())
                while ret == 1:  # CheckUpdate ongoing
                    # Adding necessary time delay for proper processing for the request
                    time.sleep(5)
                    ret, _ = self.update_test.checkUpdateStatus(self.update_test.GetStatus())

                if ret == 2:  # Check Update success
                    print("CheckUpdate success")
                    print("StartUpdate started...........")
                    self.update_test.StartUpdate()
                    # Adding necessary time delay for proper processing for the request
                    time.sleep(10)
                    ret, _ = self.update_test.checkStartUpdateStatus(self.update_test.GetStatus())
                    while ret == 1:  # StartUpdate ongoing
                        # Adding necessary time delay for proper processing for the request
                        time.sleep(5)
                        try:
                            ret, _ = self.update_test.checkStartUpdateStatus(self.update_test.GetStatus())
                        except Exception as e:
                            print(str(e))
                            break
                    if ret == 2:
                        print("StartUpdate success")
                        self.update_test.CommitInstallation()
                        print("CommitInstallation completed")
                    else:
                        print("StartUpdate failed")
                else:
                    print("CheckUpdate failed")
            else:
                print("Failed the update")
        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode

        # Wait for some time so that the DLT logging is received
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD3_UartAccess(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Cybersecurity+functionality")
        print("TESTING: SD.3 - Use case: UART access enable disable operation")

        # Clear the DLT queue before starting the test
        self.dlt_manager.queueDlt.clear_queue()
        # Initialize the test summary
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "12954")
        # Add expected DLT logs here to verify the operation
        test_summary.expected_result = ["TEST STEP: SD.3_PerformDataOperation_call- 1504 - 1",
                                        "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
                                        "TEST STEP: SD.3_PerformDataOperation-return_ 0",
                                        "TEST STEP: SD.3_PerformDataOperation_call- 1504 - 1",
                                        "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
                                        "TEST STEP: SD.3_PerformDataOperation-return_ 0",
                                        "TEST STEP: SD.3_PerformDataOperation_call- 1504 - 0",
                                        "TEST STEP: SD.2_PerformDataOperation_call-Send SPP_ANSWER_ACK_ACK cmd via SPP",
                                        "TEST STEP: SD.3_PerformDataOperation-return_ 0"]
        self.test_summary_list.append(test_summary)

        data_op_read = 0
        data_op_write = 1
        debug_serial_enable_operation = 0x5E0
        disable_serial_debug = bytes([0x00])
        enable_serial_debug = bytes([0x01])

        statusCode = StatusCode.OK
        try:
            # Disable serial debug
            self.diagnosis_test.PerformDataOperation(operation=data_op_write, did=debug_serial_enable_operation,
                                                     length=len(disable_serial_debug), databuf=disable_serial_debug)
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)
            # Enable serial debug
            self.diagnosis_test.PerformDataOperation(operation=data_op_write, did=debug_serial_enable_operation,
                                                     length=len(enable_serial_debug), databuf=enable_serial_debug)
            # Adding necessary time delay for proper processing for the request
            time.sleep(5)
            # Read serial debug state value
            self.diagnosis_test.PerformDataOperation(operation=data_op_read, did=debug_serial_enable_operation,
                                                     length=0, databuf=b'')

        except grpc.RpcError as e:
            statusCode = e.code()

        test_summary.statusCode = statusCode
        # Adding necessary time delay for proper processing for DLT logs
        time.sleep(5)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    @retry_tests
    def SD4_mTLS(self):
        print("Confluence page: https://confluence.artgroup-spa.com/display/VU4KCAM/Cybersecurity+functionality")
        print("TESTING: SD.4 - Use case: UART initialize mTLS protocol")

        # Step 0 Don't clear dlt

        # Initialize the test summary with expected DLT logs based on the sequence diagram
        test_summary = TestSummary(inspect.currentframe().f_code.co_name, "13297")
        test_summary.expected_result = [
            "TEST STEP: SD.4_Request LaVU certificate",
            # "TEST STEP: SD.4_DecryptKeyCommand sent via LibSpp",
            # "TEST STEP: SD.4_Retrieve LaVU certificate from RPMB",
            "TEST STEP: SD.4_GetLavuCertificate-return_ 0"
        ]
        self.test_summary_list.append(test_summary)
        time.sleep(10)

        # Verify the DLT logs received from the server against the expected results.
        self.VerifyDltLogs(test_summary)
        return test_summary

    def diagnosis(self):
        print("diagnosis")
        diag = DiagnosisTest(self.grpc_manager.GetGrpcConnectionChannel())
        diag.PerformDataOperation()
        diag.PerformIOCtlOperation()
        diag.PerformRoutineOperation()

    def dashcam(self):
        print("dashcam")
        dash = DashcamTest(self.grpc_manager.GetGrpcConnectionChannel())
        dash.DashcamPlayerRequest()
        dash.DeleteDashcamRequest()
        dash.ExportDashcamRequest()
        dash.GetCurrentDashcamSettings()
        dash.GetDashcamRecordingList()
        dash.GetDashcamStorageInformation()
        dash.SetDashcamFavourite()
        dash.SetDashcamSettings()
        dash.UnsetDashcamFavourite()

    def filetransfer(self):
        print("filetransfer")
        filetf = FiletransferTest(self.grpc_manager.GetGrpcConnectionChannel())
        filetf.finishSlot()
        filetf.handleSignals()
        filetf.checkSum()
        filetf.deleteRequest()
        self.test_summary_list = []

    def gps(self):
        print("gps")
        g = GpsTest(self.grpc_manager.GetGrpcConnectionChannel())
        g.BindSignal()
        g.NewPositionData()

    def memory(self):
        print("memory")
        m = MemoryTest(self.grpc_manager.GetGrpcConnectionChannel())
        m.BindSignal()
        m.DeleteMemoriesRequest()
        m.ExportMemoriesRequest()
        m.GetMemoriesRecordingStatus()
        m.GetRecordingList()
        m.GetStorageInfoRequest()
        m.MemoriesPlayerRequest()
        m.NewMemoriesRecordingRequest()
        m.SetMemoriesRecordingFavourite()
        m.StopMemoriesRecordingRequest()

    def network(self):
        print("network")
        nt = NetworkTest(self.grpc_manager.GetGrpcConnectionChannel())
        nt.GetNetwokStatus()
        nt.NetworkStatusSignal()

    def system(self):
        print("system")
        sys = SystemTest(self.grpc_manager.GetGrpcConnectionChannel())
        sys.BindSignal()
        sys.GetExportableFiles()
        sys.GetLaVUSWVersion()
        sys.Ping()
        sys.UserDateTime()

    def telemetry(self):
        print("telemetry")
        tlm = TelemetryTest(self.grpc_manager.GetGrpcConnectionChannel())
        tlm.AddDriver()
        tlm.AddIntertimeDuringRecording()
        tlm.CancelRace()
        tlm.CancelRecording()
        tlm.DeleteDriver()
        tlm.GetDriverList()
        tlm.GetSessionList()
        tlm.GetTelemetryStatus()
        tlm.GetTrackList()
        tlm.SetTrackFavourite()
        tlm.StartNewSession()
        tlm.StartNewTrackRecord()
        tlm.UnsetTrackFavourite()
        # Adding necessary time delay for proper processing for the request
        time.sleep(5)
        for key in tlm.mapSignals:
            print(key)
            a = tlm.mapSignals[key]
            while a:
                print(f"List {key}:", a.pop(0))
        tlm.stop()

    def update(self):
        print("update")
        # up = UpdateTest(self.grpc_manager.GetGrpcConnectionChannel())
        # up.CheckUpdate()
        # up.CommitInstallation()
        # up.GetStatus()
        # up.PrepareUpdate()
        # up.RollbackInstallation()
        # up.StartUpdate()

    def security(self):
        print("security")
        sec_test = SecurityTest(self.grpc_manager.GetGrpcConnectionChannel())

        # Perform various SecurityTest operations
        sec_test.Init()  # Initialize Security
        sec_test.Start()  # Start Security
        sec_test.GetFileHash(123)  # Get a file hash (ID)
        sec_test.GetLavuPrivateKey()  # Retrieve the private key
        sec_test.GetLavuCertificate()  # Retrieve the certificate

        # To simulate signal streaming call BindSignal in a background thread
        threading.Thread(target=sec_test.BindSignal, daemon=True).start()

        # Adding necessary time delay for proper processing for the request
        time.sleep(5)

        # Stop security access when done
        sec_test.Stop()

    def publish_result(self, test_summary: TestSummary):
        # if  test_summary.test_id:
        #     self.jira_manager.get_executions(self.cycle_id, test_summary.test_id)
        if isinstance(test_summary, TestSummary):
            self.report_manager.insert_test_summary_to_excel(test_summary)

    def save_report_excel(self):
        self.report_manager.save_report_excel()


if __name__ == "__main__":
    pass


here the application is not properly shutdown when the exit button clicked