#!/usr/bin/env python3 import os import sys import shutil import time import pathlib from collections import namedtuple import pyautogui import pywinctl from cereal import log from cereal import messaging from cereal.messaging import PubMaster from openpilot.common.params import Params from openpilot.common.prefix import OpenpilotPrefix from openpilot.selfdrive.test.helpers import with_processes from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert TEST_DIR = pathlib.Path(__file__).parent TEST_OUTPUT_DIR = TEST_DIR / "raylib_report" SCREENSHOTS_DIR = TEST_OUTPUT_DIR / "screenshots" UI_DELAY = 0.1 # Offroad alerts to test OFFROAD_ALERTS = ['Offroad_IsTakingSnapshot'] def setup_homescreen(click, pm: PubMaster): pass def setup_settings_device(click, pm: PubMaster): click(100, 100) def setup_settings_network(click, pm: PubMaster): setup_settings_device(click, pm) click(278, 450) def setup_settings_toggles(click, pm: PubMaster): setup_settings_device(click, pm) click(278, 600) def setup_settings_software(click, pm: PubMaster): setup_settings_device(click, pm) click(278, 720) def setup_settings_firehose(click, pm: PubMaster): setup_settings_device(click, pm) click(278, 845) def setup_settings_developer(click, pm: PubMaster): setup_settings_device(click, pm) click(278, 950) def setup_keyboard(click, pm: PubMaster): setup_settings_developer(click, pm) click(1930, 270) def setup_pair_device(click, pm: PubMaster): click(1950, 800) def setup_offroad_alert(click, pm: PubMaster): set_offroad_alert("Offroad_TemperatureTooHigh", True, extra_text='99') for alert in OFFROAD_ALERTS: set_offroad_alert(alert, True) setup_settings_device(click, pm) click(240, 216) CASES = { "homescreen": setup_homescreen, "settings_device": setup_settings_device, "settings_network": setup_settings_network, "settings_toggles": setup_settings_toggles, "settings_software": setup_settings_software, "settings_firehose": setup_settings_firehose, "settings_developer": setup_settings_developer, "keyboard": setup_keyboard, "pair_device": setup_pair_device, "offroad_alert": setup_offroad_alert, } class TestUI: def __init__(self): os.environ["SCALE"] = os.getenv("SCALE", "1") sys.modules["mouseinfo"] = False def setup(self): # Seed minimal offroad state self.pm = PubMaster(["deviceState"]) ds = messaging.new_message('deviceState') ds.deviceState.networkType = log.DeviceState.NetworkType.wifi for _ in range(5): self.pm.send('deviceState', ds) ds.clear_write_flag() time.sleep(0.05) time.sleep(0.5) try: self.ui = pywinctl.getWindowsWithTitle("UI")[0] except Exception as e: print(f"failed to find ui window, assuming that it's in the top left (for Xvfb) {e}") self.ui = namedtuple("bb", ["left", "top", "width", "height"])(0, 0, 2160, 1080) def screenshot(self, name: str): full_screenshot = pyautogui.screenshot() cropped = full_screenshot.crop((self.ui.left, self.ui.top, self.ui.left + self.ui.width, self.ui.top + self.ui.height)) cropped.save(SCREENSHOTS_DIR / f"{name}.png") def click(self, x: int, y: int, *args, **kwargs): pyautogui.mouseDown(self.ui.left + x, self.ui.top + y, *args, **kwargs) time.sleep(0.01) pyautogui.mouseUp(self.ui.left + x, self.ui.top + y, *args, **kwargs) @with_processes(["raylib_ui"]) def test_ui(self, name, setup_case): self.setup() setup_case(self.click, self.pm) self.screenshot(name) def create_screenshots(): if TEST_OUTPUT_DIR.exists(): shutil.rmtree(TEST_OUTPUT_DIR) SCREENSHOTS_DIR.mkdir(parents=True) t = TestUI() with OpenpilotPrefix(): params = Params() params.put("DongleId", "123456789012345") for name, setup in CASES.items(): t.test_ui(name, setup) if __name__ == "__main__": create_screenshots()