#![no_std] #![no_main] #![deny( clippy::mem_forget, reason = "mem::forget is generally not safe to do with esp_hal types" )] use embassy_executor::Spawner; use embassy_net::{Runner, StackResources}; use embassy_time::{Duration, Timer}; use esp_alloc as _; use esp_backtrace as _; use esp_hal::{clock::CpuClock, rng::Rng, timer::timg::TimerGroup}; use esp_wifi::{ EspWifiController, init, wifi::{ClientConfiguration, Configuration, WifiController, WifiDevice, WifiEvent, WifiState}, }; use log::info; use rust_mqtt::packet::v5::publish_packet::QualityOfService; use projekt_final::mqtt::client::{mqtt_task, mqtt_publish}; use defmt_rtt as _; extern crate alloc; esp_bootloader_esp_idf::esp_app_desc!(); macro_rules! mk_static { ($t:ty,$val:expr) => {{ static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new(); #[deny(unused_attributes)] let x = STATIC_CELL.uninit().write(($val)); x }}; } const SSID: &str = env!("SSID"); const PASSWORD: &str = env!("PASSWORD"); #[esp_hal_embassy::main] async fn main(spawner: Spawner) -> ! { esp_println::logger::init_logger_from_env(); let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max()); let peripherals = esp_hal::init(config); esp_alloc::heap_allocator!(size: 72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); let mut rng = Rng::new(peripherals.RNG); let esp_wifi_ctrl = &*mk_static!( EspWifiController<'static>, init(timg0.timer0, rng.clone()).unwrap() ); let (controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); let wifi_interface = interfaces.sta; let timg1 = TimerGroup::new(peripherals.TIMG1); esp_hal_embassy::init(timg1.timer0); let config = embassy_net::Config::dhcpv4(Default::default()); let seed = (rng.random() as u64) << 32 | rng.random() as u64; // Init network stack let (stack, runner) = embassy_net::new( wifi_interface, config, mk_static!(StackResources<3>, StackResources::<3>::new()), seed, ); spawner.spawn(connection(controller)).ok(); spawner.spawn(net_task(runner)).ok(); // Wait for link up loop { if stack.is_link_up() { break; } Timer::after(Duration::from_millis(500)).await; } info!("Waiting to get IP address..."); loop { if let Some(config) = stack.config_v4() { info!("Got IP: {}", config.address); break; } Timer::after(Duration::from_millis(500)).await; } spawner.spawn(mqtt_task(stack)).expect("failed to spawn MQTT task"); info!("MQTT task started"); loop { // TODO example mqtt_publish( "esp32/topic", b"hello from main", QualityOfService::QoS1, false, ) .await; // Avoid spamming, just an example cadence Timer::after(Duration::from_secs(5)).await; } } #[embassy_executor::task] async fn connection(mut controller: WifiController<'static>) { info!("start connection task"); info!("Device capabilities: {:?}", controller.capabilities()); loop { match esp_wifi::wifi::wifi_state() { WifiState::StaConnected => { controller.wait_for_event(WifiEvent::StaDisconnected).await; Timer::after(Duration::from_millis(5000)).await } _ => {} } if !matches!(controller.is_started(), Ok(true)) { let client_config = Configuration::Client(ClientConfiguration { ssid: SSID.into(), password: PASSWORD.into(), ..Default::default() }); controller.set_configuration(&client_config).unwrap(); info!("Starting wifi"); controller.start_async().await.unwrap(); info!("Wifi started!"); } info!("About to connect..."); match controller.connect_async().await { Ok(_) => info!("Wifi connected!"), Err(e) => { info!("Failed to connect to wifi: {e:?}"); Timer::after(Duration::from_millis(5000)).await } } } } #[embassy_executor::task] async fn net_task(mut runner: Runner<'static, WifiDevice<'static>>) { runner.run().await }