Base class for all Axion TUI (Terminal User Interface) dashboards.
Eliminates code duplication across the 12+ TUI dashboard modules by
providing shared infrastructure: console initialization, layout
scaffolding, live display loop, log/footer panels, start/stop
lifecycle, and MQTT teardown.
| Attribute |
Type |
Description |
service_name |
str |
Display name used in header/stop msg |
| Attribute |
Description |
console |
Rich Console bound to original stdout |
layout |
Rich Layout tree (root/header/body/footer) |
log_messages |
Rolling list of timestamped log entries |
status_message |
Current footer status text |
lock |
Threading Lock for shared state |
live |
Rich Live instance |
_stop_event |
Threading Event to signal shutdown |
_mqtt_client |
Paho MQTT client (if used by subclass) |
_theme |
TuiTheme loaded from config |
_start_time |
datetime when TUI was instantiated |
_heartbeat_index |
Frame counter for animated heartbeat |
| Method |
Description |
start() |
Begin live display + background update thread |
stop() |
Halt loop, disconnect MQTT, restore terminal |
log(msg, level) |
Thread-safe timestamped log append |
set_status(msg) |
Thread-safe footer status update |
_create_logs_panel() |
Standard log output panel (colorized by level) |
_create_footer() |
Footer panel with status + recent log lines |
_update_display() |
Refresh all layout regions |
_update_loop() |
Background loop: poll -> display -> refresh |
_create_layout() |
Build root layout using _get_main_panels() |
| Method |
Must Override? |
Description |
_get_main_panels() |
Yes |
Return [(name, ratio), ...] for main area |
_create_header() |
Yes |
Build the header Panel |
_create_sidebar() |
Yes |
Build the sidebar Panel |
_update_main_panels() |
Yes |
Update subclass-specific panels |
_poll_data() |
No |
Called each loop; fetch fresh data |
_on_start() |
No |
Hook before display starts (e.g. MQTT) |
from ObjTuiBase import TuiBase
class MyServiceTUI(TuiBase):
service_name = "MyService"
def __init__(self):
super().__init__()
# service-specific state here
def _get_main_panels(self) -> list:
return [("data", 2), ("logs", 1)]
def _on_start(self):
# optional: start MQTT, etc.
pass
def _poll_data(self):
# fetch data each cycle
pass
def _create_header(self) -> Panel:
# custom header
...
def _create_sidebar(self) -> Panel:
# custom sidebar
...
def _update_main_panels(self):
self.layout["data"].update(
self._create_data_panel()
)
The following TUI dashboards inherit from TuiBase:
ObjReportTUI.ReportTUI - Report server monitor
ObjWorkflowTUI.WorkflowTUI - Workflow queue monitor
ObjMqttTUI.MqttTUI - MQTT message monitor
ObjConversationTUI.ConversationTUI - Chat service monitor
ObjGoTUI.GoTUI - Go web server monitor
ObjWebhookTUI.WebhookTUI - Webhook service monitor
ObjImportTUI.ImportTUI - File import monitor
ObjAiTUI.AiTUI - AI/Ollama service monitor
ObjSchedulerMonitorTUI.SchedulerMonitorTUI - Read-only scheduler observer
ObjSchedulerTUI.SchedulerTUI - Live scheduler with shared state
ObjTicketTUI.TicketTUI - Ticket system monitor
ObjWorkflowSimulTUI.SimulTUI - Workflow simulation monitor (overrides start/stop for fd redirection and AtomicWriter)
- Subclasses that don't have a "logs" panel in their main area should
override _update_display() to skip the logs panel update.
- The
_mqtt_client attribute is initialized to None; subclasses that
use MQTT should set it in _on_start() and the base stop() will
handle disconnection automatically.
SimulTUI overrides start()/stop() for /dev/tty fd redirection
and _update_display() for AtomicWriter wrapping.