mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-21 00:03:45 +08:00
Zone 5
This commit is contained in:
Binary file not shown.
+5
-5
@@ -507,7 +507,7 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
||||
pmicTempC @39 :List(Float32);
|
||||
intakeTempC @46 :Float32;
|
||||
exhaustTempC @47 :Float32;
|
||||
caseTempC @48 :Float32;
|
||||
gnssTempC @48 :Float32;
|
||||
bottomSocTempC @50 :Float32;
|
||||
maxTempC @44 :Float32; # max of other temps, used to control fan
|
||||
thermalZones @38 :List(ThermalZone);
|
||||
@@ -522,10 +522,10 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
||||
}
|
||||
|
||||
enum ThermalStatus {
|
||||
green @0;
|
||||
yellow @1;
|
||||
red @2;
|
||||
danger @3;
|
||||
ok @0;
|
||||
warmDEPRECATED @1;
|
||||
overheated @2;
|
||||
critical @3;
|
||||
}
|
||||
|
||||
enum NetworkType {
|
||||
|
||||
@@ -28,6 +28,11 @@ IONIQ_6_BLINDSPOT_LEFT_MASK = 0x10
|
||||
CANFD_CAMERA_LEAD_MIN_DISTANCE = 0.1
|
||||
ALT_BUS_LDA_BUTTON_BURST_DEBOUNCE_NS = int(1.3e9)
|
||||
|
||||
CLASSIC_MEDIA_BUTTON_CARS = frozenset({
|
||||
CAR.HYUNDAI_ELANTRA_2024,
|
||||
CAR.HYUNDAI_ELANTRA_HEV_2024,
|
||||
})
|
||||
|
||||
|
||||
def get_non_scc_cruise_signals(CP) -> tuple[str, str, str, str, str, str]:
|
||||
if CP.flags & HyundaiFlags.EV:
|
||||
@@ -437,6 +442,9 @@ class CarState(CarStateBase):
|
||||
ret.lowSpeedAlert = self.low_speed_alert
|
||||
|
||||
fp_ret = custom.StarPilotCarState.new_message()
|
||||
if self.CP.carFingerprint in CLASSIC_MEDIA_BUTTON_CARS:
|
||||
fp_ret.modePressed = bool(cp.vl["GW_SWRC_PE"]["C_ModeSW"])
|
||||
fp_ret.customPressed = bool(cp.vl["GW_SWRC_PE"]["C_MTSSW"])
|
||||
|
||||
return ret, fp_ret
|
||||
|
||||
@@ -686,6 +694,9 @@ class CarState(CarStateBase):
|
||||
("BCM_PO_11", 0),
|
||||
("CLU13", 0),
|
||||
]
|
||||
if CP.carFingerprint in CLASSIC_MEDIA_BUTTON_CARS:
|
||||
# Steering-wheel media switches are event-driven on the refresh Elantra.
|
||||
msgs.append(("GW_SWRC_PE", 0))
|
||||
if CP.flags & HyundaiFlags.NON_SCC and not (CP.flags & HyundaiFlags.NON_SCC_NO_FCA):
|
||||
msgs.append(("FCA11", 0)) # Non-SCC trims can stop publishing FCA11; don't let it poison canValid
|
||||
|
||||
|
||||
@@ -654,6 +654,22 @@ class TestHyundaiFingerprint:
|
||||
assert DBC[CP.carFingerprint][Bus.pt] == "hyundai_can_refresh_generated"
|
||||
assert CP.safetyConfigs[-1].safetyParam & HyundaiSafetyFlags.CAN_REFRESH_MSGS
|
||||
|
||||
def test_elantra_refresh_decodes_classic_media_buttons(self):
|
||||
toggles = get_test_toggles()
|
||||
CP = CarInterface.get_params(CAR.HYUNDAI_ELANTRA_HEV_2024, gen_empty_fingerprint(), [], True, False, False, toggles)
|
||||
FPCP = CarInterface.get_starpilot_params(CAR.HYUNDAI_ELANTRA_HEV_2024, gen_empty_fingerprint(), [], CP, toggles)
|
||||
|
||||
car_state = CarState(CP, FPCP)
|
||||
can_parsers = car_state.get_can_parsers(CP)
|
||||
packer = CANPacker(DBC[CP.carFingerprint][Bus.pt])
|
||||
media_msg = packer.make_can_msg("GW_SWRC_PE", 0, {"C_ModeSW": 1, "C_MTSSW": 1})
|
||||
|
||||
can_parsers[Bus.pt].update([(1_000_000_000, [media_msg])])
|
||||
_, fp_ret = car_state.update(can_parsers, toggles)
|
||||
|
||||
assert fp_ret.modePressed
|
||||
assert fp_ret.customPressed
|
||||
|
||||
def test_hyundai_lkas_button_sets_starpilot_safety_flag(self):
|
||||
fingerprint = gen_empty_fingerprint()
|
||||
fingerprint[0][0x391] = 8
|
||||
|
||||
@@ -17,15 +17,12 @@ LEAF_ADAS_COMMAND_ADDRS = frozenset((0x1C3, 0x2B0))
|
||||
LEAF_2025_SV_PLUS_CAMERA_FW = b'6WK2CDB\x04\x18\x00\x00\x00\x00\x00R=1\x18\x99\x10\x00\x00\x00\x80'
|
||||
|
||||
# This Leaf camera uses KWP2000 rather than UDS for session management.
|
||||
LEAF_KWP_AFTER_SALES_REQUEST = b"\x10\xC0"
|
||||
LEAF_KWP_AFTER_SALES_RESPONSE = b"\x50\xC0"
|
||||
LEAF_KWP_DATA_MONITOR_REQUEST = b"\x10\xF0"
|
||||
LEAF_KWP_DATA_MONITOR_RESPONSE = b"\x50\xF0"
|
||||
LEAF_KWP_DISABLE_NORMAL_TX = b"\x28\x01"
|
||||
LEAF_KWP_ENABLE_NORMAL_TX = b"\x29\x01"
|
||||
LEAF_KWP_ENABLE_NORMAL_TX_RESPONSE = b"\x69"
|
||||
|
||||
LEAF_KWP_SESSIONS = (
|
||||
(LEAF_KWP_AFTER_SALES_REQUEST, LEAF_KWP_AFTER_SALES_RESPONSE),
|
||||
(NISSAN_DIAGNOSTIC_REQUEST_KWP, NISSAN_DIAGNOSTIC_RESPONSE_KWP),
|
||||
LEAF_KWP_TAKEOVER_SESSIONS = (
|
||||
(LEAF_KWP_DATA_MONITOR_REQUEST, LEAF_KWP_DATA_MONITOR_RESPONSE),
|
||||
)
|
||||
|
||||
|
||||
@@ -68,25 +65,45 @@ def leaf_adas_commands_silent(can_recv, settle_time=0.05, observe_time=0.15):
|
||||
return saw_adas_bus_traffic
|
||||
|
||||
|
||||
def leaf_adas_commands_present(can_recv, settle_time=0.05, observe_time=0.15):
|
||||
"""Confirm the stock ADAS command sender resumed on bus 1."""
|
||||
if can_recv is None:
|
||||
return False
|
||||
|
||||
try:
|
||||
time.sleep(settle_time)
|
||||
can_recv()
|
||||
|
||||
deadline = time.monotonic() + observe_time
|
||||
while time.monotonic() < deadline:
|
||||
for packet in can_recv(wait_for_one=True):
|
||||
if any(msg.src == LEAF_ADAS_COMMAND_BUS and msg.address in LEAF_ADAS_COMMAND_ADDRS for msg in packet):
|
||||
return True
|
||||
except Exception as e:
|
||||
ecu_log(f"Nissan Leaf ADAS TX recovery verification exception: {e}")
|
||||
return False
|
||||
|
||||
ecu_log("Nissan Leaf ADAS normal TX recovery could not be verified")
|
||||
return False
|
||||
|
||||
|
||||
def restore_leaf_adas_tx(can_recv, can_send):
|
||||
"""Re-enable normal KWP message transmission, trying both safe diagnostic sessions."""
|
||||
"""Return to the confirmed KWP default session and verify normal TX resumes."""
|
||||
if can_recv is None or can_send is None:
|
||||
return False
|
||||
|
||||
for diag_request, diag_response in LEAF_KWP_SESSIONS:
|
||||
try:
|
||||
ecu_log(f"Nissan Leaf ADAS TX restore using KWP session {diag_request.hex()}")
|
||||
query = IsoTpParallelQuery(
|
||||
can_send, can_recv, LEAF_ADAS_ECU_BUS, [LEAF_ADAS_ECU_ADDR],
|
||||
[diag_request, LEAF_KWP_ENABLE_NORMAL_TX],
|
||||
[diag_response, LEAF_KWP_ENABLE_NORMAL_TX_RESPONSE],
|
||||
response_offset=NISSAN_RX_OFFSET,
|
||||
)
|
||||
if query.get_data(0.2):
|
||||
ecu_log("Nissan Leaf ADAS normal TX restored")
|
||||
return True
|
||||
except Exception as e:
|
||||
ecu_log(f"Nissan Leaf ADAS TX restore exception: {e}")
|
||||
try:
|
||||
ecu_log("Nissan Leaf ADAS TX restore using KWP default session 1081")
|
||||
query = IsoTpParallelQuery(
|
||||
can_send, can_recv, LEAF_ADAS_ECU_BUS, [LEAF_ADAS_ECU_ADDR],
|
||||
[NISSAN_DIAGNOSTIC_REQUEST_KWP], [NISSAN_DIAGNOSTIC_RESPONSE_KWP],
|
||||
response_offset=NISSAN_RX_OFFSET,
|
||||
)
|
||||
if query.get_data(0.2) and leaf_adas_commands_present(can_recv):
|
||||
ecu_log("Nissan Leaf ADAS normal TX restored and command traffic confirmed")
|
||||
return True
|
||||
except Exception as e:
|
||||
ecu_log(f"Nissan Leaf ADAS TX restore exception: {e}")
|
||||
|
||||
ecu_log("Nissan Leaf ADAS normal TX restore was not confirmed")
|
||||
return False
|
||||
@@ -141,10 +158,10 @@ class CarInterface(CarInterfaceBase):
|
||||
from openpilot.common.params import Params
|
||||
params = Params()
|
||||
ecu_disabled = False
|
||||
for diag_request, diag_response in LEAF_KWP_SESSIONS:
|
||||
for diag_request, diag_response in LEAF_KWP_TAKEOVER_SESSIONS:
|
||||
ecu_log(f"Nissan Leaf ADAS takeover using KWP session {diag_request.hex()}")
|
||||
ecu_disabled = disable_ecu(can_recv, can_send, bus=LEAF_ADAS_ECU_BUS, addr=LEAF_ADAS_ECU_ADDR,
|
||||
com_cont_req=LEAF_KWP_DISABLE_NORMAL_TX, require_response=True, retry=3,
|
||||
com_cont_req=LEAF_KWP_DISABLE_NORMAL_TX, require_response=True, retry=1,
|
||||
diag_request=diag_request, diag_response=diag_response, response_offset=NISSAN_RX_OFFSET)
|
||||
if ecu_disabled:
|
||||
break
|
||||
|
||||
@@ -5,7 +5,8 @@ import pytest
|
||||
from opendbc.car import Bus, ButtonType, gen_empty_fingerprint, structs
|
||||
from opendbc.car.can_definitions import CanData
|
||||
from opendbc.car.nissan.carstate import CarState
|
||||
from opendbc.car.nissan.interface import CarInterface, LEAF_2025_SV_PLUS_CAMERA_FW, leaf_adas_commands_silent, restore_leaf_adas_tx
|
||||
from opendbc.car.nissan.interface import CarInterface, LEAF_2025_SV_PLUS_CAMERA_FW, leaf_adas_commands_present, \
|
||||
leaf_adas_commands_silent, restore_leaf_adas_tx
|
||||
from opendbc.car.nissan.values import CAR, CarControllerParams, NissanSafetyFlags
|
||||
|
||||
|
||||
@@ -143,28 +144,24 @@ def test_leaf_ecu_disable_is_strict_and_falls_back(monkeypatch, ecu_disabled):
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
|
||||
CarInterface.init(CP, None, None)
|
||||
|
||||
assert len(calls) == (1 if ecu_disabled else 2)
|
||||
assert len(calls) == 1
|
||||
assert calls[0]["addr"] == 0x707
|
||||
assert calls[0]["bus"] == 0
|
||||
assert calls[0]["response_offset"] == 0x20
|
||||
assert calls[0]["require_response"] is True
|
||||
assert calls[0]["diag_request"] == b"\x10\xc0"
|
||||
assert calls[0]["diag_response"] == b"\x50\xc0"
|
||||
assert calls[0]["diag_request"] == b"\x10\xf0"
|
||||
assert calls[0]["diag_response"] == b"\x50\xf0"
|
||||
assert calls[0]["com_cont_req"] == b"\x28\x01"
|
||||
assert calls[0]["retry"] == 3
|
||||
if not ecu_disabled:
|
||||
assert calls[1]["diag_request"] == b"\x10\x81"
|
||||
assert calls[1]["diag_response"] == b"\x50\x81"
|
||||
assert calls[0]["retry"] == 1
|
||||
assert CP.openpilotLongitudinalControl is ecu_disabled
|
||||
assert CP.pcmCruise is not ecu_disabled
|
||||
assert bool(CP.safetyConfigs[-1].safetyParam & NissanSafetyFlags.LONG_CONTROL) is ecu_disabled
|
||||
|
||||
|
||||
def test_leaf_kwp_session_can_confirm_ecu_disable(monkeypatch):
|
||||
def test_leaf_kwp_data_monitor_session_can_confirm_ecu_disable(monkeypatch):
|
||||
CP = CarInterface.get_params(CAR.NISSAN_LEAF, gen_empty_fingerprint(), SUPPORTED_LEAF_FW, True, False, False, None)
|
||||
results = iter((False, True))
|
||||
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: next(results))
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.disable_ecu", lambda *args, **kwargs: True)
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.leaf_adas_commands_silent", lambda *_: True)
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
|
||||
CarInterface.init(CP, None, None)
|
||||
@@ -205,7 +202,17 @@ def test_leaf_adas_command_silence_requires_live_bus_without_stock_commands(monk
|
||||
assert not leaf_adas_commands_silent(lambda wait_for_one=False: [], settle_time=0, observe_time=0.001)
|
||||
|
||||
|
||||
def test_leaf_adas_restore_uses_kwp_enable_normal_transmission(monkeypatch):
|
||||
def test_leaf_adas_command_recovery_requires_stock_command(monkeypatch):
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
|
||||
|
||||
def stock_command_traffic(wait_for_one=False):
|
||||
return [] if not wait_for_one else [[CanData(0x1C3, b"\x00" * 8, 1)]]
|
||||
|
||||
assert leaf_adas_commands_present(stock_command_traffic, settle_time=0, observe_time=0.001)
|
||||
assert not leaf_adas_commands_present(lambda wait_for_one=False: [], settle_time=0, observe_time=0.001)
|
||||
|
||||
|
||||
def test_leaf_adas_restore_returns_to_kwp_default_session(monkeypatch):
|
||||
queries = []
|
||||
|
||||
class FakeQuery:
|
||||
@@ -216,7 +223,8 @@ def test_leaf_adas_restore_uses_kwp_enable_normal_transmission(monkeypatch):
|
||||
return {(0x707, None): b""}
|
||||
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.IsoTpParallelQuery", FakeQuery)
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.leaf_adas_commands_present", lambda *_: True)
|
||||
monkeypatch.setattr("opendbc.car.nissan.interface.ecu_log", lambda *_: None)
|
||||
|
||||
assert restore_leaf_adas_tx(lambda **kwargs: [], lambda msgs: None)
|
||||
assert queries == [(0, [0x707], [b"\x10\xc0", b"\x29\x01"], [b"\x50\xc0", b"\x69"], 0x20)]
|
||||
assert queries == [(0, [0x707], [b"\x10\x81"], [b"\x50\x81"], 0x20)]
|
||||
|
||||
@@ -709,7 +709,7 @@ IONIQ_5_LOW_SPEED_CENTER_LAT = 0.40
|
||||
IONIQ_5_LOW_SPEED_CENTER_LAT_WIDTH = 0.10
|
||||
IONIQ_5_LOW_SPEED_CENTER_JERK = 0.40
|
||||
IONIQ_5_LOW_SPEED_CENTER_JERK_WIDTH = 0.12
|
||||
IONIQ_5_FRICTION_JERK_DEADZONE_MAX = 0.30
|
||||
IONIQ_5_FRICTION_JERK_DEADZONE_MAX = 0.36
|
||||
IONIQ_5_FRICTION_JERK_DEADZONE_LAT = 1.25
|
||||
IONIQ_5_FRICTION_JERK_DEADZONE_LAT_WIDTH = 0.35
|
||||
IONIQ_5_FRICTION_JERK_DEADZONE_SPEED = 18.0
|
||||
|
||||
@@ -56,7 +56,7 @@ MonitoringPolicy = log.DriverMonitoringState.MonitoringPolicy
|
||||
StarPilotEventName = custom.StarPilotOnroadEvent.EventName
|
||||
|
||||
IGNORED_SAFETY_MODES = (SafetyModel.silent, SafetyModel.noOutput)
|
||||
VALID_ONLY_COMM_ISSUE_GRACE_FRAMES = max(1, round(0.25 / DT_CTRL))
|
||||
VALID_ONLY_COMM_ISSUE_GRACE_FRAMES = max(1, round(0.5 / DT_CTRL))
|
||||
|
||||
|
||||
def evaluate_comm_issue(all_checks: bool, all_alive: bool, all_freq_ok: bool,
|
||||
@@ -515,7 +515,7 @@ class SelfdriveD:
|
||||
self.events.add(EventName.pedalPressed)
|
||||
|
||||
# Create events for temperature, disk space, and memory
|
||||
if self.sm['deviceState'].thermalStatus >= ThermalStatus.red:
|
||||
if self.sm['deviceState'].thermalStatus >= ThermalStatus.overheated:
|
||||
self.events.add(EventName.overheat)
|
||||
if self.sm['deviceState'].freeSpacePercent < 7 and not SIMULATION:
|
||||
self.events.add(EventName.outOfSpace)
|
||||
|
||||
@@ -3,6 +3,7 @@ import cereal.messaging as messaging
|
||||
from cereal import car, custom, log
|
||||
from opendbc.car.hyundai.values import CAR as HYUNDAI_CAR
|
||||
from opendbc.car.nissan.values import CAR as NISSAN_CAR
|
||||
from openpilot.common.realtime import DT_CTRL
|
||||
|
||||
from openpilot.selfdrive.selfdrived.selfdrived import (
|
||||
VALID_ONLY_COMM_ISSUE_GRACE_FRAMES,
|
||||
@@ -27,6 +28,13 @@ def test_valid_only_comm_issue_is_debounced():
|
||||
assert frames == 0
|
||||
|
||||
|
||||
def test_route_length_validity_cascade_stays_silent():
|
||||
frames = 0
|
||||
for _ in range(round(0.4 / DT_CTRL)):
|
||||
should_alert, frames = evaluate_comm_issue(False, True, True, frames)
|
||||
assert not should_alert
|
||||
|
||||
|
||||
def test_dead_or_slow_comm_issue_is_immediate():
|
||||
assert evaluate_comm_issue(False, False, True, 0) == (True, 0)
|
||||
assert evaluate_comm_issue(False, True, False, 0) == (True, 0)
|
||||
|
||||
@@ -122,9 +122,9 @@ class Sidebar(Widget):
|
||||
thermal_status = device_state.thermalStatus
|
||||
temperature = f"{int(device_state.maxTempC)}°C"
|
||||
|
||||
if thermal_status == ThermalStatus.green:
|
||||
if thermal_status == ThermalStatus.ok:
|
||||
self._temp_status.update(tr_noop("TEMP"), temperature, Colors.GOOD)
|
||||
elif thermal_status == ThermalStatus.yellow:
|
||||
elif thermal_status == ThermalStatus.warmDEPRECATED:
|
||||
self._temp_status.update(tr_noop("TEMP"), temperature, Colors.WARNING)
|
||||
else:
|
||||
self._temp_status.update(tr_noop("TEMP"), temperature, Colors.DANGER)
|
||||
|
||||
@@ -51,7 +51,8 @@ class ThermalConfig:
|
||||
memory: ThermalZone | None = None
|
||||
intake: ThermalZone | None = None
|
||||
exhaust: ThermalZone | None = None
|
||||
case: ThermalZone | None = None
|
||||
gnss: ThermalZone | None = None
|
||||
bottomSoc: ThermalZone | None = None
|
||||
|
||||
def get_msg(self):
|
||||
ret = {}
|
||||
|
||||
@@ -133,15 +133,21 @@ HardwareState = namedtuple("HardwareState", ['network_type', 'network_info', 'ne
|
||||
|
||||
# List of thermal bands. We will stay within this region as long as we are within the bounds.
|
||||
# When exiting the bounds, we'll jump to the lower or higher band. Bands are ordered in the dict.
|
||||
THERMAL_BANDS = OrderedDict({
|
||||
ThermalStatus.green: ThermalBand(None, 80.0),
|
||||
ThermalStatus.yellow: ThermalBand(75.0, 96.0),
|
||||
ThermalStatus.red: ThermalBand(88.0, 107.),
|
||||
ThermalStatus.danger: ThermalBand(94.0, None),
|
||||
})
|
||||
if HARDWARE.get_device_type() == "mici":
|
||||
THERMAL_BANDS = OrderedDict({
|
||||
ThermalStatus.ok: ThermalBand(None, 100.0),
|
||||
ThermalStatus.overheated: ThermalBand(92.0, 107.),
|
||||
ThermalStatus.critical: ThermalBand(98.0, None),
|
||||
})
|
||||
else:
|
||||
THERMAL_BANDS = OrderedDict({
|
||||
ThermalStatus.ok: ThermalBand(None, 96.0),
|
||||
ThermalStatus.overheated: ThermalBand(88.0, 107.),
|
||||
ThermalStatus.critical: ThermalBand(94.0, None),
|
||||
})
|
||||
|
||||
# Override to highest thermal band when offroad and above this temp
|
||||
OFFROAD_DANGER_TEMP = 75
|
||||
OFFROAD_DANGER_TEMP = 85 if HARDWARE.get_device_type() == "mici" else 75
|
||||
|
||||
prev_offroad_states: dict[str, tuple[bool, str | None]] = {}
|
||||
|
||||
@@ -279,7 +285,7 @@ def hardware_thread(end_event, hw_queue) -> None:
|
||||
started_ts: float | None = None
|
||||
started_seen = False
|
||||
startup_blocked_ts: float | None = None
|
||||
thermal_status = ThermalStatus.yellow
|
||||
thermal_status = ThermalStatus.ok
|
||||
|
||||
last_hw_state = HardwareState(
|
||||
network_type=NetworkType.none,
|
||||
@@ -405,13 +411,13 @@ def hardware_thread(end_event, hw_queue) -> None:
|
||||
|
||||
# StarPilot variables
|
||||
if starpilot_toggles.increase_thermal_limits:
|
||||
all_comp_temp -= (THERMAL_BANDS[ThermalStatus.danger].min_temp - THERMAL_BANDS[ThermalStatus.red].min_temp)
|
||||
all_comp_temp -= (THERMAL_BANDS[ThermalStatus.critical].min_temp - THERMAL_BANDS[ThermalStatus.overheated].min_temp)
|
||||
|
||||
is_offroad_for_5_min = (started_ts is None) and ((not started_seen) or (off_ts is None) or (time.monotonic() - off_ts > 60 * 5))
|
||||
if is_offroad_for_5_min and offroad_comp_temp > OFFROAD_DANGER_TEMP:
|
||||
# if device is offroad and already hot without the extra onroad load,
|
||||
# we want to cool down first before increasing load
|
||||
thermal_status = ThermalStatus.danger
|
||||
thermal_status = ThermalStatus.critical
|
||||
else:
|
||||
current_band = THERMAL_BANDS[thermal_status]
|
||||
band_idx = list(THERMAL_BANDS.keys()).index(thermal_status)
|
||||
@@ -434,17 +440,20 @@ def hardware_thread(end_event, hw_queue) -> None:
|
||||
startup_conditions["not_taking_snapshot"] = not params.get_bool("IsTakingSnapshot")
|
||||
|
||||
# must be at an engageable thermal band to go onroad
|
||||
startup_conditions["device_temp_engageable"] = thermal_status < ThermalStatus.red
|
||||
startup_conditions["device_temp_engageable"] = thermal_status < ThermalStatus.overheated
|
||||
|
||||
# ensure device is fully booted
|
||||
startup_conditions["device_booted"] = startup_conditions.get("device_booted", False) or HARDWARE.booted()
|
||||
|
||||
# if the temperature enters the danger zone, go offroad to cool down
|
||||
onroad_conditions["device_temp_good"] = thermal_status < ThermalStatus.danger
|
||||
onroad_conditions["device_temp_good"] = thermal_status < ThermalStatus.critical
|
||||
extra_text = f"{offroad_comp_temp:.1f}C"
|
||||
show_alert = (not onroad_conditions["device_temp_good"] or not startup_conditions["device_temp_engageable"]) and onroad_conditions["ignition"]
|
||||
set_offroad_alert_if_changed("Offroad_TemperatureTooHigh", show_alert, extra_text=extra_text)
|
||||
|
||||
if show_alert:
|
||||
msg.deviceState.fanSpeedPercentDesired = 100
|
||||
|
||||
# *** registration check ***
|
||||
if not PC:
|
||||
# we enforce this for our software, but you are welcome
|
||||
@@ -563,9 +572,10 @@ def hardware_thread(end_event, hw_queue) -> None:
|
||||
statlog.gauge("fan_speed_percent_desired", msg.deviceState.fanSpeedPercentDesired)
|
||||
statlog.gauge("screen_brightness_percent", msg.deviceState.screenBrightnessPercent)
|
||||
|
||||
# report to server once every 10 minutes
|
||||
# report to server once every 10 minutes, or every 1s when thermally blocked
|
||||
rising_edge_started = should_start and not should_start_prev
|
||||
if rising_edge_started or (count % int(600. / DT_HW)) == 0:
|
||||
status_packet_interval = 1. if show_alert else 600.
|
||||
if rising_edge_started or (count % int(status_packet_interval / DT_HW)) == 0:
|
||||
dat = {
|
||||
'count': count,
|
||||
'pandaStates': [strip_deprecated_keys(p.to_dict()) for p in pandaStates],
|
||||
|
||||
@@ -321,11 +321,12 @@ class Tici(HardwareBase):
|
||||
os.system("sudo poweroff")
|
||||
|
||||
def get_thermal_config(self):
|
||||
intake, exhaust, case = None, None, None
|
||||
intake, exhaust, gnss, bottomSoc = None, None, None, None
|
||||
if self.get_device_type() == "mici":
|
||||
case = ThermalZone("case")
|
||||
gnss = ThermalZone("gnss")
|
||||
intake = ThermalZone("intake")
|
||||
exhaust = ThermalZone("exhaust")
|
||||
bottomSoc = ThermalZone("bottom_soc")
|
||||
return ThermalConfig(cpu=[ThermalZone(f"cpu{i}-silver-usr") for i in range(4)] +
|
||||
[ThermalZone(f"cpu{i}-gold-usr") for i in range(4)],
|
||||
gpu=[ThermalZone("gpu0-usr"), ThermalZone("gpu1-usr")],
|
||||
@@ -334,7 +335,8 @@ class Tici(HardwareBase):
|
||||
pmic=[ThermalZone("pm8998_tz"), ThermalZone("pm8005_tz")],
|
||||
intake=intake,
|
||||
exhaust=exhaust,
|
||||
case=case)
|
||||
gnss=gnss,
|
||||
bottomSoc=bottomSoc)
|
||||
|
||||
def set_display_power(self, on):
|
||||
try:
|
||||
@@ -383,6 +385,9 @@ class Tici(HardwareBase):
|
||||
continue
|
||||
gov = 'ondemand' if powersave_enabled else 'performance'
|
||||
sudo_write(gov, f'/sys/devices/system/cpu/cpufreq/policy{n}/scaling_governor')
|
||||
if not powersave_enabled:
|
||||
# cap max core freq to 1689 Mhz
|
||||
sudo_write('1689600', f'/sys/devices/system/cpu/cpufreq/policy{n}/scaling_max_freq')
|
||||
|
||||
# *** IRQ config ***
|
||||
|
||||
|
||||
Reference in New Issue
Block a user