mirror of
https://github.com/infiniteCable2/openpilot.git
synced 2026-07-26 20:02:11 +08:00
ea8eaed1aa
# Conflicts: # README.md # opendbc_repo # panda # selfdrive/ui/qt/offroad/settings.cc # selfdrive/ui/translations/main_ar.ts # selfdrive/ui/translations/main_de.ts # selfdrive/ui/translations/main_es.ts # selfdrive/ui/translations/main_fr.ts # selfdrive/ui/translations/main_ja.ts # selfdrive/ui/translations/main_ko.ts # selfdrive/ui/translations/main_pt-BR.ts # selfdrive/ui/translations/main_th.ts # selfdrive/ui/translations/main_tr.ts # selfdrive/ui/translations/main_zh-CHS.ts # selfdrive/ui/translations/main_zh-CHT.ts # system/manager/build.py # system/ui/spinner.py # tinygrad_repo # tools/lib/framereader.py Merge branch 'comma-202506127-bedcb896644528aed6af448e63eeadb3dd8b2c77' into sync-20250627 # Conflicts: # opendbc/safety/tests/libsafety/SConscript Merge branch 'comma-202506127-bedcb896644528aed6af448e63eeadb3dd8b2c77' into sync-20250627 # Conflicts: # opendbc/safety/tests/libsafety/SConscript Merge remote-tracking branch 'comma/master' into sync-20250627 # Conflicts: # opendbc/safety/tests/libsafety/SConscript Merge branch 'comma-20250627-1020d355584265391eb3acb556e4353b581fa9c0' into sync-20250627 Merge branch 'comma-20250627-1020d355584265391eb3acb556e4353b581fa9c0' into sync-20250627 Sync: `commaai/opendbc:master` into `sunnypilot/opendbc:master-new` Sync: `commaai/opendbc:master` into `sunnypilot/opendbc:master-new` Sync: `commaai/panda:master` into `sunnypilot/panda:master-new` Sync: `commaai/panda:master` into `sunnypilot/panda:master-new`
153 lines
5.2 KiB
Python
Executable File
153 lines
5.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
|
|
|
This file is part of sunnypilot and is licensed under the MIT License.
|
|
See the LICENSE.md file in the root directory for more details.
|
|
"""
|
|
import logging
|
|
import os
|
|
import stat
|
|
import time
|
|
import traceback
|
|
import requests
|
|
from pathlib import Path
|
|
from urllib.request import urlopen
|
|
|
|
from cereal import messaging
|
|
from openpilot.common.params import Params
|
|
from openpilot.sunnypilot.mapd.mapd_manager import MAPD_PATH, MAPD_BIN_DIR
|
|
from openpilot.system.hardware.hw import Paths
|
|
from openpilot.common.spinner import Spinner
|
|
from openpilot.system.version import is_prebuilt
|
|
import openpilot.system.sentry as sentry
|
|
|
|
VERSION = 'v1.9.0'
|
|
URL = f"https://github.com/pfeiferj/openpilot-mapd/releases/download/{VERSION}/mapd"
|
|
|
|
|
|
class MapdInstallManager:
|
|
def __init__(self, spinner_ref: Spinner):
|
|
self._spinner = spinner_ref
|
|
|
|
def download(self) -> None:
|
|
self.ensure_directories_exist()
|
|
self._download_file()
|
|
self.update_installed_version(VERSION)
|
|
|
|
def check_and_download(self) -> None:
|
|
if self.download_needed():
|
|
self.download()
|
|
|
|
@staticmethod
|
|
def download_needed() -> bool:
|
|
return not os.path.exists(MAPD_PATH) or MapdInstallManager.get_installed_version() != VERSION
|
|
|
|
@staticmethod
|
|
def ensure_directories_exist() -> None:
|
|
if not os.path.exists(Paths.mapd_root()):
|
|
os.makedirs(Paths.mapd_root())
|
|
if not os.path.exists(MAPD_BIN_DIR):
|
|
os.makedirs(MAPD_BIN_DIR)
|
|
|
|
@staticmethod
|
|
def _safe_write_and_set_executable(file_path: Path, content: bytes) -> None:
|
|
with open(file_path, 'wb') as output:
|
|
output.write(content)
|
|
output.flush()
|
|
os.fsync(output.fileno())
|
|
current_permissions = stat.S_IMODE(os.lstat(file_path).st_mode)
|
|
os.chmod(file_path, current_permissions | stat.S_IEXEC)
|
|
|
|
def _download_file(self, num_retries=5) -> None:
|
|
temp_file = Path(MAPD_PATH + ".tmp")
|
|
download_timeout = 60
|
|
for cnt in range(num_retries):
|
|
try:
|
|
response = requests.get(URL, stream=True, timeout=download_timeout)
|
|
response.raise_for_status()
|
|
self._safe_write_and_set_executable(temp_file, response.content)
|
|
# No exceptions encountered. Safe to replace original file.
|
|
temp_file.replace(MAPD_PATH)
|
|
return
|
|
except requests.exceptions.ReadTimeout:
|
|
self._spinner.update(f"ReadTimeout caught. Timeout is [{download_timeout}]. Retrying download... [{cnt}]")
|
|
time.sleep(0.5)
|
|
except requests.exceptions.RequestException as e:
|
|
self._spinner.update(f"RequestException caught: {e}. Retrying download... [{cnt}]")
|
|
time.sleep(0.5)
|
|
|
|
# Delete temp file if the process was not successful.
|
|
if temp_file.exists():
|
|
temp_file.unlink()
|
|
logging.error("Failed to download file after all retries")
|
|
|
|
@staticmethod
|
|
def update_installed_version(version: str) -> None:
|
|
Params().put("MapdVersion", version)
|
|
|
|
@staticmethod
|
|
def get_installed_version() -> str:
|
|
return Params().get("MapdVersion", encoding="utf-8") or ""
|
|
|
|
def wait_for_internet_connection(self, return_on_failure: bool = False) -> bool:
|
|
max_retries = 10
|
|
for retries in range(max_retries + 1):
|
|
self._spinner.update(f"Waiting for internet connection... [{retries}/{max_retries}]")
|
|
time.sleep(2)
|
|
try:
|
|
_ = urlopen('https://sentry.io', timeout=10)
|
|
return True
|
|
except Exception as e:
|
|
print(f'Wait for internet failed: {e}')
|
|
if return_on_failure and retries == max_retries:
|
|
return False
|
|
|
|
return False
|
|
|
|
def non_prebuilt_install(self) -> None:
|
|
sm = messaging.SubMaster(['deviceState'])
|
|
metered = sm['deviceState'].networkMetered
|
|
|
|
if metered:
|
|
self._spinner.update("Can't proceed with mapd install since network is metered!")
|
|
time.sleep(5)
|
|
return
|
|
|
|
try:
|
|
self.ensure_directories_exist()
|
|
if not self.download_needed():
|
|
self._spinner.update("Mapd is good!")
|
|
time.sleep(0.1)
|
|
return
|
|
|
|
if self.wait_for_internet_connection(return_on_failure=True):
|
|
self._spinner.update(f"Downloading pfeiferj's mapd [{install_manager.get_installed_version()}] => [{VERSION}].")
|
|
time.sleep(0.1)
|
|
self.check_and_download()
|
|
self._spinner.close()
|
|
|
|
except Exception:
|
|
for i in range(6):
|
|
self._spinner.update("Failed to download OSM maps won't work until properly downloaded!" +
|
|
"Try again manually rebooting. " +
|
|
f"Boot will continue in {5 - i}s...")
|
|
time.sleep(1)
|
|
|
|
sentry.init(sentry.SentryProject.SELFDRIVE)
|
|
traceback.print_exc()
|
|
sentry.capture_exception()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
spinner = Spinner()
|
|
install_manager = MapdInstallManager(spinner)
|
|
install_manager.ensure_directories_exist()
|
|
if is_prebuilt():
|
|
debug_msg = f"[DEBUG] This is prebuilt, no mapd install required. VERSION: [{VERSION}], Param [{install_manager.get_installed_version()}]"
|
|
spinner.update(debug_msg)
|
|
install_manager.update_installed_version(VERSION)
|
|
else:
|
|
spinner.update(f"Checking if mapd is installed and valid. Prebuilt [{is_prebuilt()}]")
|
|
install_manager.non_prebuilt_install()
|