Files
mppt-testbench/code64/debug_console/widgets/param_group.py
grabowski e7a23a3c7e Add LVSolarBuck64 firmware and debug console with uv support
STM32G474RB firmware for solar buck converter with MPPT, CC control,
Vfly compensation, and adaptive deadtime. Includes Textual TUI debug
console for real-time telemetry, parameter tuning, and SQLite logging.

Added pyproject.toml for uv: `cd code64 && uv run debug-console`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 16:38:23 +07:00

103 lines
2.9 KiB
Python

"""Editable parameter rows per controller group."""
from textual.app import ComposeResult
from textual.containers import Vertical, Horizontal
from textual.widgets import Static, Input, Button
from ..protocol import ParamDef, PARAMS, build_param_write
class ParamRow(Horizontal):
"""Single parameter row with label, current value, input, and send button."""
DEFAULT_CSS = """
ParamRow {
height: auto;
width: 100%;
padding: 0;
margin: 0;
}
ParamRow .param-label {
width: 16;
height: 1;
padding: 0 1;
}
ParamRow .param-value {
width: 14;
height: 1;
padding: 0 1;
color: $success;
}
ParamRow Input {
width: 1fr;
}
ParamRow Button {
width: 6;
min-width: 6;
}
"""
def __init__(self, param: ParamDef, send_callback):
super().__init__()
self.param = param
self._send_callback = send_callback
def compose(self) -> ComposeResult:
yield Static(self.param.name, classes="param-label")
yield Static("---", id=f"val_{self.param.id:02x}", classes="param-value")
yield Input(placeholder="new", id=f"input_{self.param.id:02x}")
yield Button("Go", id=f"btn_{self.param.id:02x}", variant="primary")
def set_current_value(self, value: float):
fmt = self.param.fmt
label = self.query_one(f"#val_{self.param.id:02x}", Static)
label.update(f"{value:{fmt}}")
def on_button_pressed(self, event: Button.Pressed) -> None:
inp = self.query_one(Input)
try:
value = float(inp.value)
except ValueError:
return
frame = build_param_write(self.param.id, self.param.ptype, value)
self._send_callback(frame)
inp.value = ""
def on_input_submitted(self, event: Input.Submitted) -> None:
try:
value = float(event.value)
except ValueError:
return
frame = build_param_write(self.param.id, self.param.ptype, value)
self._send_callback(frame)
event.input.value = ""
class ParamGroup(Vertical):
"""A group of parameter rows for one controller."""
DEFAULT_CSS = """
ParamGroup {
width: 100%;
height: auto;
padding: 0 1;
margin: 0 0 1 0;
}
"""
def __init__(self, group_name: str, send_callback):
super().__init__()
self.group_name = group_name
self._send_callback = send_callback
self._params = [p for p in PARAMS if p.group == group_name]
def compose(self) -> ComposeResult:
yield Static(f"[bold]{self.group_name} CONTROLLER[/bold]")
for p in self._params:
yield ParamRow(p, self._send_callback)
def update_param(self, param_id: int, value: float):
for row in self.query(ParamRow):
if row.param.id == param_id:
row.set_current_value(value)
return