Add Pico display rendering abstraction
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
class Display:
|
||||
def __init__(self, driver=None):
|
||||
self.driver = driver
|
||||
self.commands = []
|
||||
|
||||
def clear(self):
|
||||
self.commands.append(("clear",))
|
||||
|
||||
def text(self, x, y, value, size=1):
|
||||
self.commands.append(("text", x, y, str(value), size))
|
||||
|
||||
def rect(self, x, y, w, h, filled=False):
|
||||
self.commands.append(("rect", x, y, w, h, filled))
|
||||
|
||||
def flush(self):
|
||||
if not self.driver:
|
||||
return
|
||||
|
||||
for command in self.commands:
|
||||
name = command[0]
|
||||
|
||||
if name == "clear":
|
||||
self.driver.clear()
|
||||
elif name == "text":
|
||||
_, x, y, value, size = command
|
||||
self.driver.text(x, y, value, size)
|
||||
elif name == "rect":
|
||||
_, x, y, w, h, filled = command
|
||||
self.driver.rect(x, y, w, h, filled)
|
||||
|
||||
self.commands = []
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
class DashboardRenderer:
|
||||
def __init__(self, display):
|
||||
self.display = display
|
||||
|
||||
def render(self, view_model):
|
||||
vm = view_model.as_dict()
|
||||
|
||||
self.display.clear()
|
||||
|
||||
top = vm["top_bar"]
|
||||
self.display.text(0, 0, f'SOC {top["soc"]}')
|
||||
self.display.text(120, 0, top["comms"])
|
||||
self.display.text(260, 0, f'ALM {top["alarms"]}')
|
||||
|
||||
battery = vm["battery"]
|
||||
self.display.text(0, 48, "Battery")
|
||||
self.display.text(
|
||||
0,
|
||||
72,
|
||||
f'{battery["voltage"]} {battery["current"]} {battery["runtime"]}',
|
||||
)
|
||||
|
||||
fridge = vm["fridge"]
|
||||
self.display.text(0, 128, "Fridge")
|
||||
self.display.text(0, 152, f'Zone 1: {fridge["zone_1"]}')
|
||||
self.display.text(0, 176, f'Zone 2: {fridge["zone_2"]}')
|
||||
|
||||
power = vm["power"]
|
||||
self.display.text(0, 232, "Power")
|
||||
self.display.text(
|
||||
0,
|
||||
256,
|
||||
f'Starlink {power["starlink"]} Fridge {power["fridge"]}',
|
||||
)
|
||||
|
||||
self.render_nav("dashboard")
|
||||
|
||||
def render_nav(self, active_screen):
|
||||
labels = [
|
||||
("dashboard", "Dash"),
|
||||
("battery", "Bat"),
|
||||
("temps", "Temps"),
|
||||
("power", "Power"),
|
||||
("system", "System"),
|
||||
]
|
||||
|
||||
x = 0
|
||||
for screen, label in labels:
|
||||
text = f"[{label}]" if screen == active_screen else label
|
||||
self.display.text(x, 440, text)
|
||||
x += 64
|
||||
@@ -722,3 +722,59 @@ def test_touch_router_ignores_unpressed_event():
|
||||
|
||||
assert handled is False
|
||||
assert screens.current_screen == "dashboard"
|
||||
|
||||
|
||||
def test_display_records_commands():
|
||||
from hardware.display import Display
|
||||
|
||||
display = Display()
|
||||
|
||||
display.clear()
|
||||
display.text(1, 2, "hello", size=2)
|
||||
display.rect(3, 4, 5, 6, filled=True)
|
||||
|
||||
assert display.commands == [
|
||||
("clear",),
|
||||
("text", 1, 2, "hello", 2),
|
||||
("rect", 3, 4, 5, 6, True),
|
||||
]
|
||||
|
||||
|
||||
def test_dashboard_renderer_creates_draw_commands():
|
||||
from hardware.display import Display
|
||||
from ui.dashboard_view_model import DashboardViewModel
|
||||
from ui.renderers import DashboardRenderer
|
||||
|
||||
state = AppState()
|
||||
state.update_from_status({
|
||||
"battery": {
|
||||
"soc": 82,
|
||||
"voltage": 13.2,
|
||||
"current": -6.4,
|
||||
"runtime_hours": 12.0,
|
||||
},
|
||||
"temps": {
|
||||
"fridge_zone_1": 34.5,
|
||||
"fridge_zone_2": 36.0,
|
||||
},
|
||||
"relays": {
|
||||
"starlink": False,
|
||||
"fridge": True,
|
||||
},
|
||||
"network": {
|
||||
"uart_connected": True,
|
||||
},
|
||||
})
|
||||
|
||||
display = Display()
|
||||
renderer = DashboardRenderer(display)
|
||||
|
||||
renderer.render(DashboardViewModel(state))
|
||||
|
||||
assert display.commands[0] == ("clear",)
|
||||
assert ("text", 0, 0, "SOC 82%", 1) in display.commands
|
||||
assert ("text", 120, 0, "UART OK", 1) in display.commands
|
||||
assert ("text", 0, 48, "Battery", 1) in display.commands
|
||||
assert ("text", 0, 128, "Fridge", 1) in display.commands
|
||||
assert ("text", 0, 232, "Power", 1) in display.commands
|
||||
assert ("text", 0, 440, "[Dash]", 1) in display.commands
|
||||
|
||||
Reference in New Issue
Block a user