Add interface preview and fix WebView bridge exposure

This commit is contained in:
2026-08-25 22:24:03 +02:00
parent e845ae7eb6
commit b48f9846d5
4 changed files with 16 additions and 12 deletions
+2
View File
@@ -4,6 +4,8 @@ A deliberately small, low-bandwidth MAVLink controller for bench-testing an
ArduSub vehicle over a USB serial connection. It sends no parameter-list
request and no telemetry-stream request.
![SUB Control interface](docs/sub-control-interface.png)
The desktop window uses a local HTML/CSS/JavaScript interface rendered by the
Windows WebView. Python remains the only launcher and owns the MAVLink worker,
arming, logging, output limiting, and parameter writes. It does not run a web
Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

+1 -1
View File
@@ -62,7 +62,7 @@
<header class="topbar">
<div><div class="eyebrow">PILOT CONSOLE</div><h1>Drive</h1></div>
<div class="connection">
<select id="port" aria-label="Serial port"><option value="">No COM ports</option></select>
<select id="port" aria-label="Serial port"><option value="">Select COM port…</option></select>
<button id="refresh" class="icon-button" title="Refresh ports">↻</button>
<button class="icon-button" data-open="link-modal" title="Link settings">•••</button>
<button id="connect" class="button connect-button">Connect</button>
+13 -11
View File
@@ -35,7 +35,9 @@ class ControlApi:
self.motor_directions: dict[int, int] = {}
self.battery_path = Path(__file__).resolve().parent / "battery_settings.json"
self.model_path = Path(__file__).resolve().parent / "model_settings.json"
self.window = None
# Leading underscore keeps the native WebView object out of js_api
# serialization. Only the small public methods below are exposed.
self._window = None
self.maximized = False
self.battery_config = {
"cells": 4, "capacity_mah": 5500, "c_rating": 35,
@@ -58,29 +60,29 @@ class ControlApi:
return [p.device for p in list_ports.comports()]
def minimize_window(self):
if self.window:
self.window.minimize()
if self._window:
self._window.minimize()
return True
def toggle_maximize_window(self):
if not self.window:
if not self._window:
return False
if self.maximized:
self.window.restore()
self._window.restore()
else:
self.window.maximize()
self._window.maximize()
self.maximized = not self.maximized
return self.maximized
def close_window(self):
if self.window:
self.window.destroy()
if self._window:
self._window.destroy()
return True
def choose_model(self):
if not self.window:
if not self._window:
raise RuntimeError("Window is not ready")
selected = self.window.create_file_dialog(
selected = self._window.create_file_dialog(
webview.OPEN_DIALOG,
allow_multiple=False,
file_types=("STL mesh (*.stl)", "STEP model (*.step;*.stp)"),
@@ -285,7 +287,7 @@ def main():
background_color="#111719", frameless=True, easy_drag=False,
shadow=True,
)
api.window = window
api._window = window
window.events.maximized += lambda: setattr(api, "maximized", True)
window.events.restored += lambda: setattr(api, "maximized", False)
try: