From 95b27b223e7a3b94328f4f377e417d8bcf5d78c5 Mon Sep 17 00:00:00 2001 From: nick Date: Wed, 3 Jun 2026 02:53:12 -0600 Subject: [PATCH] Add Pico dashboard app controller --- pico-dashboard/app.py | 46 +++++++++++++++++++++++++++++++++++++++++ tests/test_pico_core.py | 39 ++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 pico-dashboard/app.py diff --git a/pico-dashboard/app.py b/pico-dashboard/app.py new file mode 100644 index 0000000..767ebcc --- /dev/null +++ b/pico-dashboard/app.py @@ -0,0 +1,46 @@ +from alarms.alarm_manager import AlarmManager +from ui.alarm_view_model import AlarmViewModel +from ui.dashboard_view_model import DashboardViewModel + + +class PicoDashboardApp: + def __init__( + self, + app_state, + communication_service, + screen_manager, + touch_router, + display, + dashboard_renderer, + buzzer, + alarm_manager=None, + ): + self.state = app_state + self.comms = communication_service + self.screen_manager = screen_manager + self.touch_router = touch_router + self.display = display + self.dashboard_renderer = dashboard_renderer + self.buzzer = buzzer + self.alarm_manager = alarm_manager or AlarmManager() + self.alarms = [] + + def tick(self, touch_event=None): + self.comms.poll() + self.comms.auto_select_transport() + + if touch_event: + self.touch_router.handle_touch(touch_event) + + self.alarms = self.alarm_manager.evaluate(self.state) + + alarm_view = AlarmViewModel(self.alarms) + self.buzzer.update_from_alarm_view(alarm_view) + + self.render() + + def render(self): + if self.screen_manager.current_screen == "dashboard": + vm = DashboardViewModel(self.state, self.alarms) + self.dashboard_renderer.render(vm) + self.display.flush() diff --git a/tests/test_pico_core.py b/tests/test_pico_core.py index 814e550..4b5ca27 100644 --- a/tests/test_pico_core.py +++ b/tests/test_pico_core.py @@ -778,3 +778,42 @@ def test_dashboard_renderer_creates_draw_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 + + +def test_pico_dashboard_app_tick_updates_alarms_and_buzzer(): + from app import PicoDashboardApp + from comms.uart_client import UartClient + from comms.communication_service import CommunicationService + from hardware.display import Display + from hardware.buzzer import Buzzer + from ui.renderers import DashboardRenderer + from ui.touch_router import TouchRouter + + fake_uart = FakeUart() + fake_uart.read_chunks = [ + b'{"type":"status_response","battery":{"soc":10,"voltage":11.8},"temps":{"fridge_zone_1":45.0},"sensor_health":{"fridge_zone_1":true,"fridge_zone_2":true,"rear_seat":true,"outside":true},"network":{"uart_connected":true}}\n' + ] + + state = AppState() + comms = CommunicationService(UartClient(fake_uart), state) + screens = ScreenManager() + display = Display() + buzzer = Buzzer() + + app = PicoDashboardApp( + app_state=state, + communication_service=comms, + screen_manager=screens, + touch_router=TouchRouter(screens), + display=display, + dashboard_renderer=DashboardRenderer(display), + buzzer=buzzer, + ) + + app.tick() + + assert "battery_soc_low" in app.alarms + assert "battery_voltage_low" in app.alarms + assert "fridge_zone_1_high" in app.alarms + assert buzzer.enabled is True + assert display.commands