diff --git a/common/params_pyx.pyx b/common/params_pyx.pyx index f9c4bfd894..cae66468a9 100755 --- a/common/params_pyx.pyx +++ b/common/params_pyx.pyx @@ -76,6 +76,7 @@ keys = { b"Offroad_NeosUpdate": [TxType.CLEAR_ON_MANAGER_START], b"Offroad_UpdateFailed": [TxType.CLEAR_ON_MANAGER_START], b"Offroad_HardwareUnsupported": [TxType.CLEAR_ON_MANAGER_START], + b"ForcePowerDown": [TxType.CLEAR_ON_MANAGER_START], } def ensure_bytes(v): diff --git a/panda b/panda index e7a5bf8541..0ae2be95a1 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit e7a5bf85412883cc49a35be6521ccac2bb9502b7 +Subproject commit 0ae2be95a114269b12e039eabf0a563c1ca32ece diff --git a/selfdrive/hardware/base.py b/selfdrive/hardware/base.py index f6ddc1aeb5..f5274deb6c 100644 --- a/selfdrive/hardware/base.py +++ b/selfdrive/hardware/base.py @@ -1,5 +1,7 @@ from abc import abstractmethod +from collections import namedtuple +ThermalConfig = namedtuple('ThermalConfig', ['cpu', 'gpu', 'mem', 'bat', 'ambient']) class HardwareBase: @staticmethod @@ -91,3 +93,11 @@ class HardwareBase: @abstractmethod def get_current_power_draw(self): pass + + @abstractmethod + def shutdown(self): + pass + + @abstractmethod + def get_thermal_config(self): + pass diff --git a/selfdrive/hardware/eon/hardware.py b/selfdrive/hardware/eon/hardware.py index db0c590e66..4666c2a633 100644 --- a/selfdrive/hardware/eon/hardware.py +++ b/selfdrive/hardware/eon/hardware.py @@ -6,7 +6,7 @@ import struct import subprocess from cereal import log -from selfdrive.hardware.base import HardwareBase +from selfdrive.hardware.base import HardwareBase, ThermalConfig NetworkType = log.DeviceState.NetworkType NetworkStrength = log.DeviceState.NetworkStrength @@ -342,3 +342,9 @@ class Android(HardwareBase): def get_current_power_draw(self): # We don't have a good direct way to measure this on android return None + + def shutdown(self): + os.system('LD_LIBRARY_PATH="" svc power shutdown') + + def get_thermal_config(self): + return ThermalConfig(cpu=((5, 7, 10, 12), 10), gpu=((16,), 10), mem=(2, 10), bat=(29, 1000), ambient=(25, 1)) diff --git a/selfdrive/hardware/pc/hardware.py b/selfdrive/hardware/pc/hardware.py index f7b003f3b7..1744b69502 100644 --- a/selfdrive/hardware/pc/hardware.py +++ b/selfdrive/hardware/pc/hardware.py @@ -1,7 +1,7 @@ import random from cereal import log -from selfdrive.hardware.base import HardwareBase +from selfdrive.hardware.base import HardwareBase, ThermalConfig NetworkType = log.DeviceState.NetworkType NetworkStrength = log.DeviceState.NetworkStrength @@ -70,3 +70,9 @@ class Pc(HardwareBase): def get_current_power_draw(self): return 0 + + def shutdown(self): + print("SHUTDOWN!") + + def get_thermal_config(self): + return ThermalConfig(cpu=((None,), 1), gpu=((None,), 1), mem=(None, 1), bat=(None, 1), ambient=(None, 1)) diff --git a/selfdrive/hardware/tici/hardware.py b/selfdrive/hardware/tici/hardware.py index e6dbef1f3b..7fca07a89f 100644 --- a/selfdrive/hardware/tici/hardware.py +++ b/selfdrive/hardware/tici/hardware.py @@ -3,7 +3,7 @@ import subprocess from pathlib import Path from cereal import log -from selfdrive.hardware.base import HardwareBase +from selfdrive.hardware.base import HardwareBase, ThermalConfig NM = 'org.freedesktop.NetworkManager' NM_CON_ACT = NM + '.Connection.Active' @@ -176,3 +176,10 @@ class Tici(HardwareBase): def get_current_power_draw(self): return (self.read_param_file("/sys/class/hwmon/hwmon1/power1_input", int) / 1e6) + + def shutdown(self): + # Note that for this to work and have the device stay powered off, the panda needs to be in UsbPowerMode::CLIENT! + os.system("sudo poweroff") + + def get_thermal_config(self): + return ThermalConfig(cpu=((1, 2, 3, 4, 5, 6, 7, 8), 1000), gpu=((48,49), 1000), mem=(15, 1000), bat=(None, 1), ambient=(70, 1000)) diff --git a/selfdrive/thermald/power_monitoring.py b/selfdrive/thermald/power_monitoring.py index d34659eaea..1dd1885db8 100644 --- a/selfdrive/thermald/power_monitoring.py +++ b/selfdrive/thermald/power_monitoring.py @@ -165,6 +165,7 @@ class PowerMonitoring: disable_charging |= (self.car_battery_capacity_uWh <= 0) disable_charging &= (not pandaState.pandaState.ignitionLine and not pandaState.pandaState.ignitionCan) disable_charging &= (self.params.get("DisablePowerDown") != b"1") + disable_charging |= (self.params.get("ForcePowerDown") == b"1") return disable_charging # See if we need to shutdown diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index e12be46596..23f8602b2d 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -2,7 +2,6 @@ import datetime import os import time -from collections import namedtuple from typing import Dict, Optional, Tuple import psutil @@ -15,15 +14,13 @@ from common.numpy_fast import clip, interp from common.params import Params from common.realtime import DT_TRML, sec_since_boot from selfdrive.controls.lib.alertmanager import set_offroad_alert -from selfdrive.hardware import EON, HARDWARE, TICI +from selfdrive.hardware import EON, HARDWARE from selfdrive.loggerd.config import get_available_percent from selfdrive.pandad import get_expected_signature from selfdrive.swaglog import cloudlog from selfdrive.thermald.power_monitoring import PowerMonitoring from selfdrive.version import get_git_branch, terms_version, training_version -ThermalConfig = namedtuple('ThermalConfig', ['cpu', 'gpu', 'mem', 'bat', 'ambient']) - FW_SIGNATURE = get_expected_signature() ThermalStatus = log.DeviceState.ThermalStatus @@ -40,17 +37,6 @@ prev_offroad_states: Dict[str, Tuple[bool, Optional[str]]] = {} LEON = False last_eon_fan_val = None - -def get_thermal_config(): - # (tz, scale) - if EON: - return ThermalConfig(cpu=((5, 7, 10, 12), 10), gpu=((16,), 10), mem=(2, 10), bat=(29, 1000), ambient=(25, 1)) - elif TICI: - return ThermalConfig(cpu=((1, 2, 3, 4, 5, 6, 7, 8), 1000), gpu=((48,49), 1000), mem=(15, 1000), bat=(None, 1), ambient=(70, 1000)) - else: - return ThermalConfig(cpu=((None,), 1), gpu=((None,), 1), mem=(None, 1), bat=(None, 1), ambient=(None, 1)) - - def read_tz(x): if x is None: return 0 @@ -198,7 +184,7 @@ def thermald_thread(): power_monitor = PowerMonitoring() no_panda_cnt = 0 - thermal_config = get_thermal_config() + thermal_config = HARDWARE.get_thermal_config() while 1: pandaState = messaging.recv_sock(pandaState_sock, wait=True) @@ -395,7 +381,7 @@ def thermald_thread(): cloudlog.info(f"shutting device down, offroad since {off_ts}") # TODO: add function for blocking cloudlog instead of sleep time.sleep(10) - os.system('LD_LIBRARY_PATH="" svc power shutdown') + HARDWARE.shutdown() msg.deviceState.chargingError = current_filter.x > 0. and msg.deviceState.batteryPercent < 90 # if current is positive, then battery is being discharged msg.deviceState.started = started_ts is not None