diff --git a/common/params_pxd.pxd b/common/params_pxd.pxd index 14fcb311c3..28d54c0c50 100644 --- a/common/params_pxd.pxd +++ b/common/params_pxd.pxd @@ -12,5 +12,7 @@ cdef extern from "selfdrive/common/params.h": Params(bool) Params(string) string get(string, bool) nogil + bool getBool(string) int remove(string) int put(string, string) + int putBool(string, bool) diff --git a/common/params_pyx.pyx b/common/params_pyx.pyx index 92b35302ca..a062de0b7a 100755 --- a/common/params_pyx.pyx +++ b/common/params_pyx.pyx @@ -39,7 +39,6 @@ keys = { b"GithubUsername": [TxType.PERSISTENT], b"HardwareSerial": [TxType.PERSISTENT], b"HasAcceptedTerms": [TxType.PERSISTENT], - b"HasCompletedSetup": [TxType.PERSISTENT], b"IsDriverViewEnabled": [TxType.CLEAR_ON_MANAGER_START], b"IMEI": [TxType.PERSISTENT], b"IsLdwEnabled": [TxType.PERSISTENT], @@ -118,13 +117,16 @@ cdef class Params: def panda_disconnect(self): self.clear_all(TxType.CLEAR_ON_PANDA_DISCONNECT) - def get(self, key, block=False, encoding=None): + def check_key(self, key): key = ensure_bytes(key) if key not in keys: raise UnknownKeyName(key) - cdef string k = key + return key + + def get(self, key, block=False, encoding=None): + cdef string k = self.check_key(key) cdef bool b = block cdef string val @@ -144,6 +146,10 @@ cdef class Params: else: return val + def get_bool(self, key): + cdef string k = self.check_key(key) + return self.p.getBool(k) + def put(self, key, dat): """ Warning: This function blocks until the param is written to disk! @@ -151,17 +157,18 @@ cdef class Params: Use the put_nonblocking helper function in time sensitive code, but in general try to avoid writing params as much as possible. """ - key = ensure_bytes(key) dat = ensure_bytes(dat) - if key not in keys: - raise UnknownKeyName(key) + cdef string k = self.check_key(key) + self.p.put(k, dat) - self.p.put(key, dat) + def put_bool(self, key, val): + cdef string k = self.check_key(key) + self.p.putBool(k, val) def delete(self, key): - key = ensure_bytes(key) - self.p.remove(key) + cdef string k = self.check_key(key) + self.p.remove(k) def put_nonblocking(key, val, d=None): diff --git a/common/tests/test_params.py b/common/tests/test_params.py index 386b7fdd60..1fac4dbc7e 100644 --- a/common/tests/test_params.py +++ b/common/tests/test_params.py @@ -65,6 +65,15 @@ class TestParams(unittest.TestCase): with self.assertRaises(UnknownKeyName): self.params.get("swag") + with self.assertRaises(UnknownKeyName): + self.params.get_bool("swag") + + with self.assertRaises(UnknownKeyName): + self.params.put("swag", "abc") + + with self.assertRaises(UnknownKeyName): + self.params.put_bool("swag", True) + def test_params_permissions(self): permissions = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH | stat.S_IWOTH @@ -77,6 +86,22 @@ class TestParams(unittest.TestCase): self.params.delete("CarParams") assert self.params.get("CarParams") is None + def test_get_bool(self): + self.params.delete("IsMetric") + self.assertFalse(self.params.get_bool("IsMetric")) + + self.params.put_bool("IsMetric", True) + self.assertTrue(self.params.get_bool("IsMetric")) + + self.params.put_bool("IsMetric", False) + self.assertFalse(self.params.get_bool("IsMetric")) + + self.params.put("IsMetric", "1") + self.assertTrue(self.params.get_bool("IsMetric")) + + self.params.put("IsMetric", "0") + self.assertFalse(self.params.get_bool("IsMetric")) + def test_put_non_blocking_with_get_block(self): q = Params(self.tmpdir) def _delayed_writer(): diff --git a/selfdrive/camerad/snapshot/snapshot.py b/selfdrive/camerad/snapshot/snapshot.py index 39bc7be50e..eb7bb93af3 100755 --- a/selfdrive/camerad/snapshot/snapshot.py +++ b/selfdrive/camerad/snapshot/snapshot.py @@ -50,13 +50,13 @@ def get_snapshots(frame="roadCameraState", front_frame="driverCameraState"): def snapshot(): params = Params() - front_camera_allowed = int(params.get("RecordFront")) + front_camera_allowed = params.get_bool("RecordFront") - if params.get("IsOffroad") != b"1" or params.get("IsTakingSnapshot") == b"1": + if (not params.get_bool("IsOffroad")) or params.get_bool("IsTakingSnapshot"): print("Already taking snapshot") return None, None - params.put("IsTakingSnapshot", "1") + params.put_bool("IsTakingSnapshot", True) set_offroad_alert("Offroad_IsTakingSnapshot", True) time.sleep(2.0) # Give thermald time to read the param, or if just started give camerad time to start @@ -65,7 +65,7 @@ def snapshot(): subprocess.check_call(["pgrep", "camerad"]) print("Camerad already running") - params.put("IsTakingSnapshot", "0") + params.put_bool("IsTakingSnapshot", False) params.delete("Offroad_IsTakingSnapshot") return None, None except subprocess.CalledProcessError: @@ -89,7 +89,7 @@ def snapshot(): proc.send_signal(signal.SIGINT) proc.communicate() - params.put("IsTakingSnapshot", "0") + params.put_bool("IsTakingSnapshot", False) set_offroad_alert("Offroad_IsTakingSnapshot", False) if not front_camera_allowed: diff --git a/selfdrive/common/params.h b/selfdrive/common/params.h index 2362db4da5..9670abd13e 100644 --- a/selfdrive/common/params.h +++ b/selfdrive/common/params.h @@ -39,6 +39,10 @@ public: return iss.fail() ? std::nullopt : std::optional(value); } + inline bool getBool(const std::string &key) { + return getBool(key.c_str()); + } + inline bool getBool(const char *key) { return get(key) == "1"; } @@ -53,4 +57,8 @@ public: inline int putBool(const char *key, bool val) { return put(key, val ? "1" : "0", 1); } + + inline int putBool(const std::string &key, bool val) { + return putBool(key.c_str(), val); + } }; diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index b575d6eb99..d2e9842bc0 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -73,11 +73,11 @@ class Controls: # read params params = Params() - self.is_metric = params.get("IsMetric", encoding='utf8') == "1" - self.is_ldw_enabled = params.get("IsLdwEnabled", encoding='utf8') == "1" - community_feature_toggle = params.get("CommunityFeaturesToggle", encoding='utf8') == "1" - openpilot_enabled_toggle = params.get("OpenpilotEnabledToggle", encoding='utf8') == "1" - passive = params.get("Passive", encoding='utf8') == "1" or not openpilot_enabled_toggle + self.is_metric = params.get_bool("IsMetric") + self.is_ldw_enabled = params.get_bool("IsLdwEnabled") + community_feature_toggle = params.get_bool("CommunityFeaturesToggle") + openpilot_enabled_toggle = params.get_bool("OpenpilotEnabledToggle") + passive = params.get_bool("Passive") or not openpilot_enabled_toggle # detect sound card presence and ensure successful init sounds_available = HARDWARE.get_sound_card_online() diff --git a/selfdrive/controls/lib/lateral_planner.py b/selfdrive/controls/lib/lateral_planner.py index 0ea902f6ae..693d184a4f 100644 --- a/selfdrive/controls/lib/lateral_planner.py +++ b/selfdrive/controls/lib/lateral_planner.py @@ -54,7 +54,7 @@ class LateralPlanner(): self.setup_mpc() self.solution_invalid_cnt = 0 - self.use_lanelines = Params().get('EndToEndToggle') != b'1' + self.use_lanelines = not Params().get_bool('EndToEndToggle') self.lane_change_state = LaneChangeState.off self.lane_change_direction = LaneChangeDirection.none self.lane_change_timer = 0.0 diff --git a/selfdrive/controls/tests/test_startup.py b/selfdrive/controls/tests/test_startup.py index 70d1e08c6a..f6ac98fbce 100755 --- a/selfdrive/controls/tests/test_startup.py +++ b/selfdrive/controls/tests/test_startup.py @@ -45,9 +45,9 @@ class TestStartup(unittest.TestCase): params = Params() params.clear_all() - params.put("Passive", b"0") - params.put("OpenpilotEnabledToggle", b"1") - params.put("CommunityFeaturesToggle", b"1" if toggle_enabled else b"0") + params.put_bool("Passive", False) + params.put_bool("OpenpilotEnabledToggle", True) + params.put_bool("CommunityFeaturesToggle", toggle_enabled) time.sleep(2) # wait for controlsd to be ready diff --git a/selfdrive/loggerd/tests/loggerd_tests_common.py b/selfdrive/loggerd/tests/loggerd_tests_common.py index acd62ec915..bc9d4cf4d2 100644 --- a/selfdrive/loggerd/tests/loggerd_tests_common.py +++ b/selfdrive/loggerd/tests/loggerd_tests_common.py @@ -60,8 +60,17 @@ class MockParams(): "IsOffroad": b"1", } - def get(self, k): - return self.params[k] + def get(self, k, block=False, encoding=None): + val = self.params[k] + + if encoding is not None: + return val.decode(encoding) + else: + return val + + def get_bool(self, k): + val = self.params[k] + return (val == b'1') class UploaderTestCase(unittest.TestCase): f_type = "UNKNOWN" diff --git a/selfdrive/loggerd/uploader.py b/selfdrive/loggerd/uploader.py index ea7ef5a4c0..86fdfaee9b 100644 --- a/selfdrive/loggerd/uploader.py +++ b/selfdrive/loggerd/uploader.py @@ -192,7 +192,7 @@ class Uploader(): def uploader_fn(exit_event): params = Params() - dongle_id = params.get("DongleId").decode('utf8') + dongle_id = params.get("DongleId", encoding='utf8') if dongle_id is None: cloudlog.info("uploader missing dongle_id") @@ -207,7 +207,7 @@ def uploader_fn(exit_event): backoff = 0.1 while not exit_event.is_set(): sm.update(0) - offroad = params.get("IsOffroad") == b'1' + offroad = params.get_bool("IsOffroad") network_type = sm['deviceState'].networkType if not force_wifi else NetworkType.wifi if network_type == NetworkType.none: if allow_sleep: @@ -215,7 +215,7 @@ def uploader_fn(exit_event): continue on_wifi = network_type == NetworkType.wifi - allow_raw_upload = params.get("IsUploadRawEnabled") != b"0" + allow_raw_upload = params.get_bool("IsUploadRawEnabled") d = uploader.next_file_to_upload(with_raw=allow_raw_upload and on_wifi and offroad) if d is None: # Nothing to upload diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index 393b513939..9919f78032 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -25,24 +25,15 @@ def manager_init(): params.manager_start() default_params = [ - ("CommunityFeaturesToggle", "0"), - ("EndToEndToggle", "0"), ("CompletedTrainingVersion", "0"), - ("IsRHD", "0"), - ("IsMetric", "0"), - ("RecordFront", "0"), ("HasAcceptedTerms", "0"), - ("HasCompletedSetup", "0"), ("IsUploadRawEnabled", "1"), - ("IsLdwEnabled", "0"), ("LastUpdateTime", datetime.datetime.utcnow().isoformat().encode('utf8')), ("OpenpilotEnabledToggle", "1"), - ("VisionRadarToggle", "0"), - ("IsDriverViewEnabled", "0"), ] - if params.get("RecordFrontLock", encoding='utf-8') == "1": - params.put("RecordFront", "1") + if params.get_bool("RecordFrontLock"): + params.put_bool("RecordFront", True) # set unset params for k, v in default_params: @@ -123,7 +114,7 @@ def manager_thread(): not_run.append("loggerd") started = sm['deviceState'].started - driverview = params.get("IsDriverViewEnabled") == b"1" + driverview = params.get_bool("IsDriverViewEnabled") ensure_running(managed_processes.values(), started, driverview, not_run) # trigger an update after going offroad @@ -143,7 +134,7 @@ def manager_thread(): pm.send('managerState', msg) # Exit main loop when uninstall is needed - if params.get("DoUninstall", encoding='utf8') == "1": + if params.get_bool("DoUninstall"): break @@ -172,7 +163,7 @@ def main(): finally: manager_cleanup() - if Params().get("DoUninstall", encoding='utf8') == "1": + if Params().get_bool("DoUninstall"): cloudlog.warning("uninstalling") HARDWARE.uninstall() diff --git a/selfdrive/monitoring/dmonitoringd.py b/selfdrive/monitoring/dmonitoringd.py index 83313b8200..8321d37347 100755 --- a/selfdrive/monitoring/dmonitoringd.py +++ b/selfdrive/monitoring/dmonitoringd.py @@ -14,7 +14,7 @@ def dmonitoringd_thread(sm=None, pm=None): if sm is None: sm = messaging.SubMaster(['driverState', 'liveCalibration', 'carState', 'controlsState', 'modelV2'], poll=['driverState']) - driver_status = DriverStatus(rhd=Params().get("IsRHD") == b"1") + driver_status = DriverStatus(rhd=Params().get_bool("IsRHD")) sm['liveCalibration'].calStatus = Calibration.INVALID sm['liveCalibration'].rpyCalib = [0, 0, 0] diff --git a/selfdrive/test/helpers.py b/selfdrive/test/helpers.py index fda1a31755..a1719d1700 100644 --- a/selfdrive/test/helpers.py +++ b/selfdrive/test/helpers.py @@ -11,11 +11,10 @@ def set_params_enabled(): from common.params import Params params = Params() params.put("HasAcceptedTerms", terms_version) - params.put("HasCompletedSetup", "1") - params.put("OpenpilotEnabledToggle", "1") - params.put("CommunityFeaturesToggle", "1") - params.put("Passive", "0") params.put("CompletedTrainingVersion", training_version) + params.put_bool("OpenpilotEnabledToggle", True) + params.put_bool("CommunityFeaturesToggle", True) + params.put_bool("Passive", False) def phone_only(x): diff --git a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py index 010aa82023..1a2edc63ea 100755 --- a/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py +++ b/selfdrive/test/longitudinal_maneuvers/test_longitudinal.py @@ -326,9 +326,9 @@ class LongitudinalControl(unittest.TestCase): params = Params() params.clear_all() - params.put("Passive", "1" if os.getenv("PASSIVE") else "0") - params.put("OpenpilotEnabledToggle", "1") - params.put("CommunityFeaturesToggle", "1") + params.put_bool("Passive", bool(os.getenv("PASSIVE"))) + params.put_bool("OpenpilotEnabledToggle", True) + params.put_bool("CommunityFeaturesToggle", True) # hack def test_longitudinal_setup(self): diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index b988fa6f6a..b1953b8732 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -338,9 +338,9 @@ def python_replay_process(cfg, lr): params = Params() params.clear_all() params.manager_start() - params.put("OpenpilotEnabledToggle", "1") - params.put("Passive", "0") - params.put("CommunityFeaturesToggle", "1") + params.put_bool("OpenpilotEnabledToggle", True) + params.put_bool("Passive", False) + params.put_bool("CommunityFeaturesToggle", True) os.environ['NO_RADAR_SLEEP'] = "1" os.environ['SKIP_FW_QUERY'] = "1" diff --git a/selfdrive/test/test_updated.py b/selfdrive/test/test_updated.py index 8ecd27456d..b06a79fac1 100755 --- a/selfdrive/test/test_updated.py +++ b/selfdrive/test/test_updated.py @@ -92,7 +92,7 @@ class TestUpdated(unittest.TestCase): return subprocess.Popen(updated_path, env=os.environ) def _start_updater(self, offroad=True, nosleep=False): - self.params.put("IsOffroad", "1" if offroad else "0") + self.params.put_bool("IsOffroad", offroad) self.updated_proc = self._get_updated_proc() if not nosleep: time.sleep(1) diff --git a/selfdrive/thermald/power_monitoring.py b/selfdrive/thermald/power_monitoring.py index 485ebd2dee..4dda8c413f 100644 --- a/selfdrive/thermald/power_monitoring.py +++ b/selfdrive/thermald/power_monitoring.py @@ -164,8 +164,8 @@ class PowerMonitoring: disable_charging |= (self.car_voltage_mV < (VBATT_PAUSE_CHARGING * 1e3)) 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") + disable_charging &= (not self.params.get_bool("DisablePowerDown")) + disable_charging |= self.params.get_bool("ForcePowerDown") return disable_charging # See if we need to shutdown diff --git a/selfdrive/thermald/tests/test_power_monitoring.py b/selfdrive/thermald/tests/test_power_monitoring.py index 78b31c5659..d669e0922b 100755 --- a/selfdrive/thermald/tests/test_power_monitoring.py +++ b/selfdrive/thermald/tests/test_power_monitoring.py @@ -174,7 +174,7 @@ class TestPowerMonitoring(unittest.TestCase): BATT_VOLTAGE = 4 BATT_CURRENT = 0 # To stop shutting down for other reasons TEST_TIME = 100 - params.put("DisablePowerDown", b"1") + params.put_bool("DisablePowerDown", True) with pm_patch("HARDWARE.get_battery_voltage", BATT_VOLTAGE * 1e6), pm_patch("HARDWARE.get_battery_current", BATT_CURRENT * 1e6), \ pm_patch("HARDWARE.get_battery_status", "Discharging"), pm_patch("HARDWARE.get_current_power_draw", None): pm = PowerMonitoring() diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index 9f76980174..2285c5d0c7 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -327,8 +327,8 @@ def thermald_thread(): set_offroad_alert_if_changed("Offroad_ConnectivityNeeded", False) set_offroad_alert_if_changed("Offroad_ConnectivityNeededPrompt", False) - startup_conditions["up_to_date"] = params.get("Offroad_ConnectivityNeeded") is None or params.get("DisableUpdates") == b"1" - startup_conditions["not_uninstalling"] = not params.get("DoUninstall") == b"1" + startup_conditions["up_to_date"] = params.get("Offroad_ConnectivityNeeded") is None or params.get_bool("DisableUpdates") + startup_conditions["not_uninstalling"] = not params.get_bool("DoUninstall") startup_conditions["accepted_terms"] = params.get("HasAcceptedTerms") == terms_version panda_signature = params.get("PandaFirmware") @@ -339,8 +339,8 @@ def thermald_thread(): startup_conditions["free_space"] = msg.deviceState.freeSpacePercent > 2 startup_conditions["completed_training"] = params.get("CompletedTrainingVersion") == training_version or \ (current_branch in ['dashcam', 'dashcam-staging']) - startup_conditions["not_driver_view"] = not params.get("IsDriverViewEnabled") == b"1" - startup_conditions["not_taking_snapshot"] = not params.get("IsTakingSnapshot") == b"1" + startup_conditions["not_driver_view"] = not params.get_bool("IsDriverViewEnabled") + startup_conditions["not_taking_snapshot"] = not params.get_bool("IsTakingSnapshot") # 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 startup_conditions["device_temp_good"] = thermal_status < ThermalStatus.danger @@ -363,7 +363,7 @@ def thermald_thread(): cloudlog.event("Startup blocked", startup_conditions=startup_conditions) if should_start_prev or (count == 0): - params.put("IsOffroad", "1") + params.put_bool("IsOffroad", True) if TICI and DISABLE_LTE_ONROAD: os.system("sudo systemctl start --no-block lte") diff --git a/selfdrive/timezoned.py b/selfdrive/timezoned.py index 458faae147..88b3f8c611 100755 --- a/selfdrive/timezoned.py +++ b/selfdrive/timezoned.py @@ -40,7 +40,7 @@ def main(): while True: time.sleep(60) - is_onroad = params.get("IsOffroad") != b"1" + is_onroad = not params.get_bool("IsOffroad") if is_onroad: continue diff --git a/selfdrive/ui/tests/cycle_offroad_alerts.py b/selfdrive/ui/tests/cycle_offroad_alerts.py index 10614b95d4..6b3453026b 100755 --- a/selfdrive/ui/tests/cycle_offroad_alerts.py +++ b/selfdrive/ui/tests/cycle_offroad_alerts.py @@ -17,13 +17,13 @@ if __name__ == "__main__": t = 10 if len(sys.argv) < 2 else int(sys.argv[1]) while True: print("setting alert update") - params.put("UpdateAvailable", "1") + params.put_bool("UpdateAvailable", True) r = open(os.path.join(BASEDIR, "RELEASES.md"), "r").read() r = r[:r.find('\n\n')] # Slice latest release notes params.put("ReleaseNotes", r + "\n") time.sleep(t) - params.put("UpdateAvailable", "0") + params.put_bool("UpdateAvailable", False) # cycle through normal alerts for a in offroad_alerts: diff --git a/selfdrive/updated.py b/selfdrive/updated.py index 035b9a967e..ad2d880105 100755 --- a/selfdrive/updated.py +++ b/selfdrive/updated.py @@ -119,7 +119,7 @@ def set_params(new_version: bool, failed_count: int, exception: Optional[str]) - params.put("ReleaseNotes", r + b"\n") except Exception: params.put("ReleaseNotes", "") - params.put("UpdateAvailable", "1") + params.put_bool("UpdateAvailable", True) def setup_git_options(cwd: str) -> None: @@ -165,7 +165,7 @@ def init_overlay() -> None: cloudlog.info("preparing new safe staging area") params = Params() - params.put("UpdateAvailable", "0") + params.put_bool("UpdateAvailable", False) set_consistent_flag(False) dismount_overlay() if os.path.isdir(STAGING_ROOT): @@ -332,7 +332,7 @@ def fetch_update(wait_helper: WaitTimeHelper) -> bool: def main(): params = Params() - if params.get("DisableUpdates") == b"1": + if params.get_bool("DisableUpdates"): raise RuntimeError("updates are disabled by the DisableUpdates param") if EON and os.geteuid() != 0: @@ -370,7 +370,7 @@ def main(): # Don't run updater while onroad or if the time's wrong time_wrong = datetime.datetime.utcnow().year < 2019 - is_onroad = params.get("IsOffroad") != b"1" + is_onroad = not params.get_bool("IsOffroad") if is_onroad or time_wrong: wait_helper.sleep(30) cloudlog.info("not running updater, not offroad")