Files
projekt1/mqtt_display/src/display/task.rs
2026-01-19 15:53:19 +01:00

102 lines
3.8 KiB
Rust

// src/display/task.rs
use embassy_time::{Duration, Timer};
use log::{error, info};
use alloc::boxed::Box;
use mousefood::{EmbeddedBackend, EmbeddedBackendConfig};
use ratatui::Terminal;
use ssd1306::{mode::BufferedGraphicsMode, prelude::*, I2CDisplayInterface, Ssd1306};
use crate::bus::I2cDevice;
use crate::display::api::receiver;
use crate::display::tui::{render_frame, DisplayState, Screen, ScreenEvent};
use crate::contracts::DisplayCommand;
use pages_tui::prelude::*;
const REFRESH_INTERVAL_MS: u64 = 100;
#[embassy_executor::task]
pub async fn display_task(i2c: I2cDevice) {
info!("Display task starting...");
let interface = I2CDisplayInterface::new(i2c);
let mut display = Ssd1306::new(interface, DisplaySize128x32, DisplayRotation::Rotate0)
.into_buffered_graphics_mode();
if let Err(e) = display.init() {
error!("Display init failed: {:?}", e);
loop { Timer::after(Duration::from_secs(60)).await; }
}
let config = EmbeddedBackendConfig {
flush_callback: Box::new(|d: &mut Ssd1306<_, _, BufferedGraphicsMode<DisplaySize128x32>>| {
let _ = d.flush();
}),
..Default::default()
};
let backend = EmbeddedBackend::new(&mut display, config);
let mut terminal = Terminal::new(backend).expect("terminal init failed");
let mut state = DisplayState::default();
let mut orchestrator = Orchestrator::<Screen>::new();
let rx = receiver();
// Register pages
// Enum-based registration
orchestrator.register(Screen::Menu);
orchestrator.register(Screen::Imu);
orchestrator.register(Screen::Chat);
orchestrator.bind(Key::tab(), ComponentAction::Next);
orchestrator.bind(Key::enter(), ComponentAction::Select);
let _ = orchestrator.navigate_to(Screen::Menu);
info!("Display ready");
loop {
while let Ok(cmd) = rx.try_receive() {
match cmd {
DisplayCommand::PushKey(key) => {
if key == Key::tab() {
orchestrator.focus_manager_mut().next();
} else if key == Key::enter() {
if let Ok(events) = orchestrator.process_frame(key) {
for event in events {
match event {
ScreenEvent::GoToImu => {
let _ = orchestrator.navigate_to(Screen::Imu);
}
ScreenEvent::GoToChat => {
let _ = orchestrator.navigate_to(Screen::Chat);
}
ScreenEvent::NavigatePrev => {
if let Some(cur) = orchestrator.current() {
let prev = cur.prev();
let _ = orchestrator.navigate_to(prev);
}
}
ScreenEvent::NavigateNext => {
if let Some(cur) = orchestrator.current() {
let next = cur.next();
let _ = orchestrator.navigate_to(next);
}
}
}
}
}
}
}
_ => state.apply_command(cmd),
}
}
if let Some(screen) = orchestrator.current() {
render_frame(&mut terminal, screen, orchestrator.focus_manager().current(), &state);
}
Timer::after(Duration::from_millis(REFRESH_INTERVAL_MS)).await;
}
}