Files
MeshTerm/meshterm/tools/dashboard.py
T
Jean-Pierre MartineauandClaude Fable 5 62585f5602 Dashboard: the live mesh overview leading the Mesh section
One full-screen, live view of everything going on around the node,
stacked coarsest first. Activity: a three-row braille bar chart of
every packet heard over the trailing two hours — the header
indicator's big sibling, drawn from the same monitor buckets — with a
pulse line reading the rate, nodes heard, and the window's busiest
transmitter. Traffic: session tallies by packet class with
proportional bars (the monitor grows per-kind counters). RF health:
median SNR on the trace tool's quality bar and RSSI extremes from the
stored window, beside the radio's own live numbers — noise floor,
last RSSI/SNR, airtime, battery — polled the way Device info reads
them. Feed: the latest packets in fixed lanes (time, class, node,
reception, relay path), seeded from stored history via a new
recent_observations window query so the screen opens full, then
streamed straight off the event hub.

Menu-only (it rides the hub and repaints every second); scripted
inspection stays with the monitor and nodes subcommands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-11 04:00:16 -04:00

71 lines
2.4 KiB
Python

"""The ``dashboard`` tool: the live mesh overview, at the top of the Mesh section.
Opens the full-screen dashboard (see :mod:`meshterm.ui.dashboard_screen`): the two-hour
all-packet activity chart with its pulse line, the session's traffic tallies by packet
class, the window's RF health beside the radio's own live numbers, and the streaming
packet feed. It leads the Mesh section because it answers the section's first question —
*what's going on out there?* — before any specific tool is reached for.
Menu-only: the dashboard is inherently live (it rides the event hub and repaints every
second), so there is no scripted one-shot to register — the ``monitor`` and ``nodes``
subcommands cover scripted inspection.
"""
from __future__ import annotations
from typing import Any, Optional
import typer
from ..context import AppContext
from .base import Tool, ToolResult, register
@register
class DashboardTool(Tool):
"""Watch everything going on on the mesh: activity, traffic, RF health, feed."""
name = "dashboard"
title = "Dashboard"
icon = "📊"
help = "Watch the mesh live — activity, traffic, RF health, packet feed"
category = "Mesh"
order = 5 # the section's overview, above the tools it summarizes
async def prompt_params(self, ctx: AppContext) -> Optional[dict[str, Any]]:
"""Run the live dashboard; there are never parameters to collect.
The screen presents everything itself and returns when dismissed, so
returning ``None`` tells the menu the invocation is complete (the same
pattern as the ``advert`` tool).
Args:
ctx: Shared application context.
Returns:
Always ``None``.
"""
from ..ui.dashboard_screen import open_dashboard
await open_dashboard(ctx)
return None
async def run(self, ctx: AppContext, params: dict[str, Any]) -> ToolResult:
"""Nothing runs here: the dashboard lives inside :meth:`prompt_params`.
Args:
ctx: Shared application context.
params: Unused.
Returns:
An empty :class:`ToolResult` (only reachable from a scripted call).
"""
return ToolResult(summary={})
def register_cli(self, app: typer.Typer) -> None:
"""Register no CLI command — the dashboard is a live, menu-only screen.
Args:
app: The Typer application (untouched).
"""