This commit is contained in:
firestar5683
2026-07-01 13:27:44 -05:00
parent 032b2a1fde
commit 7da4359dd0
5 changed files with 245 additions and 77 deletions
+49 -16
View File
@@ -1,29 +1,57 @@
#!/usr/bin/env python3
import time
import json
import jwt
import random
import string
from typing import cast
from pathlib import Path
from datetime import datetime, timedelta, UTC
from openpilot.common.api import api_get, get_key_pair
from openpilot.common.params import Params
from openpilot.common.spinner import Spinner
from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert
from openpilot.system.hardware import HARDWARE, PC
from openpilot.system.hardware.hw import Paths
from openpilot.common.swaglog import cloudlog
UNREGISTERED_DONGLE_ID = "UnregisteredDevice"
OFFROAD_UNREGISTERED_ALERT = "Offroad_UnregisteredHardware"
KEYS = {"id_rsa": "RS256",
"id_ecdsa": "ES256"}
def api_get(*args, **kwargs):
from openpilot.common.api import api_get as api_get_impl
return api_get_impl(*args, **kwargs)
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
for key, algorithm in KEYS.items():
private_path = Path(Paths.persist_root()) / "comma" / key
public_path = Path(Paths.persist_root()) / "comma" / f"{key}.pub"
if private_path.is_file() and public_path.is_file():
return algorithm, private_path.read_text(), public_path.read_text()
return None, None, None
def _has_key_pair() -> bool:
for key in KEYS:
private_path = Path(Paths.persist_root()) / "comma" / key
public_path = Path(Paths.persist_root()) / "comma" / f"{key}.pub"
if private_path.is_file() and public_path.is_file():
return True
return False
def is_registered_device() -> bool:
dongle = Params().get("DongleId")
return dongle not in (None, UNREGISTERED_DONGLE_ID)
def _set_registration_alert(params: Params, dongle_id: str | None) -> None:
show_alert = (dongle_id == UNREGISTERED_DONGLE_ID) and not PC
if show_alert:
from openpilot.selfdrive.selfdrived.alertmanager import set_offroad_alert
set_offroad_alert(OFFROAD_UNREGISTERED_ALERT, True)
else:
params.remove(OFFROAD_UNREGISTERED_ALERT)
def register(show_spinner=False, register_konik=False) -> str | None:
"""
All devices built since March 2024 come with all
@@ -42,13 +70,18 @@ def register(show_spinner=False, register_konik=False) -> str | None:
with open(Paths.persist_root()+"/comma/dongle_id") as f:
dongle_id = f.read().strip()
# Create registration token, in the future, this key will make JWTs directly
jwt_algo, private_key, public_key = get_key_pair()
if not public_key and not register_konik:
if not _has_key_pair() and not register_konik:
dongle_id = UNREGISTERED_DONGLE_ID
cloudlog.warning("missing public key")
elif dongle_id is None or register_konik:
import json
import jwt
from datetime import datetime, timedelta, UTC
from openpilot.common.spinner import Spinner
# Create registration token, in the future, this key will make JWTs directly
jwt_algo, private_key, public_key = get_key_pair()
if show_spinner:
spinner = Spinner()
spinner.update("registering device")
@@ -73,14 +106,14 @@ def register(show_spinner=False, register_konik=False) -> str | None:
while True:
try:
register_token = jwt.encode({'register': True, 'exp': datetime.now(UTC).replace(tzinfo=None) + timedelta(hours=1)},
cast(str, private_key), algorithm=jwt_algo)
private_key, algorithm=jwt_algo)
cloudlog.info("getting pilotauth")
resp = api_get("v2/pilotauth/", method='POST', timeout=15,
imei=imei1, imei2=imei2, serial=serial, public_key=public_key, register_token=register_token)
if resp.status_code in (402, 403):
cloudlog.info(f"Unable to register device, got {resp.status_code}")
dongle_id = ''.join(random.choices(string.ascii_lowercase + string.digits, k=16))
dongle_id = UNREGISTERED_DONGLE_ID
else:
dongleauth = json.loads(resp.text)
dongle_id = dongleauth["dongle_id"]
@@ -99,7 +132,7 @@ def register(show_spinner=False, register_konik=False) -> str | None:
if not register_konik and dongle_id != params.get("KonikDongleId"):
params.put("DongleId", dongle_id)
params.put("StockDongleId", dongle_id)
set_offroad_alert("Offroad_UnregisteredHardware", (dongle_id == UNREGISTERED_DONGLE_ID) and not PC)
_set_registration_alert(params, dongle_id)
return dongle_id
+15 -12
View File
@@ -1,18 +1,11 @@
import errno
import fcntl
import os
import sys
import pathlib
import shutil
import signal
import subprocess
import tempfile
import threading
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
def unblock_stdout() -> None:
import errno
import fcntl
import signal
import sys
# get a non-blocking stdout
child_pid, child_pty = os.forkpty()
if child_pid != 0: # parent
@@ -51,7 +44,17 @@ def write_onroad_params(started, params):
def save_bootlog():
import threading
def fn():
import pathlib
import shutil
import subprocess
import tempfile
from openpilot.common.basedir import BASEDIR
from openpilot.common.params import Params
tmpdir = tempfile.mkdtemp()
env = os.environ.copy()
env['PARAMS_COPY_PATH'] = tmpdir
+52 -15
View File
@@ -2,7 +2,6 @@
import datetime
import json
import os
import shutil
from pathlib import Path
import signal
import sys
@@ -24,26 +23,18 @@ def _append_boot_timing_line(line: str) -> None:
from cereal import car, log
import cereal.messaging as messaging
from openpilot.common.utils import atomic_write
from openpilot.common.params import Params, ParamKeyFlag, ParamKeyType
from openpilot.common.text_window import TextWindow
from openpilot.system.hardware import HARDWARE
from openpilot.system.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog
from openpilot.system.manager.process import ensure_running
from openpilot.system.manager.process_config import managed_processes
from openpilot.system.athena.registration import register, UNREGISTERED_DONGLE_ID
from openpilot.common.swaglog import cloudlog, add_file_handler
from openpilot.common.swaglog import cloudlog
from openpilot.system.version import get_build_metadata, terms_version, training_version
from openpilot.system.hardware.hw import Paths
_MANAGER_CORE_IMPORT_DONE = time.monotonic()
from openpilot.starpilot.common.starpilot_functions import starpilot_boot_functions, install_starpilot, uninstall_starpilot
from openpilot.starpilot.common.starpilot_variables import (
LEGACY_STARPILOT_PARAM_RENAMES,
LEGACY_STARPILOT_STATS_KEY_RENAMES,
get_starpilot_toggles,
)
_MANAGER_IMPORT_DONE = time.monotonic()
_manager_import_timing_line = (
@@ -67,9 +58,23 @@ STARPILOT_PC_ROOT_MIGRATION_FLAG = Path("/data") / "starpilot_pc_root_v1"
STARPILOT_PARAMS_CACHE_MIGRATION_FLAG = Path("/data") / "starpilot_params_cache_v1"
STARPILOT_LEGACY_CACHE_MARKER_KEYS = ("RemapCancelToDistance",)
STARPILOT_REMOVED_PARAM_KEYS = ("HumanFollowing",)
UNREGISTERED_DONGLE_ID = "UnregisteredDevice"
POWER_WATCHDOG_PATH = "/var/tmp/power_watchdog"
LEGACY_CARMODEL_MIGRATIONS = {
"CHEVROLET_BOLT_CC_2019_2021": "CHEVROLET_BOLT_CC_2018_2021",
}
LEGACY_STARPILOT_PARAM_RENAMES = {
"FrogPilotApiToken": "StarPilotApiToken",
"FrogPilotCarParams": "StarPilotCarParams",
"FrogPilotCarParamsPersistent": "StarPilotCarParamsPersistent",
"FrogPilotDongleId": "StarPilotDongleId",
"FrogPilotStats": "StarPilotStats",
}
LEGACY_STARPILOT_STATS_KEY_RENAMES = {
"FrogPilotDrives": "StarPilotDrives",
"FrogPilotMeters": "StarPilotMeters",
"FrogPilotSeconds": "StarPilotSeconds",
}
STARPILOT_STATS_DROP_KEYS = {"CurrentMonthsKilometers", "ResetStats"}
STARPILOT_STATS_MAX_KEYS = {"LongestDistanceWithoutOverride", "MaxAcceleration"}
@@ -114,6 +119,30 @@ def _capture_manager_exception() -> None:
cloudlog.exception("failed to capture manager exception")
def _write_power_watchdog(timestamp: float) -> None:
import tempfile
tmp_file_name = None
try:
with tempfile.NamedTemporaryFile("w", dir=os.path.dirname(POWER_WATCHDOG_PATH), delete=False) as f:
tmp_file_name = f.name
f.write(str(timestamp))
os.replace(tmp_file_name, POWER_WATCHDOG_PATH)
tmp_file_name = None
finally:
if tmp_file_name is not None:
try:
os.unlink(tmp_file_name)
except FileNotFoundError:
pass
def _get_starpilot_toggles(sm=None):
from openpilot.starpilot.common.starpilot_variables import get_starpilot_toggles
return get_starpilot_toggles(sm)
def _to_text(value):
if value is None:
return None
@@ -285,6 +314,8 @@ def _copy_param_store_without_overwrite(source: Path, destination: Path) -> int:
if not source.is_dir():
return 0
import shutil
destination.mkdir(parents=True, exist_ok=True)
copied_entries = 0
for path in source.iterdir():
@@ -402,6 +433,8 @@ def _merge_tree_without_overwrite(source: Path, destination: Path) -> int:
if not source.exists():
return moved_entries
import shutil
if not destination.exists():
destination.parent.mkdir(parents=True, exist_ok=True)
shutil.move(str(source), str(destination))
@@ -881,6 +914,8 @@ def manager_init() -> None:
last_timing = _log_boot_timing("manager_init", "version_params", manager_init_start, last_timing)
# set dongle id
from openpilot.system.athena.registration import register
reg_res = register(show_spinner=True)
if reg_res:
dongle_id = reg_res
@@ -958,7 +993,7 @@ def manager_thread() -> None:
last_timing = _log_boot_timing("manager_thread", "messaging", manager_thread_start, last_timing)
write_onroad_params(False, params)
initial_toggles = get_starpilot_toggles()
initial_toggles = _get_starpilot_toggles()
last_timing = _log_boot_timing("manager_thread", "initial_toggles", manager_thread_start, last_timing)
ensure_running(managed_processes.values(), False, params=params, CP=sm['carParams'], not_run=ignore, starpilot_toggles=initial_toggles)
last_timing = _log_boot_timing("manager_thread", "initial_ensure_running", manager_thread_start, last_timing)
@@ -974,7 +1009,7 @@ def manager_thread() -> None:
params_memory = Params(memory=True)
starpilot_toggles = get_starpilot_toggles()
starpilot_toggles = _get_starpilot_toggles()
last_timing = _log_boot_timing("manager_thread", "loop_toggles", manager_thread_start, last_timing)
_log_boot_timing("manager_thread", "loop_ready", manager_thread_start, last_timing)
@@ -1024,8 +1059,7 @@ def manager_thread() -> None:
# kick AGNOS power monitoring watchdog
try:
if sm.all_checks(['deviceState']):
with atomic_write("/var/tmp/power_watchdog", "w", overwrite=True) as f:
f.write(str(time.monotonic()))
_write_power_watchdog(time.monotonic())
except Exception:
pass
@@ -1048,7 +1082,7 @@ def manager_thread() -> None:
break
# StarPilot variables
starpilot_toggles = get_starpilot_toggles(sm)
starpilot_toggles = _get_starpilot_toggles(sm)
def main() -> None:
@@ -1087,6 +1121,9 @@ if __name__ == "__main__":
except KeyboardInterrupt:
print("got CTRL-C, exiting")
except Exception:
from openpilot.common.swaglog import add_file_handler
from openpilot.common.text_window import TextWindow
add_file_handler(cloudlog)
cloudlog.exception("Manager failed to start")