diff --git a/common/params_keys.h b/common/params_keys.h index f633c93bc5..6daa7d1904 100644 --- a/common/params_keys.h +++ b/common/params_keys.h @@ -196,6 +196,7 @@ inline static std::unordered_map keys = { {"SunnylinkDongleId", {PERSISTENT, STRING}}, {"SunnylinkdPid", {PERSISTENT, INT}}, {"SunnylinkEnabled", {PERSISTENT, BOOL, "1"}}, + {"SunnylinkTempFault", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0"}}, // Backup Manager params {"BackupManager_CreateBackup", {PERSISTENT, BOOL}}, diff --git a/sunnypilot/sunnylink/api.py b/sunnypilot/sunnylink/api.py index b7838a40b0..cd2a358c60 100644 --- a/sunnypilot/sunnylink/api.py +++ b/sunnypilot/sunnylink/api.py @@ -147,7 +147,7 @@ class SunnylinkApi(BaseApi): self.params.put("SunnylinkDongleId", sunnylink_dongle_id or UNREGISTERED_SUNNYLINK_DONGLE_ID) # Set the last ping time to the current time since we were just talking to the API - last_ping = int(time.monotonic() * 1e9) if successful_registration else start_time + last_ping = int((time.monotonic() if successful_registration else start_time) * 1e9) Params().put("LastSunnylinkPingTime", last_ping) # Disable sunnylink if registration was not successful diff --git a/sunnypilot/sunnylink/registration_manager.py b/sunnypilot/sunnylink/registration_manager.py index 34323c2789..805d2482db 100755 --- a/sunnypilot/sunnylink/registration_manager.py +++ b/sunnypilot/sunnylink/registration_manager.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import time +from openpilot.common.params import Params from openpilot.common.realtime import Ratekeeper from openpilot.common.swaglog import cloudlog @@ -12,17 +13,22 @@ NetworkType = log.DeviceState.NetworkType def main(): """The main method is expected to be called by the manager when the device boots up.""" - rk = Ratekeeper(.5) - sm = messaging.SubMaster(['deviceState'], poll='deviceState') - while True: - sm.update(1000) - if sm['deviceState'].networkType != NetworkType.none: - break + try: + rk = Ratekeeper(.5) + sm = messaging.SubMaster(['deviceState'], poll='deviceState') + while True: + sm.update(1000) + if sm['deviceState'].networkType != NetworkType.none: + break - cloudlog.info(f"Waiting to become online... {time.monotonic()}") - rk.keep_time() + cloudlog.info(f"Waiting to become online... {time.monotonic()}") + rk.keep_time() - register_sunnylink() + register_sunnylink() + except Exception: + cloudlog.exception("Sunnylink registration failed") + Params().put_bool("SunnylinkTempFault", True) + raise if __name__ == "__main__": diff --git a/sunnypilot/sunnylink/utils.py b/sunnypilot/sunnylink/utils.py index 585e460e9c..e86a795170 100644 --- a/sunnypilot/sunnylink/utils.py +++ b/sunnypilot/sunnylink/utils.py @@ -6,31 +6,32 @@ from openpilot.common.params import Params, ParamKeyType from openpilot.system.version import is_prebuilt -def get_sunnylink_status(params=None) -> tuple[bool, bool]: +def get_sunnylink_status(params=None) -> tuple[bool, bool, bool]: """Get the status of Sunnylink on the device. Returns a tuple of (is_sunnylink_enabled, is_registered).""" params = params or Params() is_sunnylink_enabled = params.get_bool("SunnylinkEnabled") is_registered = params.get("SunnylinkDongleId") not in (None, UNREGISTERED_SUNNYLINK_DONGLE_ID) - return is_sunnylink_enabled, is_registered + is_on_temporary_fault = params.get_bool("SunnylinkTempFault") + return is_sunnylink_enabled, is_registered, is_on_temporary_fault def sunnylink_ready(params=None) -> bool: """Check if the device is ready to communicate with Sunnylink. That means it is enabled and registered.""" params = params or Params() - is_sunnylink_enabled, is_registered = get_sunnylink_status(params) - return is_sunnylink_enabled and is_registered + is_sunnylink_enabled, is_registered, is_on_temporary_fault = get_sunnylink_status(params) + return is_sunnylink_enabled and is_registered and not is_on_temporary_fault def use_sunnylink_uploader(params) -> bool: """Check if the device is ready to use Sunnylink and the uploader is enabled.""" - return sunnylink_ready(params) and params.get_bool("EnableSunnylinkUploader") + return not params.get_bool("NetworkMetered") and sunnylink_ready(params) and params.get_bool("EnableSunnylinkUploader") def sunnylink_need_register(params=None) -> bool: """Check if the device needs to be registered with Sunnylink.""" params = params or Params() - is_sunnylink_enabled, is_registered = get_sunnylink_status(params) - return is_sunnylink_enabled and not is_registered + is_sunnylink_enabled, is_registered, is_on_temporary_fault = get_sunnylink_status(params) + return is_sunnylink_enabled and not is_registered and not is_on_temporary_fault def register_sunnylink(): @@ -47,8 +48,12 @@ def register_sunnylink(): "timeout": 60 } - sunnylink_id = SunnylinkApi(None).register_device(None, **extra_args) - print(f"SunnyLinkId: {sunnylink_id}") + try: + sunnylink_id = SunnylinkApi(None).register_device(None, **extra_args) + print(f"SunnyLinkId: {sunnylink_id}") + except Exception: + Params().put_bool("SunnylinkTempFault", True) + raise def get_api_token():