Skip to content

User interface

This page lists some examples on how the user interface can be used. For more extensive background information on implementing these examples in a different programming language, please see the reference documentation on the user interface.

Basic user interface example

Below is a basic example implementing the user interface. In this example, the user interface has been set up for a mock key programming procedure. It demonstrates several use cases for the different UI control types.

python -m openobd run --file academy/user_interface/customer_interface.py --ticket <TICKET_NR>

from openobd import *


class CustomerInterfaceExample(OpenOBDFunction):

    def run(self):
        # Create a UiHandler object and use it to show a welcome message
        ui_handler = UiHandler(self.openobd_session)
        ui_handler.show_ui(Label(label="Welcome to the start of the procedure!", minimal_display_time=4))

        # Ensure the ignition is on before proceeding
        if not ui_handler.show_ui(YesNo(label="Is the ignition on?")):
            ui_handler.show_ui(Continue(label="Please turn the ignition on and press continue."))

        # Ensure that the correct PIN of the vehicle is entered
        while True:
            pin = ui_handler.show_ui(FreeText(label="Please enter the PIN of the vehicle."))
            if ui_handler.show_ui(YesNo(label=f"You entered: {pin}. Is this correct?")):
                break

        # Ask what type of keys should be programmed
        key_types = ["Keyless", "Transponder"]
        key_type_index = ui_handler.show_ui(Options(label="Do you want to program keyless or transponder keys?", options=key_types))

        # Ask how many keys should be programmed, and display the key currently being programmed
        key_amount = ui_handler.show_ui(Numbers(label=f"How many keys do you want to program?", minimum=1, maximum=5))
        for i in range(key_amount):
            ui_handler.show_ui(Label(label=f"{key_types[key_type_index]} key {i + 1} is currently being programmed...", minimal_display_time=3))
            ui_handler.show_ui(Label(label=f"Successfully programmed key {i + 1}!", minimal_display_time=2))

        # Show a final message and close the UI so that the chat becomes available to the customer again
        ui_handler.show_ui(Label(label="Procedure finished!", minimal_display_time=3))
        ui_handler.stop_stream()

        # Close the session with a successful result
        self.result = ServiceResult(result=[Result.RESULT_SUCCESS])

Displaying the operator interface

Besides being able to show the user interface to the customer, it is also possible to show a UI to the operator. Both of these UIs can be shown at the same time and can be updated independently. Below is an example demonstrating this.

InterfaceType.INTERFACE_OPERATOR not available - we are working on it

The option to show an operator interface is unfortunately not available for all partner dashboards! We are working on it and have this issue on our roadmap.

python -m openobd run --file academy/user_interface/operator_interface.py --ticket <TICKET_NR>

from openobd import *


class OperatorInterfaceExample(OpenOBDFunction):

    def run(self):
        # Create a UiHandler object for the customer/user (which is the default)
        customer_ui = UiHandler(self.openobd_session)
        # Create a second UiHandler object, explicitly stating that it should be shown to the operator
        operator_ui = UiHandler(self.openobd_session, target=InterfaceType.INTERFACE_OPERATOR)

        # Inform the operator that the customer is entering a PIN
        operator_ui.show_ui(Label(label="The customer is currently entering a PIN."))
        while True:
            # Wait for the customer to enter a PIN
            pin = customer_ui.show_ui(FreeText(label="Please enter the PIN of the vehicle."))

            # Tell the customer to wait while asking the operator to check the PIN
            customer_ui.show_ui(Label(label="Please wait while the operator checks if the PIN is correct."))
            if operator_ui.show_ui(YesNo(label=f"The customer entered the PIN 'f{pin}'. Is this correct?")):
                # Inform both the customer and operator that the procedure is finished
                operator_ui.show_ui(Label(label="The procedure is finished."))
                customer_ui.show_ui(Label(label="Your PIN is correct. The procedure is finished.", minimal_display_time=3))
                break
            else:
                # Inform both the operator and customer that the customer needs to enter a PIN again
                operator_ui.show_ui(Label(label="The customer is entering a PIN again."))
                customer_ui.show_ui(Label(label="The operator has indicated that the entered PIN is incorrect. Please try again.", minimal_display_time=5))

        # Close both UIs
        customer_ui.stop_stream()
        operator_ui.stop_stream()

        # Close the session with a successful result
        self.result = ServiceResult(result=[Result.RESULT_SUCCESS])

Overriding the UI

Whenever a Control message is displayed in the UI, the user must interact with it before the next message will be displayed. In case it is desired to not wait for user interaction, it is possible to immediately replace the message shown. This can be done by creating a new Control stream with the same InterfaceType as the target. This will cancel the initial Control stream and display the message sent on the new stream. Below is an example in which the user can press a button to cancel a simulated procedure. The button will be replaced if the user does not press the button before the procedure finishes.

python -m openobd run --file academy/user_interface/customer_ui_override.py --ticket <TICKET_NR>

from threading import Thread, Event
from openobd import *
import time


class CustomerUIOverrideExample(OpenOBDFunction):

    ui_handler = None               # type: UiHandler
    procedure_cancelled = None      # type: Event

    def run(self):
        # Create a UiHandler instance and let the user start the procedure
        self.ui_handler = UiHandler(self.openobd_session)
        self.ui_handler.show_ui(Continue(label="Press `Continue` to start the procedure."))
        # Keep track of whether the procedure has been cancelled
        self.procedure_cancelled = Event()

        # Start a thread that simulates a procedure
        procedure_thread = Thread(target=self.procedure)
        procedure_thread.start()

        try:
            # Give the user the option to cancel the procedure
            self.ui_handler.show_ui(Options(label="The procedure has started. Please wait.", options=["Cancel procedure"]))
            # The user pressed "Cancel procedure", so set a flag that the procedure is cancelled
            self.procedure_cancelled.set()
            self.ui_handler.show_ui(Label(label="Procedure cancelled.", minimal_display_time=3))

        except OpenOBDStreamStoppedException:
            # The stream has closed because the procedure thread took over the UI using force_display
            pass

        # Wait for the procedure thread to finish
        procedure_thread.join()
        # Close the UI
        self.ui_handler.stop_stream()

        # Close the session with a result depending on if it was cancelled
        self.result = ServiceResult(result=[Result.RESULT_FAILURE if self.procedure_cancelled.is_set() else Result.RESULT_SUCCESS])

    def procedure(self):
        # Simulate a procedure by waiting 5 seconds, checking each second if it was cancelled
        for i in range(5):
            time.sleep(1)
            if self.procedure_cancelled.is_set():
                return

        # Show a label to the user. Use force_display to replace the UI in the main thread that is waiting for user interaction
        self.ui_handler.show_ui(Label(label="The procedure was successful.", minimal_display_time=4), force_display=True)