auto type cast for `Params` (#35786)

* first

* fix

* fix

* this

* real

* time

* time

* more

* more

* fix

* subclass

* fix

* fix

* test

* fix

* ruff

* revert

* default

* json

* more

* test

* test

* d

* better

* better

* test

* one

* test

* space
pull/35795/head
Maxime Desroches 6 days ago committed by GitHub
parent 4d39d50858
commit 58d3038241
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 16
      common/params.cc
  2. 21
      common/params.h
  3. 3
      common/params.py
  4. 238
      common/params_keys.h
  5. 49
      common/params_pyx.pyx
  6. 39
      common/tests/test_params.py
  7. 5
      selfdrive/selfdrived/selfdrived.py
  8. 4
      selfdrive/selfdrived/tests/test_alerts.py
  9. 5
      selfdrive/test/test_updated.py
  10. 2
      selfdrive/ui/layouts/settings/firehose.py
  11. 12
      selfdrive/ui/widgets/offroad_alerts.py
  12. 2
      system/athena/athenad.py
  13. 6
      system/hardware/power_monitoring.py
  14. 2
      system/loggerd/logger.cc
  15. 37
      system/manager/manager.py
  16. 2
      system/updated/tests/test_base.py
  17. 14
      system/updated/updated.py

@ -115,8 +115,16 @@ bool Params::checkKey(const std::string &key) {
return keys.find(key) != keys.end();
}
ParamKeyFlag Params::getKeyFlag(const std::string &key) {
return static_cast<ParamKeyFlag>(keys[key].flags);
}
ParamKeyType Params::getKeyType(const std::string &key) {
return static_cast<ParamKeyType>(keys[key]);
return keys[key].type;
}
std::string Params::getKeyDefaultValue(const std::string &key) {
return keys[key].default_value;
}
int Params::put(const char* key, const char* value, size_t value_size) {
@ -195,17 +203,17 @@ std::map<std::string, std::string> Params::readAll() {
return util::read_files_in_dir(getParamPath());
}
void Params::clearAll(ParamKeyType key_type) {
void Params::clearAll(ParamKeyFlag key_flag) {
FileLock file_lock(params_path + "/.lock");
// 1) delete params of key_type
// 1) delete params of key_flag
// 2) delete files that are not defined in the keys.
if (DIR *d = opendir(getParamPath().c_str())) {
struct dirent *de = NULL;
while ((de = readdir(d))) {
if (de->d_type != DT_DIR) {
auto it = keys.find(de->d_name);
if (it == keys.end() || (it->second & key_type)) {
if (it == keys.end() || (it->second.flags & key_flag)) {
unlink(getParamPath(de->d_name).c_str());
}
}

@ -9,7 +9,7 @@
#include "common/queue.h"
enum ParamKeyType {
enum ParamKeyFlag {
PERSISTENT = 0x02,
CLEAR_ON_MANAGER_START = 0x04,
CLEAR_ON_ONROAD_TRANSITION = 0x08,
@ -20,6 +20,21 @@ enum ParamKeyType {
ALL = 0xFFFFFFFF
};
enum ParamKeyType {
STRING = 0,
BOOL = 1,
INT = 2,
FLOAT = 3,
TIME = 4, // ISO 8601
JSON = 5
};
struct ParamKeyAttributes {
uint32_t flags;
ParamKeyType type;
std::string default_value = "";
};
class Params {
public:
explicit Params(const std::string &path = {});
@ -30,14 +45,16 @@ public:
std::vector<std::string> allKeys() const;
bool checkKey(const std::string &key);
ParamKeyFlag getKeyFlag(const std::string &key);
ParamKeyType getKeyType(const std::string &key);
std::string getKeyDefaultValue(const std::string &key);
inline std::string getParamPath(const std::string &key = {}) {
return params_path + params_prefix + (key.empty() ? "" : "/" + key);
}
// Delete a value
int remove(const std::string &key);
void clearAll(ParamKeyType type);
void clearAll(ParamKeyFlag flag);
// helpers for reading values
std::string get(const std::string &key, bool block = false);

@ -1,5 +1,6 @@
from openpilot.common.params_pyx import Params, ParamKeyType, UnknownKeyName
from openpilot.common.params_pyx import Params, ParamKeyFlag, ParamKeyType, UnknownKeyName
assert Params
assert ParamKeyFlag
assert ParamKeyType
assert UnknownKeyName

@ -3,122 +3,124 @@
#include <string>
#include <unordered_map>
inline static std::unordered_map<std::string, uint32_t> keys = {
{"AccessToken", CLEAR_ON_MANAGER_START | DONT_LOG},
{"AdbEnabled", PERSISTENT},
{"AlwaysOnDM", PERSISTENT},
{"ApiCache_Device", PERSISTENT},
{"ApiCache_FirehoseStats", PERSISTENT},
{"AssistNowToken", PERSISTENT},
{"AthenadPid", PERSISTENT},
{"AthenadUploadQueue", PERSISTENT},
{"AthenadRecentlyViewedRoutes", PERSISTENT},
{"BootCount", PERSISTENT},
{"CalibrationParams", PERSISTENT},
{"CameraDebugExpGain", CLEAR_ON_MANAGER_START},
{"CameraDebugExpTime", CLEAR_ON_MANAGER_START},
{"CarBatteryCapacity", PERSISTENT},
{"CarParams", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"CarParamsCache", CLEAR_ON_MANAGER_START},
{"CarParamsPersistent", PERSISTENT},
{"CarParamsPrevRoute", PERSISTENT},
{"CompletedTrainingVersion", PERSISTENT},
{"ControlsReady", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"CurrentBootlog", PERSISTENT},
{"CurrentRoute", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"DisableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"DisablePowerDown", PERSISTENT},
{"DisableUpdates", PERSISTENT},
{"DisengageOnAccelerator", PERSISTENT},
{"DongleId", PERSISTENT},
{"DoReboot", CLEAR_ON_MANAGER_START},
{"DoShutdown", CLEAR_ON_MANAGER_START},
{"DoUninstall", CLEAR_ON_MANAGER_START},
{"DriverTooDistracted", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON},
{"AlphaLongitudinalEnabled", PERSISTENT | DEVELOPMENT_ONLY},
{"ExperimentalMode", PERSISTENT},
{"ExperimentalModeConfirmed", PERSISTENT},
{"FirmwareQueryDone", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"ForcePowerDown", PERSISTENT},
{"GitBranch", PERSISTENT},
{"GitCommit", PERSISTENT},
{"GitCommitDate", PERSISTENT},
{"GitDiff", PERSISTENT},
{"GithubSshKeys", PERSISTENT},
{"GithubUsername", PERSISTENT},
{"GitRemote", PERSISTENT},
{"GsmApn", PERSISTENT},
{"GsmMetered", PERSISTENT},
{"GsmRoaming", PERSISTENT},
{"HardwareSerial", PERSISTENT},
{"HasAcceptedTerms", PERSISTENT},
{"InstallDate", PERSISTENT},
{"IsDriverViewEnabled", CLEAR_ON_MANAGER_START},
{"IsEngaged", PERSISTENT},
{"IsLdwEnabled", PERSISTENT},
{"IsMetric", PERSISTENT},
{"IsOffroad", CLEAR_ON_MANAGER_START},
{"IsOnroad", PERSISTENT},
{"IsRhdDetected", PERSISTENT},
{"IsReleaseBranch", CLEAR_ON_MANAGER_START},
{"IsTakingSnapshot", CLEAR_ON_MANAGER_START},
{"IsTestedBranch", CLEAR_ON_MANAGER_START},
{"JoystickDebugMode", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"LanguageSetting", PERSISTENT},
{"LastAthenaPingTime", CLEAR_ON_MANAGER_START},
{"LastGPSPosition", PERSISTENT},
{"LastManagerExitReason", CLEAR_ON_MANAGER_START},
{"LastOffroadStatusPacket", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"LastPowerDropDetected", CLEAR_ON_MANAGER_START},
{"LastUpdateException", CLEAR_ON_MANAGER_START},
{"LastUpdateTime", PERSISTENT},
{"LiveDelay", PERSISTENT},
{"LiveParameters", PERSISTENT},
{"LiveParametersV2", PERSISTENT},
{"LiveTorqueParameters", PERSISTENT | DONT_LOG},
{"LocationFilterInitialState", PERSISTENT},
{"LongitudinalManeuverMode", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"LongitudinalPersonality", PERSISTENT},
{"NetworkMetered", PERSISTENT},
{"ObdMultiplexingChanged", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"ObdMultiplexingEnabled", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"Offroad_CarUnrecognized", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"Offroad_ConnectivityNeeded", CLEAR_ON_MANAGER_START},
{"Offroad_ConnectivityNeededPrompt", CLEAR_ON_MANAGER_START},
{"Offroad_IsTakingSnapshot", CLEAR_ON_MANAGER_START},
{"Offroad_NeosUpdate", CLEAR_ON_MANAGER_START},
{"Offroad_NoFirmware", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"Offroad_Recalibration", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"Offroad_StorageMissing", CLEAR_ON_MANAGER_START},
{"Offroad_TemperatureTooHigh", CLEAR_ON_MANAGER_START},
{"Offroad_UnregisteredHardware", CLEAR_ON_MANAGER_START},
{"Offroad_UpdateFailed", CLEAR_ON_MANAGER_START},
{"OnroadCycleRequested", CLEAR_ON_MANAGER_START},
{"OpenpilotEnabledToggle", PERSISTENT},
{"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"PandaSomResetTriggered", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"PandaSignatures", CLEAR_ON_MANAGER_START},
{"PrimeType", PERSISTENT},
{"RecordAudio", PERSISTENT},
{"RecordFront", PERSISTENT},
{"RecordFrontLock", PERSISTENT}, // for the internal fleet
{"SecOCKey", PERSISTENT | DONT_LOG},
{"RouteCount", PERSISTENT},
{"SnoozeUpdate", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
{"SshEnabled", PERSISTENT},
{"TermsVersion", PERSISTENT},
{"TrainingVersion", PERSISTENT},
{"UbloxAvailable", PERSISTENT},
{"UpdateAvailable", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
{"UpdateFailedCount", CLEAR_ON_MANAGER_START},
{"UpdaterAvailableBranches", PERSISTENT},
{"UpdaterCurrentDescription", CLEAR_ON_MANAGER_START},
{"UpdaterCurrentReleaseNotes", CLEAR_ON_MANAGER_START},
{"UpdaterFetchAvailable", CLEAR_ON_MANAGER_START},
{"UpdaterNewDescription", CLEAR_ON_MANAGER_START},
{"UpdaterNewReleaseNotes", CLEAR_ON_MANAGER_START},
{"UpdaterState", CLEAR_ON_MANAGER_START},
{"UpdaterTargetBranch", CLEAR_ON_MANAGER_START},
{"UpdaterLastFetchTime", PERSISTENT},
{"Version", PERSISTENT},
#include "cereal/gen/cpp/log.capnp.h"
inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}},
{"AdbEnabled", {PERSISTENT, BOOL}},
{"AlwaysOnDM", {PERSISTENT, BOOL}},
{"ApiCache_Device", {PERSISTENT, STRING}},
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
{"AssistNowToken", {PERSISTENT, STRING}},
{"AthenadPid", {PERSISTENT, STRING}},
{"AthenadUploadQueue", {PERSISTENT, JSON}},
{"AthenadRecentlyViewedRoutes", {PERSISTENT, STRING}},
{"BootCount", {PERSISTENT, INT}},
{"CalibrationParams", {PERSISTENT, STRING}},
{"CameraDebugExpGain", {CLEAR_ON_MANAGER_START, STRING}},
{"CameraDebugExpTime", {CLEAR_ON_MANAGER_START, STRING}},
{"CarBatteryCapacity", {PERSISTENT, INT}},
{"CarParams", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"CarParamsCache", {CLEAR_ON_MANAGER_START, STRING}},
{"CarParamsPersistent", {PERSISTENT, STRING}},
{"CarParamsPrevRoute", {PERSISTENT, STRING}},
{"CompletedTrainingVersion", {PERSISTENT, STRING, "0"}},
{"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"CurrentBootlog", {PERSISTENT, STRING}},
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"DisablePowerDown", {PERSISTENT, BOOL}},
{"DisableUpdates", {PERSISTENT, BOOL}},
{"DisengageOnAccelerator", {PERSISTENT, BOOL, "0"}},
{"DongleId", {PERSISTENT, STRING}},
{"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}},
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY, BOOL}},
{"ExperimentalMode", {PERSISTENT, BOOL}},
{"ExperimentalModeConfirmed", {PERSISTENT, BOOL}},
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"ForcePowerDown", {PERSISTENT, BOOL}},
{"GitBranch", {PERSISTENT, STRING}},
{"GitCommit", {PERSISTENT, STRING}},
{"GitCommitDate", {PERSISTENT, STRING}},
{"GitDiff", {PERSISTENT, STRING}},
{"GithubSshKeys", {PERSISTENT, STRING}},
{"GithubUsername", {PERSISTENT, STRING}},
{"GitRemote", {PERSISTENT, STRING}},
{"GsmApn", {PERSISTENT, STRING}},
{"GsmMetered", {PERSISTENT, BOOL, "1"}},
{"GsmRoaming", {PERSISTENT, BOOL}},
{"HardwareSerial", {PERSISTENT, STRING}},
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
{"InstallDate", {PERSISTENT, TIME}},
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
{"IsEngaged", {PERSISTENT, BOOL}},
{"IsLdwEnabled", {PERSISTENT, BOOL}},
{"IsMetric", {PERSISTENT, BOOL}},
{"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}},
{"IsOnroad", {PERSISTENT, BOOL}},
{"IsRhdDetected", {PERSISTENT, BOOL}},
{"IsReleaseBranch", {CLEAR_ON_MANAGER_START, BOOL}},
{"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}},
{"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}},
{"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"LanguageSetting", {PERSISTENT, STRING, "main_en"}},
{"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}},
{"LastGPSPosition", {PERSISTENT, STRING}},
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
{"LastUpdateTime", {PERSISTENT, TIME}},
{"LiveDelay", {PERSISTENT, STRING}},
{"LiveParameters", {PERSISTENT, STRING}},
{"LiveParametersV2", {PERSISTENT, STRING}},
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, STRING}},
{"LocationFilterInitialState", {PERSISTENT, STRING}},
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"LongitudinalPersonality", {PERSISTENT, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
{"NetworkMetered", {PERSISTENT, BOOL}},
{"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"ObdMultiplexingEnabled", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"Offroad_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
{"Offroad_ConnectivityNeeded", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_ConnectivityNeededPrompt", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_IsTakingSnapshot", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
{"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
{"Offroad_StorageMissing", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}},
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
{"OpenpilotEnabledToggle", {PERSISTENT, BOOL, "1"}},
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"PandaSomResetTriggered", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"PandaSignatures", {CLEAR_ON_MANAGER_START, STRING}},
{"PrimeType", {PERSISTENT, INT}},
{"RecordAudio", {PERSISTENT, BOOL}},
{"RecordFront", {PERSISTENT, BOOL}},
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
{"SecOCKey", {PERSISTENT | DONT_LOG, STRING}},
{"RouteCount", {PERSISTENT, INT}},
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"SshEnabled", {PERSISTENT, BOOL}},
{"TermsVersion", {PERSISTENT, STRING}},
{"TrainingVersion", {PERSISTENT, STRING}},
{"UbloxAvailable", {PERSISTENT, BOOL}},
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
{"UpdateFailedCount", {CLEAR_ON_MANAGER_START, INT}},
{"UpdaterAvailableBranches", {PERSISTENT, STRING}},
{"UpdaterCurrentDescription", {CLEAR_ON_MANAGER_START, STRING}},
{"UpdaterCurrentReleaseNotes", {CLEAR_ON_MANAGER_START, STRING}},
{"UpdaterFetchAvailable", {CLEAR_ON_MANAGER_START, BOOL}},
{"UpdaterNewDescription", {CLEAR_ON_MANAGER_START, STRING}},
{"UpdaterNewReleaseNotes", {CLEAR_ON_MANAGER_START, STRING}},
{"UpdaterState", {CLEAR_ON_MANAGER_START, STRING}},
{"UpdaterTargetBranch", {CLEAR_ON_MANAGER_START, STRING}},
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
{"Version", {PERSISTENT, STRING}},
};

@ -1,11 +1,13 @@
# distutils: language = c++
# cython: language_level = 3
import datetime
import json
from libcpp cimport bool
from libcpp.string cimport string
from libcpp.vector cimport vector
cdef extern from "common/params.h":
cpdef enum ParamKeyType:
cpdef enum ParamKeyFlag:
PERSISTENT
CLEAR_ON_MANAGER_START
CLEAR_ON_ONROAD_TRANSITION
@ -14,6 +16,14 @@ cdef extern from "common/params.h":
CLEAR_ON_IGNITION_ON
ALL
cpdef enum ParamKeyType:
STRING
BOOL
INT
FLOAT
TIME
JSON
cdef cppclass c_Params "Params":
c_Params(string) except + nogil
string get(string, bool) nogil
@ -24,8 +34,10 @@ cdef extern from "common/params.h":
void putBoolNonBlocking(string, bool) nogil
int putBool(string, bool) nogil
bool checkKey(string) nogil
ParamKeyType getKeyType(string) nogil
string getKeyDefaultValue(string) nogil
string getParamPath(string) nogil
void clearAll(ParamKeyType)
void clearAll(ParamKeyFlag)
vector[string] allKeys()
@ -51,8 +63,8 @@ cdef class Params:
def __dealloc__(self):
del self.p
def clear_all(self, tx_type=ParamKeyType.ALL):
self.p.clearAll(tx_type)
def clear_all(self, tx_flag=ParamKeyFlag.ALL):
self.p.clearAll(tx_flag)
def check_key(self, key):
key = ensure_bytes(key)
@ -60,8 +72,28 @@ cdef class Params:
raise UnknownKeyName(key)
return key
def get(self, key, bool block=False, encoding=None):
def cast(self, value, t, default):
try:
if t == STRING:
return value
elif t == BOOL:
return value == b"1"
elif t == INT:
return int(value)
elif t == FLOAT:
return float(value)
elif t == TIME:
return datetime.datetime.fromisoformat(value)
elif t == JSON:
return json.loads(value)
else:
return default
except (TypeError, ValueError):
return default
def get(self, key, bool block=False, encoding=None, default=None):
cdef string k = self.check_key(key)
cdef ParamKeyType t = self.p.getKeyType(ensure_bytes(key))
cdef string val
with nogil:
val = self.p.get(k, block)
@ -72,9 +104,9 @@ cdef class Params:
# it means we got an interrupt while waiting
raise KeyboardInterrupt
else:
return None
return default
return val if encoding is None else val.decode(encoding)
return self.cast(val if encoding is None else val.decode(encoding), t, default)
def get_bool(self, key, bool block=False):
cdef string k = self.check_key(key)
@ -122,3 +154,6 @@ cdef class Params:
def all_keys(self):
return self.p.allKeys()
def get_default_value(self, key):
return self.p.getKeyDefaultValue(self.check_key(key))

@ -1,10 +1,12 @@
import pytest
import datetime
import json
import os
import threading
import time
import uuid
from openpilot.common.params import Params, ParamKeyType, UnknownKeyName
from openpilot.common.params import Params, ParamKeyFlag, UnknownKeyName
class TestParams:
def setup_method(self):
@ -29,7 +31,7 @@ class TestParams:
f.write("test")
assert os.path.isfile(undefined_param)
self.params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START)
self.params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START)
assert self.params.get("CarParams") is None
assert self.params.get("DongleId") is not None
assert not os.path.isfile(undefined_param)
@ -107,3 +109,36 @@ class TestParams:
assert len(keys) > 20
assert len(keys) == len(set(keys))
assert b"CarParams" in keys
def test_params_default_init_value(self):
assert self.params.get_default_value("LanguageSetting")
assert self.params.get_default_value("LongitudinalPersonality")
assert not self.params.get_default_value("LiveParameters")
def test_params_get_type(self):
# json
self.params.put("ApiCache_FirehoseStats", json.dumps({"a": 0}))
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
# int
self.params.put("BootCount", str(1441))
assert self.params.get("BootCount") == 1441
# bool
self.params.put("AdbEnabled", "1")
assert self.params.get("AdbEnabled")
# time
now = datetime.datetime.now(datetime.UTC)
self.params.put("InstallDate", str(now))
assert self.params.get("InstallDate", encoding="utf-8") == now
def test_params_get_default(self):
now = datetime.datetime.now(datetime.UTC)
self.params.remove("InstallDate")
assert self.params.get("InstallDate", encoding="utf-8") is None
assert self.params.get("InstallDate", encoding="utf-8", default=now) == now
self.params.put("BootCount", "1xx1")
assert self.params.get("BootCount", encoding="utf-8") is None
assert self.params.get("BootCount", encoding="utf-8", default=1441) == 1441

@ -478,10 +478,7 @@ class SelfdriveD:
self.CS_prev = CS
def read_personality_param(self):
try:
return int(self.params.get('LongitudinalPersonality'))
except (ValueError, TypeError):
return log.LongitudinalPersonality.standard
return self.params.get('LongitudinalPersonality', default=log.LongitudinalPersonality.standard)
def params_thread(self, evt):
while not evt.is_set():

@ -111,7 +111,7 @@ class TestAlerts:
alert = copy.copy(self.offroad_alerts[a])
set_offroad_alert(a, True)
alert['extra'] = ''
assert json.dumps(alert) == params.get(a, encoding='utf8')
assert alert == params.get(a, encoding='utf8')
# then delete it
set_offroad_alert(a, False)
@ -125,6 +125,6 @@ class TestAlerts:
alert = self.offroad_alerts[a]
set_offroad_alert(a, True, extra_text="a"*i)
written_alert = json.loads(params.get(a, encoding='utf8'))
written_alert = params.get(a, encoding='utf8')
assert "a"*i == written_alert['extra']
assert alert["text"] == written_alert['text']

@ -162,8 +162,7 @@ class TestUpdated:
def _check_update_state(self, update_available):
# make sure LastUpdateTime is recent
t = self._read_param("LastUpdateTime")
last_update_time = datetime.datetime.fromisoformat(t)
last_update_time = self._read_param("LastUpdateTime", encoding="utf-8")
td = datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_update_time
assert td.total_seconds() < 10
self.params.remove("LastUpdateTime")
@ -174,7 +173,7 @@ class TestUpdated:
# check params
update = self._read_param("UpdateAvailable")
assert update == "1" == update_available, f"UpdateAvailable: {repr(update)}"
assert self._read_param("UpdateFailedCount") == "0"
assert self._read_param("UpdateFailedCount") == 0
# TODO: check that the finalized update actually matches remote
# check the .overlay_init and .overlay_consistent flags

@ -55,7 +55,7 @@ class FirehoseLayout(Widget):
if not stats:
return 0
try:
return int(json.loads(stats).get("firehose", 0))
return int(stats.get("firehose", 0))
except Exception:
cloudlog.exception(f"Failed to decode firehose stats: {stats}")
return 0

@ -190,14 +190,10 @@ class OffroadAlert(AbstractAlert):
for alert_data in self.sorted_alerts:
text = ""
bytes_data = self.params.get(alert_data.key)
if bytes_data:
try:
alert_json = json.loads(bytes_data)
text = alert_json.get("text", "").replace("{}", alert_json.get("extra", ""))
except json.JSONDecodeError:
text = ""
alert_json = self.params.get(alert_data.key)
if alert_json:
text = alert_json.get("text", "").replace("{}", alert_json.get("extra", ""))
alert_data.text = text
alert_data.visible = bool(text)

@ -151,7 +151,7 @@ class UploadQueueCache:
try:
upload_queue_json = Params().get("AthenadUploadQueue")
if upload_queue_json is not None:
for item in json.loads(upload_queue_json):
for item in upload_queue_json:
upload_queue.put(UploadItem.from_dict(item))
except Exception:
cloudlog.exception("athena.UploadQueueCache.initialize.exception")

@ -29,12 +29,10 @@ class PowerMonitoring:
self.car_voltage_instant_mV = 12e3 # Last value of peripheralState voltage
self.integration_lock = threading.Lock()
car_battery_capacity_uWh = self.params.get("CarBatteryCapacity")
if car_battery_capacity_uWh is None:
car_battery_capacity_uWh = 0
car_battery_capacity_uWh = self.params.get("CarBatteryCapacity", default=0)
# Reset capacity if it's low
self.car_battery_capacity_uWh = max((CAR_BATTERY_CAPACITY_uWh / 10), int(car_battery_capacity_uWh))
self.car_battery_capacity_uWh = max((CAR_BATTERY_CAPACITY_uWh / 10), car_battery_capacity_uWh)
# Calculation tick
def calculate(self, voltage: int | None, ignition: bool):

@ -59,7 +59,7 @@ kj::Array<capnp::word> logger_build_init_data() {
for (auto& [key, value] : params_map) {
auto lentry = lparams[j];
lentry.setKey(key);
if ( !(params.getKeyType(key) & DONT_LOG) ) {
if ( !(params.getKeyFlag(key) & DONT_LOG) ) {
lentry.setValue(capnp::Data::Reader((const kj::byte*)value.data(), value.size()));
}
j++;

@ -8,7 +8,7 @@ import traceback
from cereal import log
import cereal.messaging as messaging
import openpilot.system.sentry as sentry
from openpilot.common.params import Params, ParamKeyType
from openpilot.common.params import Params, ParamKeyFlag
from openpilot.common.text_window import TextWindow
from openpilot.system.hardware import HARDWARE
from openpilot.system.manager.helpers import unblock_stdout, write_onroad_params, save_bootlog
@ -26,30 +26,21 @@ def manager_init() -> None:
build_metadata = get_build_metadata()
params = Params()
params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START)
params.clear_all(ParamKeyType.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyType.CLEAR_ON_OFFROAD_TRANSITION)
params.clear_all(ParamKeyType.CLEAR_ON_IGNITION_ON)
params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START)
params.clear_all(ParamKeyFlag.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_OFFROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_IGNITION_ON)
if build_metadata.release_channel:
params.clear_all(ParamKeyType.DEVELOPMENT_ONLY)
default_params: list[tuple[str, str | bytes]] = [
("CompletedTrainingVersion", "0"),
("DisengageOnAccelerator", "0"),
("GsmMetered", "1"),
("HasAcceptedTerms", "0"),
("LanguageSetting", "main_en"),
("OpenpilotEnabledToggle", "1"),
("LongitudinalPersonality", str(log.LongitudinalPersonality.standard)),
]
params.clear_all(ParamKeyFlag.DEVELOPMENT_ONLY)
if params.get_bool("RecordFrontLock"):
params.put_bool("RecordFront", True)
# set unset params
for k, v in default_params:
if params.get(k) is None:
params.put(k, v)
# set unset params to their default value
for k in params.all_keys():
default_value = params.get_default_value(k)
if default_value and not params.get(k):
params.put(k, default_value)
# Create folders needed for msgq
try:
@ -142,13 +133,13 @@ def manager_thread() -> None:
started = sm['deviceState'].started
if started and not started_prev:
params.clear_all(ParamKeyType.CLEAR_ON_ONROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_ONROAD_TRANSITION)
elif not started and started_prev:
params.clear_all(ParamKeyType.CLEAR_ON_OFFROAD_TRANSITION)
params.clear_all(ParamKeyFlag.CLEAR_ON_OFFROAD_TRANSITION)
ignition = any(ps.ignitionLine or ps.ignitionCan for ps in sm['pandaStates'] if ps.pandaType != log.PandaState.PandaType.unknown)
if ignition and not ignition_prev:
params.clear_all(ParamKeyType.CLEAR_ON_IGNITION_ON)
params.clear_all(ParamKeyFlag.CLEAR_ON_IGNITION_ON)
# update onroad params, which drives pandad's safety setter thread
if started != started_prev:

@ -152,7 +152,7 @@ class ParamsBaseUpdateTest(TestBaseUpdate):
def wait_for_failed(self):
self.wait_for_condition(lambda: self.params.get("UpdateFailedCount", encoding="utf-8") is not None and \
int(self.params.get("UpdateFailedCount", encoding="utf-8")) > 0)
self.params.get("UpdateFailedCount", encoding="utf-8") > 0)
def wait_for_fetch_available(self):
self.wait_for_condition(lambda: self.params.get_bool("UpdaterFetchAvailable"))

@ -63,14 +63,6 @@ def write_time_to_param(params, param) -> None:
t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None)
params.put(param, t.isoformat().encode('utf8'))
def read_time_from_param(params, param) -> datetime.datetime | None:
t = params.get(param, encoding='utf8')
try:
return datetime.datetime.fromisoformat(t)
except (TypeError, ValueError):
pass
return None
def run(cmd: list[str], cwd: str = None) -> str:
return subprocess.check_output(cmd, cwd=cwd, stderr=subprocess.STDOUT, encoding='utf8')
@ -283,7 +275,7 @@ class Updater:
if update_success:
write_time_to_param(self.params, "LastUpdateTime")
else:
t = read_time_from_param(self.params, "LastUpdateTime")
t = self.params.get("LastUpdateTime", encoding="utf8")
if t is not None:
last_update = t
@ -428,7 +420,7 @@ def main() -> None:
if Path(os.path.join(STAGING_ROOT, "old_openpilot")).is_dir():
cloudlog.event("update installed")
if not params.get("InstallDate"):
if not params.get("InstallDate", encoding="utf-8"):
t = datetime.datetime.now(datetime.UTC).replace(tzinfo=None).isoformat()
params.put("InstallDate", t.encode('utf8'))
@ -468,7 +460,7 @@ def main() -> None:
updater.check_for_update()
# download update
last_fetch = read_time_from_param(params, "UpdaterLastFetchTime")
last_fetch = params.get("UpdaterLastFetchTime", encoding="utf8")
timed_out = last_fetch is None or (datetime.datetime.now(datetime.UTC).replace(tzinfo=None) - last_fetch > datetime.timedelta(days=3))
user_requested_fetch = wait_helper.user_request == UserRequest.FETCH
if params.get_bool("NetworkMetered") and not timed_out and not user_requested_fetch:

Loading…
Cancel
Save