#!/usr/bin/env python3
import sys
import subprocess
import threading
import pyray as rl
from enum import IntEnum
from openpilot . system . hardware import HARDWARE
from openpilot . system . ui . lib . application import gui_app , FontWeight
raylib: clean up networking (#36039)
* stasj
* remove one of many classes
* clean up and fix
* clean up
* stash/draft: oh this is sick
* so epic
* some clean up
* what the fuck, it doesn't even use these
* more epic initializers + make it kind of work
* so simple, wonder if we should further 2x reduce line count
* i've never ever seen this pattern b4, rm
* remove bs add niceness
* minor organization
* set security type and support listing and rming conns
* forget and connect
* jeepney is actually pretty good, it's 2x faster to get wifi device (0.005s to 0.002s)
* temp
* do blocking add in worker thread
* add jeepney
* lets finish with python-dbus first then evaluate - revert jeepney
This reverts commit 7de04b11c2285c298bb1ec907782026c795ab207.
and
* safe wrap
* missing
* saved connections
* set rest of callbacks
* skip hidden APs, simplify _running
* add state management
* either wrong password or disconnected for now
* i can't believe we didn't check this...
* disable button if unsupported!!!
* hide/show event no lag hopefully yayay
* fix hide event
* remove old wifi manager
* cache wifi device path + some clean up
* more clean up
* more clean up
* temp disable blocking prime thread
* hackily get device path once
* ok
* debug
* fix open networks
* debug
* clean up
* all threads wait for device path, and user functions dont ever attempt to get, just skip
* same place
* helper
* Revert "helper"
This reverts commit e237d9a720915fb6bd67c539123d3e2d9d582ce1.
* organize?
* Revert "organize?"
This reverts commit 3aca3e5d629c947711ade88799febeb3f61eda87.
* c word is a bad word
* rk monitor debug for now
* nothing crazy
* improve checkmark responsiveness
* when forgetting: this is correct, but feels unresponsive
* this feels good
* need these two to keep forgetting and activating responsive
* sort by connected, strength, then name
* handle non-critical race condition
* log more
* unused
* oh jubilee is sick you can block on signals!!
* proof of concept to see if works on device
whoiops
* so sucking fick
* ah this is not generic, it's a filter on the return vals
* flip around to not drop
* oh thank god
* fix
* stash
* atomic replace
* clean up
* add old to keep track of what's moved over
* these are already moved
* so much junk
* so much junk
* more
* tethering wasn't used so we can ignore that for now
* no params now
* rm duplicate imports
* not used anymore
* move get wifi device over to jeepney! ~no additional lines
* request scan w/ keepney
* get_conns
* _connection_by_ssid_jeepney is 2x faster (0.01 vs 0.02s)
* do forget and activate
* _update_networks matches!
* rm old update_networks
* replace connect_to_network, about same time (yes i removed thread call)
* no more python-dbus!k
* doesn't hurt
* AP.from_dbus: actually handle incorrect paths w/ jeep + more efficient single call
* properly handle errors
* it's jeepney now
* less state
* using the thread safe router passes a race condition test that conn failed!
* bad to copy from old wifimanager
* fix conn usage
* clean up
* curious if locks are lagging
* not for now
* Revert "curious if locks are lagging"
This reverts commit 085dd185b083f5905a4e71ba3e8c0565175e04aa.
* clean up _monitor_state
* remove tests
* clean up dataclasses
* sort
* lint: okay fine it can be non by virtue of exiting right at the perfect time
* some network clean up
* some wifi manager clean up
* this is handled
* stop can be called manually, from deleting wifimanager, or exiting python. some protection
* its not mutable anymore
* scan on enter
* clean up
* back
* lint
* catch dbus fail to connect
catch dbus fail to connect
3 days ago
from openpilot . system . ui . lib . wifi_manager import WifiManager
from openpilot . system . ui . widgets import Widget
from openpilot . system . ui . widgets . button import gui_button , ButtonStyle
from openpilot . system . ui . widgets . label import gui_text_box , gui_label
from openpilot . system . ui . widgets . network import WifiManagerUI
# Constants
MARGIN = 50
BUTTON_HEIGHT = 160
BUTTON_WIDTH = 400
PROGRESS_BAR_HEIGHT = 72
TITLE_FONT_SIZE = 80
BODY_FONT_SIZE = 65
BACKGROUND_COLOR = rl . BLACK
PROGRESS_BG_COLOR = rl . Color ( 41 , 41 , 41 , 255 )
PROGRESS_COLOR = rl . Color ( 54 , 77 , 239 , 255 )
class Screen ( IntEnum ) :
PROMPT = 0
WIFI = 1
PROGRESS = 2
class Updater ( Widget ) :
def __init__ ( self , updater_path , manifest_path ) :
super ( ) . __init__ ( )
self . updater = updater_path
self . manifest = manifest_path
self . current_screen = Screen . PROMPT
self . progress_value = 0
self . progress_text = " Loading... "
self . show_reboot_button = False
self . process = None
self . update_thread = None
raylib: clean up networking (#36039)
* stasj
* remove one of many classes
* clean up and fix
* clean up
* stash/draft: oh this is sick
* so epic
* some clean up
* what the fuck, it doesn't even use these
* more epic initializers + make it kind of work
* so simple, wonder if we should further 2x reduce line count
* i've never ever seen this pattern b4, rm
* remove bs add niceness
* minor organization
* set security type and support listing and rming conns
* forget and connect
* jeepney is actually pretty good, it's 2x faster to get wifi device (0.005s to 0.002s)
* temp
* do blocking add in worker thread
* add jeepney
* lets finish with python-dbus first then evaluate - revert jeepney
This reverts commit 7de04b11c2285c298bb1ec907782026c795ab207.
and
* safe wrap
* missing
* saved connections
* set rest of callbacks
* skip hidden APs, simplify _running
* add state management
* either wrong password or disconnected for now
* i can't believe we didn't check this...
* disable button if unsupported!!!
* hide/show event no lag hopefully yayay
* fix hide event
* remove old wifi manager
* cache wifi device path + some clean up
* more clean up
* more clean up
* temp disable blocking prime thread
* hackily get device path once
* ok
* debug
* fix open networks
* debug
* clean up
* all threads wait for device path, and user functions dont ever attempt to get, just skip
* same place
* helper
* Revert "helper"
This reverts commit e237d9a720915fb6bd67c539123d3e2d9d582ce1.
* organize?
* Revert "organize?"
This reverts commit 3aca3e5d629c947711ade88799febeb3f61eda87.
* c word is a bad word
* rk monitor debug for now
* nothing crazy
* improve checkmark responsiveness
* when forgetting: this is correct, but feels unresponsive
* this feels good
* need these two to keep forgetting and activating responsive
* sort by connected, strength, then name
* handle non-critical race condition
* log more
* unused
* oh jubilee is sick you can block on signals!!
* proof of concept to see if works on device
whoiops
* so sucking fick
* ah this is not generic, it's a filter on the return vals
* flip around to not drop
* oh thank god
* fix
* stash
* atomic replace
* clean up
* add old to keep track of what's moved over
* these are already moved
* so much junk
* so much junk
* more
* tethering wasn't used so we can ignore that for now
* no params now
* rm duplicate imports
* not used anymore
* move get wifi device over to jeepney! ~no additional lines
* request scan w/ keepney
* get_conns
* _connection_by_ssid_jeepney is 2x faster (0.01 vs 0.02s)
* do forget and activate
* _update_networks matches!
* rm old update_networks
* replace connect_to_network, about same time (yes i removed thread call)
* no more python-dbus!k
* doesn't hurt
* AP.from_dbus: actually handle incorrect paths w/ jeep + more efficient single call
* properly handle errors
* it's jeepney now
* less state
* using the thread safe router passes a race condition test that conn failed!
* bad to copy from old wifimanager
* fix conn usage
* clean up
* curious if locks are lagging
* not for now
* Revert "curious if locks are lagging"
This reverts commit 085dd185b083f5905a4e71ba3e8c0565175e04aa.
* clean up _monitor_state
* remove tests
* clean up dataclasses
* sort
* lint: okay fine it can be non by virtue of exiting right at the perfect time
* some network clean up
* some wifi manager clean up
* this is handled
* stop can be called manually, from deleting wifimanager, or exiting python. some protection
* its not mutable anymore
* scan on enter
* clean up
* back
* lint
* catch dbus fail to connect
catch dbus fail to connect
3 days ago
self . wifi_manager_ui = WifiManagerUI ( WifiManager ( ) )
def install_update ( self ) :
self . current_screen = Screen . PROGRESS
self . progress_value = 0
self . progress_text = " Downloading... "
self . show_reboot_button = False
# Start the update process in a separate thread
self . update_thread = threading . Thread ( target = self . _run_update_process )
self . update_thread . daemon = True
self . update_thread . start ( )
def _run_update_process ( self ) :
# TODO: just import it and run in a thread without a subprocess
cmd = [ self . updater , " --swap " , self . manifest ]
self . process = subprocess . Popen ( cmd , stdout = subprocess . PIPE , stderr = subprocess . PIPE ,
text = True , bufsize = 1 , universal_newlines = True )
for line in self . process . stdout :
parts = line . strip ( ) . split ( " : " )
if len ( parts ) == 2 :
self . progress_text = parts [ 0 ]
try :
self . progress_value = int ( float ( parts [ 1 ] ) )
except ValueError :
pass
exit_code = self . process . wait ( )
if exit_code == 0 :
HARDWARE . reboot ( )
else :
self . progress_text = " Update failed "
self . show_reboot_button = True
def render_prompt_screen ( self , rect : rl . Rectangle ) :
# Title
title_rect = rl . Rectangle ( MARGIN + 50 , 250 , rect . width - MARGIN * 2 - 100 , TITLE_FONT_SIZE )
gui_label ( title_rect , " Update Required " , TITLE_FONT_SIZE , font_weight = FontWeight . BOLD )
# Description
desc_text = ( " An operating system update is required. Connect your device to Wi-Fi for the fastest update experience. " +
" The download size is approximately 1GB. " )
desc_rect = rl . Rectangle ( MARGIN + 50 , 250 + TITLE_FONT_SIZE + 75 , rect . width - MARGIN * 2 - 100 , BODY_FONT_SIZE * 3 )
gui_text_box ( desc_rect , desc_text , BODY_FONT_SIZE )
# Buttons at the bottom
button_y = rect . height - MARGIN - BUTTON_HEIGHT
button_width = ( rect . width - MARGIN * 3 ) / / 2
# WiFi button
wifi_button_rect = rl . Rectangle ( MARGIN , button_y , button_width , BUTTON_HEIGHT )
if gui_button ( wifi_button_rect , " Connect to Wi-Fi " ) :
self . current_screen = Screen . WIFI
return # Return to avoid processing other buttons after screen change
# Install button
install_button_rect = rl . Rectangle ( MARGIN * 2 + button_width , button_y , button_width , BUTTON_HEIGHT )
if gui_button ( install_button_rect , " Install " , button_style = ButtonStyle . PRIMARY ) :
self . install_update ( )
return # Return to avoid further processing after action
def render_wifi_screen ( self , rect : rl . Rectangle ) :
# Draw the Wi-Fi manager UI
wifi_rect = rl . Rectangle ( MARGIN + 50 , MARGIN , rect . width - MARGIN * 2 - 100 , rect . height - MARGIN * 2 - BUTTON_HEIGHT - 20 )
self . wifi_manager_ui . render ( wifi_rect )
back_button_rect = rl . Rectangle ( MARGIN , rect . height - MARGIN - BUTTON_HEIGHT , BUTTON_WIDTH , BUTTON_HEIGHT )
if gui_button ( back_button_rect , " Back " ) :
self . current_screen = Screen . PROMPT
return # Return to avoid processing other interactions after screen change
def render_progress_screen ( self , rect : rl . Rectangle ) :
title_rect = rl . Rectangle ( MARGIN + 100 , 330 , rect . width - MARGIN * 2 - 200 , 100 )
gui_label ( title_rect , self . progress_text , 90 , font_weight = FontWeight . SEMI_BOLD )
# Progress bar
bar_rect = rl . Rectangle ( MARGIN + 100 , 330 + 100 + 100 , rect . width - MARGIN * 2 - 200 , PROGRESS_BAR_HEIGHT )
rl . draw_rectangle_rounded ( bar_rect , 0.5 , 10 , PROGRESS_BG_COLOR )
# Calculate the width of the progress chunk
progress_width = ( bar_rect . width * self . progress_value ) / 100
if progress_width > 0 :
progress_rect = rl . Rectangle ( bar_rect . x , bar_rect . y , progress_width , bar_rect . height )
rl . draw_rectangle_rounded ( progress_rect , 0.5 , 10 , PROGRESS_COLOR )
# Show reboot button if needed
if self . show_reboot_button :
reboot_rect = rl . Rectangle ( MARGIN + 100 , rect . height - MARGIN - BUTTON_HEIGHT , BUTTON_WIDTH , BUTTON_HEIGHT )
if gui_button ( reboot_rect , " Reboot " ) :
# Return True to signal main loop to exit before rebooting
HARDWARE . reboot ( )
return
def _render ( self , rect : rl . Rectangle ) :
if self . current_screen == Screen . PROMPT :
self . render_prompt_screen ( rect )
elif self . current_screen == Screen . WIFI :
self . render_wifi_screen ( rect )
elif self . current_screen == Screen . PROGRESS :
self . render_progress_screen ( rect )
def main ( ) :
if len ( sys . argv ) < 3 :
print ( " Usage: updater.py <updater_path> <manifest_path> " )
sys . exit ( 1 )
updater_path = sys . argv [ 1 ]
manifest_path = sys . argv [ 2 ]
try :
gui_app . init_window ( " System Update " )
updater = Updater ( updater_path , manifest_path )
for _ in gui_app . render ( ) :
updater . render ( rl . Rectangle ( 0 , 0 , gui_app . width , gui_app . height ) )
finally :
# Make sure we clean up even if there's an error
gui_app . close ( )
if __name__ == " __main__ " :
main ( )