From 9589d2149d2e868fde7c62d53e01df95226b5a79 Mon Sep 17 00:00:00 2001 From: FrogAi <91348155+FrogAi@users.noreply.github.com> Date: Mon, 15 Apr 2024 00:13:48 -0700 Subject: [PATCH] Automatic updates Added function to automatically update FrogPilot for a completely "set and forget" experience. --- common/params.cc | 2 + selfdrive/frogpilot/frogpilot_process.py | 43 +++++++++++++++++++- selfdrive/ui/qt/offroad/software_settings.cc | 13 ++++++ selfdrive/updated/updated.py | 7 ++++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/common/params.cc b/common/params.cc index c763f05f6..dd4e96072 100644 --- a/common/params.cc +++ b/common/params.cc @@ -216,6 +216,7 @@ std::unordered_map keys = { {"AlwaysOnLateral", PERSISTENT}, {"AlwaysOnLateralMain", PERSISTENT}, {"ApiCache_DriveStats", PERSISTENT}, + {"AutomaticUpdates", PERSISTENT}, {"CustomAlerts", PERSISTENT}, {"CustomPaths", PERSISTENT}, {"CustomUI", PERSISTENT}, @@ -227,6 +228,7 @@ std::unordered_map keys = { {"HideAOLStatusBar", PERSISTENT}, {"LateralTune", PERSISTENT}, {"LongitudinalTune", PERSISTENT}, + {"ManualUpdateInitiated", PERSISTENT}, {"PauseAOLOnBrake", PERSISTENT}, {"PromptDistractedVolume", PERSISTENT}, {"PromptVolume", PERSISTENT}, diff --git a/selfdrive/frogpilot/frogpilot_process.py b/selfdrive/frogpilot/frogpilot_process.py index 583e6af59..5f1d4e569 100644 --- a/selfdrive/frogpilot/frogpilot_process.py +++ b/selfdrive/frogpilot/frogpilot_process.py @@ -1,6 +1,10 @@ import datetime +import http.client import os +import socket import time +import urllib.error +import urllib.request import cereal.messaging as messaging @@ -13,7 +17,34 @@ from openpilot.system.hardware import HARDWARE from openpilot.selfdrive.frogpilot.controls.frogpilot_planner import FrogPilotPlanner from openpilot.selfdrive.frogpilot.controls.lib.frogpilot_functions import FrogPilotFunctions -NetworkType = log.DeviceState.NetworkType +WIFI = log.DeviceState.NetworkType.wifi + +def automatic_update_check(params): + update_available = params.get_bool("UpdaterFetchAvailable") + update_ready = params.get_bool("UpdateAvailable") + update_state = params.get("UpdaterState", encoding='utf8') + + if update_ready: + HARDWARE.reboot() + elif update_available: + os.system("pkill -SIGHUP -f selfdrive.updated.updated") + elif update_state == "idle": + os.system("pkill -SIGUSR1 -f selfdrive.updated.updated") + +def github_pinged(url="https://github.com", timeout=5): + try: + urllib.request.urlopen(url, timeout=timeout) + return True + except (urllib.error.URLError, socket.timeout, http.client.RemoteDisconnected): + return False + +def time_checks(automatic_updates, deviceState, params): + if github_pinged(): + screen_off = deviceState.screenBrightnessPercent == 0 + wifi_connection = deviceState.networkType == WIFI + + if automatic_updates and screen_off and wifi_connection: + automatic_update_check(params) def frogpilot_thread(): config_realtime_process(5, Priority.CTRL_LOW) @@ -25,6 +56,8 @@ def frogpilot_thread(): CP = None + automatic_updates = params.get_bool("AutomaticUpdates") + first_run = True time_validated = system_time_valid() pm = messaging.PubMaster(['frogpilotPlan']) @@ -51,6 +84,8 @@ def frogpilot_thread(): frogpilot_planner.publish(sm, pm) if params_memory.get_bool("FrogPilotTogglesUpdated"): + automatic_updates = params.get_bool("AutomaticUpdates") + if started: frogpilot_planner.update_frogpilot_params() @@ -59,6 +94,12 @@ def frogpilot_thread(): if not time_validated: continue + if datetime.datetime.now().second == 0 or first_run or params_memory.get_bool("ManualUpdateInitiated"): + if not started: + time_checks(automatic_updates, deviceState, params) + + first_run = False + time.sleep(DT_MDL) def main(): diff --git a/selfdrive/ui/qt/offroad/software_settings.cc b/selfdrive/ui/qt/offroad/software_settings.cc index 0d5621481..cb23a5049 100644 --- a/selfdrive/ui/qt/offroad/software_settings.cc +++ b/selfdrive/ui/qt/offroad/software_settings.cc @@ -30,6 +30,18 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent), scene(uiStat versionLbl = new LabelControl(tr("Current Version"), ""); addItem(versionLbl); + // automatic updates toggle + ParamControl *automaticUpdatesToggle = new ParamControl("AutomaticUpdates", tr("Automatically Update FrogPilot"), + tr("FrogPilot will automatically update itself and it's assets when you're offroad and connected to Wi-Fi."), ""); + connect(automaticUpdatesToggle, &ToggleControl::toggleFlipped, [this]() { + std::thread([this]() { + paramsMemory.putBool("FrogPilotTogglesUpdated", true); + std::this_thread::sleep_for(std::chrono::seconds(1)); + paramsMemory.putBool("FrogPilotTogglesUpdated", false); + }).detach(); + }); + addItem(automaticUpdatesToggle); + // download update btn downloadBtn = new ButtonControl(tr("Download"), tr("CHECK")); connect(downloadBtn, &ButtonControl::clicked, [=]() { @@ -39,6 +51,7 @@ SoftwarePanel::SoftwarePanel(QWidget* parent) : ListWidget(parent), scene(uiStat } else { std::system("pkill -SIGHUP -f selfdrive.updated.updated"); } + paramsMemory.putBool("ManualUpdateInitiated", true); }); addItem(downloadBtn); diff --git a/selfdrive/updated/updated.py b/selfdrive/updated/updated.py index c4002eb13..c2010c90e 100755 --- a/selfdrive/updated/updated.py +++ b/selfdrive/updated/updated.py @@ -446,6 +446,7 @@ def main() -> None: # Run the update loop first_run = True + branches_set = "FrogPilot" in (params.get("UpdaterAvailableBranches", encoding='utf-8') or "").split(',') while True: wait_helper.ready_event.clear() @@ -463,11 +464,17 @@ def main() -> None: wait_helper.sleep(60) continue + if not (params.get_bool("AutomaticUpdates") or params_memory.get_bool("ManualUpdateInitiated") or not branches_set): + wait_helper.sleep(60*60*24*365*100) + continue + update_failed_count += 1 # check for update params.put("UpdaterState", "checking...") updater.check_for_update() + branches_set = True + params_memory.put_bool("ManualUpdateInitiated", False) # download update last_fetch = read_time_from_param(params, "UpdaterLastFetchTime")