From e7b40f61a8022cdacccb2d276be7bc923fe79178 Mon Sep 17 00:00:00 2001 From: DevTekVE Date: Mon, 27 May 2024 19:44:41 +0200 Subject: [PATCH] Add support for network metering and PrimeType checking in sunnylinkd This commit introduces network metering and PrimeType checking in sunnylinkd. The implementation includes an additional threading event and a new log handler function, 'sunny_log_handler'. It defines PrimeType and metering conditions to set and clear the new threading event as part of the main processing loop in handle_long_poll function. --- selfdrive/athena/sunnylinkd.py | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/selfdrive/athena/sunnylinkd.py b/selfdrive/athena/sunnylinkd.py index 6eaec38181..6ebf6bf653 100755 --- a/selfdrive/athena/sunnylinkd.py +++ b/selfdrive/athena/sunnylinkd.py @@ -20,6 +20,7 @@ from openpilot.common.api import SunnylinkApi from openpilot.common.params import Params from openpilot.common.realtime import set_core_affinity from openpilot.common.swaglog import cloudlog +import cereal.messaging as messaging SUNNYLINK_ATHENA_HOST = os.getenv('SUNNYLINK_ATHENA_HOST', 'wss://ws.stg.api.sunnypilot.ai') HANDLER_THREADS = int(os.getenv('HANDLER_THREADS', "4")) @@ -29,7 +30,9 @@ SUNNYLINK_LOG_ATTR_NAME = "user.sunny.upload" params = Params() sunnylink_api = SunnylinkApi(params.get("SunnylinkDongleId", encoding='utf-8')) def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None: + sm = messaging.SubMaster(['deviceState']) end_event = threading.Event() + comma_prime_cellular_end_event = threading.Event() threads = [ threading.Thread(target=ws_manage, args=(ws, end_event), name='ws_manage'), @@ -38,7 +41,7 @@ def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None: threading.Thread(target=ws_ping, args=(ws, end_event), name='ws_ping'), threading.Thread(target=ws_queue, args=(end_event,), name='ws_queue'), # threading.Thread(target=upload_handler, args=(end_event,), name='upload_handler'), - threading.Thread(target=log_handler, args=(end_event,SUNNYLINK_LOG_ATTR_NAME,), name='log_handler'), + threading.Thread(target=sunny_log_handler, args=(end_event, comma_prime_cellular_end_event), name='log_handler'), # threading.Thread(target=stat_handler, args=(end_event,), name='stat_handler'), ] + [ threading.Thread(target=jsonrpc_handler, args=(end_event,), name=f'worker_{x}') @@ -49,10 +52,24 @@ def handle_long_poll(ws: WebSocket, exit_event: threading.Event | None) -> None: thread.start() try: while not end_event.wait(0.1): + sm.update(0) if exit_event is not None and exit_event.is_set(): end_event.set() + comma_prime_cellular_end_event.set() + + prime_type = params.get("PrimeType", encoding='utf-8') + metered = sm['deviceState'].networkMetered + + if int(prime_type) > 2 and metered: + cloudlog.info(f"sunnylinkd.handle_long_poll: PrimeType({prime_type}) > 2 and networkMetered({metered})") + comma_prime_cellular_end_event.set() + elif comma_prime_cellular_end_event.is_set(): + cloudlog.info(f"sunnylinkd.handle_long_poll: comma_prime_cellular_end_event is set and not PrimeType({prime_type}) > 2 or not networkMetered({metered})") + comma_prime_cellular_end_event.clear() + except (KeyboardInterrupt, SystemExit): end_event.set() + comma_prime_cellular_end_event.set() raise finally: for thread in threads: @@ -114,6 +131,13 @@ def ws_queue(end_event: threading.Event) -> None: cloudlog.debug("Resume requested or end_event is set, exiting ws_queue thread") +def sunny_log_handler(end_event: threading.Event, comma_prime_cellular_end_event: threading.Event) -> None: + while not end_event.wait(0.1): + if not comma_prime_cellular_end_event.is_set(): + log_handler(comma_prime_cellular_end_event, SUNNYLINK_LOG_ATTR_NAME) + comma_prime_cellular_end_event.set() + + @dispatcher.add_method def getParamsAllKeys() -> list[str]: keys: list[str] = [k.decode('utf-8') for k in Params().all_keys()]