"""Run the real Device class without opening a display or native IPC sockets.""" import ast from collections.abc import Callable from enum import Enum from pathlib import Path from types import SimpleNamespace import numpy as np import pytest from openpilot.common.filter_simple import FirstOrderFilter from openpilot.starpilot.common import screen_settings as screen class Params: def __init__(self, values): self.values = values def get(self, key): return self.values.get(key) def get_int(self, key, **kwargs): return int(self.values.get(key, 101 if 'Brightness' in key else 30)) def get_bool(self, key): return bool(self.values.get(key, False)) class Messages(dict): def __init__(self): super().__init__(selfdriveState=SimpleNamespace(enabled=False, alertSize='none', alertStatus='normal'), starpilotSelfdriveState=SimpleNamespace(alertSize='none', alertStatus='normal'), carState=SimpleNamespace(leftBlinker=False, rightBlinker=False, brakePressed=False, gasPressed=False, gearShifter='drive', buttonEvents=[])) self.updated = dict.fromkeys(self, True) self.recv_frame = dict.fromkeys(self, 1) self.recv_time = dict.fromkeys(self, 100) self.logMonoTime = dict.fromkeys(self, 1) self.valid = dict.fromkeys(self, True) self.alive = dict.fromkeys(self, True) def make_device(*, device_type="tici", **settings): status = Enum('UIStatus', 'DISENGAGED ENGAGED OVERRIDE') state = SimpleNamespace(started=True, ignition=True, status=status.DISENGAGED, light_sensor=-1, started_time=0, started_frame=0, starpilot_toggles={}, params_memory=Params({}), ui_params=Params({'ScreenManagement': True, 'ScreenBrightness': 101, 'ScreenBrightnessOnroad': 101, 'StandbyMode': True, **settings}), sm=Messages()) app = SimpleNamespace(target_fps=20, big_ui=lambda: False, mouse_events=[], set_should_render=lambda value: None) env = {**vars(screen), 'ui_state': state, 'gui_app': app, 'UIStatus': status, 'BACKLIGHT_OFFROAD': 65, 'np': np, 'time': SimpleNamespace(monotonic=lambda: 100), 'FirstOrderFilter': FirstOrderFilter, 'Callable': Callable, 'HARDWARE': SimpleNamespace(set_display_power=lambda value: None, get_device_type=lambda: device_type), 'cloudlog': SimpleNamespace(debug=lambda value: None), 'PC': False, 'TICI': True} source = Path(__file__).resolve().parents[3] / 'selfdrive/ui/ui_state.py' node = next(n for n in ast.parse(source.read_text()).body if isinstance(n, ast.ClassDef) and n.name == 'Device') exec(compile(ast.Module(body=[node], type_ignores=[]), str(source), 'exec'), env) device = env['Device']() device._brightness_filter = SimpleNamespace(update=lambda value: value) device._ignition = True device._interaction_time = 90 return device, state, app def test_driving_and_parked_offsets_apply_independently(): device, state, _ = make_device(StandbyMode=False, ScreenBrightnessOffset=-20, ScreenBrightnessOnroadOffset=15) assert device._calculate_brightness() == 75 state.started = False assert device._calculate_brightness() == 52 def test_offset_is_ignored_in_manual_and_when_screen_settings_disabled(): device, _, _ = make_device(StandbyMode=False, ScreenBrightnessOnroad=22, ScreenBrightnessOnroadOffset=50) assert device._calculate_brightness() == 22 device._params.values['ScreenManagement'] = False device._refresh_screen_settings(force=True) assert device._calculate_brightness() == 65 def test_parked_zero_can_be_woken_by_touch_then_times_out_without_standby(): device, state, app = make_device(StandbyMode=False, ScreenBrightness=0) state.started = state.ignition = device._ignition = False assert device._calculate_brightness() == 0 app.mouse_events = [SimpleNamespace(left_down=True)] device._update_wakefulness() assert device._calculate_brightness() == 5 app.mouse_events = [] device._interaction_time = 90 device._update_wakefulness() assert not device.awake assert device._calculate_brightness() == 0 @pytest.mark.parametrize('key,field,value', [ ('StandbyWakeInfoAlert', 'alertSize', 'small'), ('StandbyWakeWarningAlert', 'alertStatus', 'userPrompt'), ('StandbyWakeCriticalAlert', 'alertStatus', 'critical'), ]) def test_only_selected_alert_categories_wake(key, field, value): settings = dict.fromkeys(screen.SCREEN_WAKE_KEYS, False) device, state, _ = make_device(**settings) state.sm['selfdriveState'].alertSize = 'small' setattr(state.sm['selfdriveState'], field, value) device._update_wakefulness() assert device._calculate_brightness() == 0 device._params.values[key] = True device._refresh_screen_settings(force=True) device._interaction_time = 90 device._update_wakefulness() assert device._calculate_brightness() == 65 @pytest.mark.parametrize('key,field', [ ('StandbyWakeTurnSignal', 'leftBlinker'), ]) def test_selected_driver_input_wakes_once_and_can_sleep_while_held(key, field): device, state, _ = make_device(**dict.fromkeys(screen.SCREEN_WAKE_KEYS, False)) device._params.values[key] = True device._refresh_screen_settings(force=True) device._update_wakefulness() setattr(state.sm['carState'], field, True) device._update_wakefulness() assert device._calculate_brightness() == 65 device._interaction_time = 90 device._update_wakefulness() assert device._calculate_brightness() == 0 def test_runtime_limits_legacy_offsets_to_thirty_percent(): device, state, _ = make_device(StandbyMode=False, ScreenBrightnessOffset=-100, ScreenBrightnessOnroadOffset=-100) assert device._calculate_brightness() == 46 state.started = False assert device._calculate_brightness() == 46 @pytest.mark.parametrize('key', sorted(screen.SCREEN_WAKE_KEYS)) @pytest.mark.parametrize('selected', [False, True]) def test_every_wake_choice_controls_its_own_event(key, selected): settings = dict.fromkeys(screen.SCREEN_WAKE_KEYS, False) settings[key] = selected device, state, app = make_device(**settings) device._update_wakefulness() # Seed signals; startup is not a driver event. if key == 'StandbyWakeEngage': state.sm['selfdriveState'].enabled = True state.status = type(state.status).ENGAGED elif key == 'StandbyWakeDisengage': state.sm['selfdriveState'].enabled = True state.status = type(state.status).ENGAGED device._update_wakefulness() state.sm['selfdriveState'].enabled = False state.status = type(state.status).DISENGAGED elif key.endswith('Alert'): alert = state.sm['selfdriveState'] alert.alertSize = 'small' alert.alertStatus = {'StandbyWakeInfoAlert': 'normal', 'StandbyWakeWarningAlert': 'userPrompt', 'StandbyWakeCriticalAlert': 'critical'}[key] elif key == 'StandbyWakeButton': state.params_memory.values['StandbyButtonPressTime'] = 99_500_000_000 elif key == 'StandbyWakeTurnSignal': state.sm['carState'].leftBlinker = True else: pytest.fail('No stimulus for wake option ' + key) device._interaction_time = 90 device._update_wakefulness() assert (device._calculate_brightness() > 0) is selected def test_external_button_press_is_fresh_and_consumed_once(): settings = dict.fromkeys(screen.SCREEN_WAKE_KEYS, False) settings['StandbyWakeButton'] = True device, state, _ = make_device(**settings) device._update_wakefulness() state.params_memory.values['StandbyButtonPressTime'] = 99_500_000_000 device._update_wakefulness() assert (device._calculate_brightness() > 0) is True device._interaction_time = 90 device._update_wakefulness() assert device._calculate_brightness() == 0 state.params_memory.values['StandbyButtonPressTime'] = 95_000_000_000 device._update_wakefulness() assert device._calculate_brightness() == 0 def test_consumed_button_press_is_not_replayed_between_ui_frames(): device, state, _ = make_device(StandbyWakeButton=True) device._update_wakefulness() state.params_memory.values['StandbyButtonPressTime'] = 99_500_000_000 device._update_wakefulness() assert device._calculate_brightness() > 0 device._interaction_time = 90 device._update_wakefulness() assert device._calculate_brightness() == 0 def test_hidden_secondary_alert_does_not_bypass_primary_category_selection(): settings = dict.fromkeys(screen.SCREEN_WAKE_KEYS, False) settings['StandbyWakeInfoAlert'] = True device, state, _ = make_device(**settings) state.sm['selfdriveState'].alertStatus = 'critical' state.sm['selfdriveState'].alertSize = 'full' state.sm['starpilotSelfdriveState'].alertSize = 'small' device._update_wakefulness() assert device._active_standby_alerts() == {'StandbyWakeCriticalAlert'} assert device._calculate_brightness() == 0 @pytest.mark.parametrize('device_type', ['tici', 'mici']) def test_dom_alert_predicate_does_not_depend_on_renderer_hide_setting(device_type): device, state, _ = make_device(device_type=device_type) state.starpilot_toggles['hide_alerts'] = True state.sm['selfdriveState'].alertSize = 'small' device._update_wakefulness() assert (device._calculate_brightness() > 0) is True def test_bluetooth_wake_during_ignition_only_standby(): settings = dict.fromkeys(screen.SCREEN_WAKE_KEYS, False) settings["StandbyWakeButton"] = True device, state, _ = make_device(**settings) state.started = False state.ignition = device._ignition = True device._update_wakefulness() state.params_memory.values['StandbyButtonPressTime'] = 99_500_000_000 device._update_wakefulness() assert (device._calculate_brightness() > 0) is True