DataSourceConfig refactored to enum: External/Clock/StaticText. Clock generates formatted time via chrono, static text emits configured string. ESP32: connection status indicator (green/red dot bottom-right), per-widget clear before redraw, RenderEvent enum for local + server messages. Polling uses DataUpdate instead of ScreenUpdate to avoid wiping widget state. Empty mappings passthrough raw source data for internal sources.
77 lines
2.4 KiB
Rust
77 lines
2.4 KiB
Rust
mod adapters;
|
|
mod boot;
|
|
mod config;
|
|
mod hal;
|
|
mod provisioning;
|
|
mod tasks;
|
|
|
|
use std::sync::mpsc;
|
|
use esp_idf_hal::peripherals::Peripherals;
|
|
use esp_idf_svc::eventloop::EspSystemEventLoop;
|
|
use esp_idf_svc::nvs::EspDefaultNvsPartition;
|
|
use log::info;
|
|
|
|
fn main() {
|
|
esp_idf_svc::sys::link_patches();
|
|
esp_idf_svc::log::EspLogger::initialize_default();
|
|
|
|
info!("=== K-Frame ESP32 ===");
|
|
|
|
let peripherals = Peripherals::take().unwrap();
|
|
let sysloop = EspSystemEventLoop::take().unwrap();
|
|
let nvs = EspDefaultNvsPartition::take().unwrap();
|
|
|
|
let mut display = hal::display::init(hal::display::DisplayHardware {
|
|
spi: peripherals.spi2,
|
|
sclk: peripherals.pins.gpio18.into(),
|
|
mosi: peripherals.pins.gpio23.into(),
|
|
cs: peripherals.pins.gpio26.into(),
|
|
dc: peripherals.pins.gpio21.into(),
|
|
rst: peripherals.pins.gpio22.into(),
|
|
});
|
|
info!("Display ready");
|
|
|
|
match provisioning::read_config(nvs.clone()) {
|
|
Some(cfg) => run_station(peripherals.modem, sysloop, nvs, cfg, display),
|
|
None => {
|
|
info!("No config found, entering setup mode");
|
|
run_setup(peripherals.modem, sysloop, nvs, &mut display);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn run_station(
|
|
modem: esp_idf_hal::modem::Modem<'static>,
|
|
sysloop: EspSystemEventLoop,
|
|
nvs: EspDefaultNvsPartition,
|
|
cfg: provisioning::DeviceConfig,
|
|
display: adapters::display::Esp32DisplayAdapter,
|
|
) {
|
|
info!("Connecting WiFi...");
|
|
match hal::wifi::init(modem, sysloop.clone(), nvs.clone(), &cfg.wifi_ssid, &cfg.wifi_pass) {
|
|
Ok(_wifi) => {
|
|
let (tx, rx) = mpsc::channel::<tasks::RenderEvent>();
|
|
tasks::network::spawn(cfg.server_addr, tx);
|
|
tasks::render::run(config::SCREEN, display, rx);
|
|
}
|
|
Err(e) => {
|
|
info!("WiFi failed ({e}), clearing config and rebooting to setup mode");
|
|
provisioning::clear_config(nvs);
|
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
|
unsafe { esp_idf_svc::sys::esp_restart(); }
|
|
}
|
|
}
|
|
}
|
|
|
|
fn run_setup(
|
|
modem: esp_idf_hal::modem::Modem<'static>,
|
|
sysloop: EspSystemEventLoop,
|
|
nvs: EspDefaultNvsPartition,
|
|
display: &mut adapters::display::Esp32DisplayAdapter,
|
|
) {
|
|
let _wifi = hal::wifi::init_ap(modem, sysloop, nvs.clone())
|
|
.expect("AP mode failed");
|
|
|
|
provisioning::portal::run_captive_portal(nvs, display);
|
|
}
|