openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

158 lines
5.7 KiB

import asyncio
import pyray as rl
from enum import IntEnum
from openpilot.system.ui.lib.wifi_manager import WifiManager, NetworkInfo
from openpilot.system.ui.lib.application import gui_app
from openpilot.system.ui.lib.button import gui_button
from openpilot.system.ui.lib.label import gui_label
from openpilot.system.ui.lib.scroll_panel import GuiScrollPanel
from openpilot.system.ui.widgets.keyboard import Keyboard
from openpilot.system.ui.widgets.confirm_dialog import confirm_dialog
NM_DEVICE_STATE_NEED_AUTH = 60
ITEM_HEIGHT = 160
class ActionState(IntEnum):
NONE = 0
CONNECT = 1
CONNECTING = 2
FORGOT = 3
FORGETTING = 4
NEED_AUTH = 5
SHOW_FORGOT_CONFIRM = 6
class WifiManagerUI:
def __init__(self, wifi_manager):
self.wifi_manager = wifi_manager
self.wifi_manager.need_auth_callback = self._on_need_auth
self.wifi_manager.activated_callback = self._on_activated
self._selected_network = None
self.btn_width = 200
self.current_action: ActionState = ActionState.NONE
self.scroll_panel = GuiScrollPanel()
self.keyboard = Keyboard()
asyncio.create_task(self._initialize())
async def _initialize(self) -> None:
try:
await self.wifi_manager.connect()
except Exception as e:
print(f"Initialization error: {e}")
def render(self, rect: rl.Rectangle):
if not self.wifi_manager.networks:
gui_label(rect, "Scanning Wi-Fi networks...", 40, alignment=rl.GuiTextAlignment.TEXT_ALIGN_CENTER)
return
if self.current_action == ActionState.SHOW_FORGOT_CONFIRM:
result = confirm_dialog(rect, f'Forget Wi-Fi Network "{self._selected_network.ssid}"?', 'Forget')
if result == 1:
asyncio.create_task(self.forgot_network())
elif result == 0:
self.current_action = ActionState.NONE
return
if self.current_action == ActionState.NEED_AUTH:
result = self.keyboard.render(rect, 'Enter password', f'for {self._selected_network.ssid}')
if result == 1:
asyncio.create_task(self.connect_to_network(self.keyboard.text))
elif result == 0:
self.current_action = ActionState.NONE
return
self._draw_network_list(rect)
def _draw_network_list(self, rect: rl.Rectangle):
content_rect = rl.Rectangle(rect.x, rect.y, rect.width, len(self.wifi_manager.networks) * ITEM_HEIGHT)
offset = self.scroll_panel.handle_scroll(rect, content_rect)
clicked = self.scroll_panel.is_click_valid()
rl.begin_scissor_mode(int(rect.x), int(rect.y), int(rect.width), int(rect.height))
for i, network in enumerate(self.wifi_manager.networks):
y_offset = rect.y + i * ITEM_HEIGHT + offset.y
item_rect = rl.Rectangle(rect.x, y_offset, rect.width, ITEM_HEIGHT)
if not rl.check_collision_recs(item_rect, rect):
continue
self._draw_network_item(item_rect, network, clicked)
if i < len(self.wifi_manager.networks) - 1:
line_y = int(item_rect.y + item_rect.height - 1)
rl.draw_line(int(item_rect.x), int(line_y), int(item_rect.x + item_rect.width), line_y, rl.LIGHTGRAY)
rl.end_scissor_mode()
def _draw_network_item(self, rect, network: NetworkInfo, clicked: bool):
label_rect = rl.Rectangle(rect.x, rect.y, rect.width - self.btn_width * 2, ITEM_HEIGHT)
state_rect = rl.Rectangle(rect.x + rect.width - self.btn_width * 2 - 150, rect.y, 300, ITEM_HEIGHT)
gui_label(label_rect, network.ssid, 55)
if network.is_connected and self.current_action == ActionState.NONE:
rl.gui_label(state_rect, "Connected")
elif self.current_action == ActionState.CONNECTING and self._selected_network and self._selected_network.ssid == network.ssid:
rl.gui_label(state_rect, "CONNECTING...")
# If the network is saved, show the "Forget" button
if self.wifi_manager.is_saved(network.ssid):
forget_btn_rect = rl.Rectangle(
rect.x + rect.width - self.btn_width,
rect.y + (ITEM_HEIGHT - 80) / 2,
self.btn_width,
80,
)
if gui_button(forget_btn_rect, "Forget") and self.current_action == ActionState.NONE and clicked:
self._selected_network = network
self.current_action = ActionState.SHOW_FORGOT_CONFIRM
if (
self.current_action == ActionState.NONE
and rl.check_collision_point_rec(rl.get_mouse_position(), label_rect)
and clicked
):
self._selected_network = network
if not self.wifi_manager.is_saved(self._selected_network.ssid):
self.current_action = ActionState.NEED_AUTH
else:
asyncio.create_task(self.connect_to_network())
async def forgot_network(self):
self.current_action = ActionState.FORGETTING
await self.wifi_manager.forget_connection(self._selected_network.ssid)
self.current_action = ActionState.NONE
async def connect_to_network(self, password=''):
self.current_action = ActionState.CONNECTING
if self.wifi_manager.is_saved(self._selected_network.ssid) and not password:
await self.wifi_manager.activate_connection(self._selected_network.ssid)
else:
await self.wifi_manager.connect_to_network(self._selected_network.ssid, password)
def _on_need_auth(self):
if self.current_action == ActionState.CONNECTING and self._selected_network:
self.current_action = ActionState.NEED_AUTH
def _on_activated(self):
if self.current_action == ActionState.CONNECTING:
self.current_action = ActionState.NONE
async def main():
gui_app.init_window("Wifi Manager")
wifi_manager = WifiManager()
wifi_ui = WifiManagerUI(wifi_manager)
while not rl.window_should_close():
rl.begin_drawing()
rl.clear_background(rl.BLACK)
wifi_ui.render(rl.Rectangle(50, 50, gui_app.width - 100, gui_app.height - 100))
rl.end_drawing()
await asyncio.sleep(0.001)
if __name__ == "__main__":
asyncio.run(main())