mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-22 23:12:09 +08:00
30350f4207
* initial * start to support nav stack in settings panels + fix some navwidget bugs * add deprecation warning and move more to new nav stack * fix overriding NavWidget enabled and do developer panel * fix interactive timeout and do main * more device, not done yet * minor network fixes * dcam dialog * start onboarding * fix onboarding * do mici setup * remove now useless CUSTOM_SOFTWARE * support big ui with old modal overlay * reset can be old modal overlay, but updater needs new since it uses wifiui * flip name truthiness to inspire excitement * all *should* work, but will do pass later * clean up main * clean up settiings * clean up dialog and developer * cleanup mici setup some * rm one more * fix keyboard * revert * might as well but clarify * fix networkinfopage buttons * lint * nice clean up from cursor * animate background fade with position * fix device overlays * cursor fix pt1 cursor fix pt2 * rm print * capital * temp fix from cursor for onboarding not freeing space after reviewing training guide * fix home screen scroller snap not resetting * stash * nice gradient on top * 40 * 20 * no gradient * return unused returns and always show regulatory btn * nice! * clean up * new_modal is always true! * more clean up * clean up * big only renders top 1 * fixup setup and updater * stash * Revert "stash" This reverts commit 3cfb226ccb51869ed1f7d630b5fdd6725ad094d5. * fix mici keys coming in from top * clean up * fix mici dialogs like tici, pop first incase call back pushes * clever way but not not * Revert "clever way but not not" This reverts commit f69d106df61262f049df20cc1a9064ca1e6feeb7. * more setup * mici keyboard: fix not disabling below * cmt * fix wifi callbacks not running in rare case * clean up network * clean up network * clean up dialog * pairing * rm * todo * fix replay * they push themselkves! * clean up ui_state * clean up application * clean up * stash * Revert "stash" This reverts commit 07d3f5f26c99ef891086b6fe03095d53a62b8631. * typing * lint
133 lines
4.5 KiB
Python
Executable File
133 lines
4.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import os
|
|
import sys
|
|
import threading
|
|
import time
|
|
from enum import IntEnum
|
|
|
|
import pyray as rl
|
|
|
|
from openpilot.system.hardware import PC
|
|
from openpilot.system.ui.lib.application import gui_app, FontWeight, FONT_SCALE
|
|
from openpilot.system.ui.widgets import Widget
|
|
from openpilot.system.ui.widgets.button import Button, ButtonStyle
|
|
from openpilot.system.ui.widgets.label import gui_label, gui_text_box
|
|
|
|
USERDATA = "/dev/disk/by-partlabel/userdata"
|
|
TIMEOUT = 3*60
|
|
|
|
|
|
class ResetMode(IntEnum):
|
|
USER_RESET = 0 # user initiated a factory reset from openpilot
|
|
RECOVER = 1 # userdata is corrupt for some reason, give a chance to recover
|
|
FORMAT = 2 # finish up a factory reset from a tool that doesn't flash an empty partition to userdata
|
|
|
|
|
|
class ResetState(IntEnum):
|
|
NONE = 0
|
|
CONFIRM = 1
|
|
RESETTING = 2
|
|
FAILED = 3
|
|
|
|
|
|
class Reset(Widget):
|
|
def __init__(self, mode):
|
|
super().__init__()
|
|
self._mode = mode
|
|
self._previous_reset_state = None
|
|
self._reset_state = ResetState.NONE
|
|
self._cancel_button = Button("Cancel", gui_app.request_close)
|
|
self._confirm_button = Button("Confirm", self._confirm, button_style=ButtonStyle.PRIMARY)
|
|
self._reboot_button = Button("Reboot", lambda: os.system("sudo reboot"))
|
|
|
|
def _do_erase(self):
|
|
if PC:
|
|
return
|
|
|
|
# Removing data and formatting
|
|
rm = os.system("sudo rm -rf /data/*")
|
|
os.system(f"sudo umount {USERDATA}")
|
|
fmt = os.system(f"yes | sudo mkfs.ext4 {USERDATA}")
|
|
|
|
if rm == 0 or fmt == 0:
|
|
os.system("sudo reboot")
|
|
else:
|
|
self._reset_state = ResetState.FAILED
|
|
|
|
def start_reset(self):
|
|
self._reset_state = ResetState.RESETTING
|
|
threading.Timer(0.1, self._do_erase).start()
|
|
|
|
def _update_state(self):
|
|
if self._reset_state != self._previous_reset_state:
|
|
self._previous_reset_state = self._reset_state
|
|
self._timeout_st = time.monotonic()
|
|
elif self._reset_state != ResetState.RESETTING and (time.monotonic() - self._timeout_st) > TIMEOUT:
|
|
exit(0)
|
|
|
|
def _render(self, _):
|
|
content_rect = rl.Rectangle(45, 200, self._rect.width - 90, self._rect.height - 245)
|
|
|
|
label_rect = rl.Rectangle(content_rect.x + 140, content_rect.y, content_rect.width - 280, 100 * FONT_SCALE)
|
|
gui_label(label_rect, "System Reset", 100, font_weight=FontWeight.BOLD)
|
|
|
|
text_rect = rl.Rectangle(content_rect.x + 140, content_rect.y + 140, content_rect.width - 280, content_rect.height - 90 - 100 * FONT_SCALE)
|
|
gui_text_box(text_rect, self._get_body_text(), 90)
|
|
|
|
button_height = 160
|
|
button_spacing = 50
|
|
button_top = content_rect.y + content_rect.height - button_height
|
|
button_width = (content_rect.width - button_spacing) / 2.0
|
|
|
|
if self._reset_state != ResetState.RESETTING:
|
|
if self._mode == ResetMode.RECOVER:
|
|
self._reboot_button.render(rl.Rectangle(content_rect.x, button_top, button_width, button_height))
|
|
elif self._mode == ResetMode.USER_RESET:
|
|
self._cancel_button.render(rl.Rectangle(content_rect.x, button_top, button_width, button_height))
|
|
|
|
if self._reset_state != ResetState.FAILED:
|
|
self._confirm_button.render(rl.Rectangle(content_rect.x + button_width + 50, button_top, button_width, button_height))
|
|
else:
|
|
self._reboot_button.render(rl.Rectangle(content_rect.x, button_top, content_rect.width, button_height))
|
|
|
|
def _confirm(self):
|
|
if self._reset_state == ResetState.CONFIRM:
|
|
self.start_reset()
|
|
else:
|
|
self._reset_state = ResetState.CONFIRM
|
|
|
|
def _get_body_text(self):
|
|
if self._reset_state == ResetState.CONFIRM:
|
|
return "Are you sure you want to reset your device?"
|
|
if self._reset_state == ResetState.RESETTING:
|
|
return "Resetting device...\nThis may take up to a minute."
|
|
if self._reset_state == ResetState.FAILED:
|
|
return "Reset failed. Reboot to try again."
|
|
if self._mode == ResetMode.RECOVER:
|
|
return "Unable to mount data partition. Partition may be corrupted. Press confirm to erase and reset your device."
|
|
return "System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot."
|
|
|
|
|
|
def main():
|
|
mode = ResetMode.USER_RESET
|
|
if len(sys.argv) > 1:
|
|
if sys.argv[1] == '--recover':
|
|
mode = ResetMode.RECOVER
|
|
elif sys.argv[1] == "--format":
|
|
mode = ResetMode.FORMAT
|
|
|
|
gui_app.init_window("System Reset", 20)
|
|
reset = Reset(mode)
|
|
|
|
if mode == ResetMode.FORMAT:
|
|
reset.start_reset()
|
|
|
|
gui_app.push_widget(reset)
|
|
|
|
for _ in gui_app.render():
|
|
pass
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|