sunnylink: enhance fault handling and parameter checks (#1323)

* enhance sunnylink fault handling and parameter checks

- Added `SunnylinkTempFault` to handle temporary registration issues.
- Updated methods to account for new fault state, improving robustness.
- Improved uploader logic by considering metered network restrictions.

* maybe it was overkill

* Lol, kinda important

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
This commit is contained in:
DevTekVE
2025-10-09 05:37:21 +02:00
committed by GitHub
parent 7aac14e6fc
commit 12a4b1b561
4 changed files with 31 additions and 19 deletions

View File

@@ -196,6 +196,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> 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}},

View File

@@ -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

View File

@@ -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__":

View File

@@ -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():