diff --git a/common/params.cc b/common/params.cc index 070e4e4df..77cb677a1 100644 --- a/common/params.cc +++ b/common/params.cc @@ -231,6 +231,8 @@ std::unordered_map keys = { {"dp_lat_road_edge_detection", PERSISTENT}, {"dp_device_disable_logging", PERSISTENT}, {"dp_toyota_pcm_compensation", PERSISTENT}, + {"dp_device_is_clone", PERSISTENT}, + {"dp_device_dm_unavailable", PERSISTENT}, }; } // namespace diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index d3dbdc5a6..ea5c98b1c 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -67,6 +67,8 @@ class Controls: self._dp_alka_active = True self._dp_lat_lane_change_assist_mode = int(self.params.get("dp_lat_lane_change_assist_mode")) self._dp_lat_lane_change_assist_mode_disable_active = False + self._dp_device_dm_unavailable = self.params.get_bool("dp_device_dm_unavailable") + self._dp_device_dm_unavailable_active = True if self._dp_device_dm_unavailable else False if CI is None: cloudlog.info("controlsd is waiting for CarParams") @@ -89,6 +91,9 @@ class Controls: self.sensor_packets = ["accelerometer", "gyroscope"] self.camera_packets = ["roadCameraState", "driverCameraState", "wideRoadCameraState"] + if self._dp_device_dm_unavailable_active: + self.camera_packets.remove("driverCameraState") + self.log_sock = messaging.sub_sock('androidLog') # TODO: de-couple controlsd with card/conflate on carState without introducing controls mismatches @@ -310,7 +315,14 @@ class Controls: else: if not SIMULATION and not self.rk.lagging: if not self.sm.all_alive(self.camera_packets): - self.events.add(EventName.cameraMalfunction) + if not self._dp_device_dm_unavailable_active and not self.sm.all_alive(['driverCameraState']): + self._dp_device_dm_unavailable_active = True + self.params.put_bool("dp_device_dm_unavailable", True) + + if self._dp_device_dm_unavailable_active and not self.sm.all_alive(['driverCameraState']): + pass + else: + self.events.add(EventName.cameraMalfunction) elif not self.sm.all_freq_ok(self.camera_packets): self.events.add(EventName.cameraFrameRate) if not REPLAY and self.rk.lagging: diff --git a/selfdrive/pandad/pandad.cc b/selfdrive/pandad/pandad.cc index 095a7893b..4166e3d97 100644 --- a/selfdrive/pandad/pandad.cc +++ b/selfdrive/pandad/pandad.cc @@ -506,6 +506,9 @@ void peripheral_control_thread(Panda *panda, bool no_fan_control) { FirstOrderFilter integ_lines_filter(0, 30.0, 0.05); + // dp + bool dp_device_dm_unavailable = Params().getBool("dp_device_dm_unavailable"); + while (!do_exit && panda->connected()) { sm.update(1000); @@ -518,7 +521,7 @@ void peripheral_control_thread(Panda *panda, bool no_fan_control) { } } - if (sm.updated("driverCameraState")) { + if (!dp_device_dm_unavailable && sm.updated("driverCameraState")) { auto event = sm["driverCameraState"]; int cur_integ_lines = event.getDriverCameraState().getIntegLines(); diff --git a/selfdrive/ui/qt/offroad/settings.cc b/selfdrive/ui/qt/offroad/settings.cc index eceb57382..7d5cd6c14 100644 --- a/selfdrive/ui/qt/offroad/settings.cc +++ b/selfdrive/ui/qt/offroad/settings.cc @@ -209,12 +209,12 @@ DevicePanel::DevicePanel(SettingsWindow *parent) : ListWidget(parent) { addItem(pair_device); // offroad-only buttons - + if (!params.getBool("dp_device_dm_unavailable")) { auto dcamBtn = new ButtonControl(tr("Driver Camera"), tr("PREVIEW"), tr("Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)")); connect(dcamBtn, &ButtonControl::clicked, [=]() { emit showDriverView(); }); addItem(dcamBtn); - + } auto resetCalibBtn = new ButtonControl(tr("Reset Calibration"), tr("RESET"), ""); connect(resetCalibBtn, &ButtonControl::showDescriptionEvent, this, &DevicePanel::updateCalibDescription); connect(resetCalibBtn, &ButtonControl::clicked, [&]() { diff --git a/selfdrive/ui/qt/widgets/prime.cc b/selfdrive/ui/qt/widgets/prime.cc index 25712c26c..c76f2db52 100644 --- a/selfdrive/ui/qt/widgets/prime.cc +++ b/selfdrive/ui/qt/widgets/prime.cc @@ -16,6 +16,9 @@ #include "selfdrive/ui/qt/qt_window.h" #include "selfdrive/ui/qt/widgets/wifi.h" +// dp +#include "common/params.h" + using qrcodegen::QrCode; PairingQRWidget::PairingQRWidget(QWidget* parent) : QWidget(parent) { @@ -225,10 +228,21 @@ SetupWidget::SetupWidget(QWidget* parent) : QFrame(parent) { content_layout->setContentsMargins(0, 0, 0, 0); content_layout->setSpacing(30); + // dp - hide it + if (!Params().getBool("dp_device_dm_unavailable") && !Params().getBool("dp_device_is_clone")) { WiFiPromptWidget *wifi_prompt = new WiFiPromptWidget; QObject::connect(wifi_prompt, &WiFiPromptWidget::openSettings, this, &SetupWidget::openSettings); content_layout->addWidget(wifi_prompt); content_layout->addStretch(); + } else { + // rick - add an empty box to preserve layout + QVBoxLayout *empty_layout = new QVBoxLayout(); + empty_layout->setContentsMargins(56, 40, 56, 40); + empty_layout->setSpacing(20); + content_layout->addLayout(empty_layout); + content_layout->addStretch(); + } + mainLayout->addWidget(content); diff --git a/system/athena/registration.py b/system/athena/registration.py index 97289e419..be9debf61 100755 --- a/system/athena/registration.py +++ b/system/athena/registration.py @@ -13,6 +13,8 @@ from openpilot.system.hardware import HARDWARE, PC from openpilot.system.hardware.hw import Paths from openpilot.common.swaglog import cloudlog +# dp +import os UNREGISTERED_DONGLE_ID = "UnregisteredDevice" @@ -92,6 +94,16 @@ def register(show_spinner=False) -> str | None: if dongle_id: params.put("DongleId", dongle_id) set_offroad_alert("Offroad_UnofficialHardware", (dongle_id == UNREGISTERED_DONGLE_ID) and not PC) + # dp - detecting clone device + if dongle_id == UNREGISTERED_DONGLE_ID: + params.put_bool("dp_device_is_clone", True) + set_offroad_alert("Offroad_UnofficialHardware", False) + else: + # clean log if no longer clone + if params.get_bool("dp_device_is_clone"): + if not PC: + os.system("rm -fr /data/media/0/realdata/*") + params.put_bool("dp_device_is_clone", False) return dongle_id diff --git a/system/hardware/hardwared.py b/system/hardware/hardwared.py index 4caff20d8..7ee664031 100755 --- a/system/hardware/hardwared.py +++ b/system/hardware/hardwared.py @@ -206,6 +206,9 @@ def hardware_thread(end_event, hw_queue) -> None: fan_controller = None + # dp + dp_device_is_clone = params.get_bool("dp_device_is_clone") + while not end_event.is_set(): sm.update(PANDA_STATES_TIMEOUT) @@ -318,7 +321,8 @@ def hardware_thread(end_event, hw_queue) -> None: set_offroad_alert_if_changed("Offroad_TemperatureTooHigh", show_alert, extra_text=extra_text) # TODO: this should move to TICI.initialize_hardware, but we currently can't import params there - if TICI: + # dp - only check nvme issue with comma device + if TICI and not dp_device_is_clone: if not os.path.isfile("/persist/comma/living-in-the-moment"): if not Path("/data/media").is_mount(): set_offroad_alert_if_changed("Offroad_StorageMissing", True) diff --git a/system/manager/manager.py b/system/manager/manager.py index 6904677da..cf4599bb6 100755 --- a/system/manager/manager.py +++ b/system/manager/manager.py @@ -70,6 +70,8 @@ def manager_init() -> None: ("dp_lat_road_edge_detection", "0"), ("dp_device_disable_logging", "0"), ("dp_toyota_pcm_compensation", "0"), + ("dp_device_is_clone", "0"), + ("dp_device_dm_unavailable", "0"), ] if not PC: default_params.append(("LastUpdateTime", datetime.datetime.now(datetime.UTC).replace(tzinfo=None).isoformat().encode('utf8'))) @@ -153,6 +155,14 @@ def manager_thread() -> None: params = Params() ignore: list[str] = [] + # dp + dp_device_dm_unavailable = params.get_bool("dp_device_dm_unavailable") + dp_device_is_clone = params.get_bool("dp_device_is_clone") + if dp_device_is_clone or dp_device_dm_unavailable: + ignore += ["manage_athenad", "uploader"] + if dp_device_dm_unavailable: + ignore += ["dmonitoringd", "dmonitoringmodeld"] + if params.get("DongleId", encoding='utf8') in (None, UNREGISTERED_DONGLE_ID): ignore += ["manage_athenad", "uploader"] if os.getenv("NOBOARD") is not None: diff --git a/system/manager/process_config.py b/system/manager/process_config.py index 4e9cdc102..4956cf72c 100644 --- a/system/manager/process_config.py +++ b/system/manager/process_config.py @@ -50,6 +50,9 @@ def dp_onroad_uploads(started, params, CP: car.CarParams) -> bool: else: return always_run(started, params, CP) +def dpdmonitoringd(started, params, CP: car.CarParams) -> bool: + return params.get_bool("dp_device_dm_unavailable") and started + procs = [ DaemonProcess("manage_athenad", "system.athena.manage_athenad", "AthenadPid"), @@ -94,6 +97,9 @@ procs = [ NativeProcess("bridge", "cereal/messaging", ["./bridge"], notcar), PythonProcess("webrtcd", "system.webrtc.webrtcd", notcar), PythonProcess("webjoystick", "tools.bodyteleop.web", notcar), + + #dp + PythonProcess("dpdmonitoringd", "dp_ext.selfdrive.monitoring.dmonitoringd", dpdmonitoringd, enabled=not PC), ] managed_processes = {p.name: p for p in procs}