@ -1,20 +1,18 @@
#!/usr/bin/env python3
#!/usr/bin/env python3
import os
import os
import json
import copy
import datetime
import datetime
import psutil
import psutil
from smbus2 import SMBus
from smbus2 import SMBus
from cereal import log
from cereal import log
from common . android import ANDROID , get_network_type , get_network_strength
from common . android import ANDROID , get_network_type , get_network_strength
from common . basedir import BASEDIR
from common . params import Params , put_nonblocking
from common . params import Params , put_nonblocking
from common . realtime import sec_since_boot , DT_TRML
from common . realtime import sec_since_boot , DT_TRML
from common . numpy_fast import clip , interp
from common . numpy_fast import clip , interp
from common . filter_simple import FirstOrderFilter
from common . filter_simple import FirstOrderFilter
from selfdrive . version import terms_version , training_version
from selfdrive . version import terms_version , training_version , get_git_branch
from selfdrive . swaglog import cloudlog
from selfdrive . swaglog import cloudlog
import cereal . messaging as messaging
import cereal . messaging as messaging
from selfdrive . controls . lib . alertmanager import set_offroad_alert
from selfdrive . loggerd . config import get_available_percent
from selfdrive . loggerd . config import get_available_percent
from selfdrive . pandad import get_expected_signature
from selfdrive . pandad import get_expected_signature
from selfdrive . thermald . power_monitoring import PowerMonitoring , get_battery_capacity , get_battery_status , \
from selfdrive . thermald . power_monitoring import PowerMonitoring , get_battery_capacity , get_battery_status , \
@ -35,10 +33,6 @@ LEON = False
last_eon_fan_val = None
last_eon_fan_val = None
with open ( BASEDIR + " /selfdrive/controls/lib/alerts_offroad.json " ) as json_file :
OFFROAD_ALERTS = json . load ( json_file )
def read_tz ( x , clip = True ) :
def read_tz ( x , clip = True ) :
if not ANDROID :
if not ANDROID :
# we don't monitor thermal on PC
# we don't monitor thermal on PC
@ -171,6 +165,7 @@ def thermald_thread():
thermal_status_prev = ThermalStatus . green
thermal_status_prev = ThermalStatus . green
usb_power = True
usb_power = True
usb_power_prev = True
usb_power_prev = True
current_branch = get_git_branch ( )
network_type = NetworkType . none
network_type = NetworkType . none
network_strength = NetworkStrength . unknown
network_strength = NetworkStrength . unknown
@ -179,7 +174,7 @@ def thermald_thread():
cpu_temp_filter = FirstOrderFilter ( 0. , CPU_TEMP_TAU , DT_TRML )
cpu_temp_filter = FirstOrderFilter ( 0. , CPU_TEMP_TAU , DT_TRML )
health_prev = None
health_prev = None
fw_version_match_prev = True
fw_version_match_prev = True
current_connectivity _alert = None
current_update _alert = None
time_valid_prev = True
time_valid_prev = True
should_start_prev = False
should_start_prev = False
handle_fan = None
handle_fan = None
@ -300,9 +295,9 @@ def thermald_thread():
# show invalid date/time alert
# show invalid date/time alert
time_valid = now . year > = 2019
time_valid = now . year > = 2019
if time_valid and not time_valid_prev :
if time_valid and not time_valid_prev :
params . delete ( " Offroad_InvalidTime " )
set_offroad_alert ( " Offroad_InvalidTime " , False )
if not time_valid and time_valid_prev :
if not time_valid and time_valid_prev :
put_nonblocking ( " Offroad_InvalidTime " , json . dumps ( OFFROAD_ALERTS [ " Offroad_InvalidTime " ] ) )
set_offroad_alert ( " Offroad_InvalidTime " , True )
time_valid_prev = time_valid
time_valid_prev = time_valid
# Show update prompt
# Show update prompt
@ -314,24 +309,37 @@ def thermald_thread():
update_failed_count = params . get ( " UpdateFailedCount " )
update_failed_count = params . get ( " UpdateFailedCount " )
update_failed_count = 0 if update_failed_count is None else int ( update_failed_count )
update_failed_count = 0 if update_failed_count is None else int ( update_failed_count )
last_update_exception = params . get ( " LastUpdateException " , encoding = ' utf8 ' )
if dt . days > DAYS_NO_CONNECTIVITY_MAX and update_failed_count > 1 :
if update_failed_count > 15 and last_update_exception is not None :
if current_connectivity_alert != " expired " :
if current_branch in [ " release2 " , " dashcam " ] :
current_connectivity_alert = " expired "
extra_text = " Ensure the software is correctly installed "
params . delete ( " Offroad_ConnectivityNeededPrompt " )
else :
put_nonblocking ( " Offroad_ConnectivityNeeded " , json . dumps ( OFFROAD_ALERTS [ " Offroad_ConnectivityNeeded " ] ) )
extra_text = last_update_exception
if current_update_alert != " update " + extra_text :
current_update_alert = " update " + extra_text
set_offroad_alert ( " Offroad_ConnectivityNeeded " , False )
set_offroad_alert ( " Offroad_ConnectivityNeededPrompt " , False )
set_offroad_alert ( " Offroad_UpdateFailed " , True , extra_text = extra_text )
elif dt . days > DAYS_NO_CONNECTIVITY_MAX and update_failed_count > 1 :
if current_update_alert != " expired " :
current_update_alert = " expired "
set_offroad_alert ( " Offroad_UpdateFailed " , False )
set_offroad_alert ( " Offroad_ConnectivityNeededPrompt " , False )
set_offroad_alert ( " Offroad_ConnectivityNeeded " , True )
elif dt . days > DAYS_NO_CONNECTIVITY_PROMPT :
elif dt . days > DAYS_NO_CONNECTIVITY_PROMPT :
remaining_time = str ( max ( DAYS_NO_CONNECTIVITY_MAX - dt . days , 0 ) )
remaining_time = str ( max ( DAYS_NO_CONNECTIVITY_MAX - dt . days , 0 ) )
if current_connectivity_alert != " prompt " + remaining_time :
if current_update _alert != " prompt " + remaining_time :
current_connectivity_alert = " prompt " + remaining_time
current_update _alert = " prompt " + remaining_time
alert_connectivity_prompt = copy . copy ( OFFROAD_ALERTS [ " Offroad_ConnectivityNeededPrompt " ] )
set_offroad_alert ( " Offroad_UpdateFailed " , False )
alert_connectivity_prompt [ " text " ] + = remaining_time + " days. "
set_offroad_alert ( " Offroad_ConnectivityNeeded " , False )
params . delete ( " Offroad_ConnectivityNeeded " )
set_offroad_alert ( " Offroad_ConnectivityNeededPrompt " , True , extra_text = f " { remaining_time } days. " )
put_nonblocking ( " Offroad_ConnectivityNeededPrompt " , json . dumps ( alert_connectivity_prompt ) )
elif current_update_alert is not None :
elif current_connectivity_alert is not None :
current_update_alert = None
current_connectivity_alert = None
set_offroad_alert ( " Offroad_UpdateFailed " , False )
params . delete ( " Offroad_ConnectivityNeeded " )
set_offroad_alert ( " Offroad_ConnectivityNeeded " , False )
params . delete ( " Offroad_ConnectivityNeededPrompt " )
set_offroad_alert ( " Offroad_ConnectivityNeededPrompt " , False )
do_uninstall = params . get ( " DoUninstall " ) == b " 1 "
do_uninstall = params . get ( " DoUninstall " ) == b " 1 "
accepted_terms = params . get ( " HasAcceptedTerms " ) == terms_version
accepted_terms = params . get ( " HasAcceptedTerms " ) == terms_version
@ -361,19 +369,19 @@ def thermald_thread():
should_start = should_start and ( not is_taking_snapshot ) and ( not is_viewing_driver )
should_start = should_start and ( not is_taking_snapshot ) and ( not is_viewing_driver )
if fw_version_match and not fw_version_match_prev :
if fw_version_match and not fw_version_match_prev :
params . delete ( " Offroad_PandaFirmwareMismatch " )
set_offroad_alert ( " Offroad_PandaFirmwareMismatch " , False )
if not fw_version_match and fw_version_match_prev :
if not fw_version_match and fw_version_match_prev :
put_nonblocking ( " Offroad_PandaFirmwareMismatch " , json . dumps ( OFFROAD_ALERTS [ " Offroad_PandaFirmwareMismatch " ] ) )
set_offroad_alert ( " Offroad_PandaFirmwareMismatch " , True )
# if any CPU gets above 107 or the battery gets above 63, kill all processes
# if any CPU gets above 107 or the battery gets above 63, kill all processes
# controls will warn with CPU above 95 or battery above 60
# controls will warn with CPU above 95 or battery above 60
if thermal_status > = ThermalStatus . danger :
if thermal_status > = ThermalStatus . danger :
should_start = False
should_start = False
if thermal_status_prev < ThermalStatus . danger :
if thermal_status_prev < ThermalStatus . danger :
put_nonblocking ( " Offroad_TemperatureTooHigh " , json . dumps ( OFFROAD_ALERTS [ " Offroad_TemperatureTooHigh " ] ) )
set_offroad_alert ( " Offroad_TemperatureTooHigh " , True )
else :
else :
if thermal_status_prev > = ThermalStatus . danger :
if thermal_status_prev > = ThermalStatus . danger :
params . delete ( " Offroad_TemperatureTooHigh " )
set_offroad_alert ( " Offroad_TemperatureTooHigh " , False )
if should_start :
if should_start :
if not should_start_prev :
if not should_start_prev :
@ -411,9 +419,9 @@ def thermald_thread():
thermal_sock . send ( msg . to_bytes ( ) )
thermal_sock . send ( msg . to_bytes ( ) )
if usb_power_prev and not usb_power :
if usb_power_prev and not usb_power :
put_nonblocking ( " Offroad_ChargeDisabled " , json . dumps ( OFFROAD_ALERTS [ " Offroad_ChargeDisabled " ] ) )
set_offroad_alert ( " Offroad_ChargeDisabled " , True )
elif usb_power and not usb_power_prev :
elif usb_power and not usb_power_prev :
params . delete ( " Offroad_ChargeDisabled " )
set_offroad_alert ( " Offroad_ChargeDisabled " , False )
thermal_status_prev = thermal_status
thermal_status_prev = thermal_status
usb_power_prev = usb_power
usb_power_prev = usb_power