Files
MeshTerm/meshtools/ui/theme.py
T
Jean-Pierre MartineauandClaude Opus 4.8 43353f83a9 Initial commit: MeshTools with device discovery & selection
MeshTools is a Rich+Questionary interactive / Typer-scriptable toolkit for
tuning a MeshCore mesh over a serial companion device, with SQLite-logged runs
and Plotly visualizations. Includes the skeleton (trace, info, history),
TX-power optimization, and a MockDevice simulator (--mock).

Device discovery & selection:
- core/discovery.py: enumerate serial ports (pyserial), flag/sort likely LoRa
  hardware by USB vendor id, stable_id for replug-safe identity.
- core/device_store.py: remember the last successfully connected device in
  <config_dir>/devices.json (independent of --db).
- core/selection.py: non-interactive resolver (--port > profile > remembered >
  sole device > guidance error) for the CLI.
- ui/device_picker.py + menu startup: interactive picker preselecting the
  remembered default; banner reflects the choice.
- tools/devices.py: `meshtools devices` lists/marks attached devices.
- AppContext resolves the port and records last-known-good on connect success.

Fixes:
- theme.py: force UTF-8 on stdout/stderr so glyphs don't crash legacy consoles.
- connection.py: friendly message when meshcore is missing; pin meshcore>=2.3.
- trace/tx-optimize: fall back to free-text target entry when the device
  reports no contacts (autocomplete requires non-empty choices).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 17:02:34 -04:00

61 lines
1.7 KiB
Python

"""Shared Rich theme and console factory for a consistent, modern look."""
from __future__ import annotations
from rich.console import Console
from rich.theme import Theme
MESH_THEME = Theme(
{
"brand": "bold #5eead4",
"accent": "bold #818cf8",
"ok": "bold #4ade80",
"warn": "bold #fbbf24",
"err": "bold #f87171",
"muted": "#94a3b8",
"snr.good": "bold #4ade80",
"snr.ok": "bold #fbbf24",
"snr.bad": "bold #f87171",
}
)
def make_console() -> Console:
"""Create the application's themed Rich console.
On legacy Windows consoles the standard streams default to ``cp1252``, which cannot
encode the box-drawing and marker glyphs (``◆ ● ★``) the UI uses; this reconfigures
them to UTF-8 where the runtime supports it so output never raises ``UnicodeEncodeError``.
Returns:
A :class:`rich.console.Console` configured with the MeshTools theme.
"""
import sys
for stream in (sys.stdout, sys.stderr):
reconfigure = getattr(stream, "reconfigure", None)
if reconfigure is not None:
try:
reconfigure(encoding="utf-8")
except (ValueError, OSError): # pragma: no cover - stream not reconfigurable
pass
return Console(theme=MESH_THEME)
def snr_style(snr: float | None) -> str:
"""Return a theme style name describing an SNR value's quality.
Args:
snr: An SNR reading in dB, or ``None``.
Returns:
``"snr.good"``, ``"snr.ok"``, ``"snr.bad"``, or ``"muted"`` for ``None``.
"""
if snr is None:
return "muted"
if snr >= 5:
return "snr.good"
if snr >= -5:
return "snr.ok"
return "snr.bad"