Add interface preview and fix WebView bridge exposure
This commit is contained in:
@@ -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
|
ArduSub vehicle over a USB serial connection. It sends no parameter-list
|
||||||
request and no telemetry-stream request.
|
request and no telemetry-stream request.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
The desktop window uses a local HTML/CSS/JavaScript interface rendered by the
|
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,
|
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
|
arming, logging, output limiting, and parameter writes. It does not run a web
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
@@ -62,7 +62,7 @@
|
|||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div><div class="eyebrow">PILOT CONSOLE</div><h1>Drive</h1></div>
|
<div><div class="eyebrow">PILOT CONSOLE</div><h1>Drive</h1></div>
|
||||||
<div class="connection">
|
<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 id="refresh" class="icon-button" title="Refresh ports">↻</button>
|
||||||
<button class="icon-button" data-open="link-modal" title="Link settings">•••</button>
|
<button class="icon-button" data-open="link-modal" title="Link settings">•••</button>
|
||||||
<button id="connect" class="button connect-button">Connect</button>
|
<button id="connect" class="button connect-button">Connect</button>
|
||||||
|
|||||||
+13
-11
@@ -35,7 +35,9 @@ class ControlApi:
|
|||||||
self.motor_directions: dict[int, int] = {}
|
self.motor_directions: dict[int, int] = {}
|
||||||
self.battery_path = Path(__file__).resolve().parent / "battery_settings.json"
|
self.battery_path = Path(__file__).resolve().parent / "battery_settings.json"
|
||||||
self.model_path = Path(__file__).resolve().parent / "model_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.maximized = False
|
||||||
self.battery_config = {
|
self.battery_config = {
|
||||||
"cells": 4, "capacity_mah": 5500, "c_rating": 35,
|
"cells": 4, "capacity_mah": 5500, "c_rating": 35,
|
||||||
@@ -58,29 +60,29 @@ class ControlApi:
|
|||||||
return [p.device for p in list_ports.comports()]
|
return [p.device for p in list_ports.comports()]
|
||||||
|
|
||||||
def minimize_window(self):
|
def minimize_window(self):
|
||||||
if self.window:
|
if self._window:
|
||||||
self.window.minimize()
|
self._window.minimize()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def toggle_maximize_window(self):
|
def toggle_maximize_window(self):
|
||||||
if not self.window:
|
if not self._window:
|
||||||
return False
|
return False
|
||||||
if self.maximized:
|
if self.maximized:
|
||||||
self.window.restore()
|
self._window.restore()
|
||||||
else:
|
else:
|
||||||
self.window.maximize()
|
self._window.maximize()
|
||||||
self.maximized = not self.maximized
|
self.maximized = not self.maximized
|
||||||
return self.maximized
|
return self.maximized
|
||||||
|
|
||||||
def close_window(self):
|
def close_window(self):
|
||||||
if self.window:
|
if self._window:
|
||||||
self.window.destroy()
|
self._window.destroy()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def choose_model(self):
|
def choose_model(self):
|
||||||
if not self.window:
|
if not self._window:
|
||||||
raise RuntimeError("Window is not ready")
|
raise RuntimeError("Window is not ready")
|
||||||
selected = self.window.create_file_dialog(
|
selected = self._window.create_file_dialog(
|
||||||
webview.OPEN_DIALOG,
|
webview.OPEN_DIALOG,
|
||||||
allow_multiple=False,
|
allow_multiple=False,
|
||||||
file_types=("STL mesh (*.stl)", "STEP model (*.step;*.stp)"),
|
file_types=("STL mesh (*.stl)", "STEP model (*.step;*.stp)"),
|
||||||
@@ -285,7 +287,7 @@ def main():
|
|||||||
background_color="#111719", frameless=True, easy_drag=False,
|
background_color="#111719", frameless=True, easy_drag=False,
|
||||||
shadow=True,
|
shadow=True,
|
||||||
)
|
)
|
||||||
api.window = window
|
api._window = window
|
||||||
window.events.maximized += lambda: setattr(api, "maximized", True)
|
window.events.maximized += lambda: setattr(api, "maximized", True)
|
||||||
window.events.restored += lambda: setattr(api, "maximized", False)
|
window.events.restored += lambda: setattr(api, "maximized", False)
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user