diff --git a/selfdrive/monitoring/driver_monitor.py b/selfdrive/monitoring/driver_monitor.py
index 2279002..74e0067 100644
--- a/selfdrive/monitoring/driver_monitor.py
+++ b/selfdrive/monitoring/driver_monitor.py
@@ -19,12 +19,19 @@ class DRIVER_MONITOR_SETTINGS():
def __init__(self):
self._DT_DMON = DT_DMON
# ref (page15-16): https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:42018X1947&rid=2
- self._AWARENESS_TIME = 30. # passive wheeltouch total timeout
- self._AWARENESS_PRE_TIME_TILL_TERMINAL = 15.
- self._AWARENESS_PROMPT_TIME_TILL_TERMINAL = 6.
- self._DISTRACTED_TIME = 11. # active monitoring total timeout
- self._DISTRACTED_PRE_TIME_TILL_TERMINAL = 8.
- self._DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 6.
+ # self._AWARENESS_TIME = 30. # passive wheeltouch total timeout
+ # self._AWARENESS_PRE_TIME_TILL_TERMINAL = 15.
+ # self._AWARENESS_PROMPT_TIME_TILL_TERMINAL = 6.
+ # self._DISTRACTED_TIME = 11. # active monitoring total timeout
+ # self._DISTRACTED_PRE_TIME_TILL_TERMINAL = 8.
+ # self._DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 6.
+
+ self._AWARENESS_TIME = 60. # passive wheeltouch total timeout
+ self._AWARENESS_PRE_TIME_TILL_TERMINAL = 60.
+ self._AWARENESS_PROMPT_TIME_TILL_TERMINAL = 30.
+ self._DISTRACTED_TIME = 30. # active monitoring total timeout
+ self._DISTRACTED_PRE_TIME_TILL_TERMINAL = 60.
+ self._DISTRACTED_PROMPT_TIME_TILL_TERMINAL = 30.
self._FACE_THRESHOLD = 0.7
self._EYE_THRESHOLD = 0.65
diff --git a/selfdrive/ui/.gitignore b/selfdrive/ui/.gitignore
old mode 100644
new mode 100755
index f972481..99f9097
--- a/selfdrive/ui/.gitignore
+++ b/selfdrive/ui/.gitignore
@@ -3,13 +3,11 @@ moc_*
translations/main_test_en.*
-_text
-_spinner
-
ui
-mui
watch3
installer/installers/*
+qt/text
+qt/spinner
qt/setup/setup
qt/setup/reset
qt/setup/wifi
diff --git a/selfdrive/ui/SConscript b/selfdrive/ui/SConscript
new file mode 100755
index 0000000..8a90134
--- /dev/null
+++ b/selfdrive/ui/SConscript
@@ -0,0 +1,154 @@
+import os
+import json
+Import('qt_env', 'arch', 'common', 'messaging', 'visionipc',
+ 'cereal', 'transformations')
+
+base_libs = [common, messaging, cereal, visionipc, transformations, 'zmq',
+ 'capnp', 'kj', 'm', 'OpenCL', 'ssl', 'crypto', 'pthread', 'OmxCore', 'avformat', 'avcodec', 'avutil', 'yuv'] + qt_env["LIBS"]
+
+if arch == 'larch64':
+ base_libs.append('EGL')
+
+maps = arch in ['larch64', 'aarch64', 'x86_64']
+
+if maps and arch != 'larch64':
+ rpath = [Dir(f"#third_party/mapbox-gl-native-qt/{arch}").srcnode().abspath]
+ qt_env["RPATH"] += rpath
+
+if arch == "Darwin":
+ del base_libs[base_libs.index('OpenCL')]
+ qt_env['FRAMEWORKS'] += ['OpenCL']
+
+qt_util = qt_env.Library("qt_util", ["#selfdrive/ui/qt/api.cc", "#selfdrive/ui/qt/util.cc"], LIBS=base_libs)
+widgets_src = ["ui.cc", "qt/widgets/input.cc", "qt/widgets/drive_stats.cc", "qt/widgets/wifi.cc",
+ "qt/widgets/ssh_keys.cc", "qt/widgets/toggle.cc", "qt/widgets/controls.cc",
+ "qt/widgets/offroad_alerts.cc", "qt/widgets/prime.cc", "qt/widgets/keyboard.cc",
+ "qt/widgets/scrollview.cc", "qt/widgets/cameraview.cc", "#third_party/qrcode/QrCode.cc",
+ "qt/request_repeater.cc", "qt/qt_window.cc", "qt/network/networking.cc", "qt/network/wifi_manager.cc",
+ "../frogpilot/ui/frogpilot_functions.cc", "../frogpilot/navigation/ui/navigation_settings.cc",
+ "../frogpilot/ui/control_settings.cc", "../frogpilot/ui/vehicle_settings.cc",
+ "../frogpilot/ui/visual_settings.cc",
+ "../oscarpilot/settings/settings.cc", "../oscarpilot/settings/basic.cc",
+ ]
+
+qt_env['CPPDEFINES'] = []
+if maps:
+ base_libs += ['qmapboxgl']
+ widgets_src += ["qt/maps/map_helpers.cc", "qt/maps/map_settings.cc", "qt/maps/map.cc", "qt/maps/map_panel.cc",
+ "qt/maps/map_eta.cc", "qt/maps/map_instructions.cc"]
+ qt_env['CPPDEFINES'] += ["ENABLE_MAPS"]
+
+widgets = qt_env.Library("qt_widgets", widgets_src, LIBS=base_libs)
+Export('widgets')
+qt_libs = [widgets, qt_util] + base_libs
+
+qt_src = ["main.cc", "qt/sidebar.cc", "qt/onroad.cc", "qt/body.cc",
+ "qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc",
+ "qt/offroad/software_settings.cc", "qt/offroad/onboarding.cc",
+ "qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc",
+ "../frogpilot/screenrecorder/omx_encoder.cc", "../frogpilot/screenrecorder/screenrecorder.cc"]
+
+def is_running_on_wsl2():
+ try:
+ with open('/proc/version', 'r') as f:
+ return 'WSL2' in f.read()
+ except FileNotFoundError:
+ return False
+
+if is_running_on_wsl2():
+ qt_env.Append(CXXFLAGS=['-DWSL2'])
+ base_libs.remove('OmxCore')
+ qt_libs.remove('OmxCore')
+ qt_src.remove("../frogpilot/screenrecorder/screenrecorder.cc")
+ qt_src.remove("../frogpilot/screenrecorder/omx_encoder.cc")
+ print("Building for WSL2. Removing Screen Recorder")
+
+# build translation files
+with open(File("translations/languages.json").abspath) as f:
+ languages = json.loads(f.read())
+translation_sources = [f"#selfdrive/ui/translations/{l}.ts" for l in languages.values()]
+translation_targets = [src.replace(".ts", ".qm") for src in translation_sources]
+lrelease_bin = 'third_party/qt5/larch64/bin/lrelease' if arch == 'larch64' else 'lrelease'
+
+lupdate = qt_env.Command(translation_sources, qt_src + widgets_src, "selfdrive/ui/update_translations.py")
+lrelease = qt_env.Command(translation_targets, translation_sources, f"{lrelease_bin} $SOURCES")
+qt_env.Depends(lrelease, lupdate)
+qt_env.NoClean(translation_sources)
+qt_env.Precious(translation_sources)
+qt_env.NoCache(lupdate)
+
+# create qrc file for compiled translations to include with assets
+translations_assets_src = "#selfdrive/assets/translations_assets.qrc"
+with open(File(translations_assets_src).abspath, 'w') as f:
+ f.write('\n\n')
+ f.write('\n'.join([f'../ui/translations/{l}.qm' for l in languages.values()]))
+ f.write('\n\n')
+
+# build assets
+assets = "#selfdrive/assets/assets.cc"
+assets_src = "#selfdrive/assets/assets.qrc"
+qt_env.Command(assets, [assets_src, translations_assets_src], f"rcc $SOURCES -o $TARGET")
+qt_env.Depends(assets, Glob('#selfdrive/assets/*', exclude=[assets, assets_src, translations_assets_src, "#selfdrive/assets/assets.o"]) + [lrelease])
+asset_obj = qt_env.Object("assets", assets)
+
+qt_env.SharedLibrary("qt/python_helpers", ["qt/qt_window.cc"], LIBS=qt_libs)
+
+# spinner and text window
+qt_env.Program("qt/text", ["qt/text.cc"], LIBS=qt_libs)
+qt_env.Program("qt/spinner", ["qt/spinner.cc"], LIBS=qt_libs)
+
+# build main UI
+qt_env.Program("ui", qt_src + [asset_obj], LIBS=qt_libs)
+if GetOption('extras'):
+ qt_src.remove("main.cc") # replaced by test_runner
+ qt_env.Program('tests/test_translations', [asset_obj, 'tests/test_runner.cc', 'tests/test_translations.cc'] + qt_src, LIBS=qt_libs)
+ qt_env.Program('tests/ui_snapshot', [asset_obj, "tests/ui_snapshot.cc"] + qt_src, LIBS=qt_libs)
+
+qt_env['CPPPATH'] += ["../frogpilot/screenrecorder/openmax/include/"]
+
+if GetOption('extras') and arch != "Darwin":
+ # setup and factory resetter
+ qt_env.Program("qt/setup/reset", ["qt/setup/reset.cc"], LIBS=qt_libs)
+ qt_env.Program("qt/setup/setup", ["qt/setup/setup.cc", asset_obj],
+ LIBS=qt_libs + ['curl', 'common', 'json11'])
+
+ # build updater UI
+ qt_env.Program("qt/setup/updater", ["qt/setup/updater.cc", asset_obj], LIBS=qt_libs)
+
+ # build installers
+ senv = qt_env.Clone()
+ senv['LINKFLAGS'].append('-Wl,-strip-debug')
+
+ release = "release3"
+ dashcam = "dashcam3"
+ installers = [
+ ("openpilot", release),
+ ("openpilot_test", f"{release}-staging"),
+ ("openpilot_nightly", "nightly"),
+ ("openpilot_internal", "master"),
+ ("dashcam", dashcam),
+ ("dashcam_test", f"{dashcam}-staging"),
+ ]
+
+ cont = {}
+ for brand in ("openpilot", "dashcam"):
+ cont[brand] = senv.Command(f"installer/continue_{brand}.o", f"installer/continue_{brand}.sh",
+ "ld -r -b binary -o $TARGET $SOURCE")
+ for name, branch in installers:
+ brand = "dashcam" if "dashcam" in branch else "openpilot"
+ d = {'BRANCH': f"'\"{branch}\"'", 'BRAND': f"'\"{brand}\"'"}
+ if "internal" in name:
+ d['INTERNAL'] = "1"
+
+ import requests
+ r = requests.get("https://github.com/commaci2.keys")
+ r.raise_for_status()
+ d['SSH_KEYS'] = f'\\"{r.text.strip()}\\"'
+ obj = senv.Object(f"installer/installers/installer_{name}.o", ["installer/installer.cc"], CPPDEFINES=d)
+ f = senv.Program(f"installer/installers/installer_{name}", [obj, cont[brand]], LIBS=qt_libs)
+ # keep installers small
+ assert f[0].get_size() < 350*1e3
+
+# build watch3
+if arch in ['x86_64', 'aarch64', 'Darwin'] or GetOption('extras'):
+ qt_env.Program("watch3", ["watch3.cc"], LIBS=qt_libs + ['common', 'json11', 'zmq', 'visionipc', 'messaging'])
diff --git a/selfdrive/ui/_spinner b/selfdrive/ui/_spinner
deleted file mode 100755
index 0e10c27..0000000
Binary files a/selfdrive/ui/_spinner and /dev/null differ
diff --git a/selfdrive/ui/_text b/selfdrive/ui/_text
deleted file mode 100755
index cc7647e..0000000
Binary files a/selfdrive/ui/_text and /dev/null differ
diff --git a/selfdrive/ui/installer/installer.cc b/selfdrive/ui/installer/installer.cc
new file mode 100755
index 0000000..179ce60
--- /dev/null
+++ b/selfdrive/ui/installer/installer.cc
@@ -0,0 +1,221 @@
+#include
+#include
+
+#include
+#include
+#include