Params: python-like interface (#20506)

* rebase master

* delete outdated test_params.c

* putBool & more robust getBool

* putBool(SshEnabled)
albatross
Dean Lee 2021-03-30 18:54:59 +08:00 committed by GitHub
parent b5450a7cc5
commit 98e55996f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 111 additions and 252 deletions

View File

@ -12,5 +12,5 @@ cdef extern from "selfdrive/common/params.h":
Params(bool)
Params(string)
string get(string, bool) nogil
int delete_db_value(string)
int write_db_value(string, string)
int remove(string)
int put(string, string)

View File

@ -157,11 +157,11 @@ cdef class Params:
if key not in keys:
raise UnknownKeyName(key)
self.p.write_db_value(key, dat)
self.p.put(key, dat)
def delete(self, key):
key = ensure_bytes(key)
self.p.delete_db_value(key)
self.p.remove(key)
def put_nonblocking(key, val, d=None):

View File

@ -71,12 +71,11 @@ void safety_setter_thread() {
return;
};
std::vector<char> value_vin = Params().read_db_bytes("CarVin");
std::string value_vin = Params().get("CarVin");
if (value_vin.size() > 0) {
// sanity check VIN format
assert(value_vin.size() == 17);
std::string str_vin(value_vin.begin(), value_vin.end());
LOGW("got CarVin %s", str_vin.c_str());
LOGW("got CarVin %s", value_vin.c_str());
break;
}
util::sleep_for(100);
@ -85,7 +84,7 @@ void safety_setter_thread() {
// VIN query done, stop listening to OBDII
panda->set_safety_model(cereal::CarParams::SafetyModel::NO_OUTPUT);
std::vector<char> params;
std::string params;
LOGW("waiting for params to set safety model");
while (true) {
if (do_exit || !panda->connected){
@ -93,7 +92,7 @@ void safety_setter_thread() {
return;
};
params = Params().read_db_bytes("CarParams");
params = Params().get("CarParams");
if (params.size() > 0) break;
util::sleep_for(100);
}
@ -133,7 +132,7 @@ bool usb_connect() {
}
if (auto fw_sig = tmp_panda->get_firmware_version(); fw_sig) {
params.write_db_value("PandaFirmware", (const char *)fw_sig->data(), fw_sig->size());
params.put("PandaFirmware", (const char *)fw_sig->data(), fw_sig->size());
// Convert to hex for offroad
char fw_sig_hex_buf[16] = {0};
@ -143,13 +142,13 @@ bool usb_connect() {
fw_sig_hex_buf[2*i+1] = NIBBLE_TO_HEX((uint8_t)fw_sig_buf[i] & 0xF);
}
params.write_db_value("PandaFirmwareHex", fw_sig_hex_buf, 16);
params.put("PandaFirmwareHex", fw_sig_hex_buf, 16);
LOGW("fw signature: %.*s", 16, fw_sig_hex_buf);
} else { return false; }
// get panda serial
if (auto serial = tmp_panda->get_serial(); serial) {
params.write_db_value("PandaDongleId", serial->c_str(), serial->length());
params.put("PandaDongleId", serial->c_str(), serial->length());
LOGW("panda serial: %s", serial->c_str());
} else { return false; }
@ -313,9 +312,9 @@ void panda_state_thread(bool spoofing_started) {
// clear VIN, CarParams, and set new safety on car start
if (ignition && !ignition_last) {
int result = params.delete_db_value("CarVin");
int result = params.remove("CarVin");
assert((result == 0) || (result == ERR_NO_VALUE));
result = params.delete_db_value("CarParams");
result = params.remove("CarParams");
assert((result == 0) || (result == ERR_NO_VALUE));
if (!safety_setter_thread_running) {

View File

@ -352,7 +352,7 @@ void common_process_driver_camera(SubMaster *sm, PubMaster *pm, CameraState *c,
const CameraBuf *b = &c->buf;
static int x_min = 0, x_max = 0, y_min = 0, y_max = 0;
static const bool is_rhd = Params().read_db_bool("IsRHD");
static const bool is_rhd = Params().getBool("IsRHD");
// auto exposure
if (cnt % 3 == 0) {

View File

@ -11,9 +11,6 @@
#include <sys/file.h>
#include <sys/stat.h>
#include <map>
#include <string>
#include <iostream>
#include <csignal>
#include <string.h>
@ -83,15 +80,11 @@ Params::Params(bool persistent_param){
params_path = persistent_param ? persistent_params_path : default_params_path;
}
Params::Params(std::string path) {
Params::Params(const std::string &path) {
params_path = path;
}
int Params::write_db_value(std::string key, std::string dat){
return write_db_value(key.c_str(), dat.c_str(), dat.length());
}
int Params::write_db_value(const char* key, const char* value, size_t value_size) {
int Params::put(const char* key, const char* value, size_t value_size) {
// Information about safely and atomically writing a file: https://lwn.net/Articles/457667/
// 1) Create temp file
// 2) Write data to temp file
@ -213,7 +206,7 @@ cleanup:
return result;
}
int Params::delete_db_value(std::string key) {
int Params::remove(const char *key) {
int lock_fd = -1;
int result;
std::string path;
@ -230,7 +223,7 @@ int Params::delete_db_value(std::string key) {
// Delete value.
path = params_path + "/d/" + key;
result = remove(path.c_str());
result = ::remove(path.c_str());
if (result != 0) {
result = ERR_NO_VALUE;
goto cleanup;
@ -251,52 +244,28 @@ cleanup:
return result;
}
std::string Params::get(std::string key, bool block){
char* value;
size_t size;
int r;
if (block) {
r = read_db_value_blocking((const char*)key.c_str(), &value, &size);
std::string Params::get(const char *key, bool block) {
std::string path = params_path + "/d/" + key;
if (!block) {
return util::read_file(path);
} else {
r = read_db_value((const char*)key.c_str(), &value, &size);
}
// blocking read until successful
params_do_exit = 0;
void (*prev_handler_sigint)(int) = std::signal(SIGINT, params_sig_handler);
void (*prev_handler_sigterm)(int) = std::signal(SIGTERM, params_sig_handler);
if (r == 0){
std::string s(value, size);
free(value);
return s;
} else {
return "";
}
}
int Params::read_db_value(const char* key, char** value, size_t* value_sz) {
std::string path = params_path + "/d/" + std::string(key);
*value = static_cast<char*>(read_file(path.c_str(), value_sz));
if (*value == NULL) {
return -22;
}
return 0;
}
int Params::read_db_value_blocking(const char* key, char** value, size_t* value_sz) {
params_do_exit = 0;
void (*prev_handler_sigint)(int) = std::signal(SIGINT, params_sig_handler);
void (*prev_handler_sigterm)(int) = std::signal(SIGTERM, params_sig_handler);
while (!params_do_exit) {
const int result = read_db_value(key, value, value_sz);
if (result == 0) {
break;
} else {
util::sleep_for(100); // 0.1 s
std::string value;
while (!params_do_exit) {
if (value = util::read_file(path); !value.empty()) {
break;
}
util::sleep_for(100); // 0.1 s
}
}
std::signal(SIGINT, prev_handler_sigint);
std::signal(SIGTERM, prev_handler_sigterm);
return params_do_exit; // Return 0 if we had no interrupt
std::signal(SIGINT, prev_handler_sigint);
std::signal(SIGTERM, prev_handler_sigterm);
return value;
}
}
int Params::read_db_all(std::map<std::string, std::string> *params) {
@ -334,20 +303,3 @@ int Params::read_db_all(std::map<std::string, std::string> *params) {
close(lock_fd);
return 0;
}
std::vector<char> Params::read_db_bytes(const char* param_name) {
std::vector<char> bytes;
char* value;
size_t sz;
int result = read_db_value(param_name, &value, &sz);
if (result == 0) {
bytes.assign(value, value+sz);
free(value);
}
return bytes;
}
bool Params::read_db_bool(const char* param_name) {
std::vector<char> bytes = read_db_bytes(param_name);
return bytes.size() > 0 and bytes[0] == '1';
}

View File

@ -1,8 +1,9 @@
#pragma once
#include <stddef.h>
#include <map>
#include <string>
#include <vector>
#include <sstream>
#define ERR_NO_VALUE -33
@ -12,35 +13,44 @@ private:
public:
Params(bool persistent_param = false);
Params(std::string path);
Params(const std::string &path);
int write_db_value(std::string key, std::string dat);
int write_db_value(const char* key, const char* value, size_t value_size);
// Reads a value from the params database.
// Inputs:
// key: The key to read.
// value: A pointer where a newly allocated string containing the db value will
// be written.
// value_sz: A pointer where the size of value will be written. Does not
// include the NULL terminator.
// persistent_param: Boolean indicating if the param store in the /persist partition is to be used.
// e.g. for sensor calibration files. Will not be cleared after wipe or re-install.
//
// Returns: Negative on failure, otherwise 0.
int read_db_value(const char* key, char** value, size_t* value_sz);
// Delete a value from the params database.
// Inputs are the same as read_db_value, without value and value_sz.
int delete_db_value(std::string key);
// Reads a value from the params database, blocking until successful.
// Inputs are the same as read_db_value.
int read_db_value_blocking(const char* key, char** value, size_t* value_sz);
// Delete a value
int remove(const char *key);
inline int remove(const std::string &key) {
return remove (key.c_str());
}
// read all values
int read_db_all(std::map<std::string, std::string> *params);
std::vector<char> read_db_bytes(const char* param_name);
bool read_db_bool(const char* param_name);
std::string get(std::string key, bool block=false);
// read a value
std::string get(const char *key, bool block = false);
inline std::string get(const std::string &key, bool block = false) {
return get(key.c_str(), block);
}
template <class T>
std::optional<T> get(const char *key, bool block = false) {
std::istringstream iss(get(key, block));
T value{};
iss >> value;
return iss.fail() ? std::nullopt : std::optional(value);
}
inline bool getBool(const char *key) {
return get(key) == "1";
}
// write a value
int put(const char* key, const char* val, size_t value_size);
inline int put(const std::string &key, const std::string &val) {
return put(key.c_str(), val.data(), val.size());
}
inline int putBool(const char *key, bool val) {
return put(key, val ? "1" : "0", 1);
}
};

View File

@ -1,64 +0,0 @@
#include "selfdrive/common/params.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char* const kUsage = "%s: read|write|read_block params_path key [value]\n";
int main(int argc, const char* argv[]) {
if (argc < 4) {
printf(kUsage, argv[0]);
return 0;
}
const char* params_path = argv[2];
const char* key = argv[3];
if (strcmp(argv[1], "read") == 0) {
char* value;
size_t value_size;
int result = read_db_value(params_path, key, &value, &value_size);
if (result >= 0) {
fprintf(stdout, "Read %zu bytes: ", value_size);
fwrite(value, 1, value_size, stdout);
fprintf(stdout, "\n");
free(value);
} else {
fprintf(stderr, "Error reading: %d\n", result);
return -1;
}
} else if (strcmp(argv[1], "write") == 0) {
if (argc < 5) {
fprintf(stderr, "Error: write value required\n");
return 1;
}
const char* value = argv[4];
const size_t value_size = strlen(value);
int result = write_db_value(params_path, key, value, value_size);
if (result >= 0) {
fprintf(stdout, "Wrote %s to %s\n", value, key);
} else {
fprintf(stderr, "Error writing: %d\n", result);
return -1;
}
} else if (strcmp(argv[1], "read_block") == 0) {
char* value;
size_t value_size;
read_db_value_blocking(params_path, key, &value, &value_size);
fprintf(stdout, "Read %zu bytes: ", value_size);
fwrite(value, 1, value_size, stdout);
fprintf(stdout, "\n");
free(value);
} else {
printf(kUsage, argv[0]);
return 1;
}
return 0;
}
// BUILD:
// $ gcc -I$HOME/one selfdrive/common/test_params.c selfdrive/common/params.c selfdrive/common/util.cc -o ./test_params
// $ seq 0 100000 | xargs -P20 -I{} ./test_params write /data/params DongleId {} && sleep 0.1 &
// $ while ./test_params read /data/params DongleId; do sleep 0.05; done

View File

@ -27,6 +27,6 @@ public:
};
static void set_display_power(bool on) {};
static bool get_ssh_enabled() { return Params().read_db_bool("SshEnabled"); };
static void set_ssh_enabled(bool enabled) { Params().write_db_value("SshEnabled", (enabled ? "1" : "0")); };
static bool get_ssh_enabled() { return Params().getBool("SshEnabled"); };
static void set_ssh_enabled(bool enabled) { Params().putBool("SshEnabled", enabled); };
};

View File

@ -102,7 +102,7 @@ kj::Array<capnp::word> logger_build_init_data() {
init.setGitCommit(params.get("GitCommit"));
init.setGitBranch(params.get("GitBranch"));
init.setGitRemote(params.get("GitRemote"));
init.setPassive(params.read_db_bool("Passive"));
init.setPassive(params.getBool("Passive"));
{
std::map<std::string, std::string> params_map;
params.read_db_all(&params_map);

View File

@ -369,7 +369,7 @@ int main(int argc, char** argv) {
s.rotate_state[LOG_CAMERA_ID_FCAMERA].enabled = true;
#if defined(QCOM) || defined(QCOM2)
bool record_front = Params().read_db_bool("RecordFront");
bool record_front = Params().getBool("RecordFront");
if (record_front) {
encoder_threads.push_back(std::thread(encoder_thread, LOG_CAMERA_ID_DCAMERA));
s.rotate_state[LOG_CAMERA_ID_DCAMERA].enabled = true;

View File

@ -25,7 +25,7 @@ void dmonitoring_init(DMonitoringModelState* s) {
int runtime = USE_DSP_RUNTIME;
s->m = new DefaultRunModel(model_path, &s->output[0], OUTPUT_SIZE, runtime);
s->is_rhd = Params().read_db_bool("IsRHD");
s->is_rhd = Params().getBool("IsRHD");
}
template <class T>

View File

@ -70,7 +70,7 @@ void model_init(ModelState* s, cl_device_id device_id, cl_context context) {
#endif
#ifdef TRAFFIC_CONVENTION
const int idx = Params().read_db_bool("IsRHD") ? 1 : 0;
const int idx = Params().getBool("IsRHD") ? 1 : 0;
s->traffic_convention[idx] = 1.0;
s->m->addTrafficConvention(s->traffic_convention, TRAFFIC_CONVENTION_LEN);
#endif

View File

@ -134,12 +134,12 @@ void RequestRepeater::requestFinished(){
if (reply->error() == QNetworkReply::NoError) {
// save to cache
if (!cache_key.isEmpty()) {
Params().write_db_value(cache_key.toStdString(), response.toStdString());
Params().put(cache_key.toStdString(), response.toStdString());
}
emit receivedResponse(response);
} else {
if (!cache_key.isEmpty()) {
Params().delete_db_value(cache_key.toStdString());
Params().remove(cache_key.toStdString());
}
emit failedResponse(reply->errorString());
}

View File

@ -51,7 +51,7 @@ HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) {
void HomeWindow::mousePressEvent(QMouseEvent* e) {
UIState* ui_state = &glWindow->ui_state;
if (GLWindow::ui_state.scene.driver_view) {
Params().write_db_value("IsDriverViewEnabled", "0", 1);
Params().putBool("IsDriverViewEnabled", false);
GLWindow::ui_state.scene.driver_view = false;
return;
}
@ -88,7 +88,7 @@ OffroadHome::OffroadHome(QWidget* parent) : QWidget(parent) {
QObject::connect(alert_notification, SIGNAL(released()), this, SLOT(openAlerts()));
header_layout->addWidget(alert_notification, 0, Qt::AlignHCenter | Qt::AlignRight);
std::string brand = Params().read_db_bool("Passive") ? "dashcam" : "openpilot";
std::string brand = Params().getBool("Passive") ? "dashcam" : "openpilot";
QLabel* version = new QLabel(QString::fromStdString(brand + " v" + Params().get("Version")));
version->setStyleSheet(R"(font-size: 55px;)");
header_layout->addWidget(version, 0, Qt::AlignHCenter | Qt::AlignRight);
@ -230,12 +230,8 @@ GLWindow::GLWindow(QWidget* parent) : brightness_filter(BACKLIGHT_OFFROAD, BACKL
backlight_timer = new QTimer(this);
QObject::connect(backlight_timer, SIGNAL(timeout()), this, SLOT(backlightUpdate()));
int result = read_param(&brightness_b, "BRIGHTNESS_B", true);
result += read_param(&brightness_m, "BRIGHTNESS_M", true);
if (result != 0) {
brightness_b = 10.0;
brightness_m = 0.1;
}
brightness_b = Params().get<float>("BRIGHTNESS_B").value_or(10.0);
brightness_m = Params().get<float>("BRIGHTNESS_M").value_or(0.1);
}
GLWindow::~GLWindow() {

View File

@ -127,13 +127,13 @@ OnboardingWindow::OnboardingWindow(QWidget *parent) : QStackedWidget(parent) {
addWidget(terms);
connect(terms, &TermsPage::acceptedTerms, [=](){
Params().write_db_value("HasAcceptedTerms", current_terms_version);
Params().put("HasAcceptedTerms", current_terms_version);
updateActiveScreen();
});
TrainingGuide* tr = new TrainingGuide(this);
connect(tr, &TrainingGuide::completedTraining, [=](){
Params().write_db_value("CompletedTrainingVersion", current_training_version);
Params().put("CompletedTrainingVersion", current_training_version);
updateActiveScreen();
});
addWidget(tr);

View File

@ -61,7 +61,7 @@ QWidget * toggles_panel() {
"In this mode openpilot will ignore lanelines and just drive how it thinks a human would.",
"../assets/offroad/icon_road.png"));
bool record_lock = Params().read_db_bool("RecordFrontLock");
bool record_lock = Params().getBool("RecordFrontLock");
record_toggle->setEnabled(!record_lock);
QWidget *widget = new QWidget;
@ -87,29 +87,29 @@ DevicePanel::DevicePanel(QWidget* parent) : QWidget(parent) {
offroad_btns.append(new ButtonControl("Driver Camera", "PREVIEW",
"Preview the driver facing camera to help optimize device mounting position for best driver monitoring experience. (vehicle must be off)",
[=]() {
Params().write_db_value("IsDriverViewEnabled", "1", 1);
Params().putBool("IsDriverViewEnabled", true);
GLWindow::ui_state.scene.driver_view = true; }
));
offroad_btns.append(new ButtonControl("Reset Calibration", "RESET",
"openpilot requires the device to be mounted within 4° left or right and within 5° up or down. openpilot is continuously calibrating, resetting is rarely required.", [=]() {
if (ConfirmationDialog::confirm("Are you sure you want to reset calibration?")) {
Params().delete_db_value("CalibrationParams");
Params().remove("CalibrationParams");
}
}));
offroad_btns.append(new ButtonControl("Review Training Guide", "REVIEW",
"Review the rules, features, and limitations of openpilot", [=]() {
if (ConfirmationDialog::confirm("Are you sure you want to review the training guide?")) {
Params().delete_db_value("CompletedTrainingVersion");
Params().remove("CompletedTrainingVersion");
emit reviewTrainingGuide();
}
}));
QString brand = params.read_db_bool("Passive") ? "dashcam" : "openpilot";
QString brand = params.getBool("Passive") ? "dashcam" : "openpilot";
offroad_btns.append(new ButtonControl("Uninstall " + brand, "UNINSTALL", "", [=]() {
if (ConfirmationDialog::confirm("Are you sure you want to uninstall?")) {
Params().write_db_value("DoUninstall", "1");
Params().putBool("DoUninstall", true);
}
}));
@ -161,7 +161,7 @@ DeveloperPanel::DeveloperPanel(QWidget* parent) : QFrame(parent) {
void DeveloperPanel::showEvent(QShowEvent *event) {
Params params = Params();
std::string brand = params.read_db_bool("Passive") ? "dashcam" : "openpilot";
std::string brand = params.getBool("Passive") ? "dashcam" : "openpilot";
QList<QPair<QString, std::string>> dev_params = {
{"Version", brand + " v" + params.get("Version", false).substr(0, 14)},
{"Git Branch", params.get("GitBranch", false)},

View File

@ -109,12 +109,11 @@ class ParamControl : public ToggleControl {
public:
ParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon, QWidget *parent = nullptr) : ToggleControl(title, desc, icon, parent) {
// set initial state from param
if (Params().read_db_bool(param.toStdString().c_str())) {
if (Params().getBool(param.toStdString().c_str())) {
toggle.togglePosition();
}
QObject::connect(this, &ToggleControl::toggleFlipped, [=](int state) {
char value = state ? '1' : '0';
Params().write_db_value(param.toStdString().c_str(), &value, 1);
Params().putBool(param.toStdString().c_str(), (bool)state);
});
}
};

View File

@ -36,7 +36,7 @@ void DriveStats::parseResponse(QString response) {
labels.hours->setText(QString::number((int)(obj["minutes"].toDouble() / 60)));
};
bool metric = Params().read_db_bool("IsMetric");
bool metric = Params().getBool("IsMetric");
QJsonObject json = doc.object();
update(json["all"].toObject(), all_, metric);
update(json["week"].toObject(), week_, metric);
@ -51,7 +51,7 @@ DriveStats::DriveStats(QWidget* parent) : QWidget(parent) {
gl->addLayout(build_stat_layout(&labels.hours, "HOURS"), row, 2, 3, 1);
};
const char* distance_unit = Params().read_db_bool("IsMetric") ? "KM" : "MILES";
const char* distance_unit = Params().getBool("IsMetric") ? "KM" : "MILES";
QGridLayout* gl = new QGridLayout();
gl->setMargin(0);
gl->addWidget(new QLabel("ALL TIME"), 0, 0, 1, 3);

View File

@ -80,9 +80,9 @@ void OffroadAlert::refresh() {
void OffroadAlert::updateAlerts() {
alertCount = 0;
updateAvailable = params.read_db_bool("UpdateAvailable");
updateAvailable = params.getBool("UpdateAvailable");
for (const auto& [key, label] : alerts) {
auto bytes = params.read_db_bytes(key.c_str());
auto bytes = params.get(key.c_str());
if (bytes.size()) {
QJsonDocument doc_par = QJsonDocument::fromJson(QByteArray(bytes.data(), bytes.size()));
QJsonObject obj = doc_par.object();

View File

@ -34,8 +34,8 @@ SshControl::SshControl() : AbstractControl("SSH Keys", "Warning: This grants SSH
getUserKeys(username);
}
} else {
Params().delete_db_value("GithubUsername");
Params().delete_db_value("GithubSshKeys");
Params().remove("GithubUsername");
Params().remove("GithubSshKeys");
refresh();
}
});
@ -89,8 +89,8 @@ void SshControl::parseResponse(){
networkTimer->stop();
QString response = reply->readAll();
if (reply->error() == QNetworkReply::NoError && response.length()) {
Params().write_db_value("GithubUsername", username.toStdString());
Params().write_db_value("GithubSshKeys", response.toStdString());
Params().put("GithubUsername", username.toStdString());
Params().put("GithubSshKeys", response.toStdString());
} else if(reply->error() == QNetworkReply::NoError){
err = "Username '" + username + "' has no keys on GitHub";
} else {

View File

@ -10,13 +10,6 @@
#include "ui.hpp"
#include "paint.hpp"
int write_param_float(float param, const char* param_name, bool persistent_param) {
char s[16];
int size = snprintf(s, sizeof(s), "%f", param);
return Params(persistent_param).write_db_value(param_name, s, size < sizeof(s) ? size : sizeof(s));
}
// Projects a point in car to space to the corresponding point in full frame
// image space.
static bool calib_frame_to_full_frame(const UIState *s, float in_x, float in_y, float in_z, vertex_data *out) {
@ -279,14 +272,13 @@ static void update_alert(UIState *s) {
static void update_params(UIState *s) {
const uint64_t frame = s->sm->frame;
UIScene &scene = s->scene;
Params params;
if (frame % (5*UI_FREQ) == 0) {
read_param(&scene.is_metric, "IsMetric");
scene.is_metric = params.getBool("IsMetric");
} else if (frame % (6*UI_FREQ) == 0) {
scene.athenaStatus = NET_DISCONNECTED;
uint64_t last_ping = 0;
if (read_param(&last_ping, "LastAthenaPingTime") == 0) {
scene.athenaStatus = nanos_since_boot() - last_ping < 70e9 ? NET_CONNECTED : NET_ERROR;
if (auto last_ping = params.get<float>("LastAthenaPingTime"); last_ping) {
scene.athenaStatus = nanos_since_boot() - *last_ping < 70e9 ? NET_CONNECTED : NET_ERROR;
}
}
}
@ -329,8 +321,8 @@ static void update_status(UIState *s) {
s->status = STATUS_DISENGAGED;
s->scene.started_frame = s->sm->frame;
read_param(&s->scene.is_rhd, "IsRHD");
read_param(&s->scene.end_to_end, "EndToEndToggle");
s->scene.is_rhd = Params().getBool("IsRHD");
s->scene.end_to_end = Params().getBool("EndToEndToggle");
s->sidebar_collapsed = true;
s->scene.alert_size = cereal::ControlsState::AlertSize::NONE;
s->vipc_client = s->scene.driver_view ? s->vipc_client_front : s->vipc_client_rear;

View File

@ -171,28 +171,3 @@ typedef struct UIState {
void ui_init(UIState *s);
void ui_update(UIState *s);
int write_param_float(float param, const char* param_name, bool persistent_param = false);
template <class T>
int read_param(T* param, const char *param_name, bool persistent_param = false){
T param_orig = *param;
char *value;
size_t sz;
int result = Params(persistent_param).read_db_value(param_name, &value, &sz);
if (result == 0){
std::string s = std::string(value, sz); // value is not null terminated
free(value);
// Parse result
std::istringstream iss(s);
iss >> *param;
// Restore original value if parsing failed
if (iss.fail()) {
*param = param_orig;
result = -1;
}
}
return result;
}