#![allow(unexpected_cfgs)]
fn main() -> anyhow::Result<()> {
esp_idf_svc::sys::link_patches();
esp_idf_svc::log::EspLogger::initialize_default();
#[cfg(any(esp32h2, esp32h4))]
{
log::error!("This example only works on MCUs which do have Wifi support.");
}
#[cfg(not(any(esp32h2, esp32h4)))]
{
#[cfg(i_have_done_all_configs_from_the_top_comment)]
example::main()?;
#[cfg(not(i_have_done_all_configs_from_the_top_comment))]
{
log::error!("Please follow the instructions in the source code.");
}
}
Ok(())
}
#[cfg(i_have_done_all_configs_from_the_top_comment)] #[cfg(not(any(esp32h2, esp32h4)))]
mod example {
use core::convert::TryInto;
use core::net::Ipv6Addr;
use std::sync::Arc;
use log::info;
use embedded_svc::wifi::{AuthMethod, ClientConfiguration, Configuration};
use esp_idf_svc::eventloop::EspSystemSubscription;
use esp_idf_svc::hal::peripherals::Peripherals;
use esp_idf_svc::handle::RawHandle;
use esp_idf_svc::io::vfs::MountedEventfs;
use esp_idf_svc::sys::{
esp, esp_ip6_addr_t, esp_netif_create_ip6_linklocal, esp_netif_get_all_ip6,
mdns_hostname_set, mdns_init, LWIP_IPV6_NUM_ADDRESSES,
};
use esp_idf_svc::thread::{EspThread, ThreadEvent};
use esp_idf_svc::wifi::{BlockingWifi, EspWifi};
use esp_idf_svc::{eventloop::EspSystemEventLoop, nvs::EspDefaultNvsPartition};
const SSID: &str = env!("WIFI_SSID");
const PASSWORD: &str = env!("WIFI_PASS");
pub fn main() -> anyhow::Result<()> {
let peripherals = Peripherals::take()?;
let sys_loop = EspSystemEventLoop::take()?;
let nvs = EspDefaultNvsPartition::take()?;
#[cfg(esp32c6)]
let (wifi_modem, _thread_modem, _) = { peripherals.modem.split() };
#[cfg(not(esp32c6))]
let wifi_modem = peripherals.modem;
let mounted_event_fs = Arc::new(MountedEventfs::mount(6)?);
let mut wifi = BlockingWifi::wrap(
EspWifi::new(wifi_modem, sys_loop.clone(), Some(nvs.clone()))?,
sys_loop.clone(),
)?;
wifi.start()?;
unsafe {
EspThread::set_backbone_netif(Some(wifi.wifi().sta_netif()));
}
#[cfg(esp32c6)]
let mut thread = EspThread::new_br(_thread_modem, sys_loop.clone(), nvs, mounted_event_fs)?;
#[cfg(not(esp32c6))]
let mut thread = EspThread::new_br_uart(
peripherals.uart1,
peripherals.pins.gpio2,
peripherals.pins.gpio3,
&esp_idf_svc::thread::config::uart_default_cfg(),
sys_loop.clone(),
nvs,
mounted_event_fs,
wifi.wifi().sta_netif(),
)?;
#[cfg(esp32c6)]
thread.init_coex()?;
connect_wifi(&mut wifi)?;
let ip_info = wifi.wifi().sta_netif().get_ip_info()?;
info!("Wifi DHCP info: {:?}", ip_info);
info!("Initializing Thread Border Router...");
let _subscription = log_thread_sysloop(sys_loop)?;
thread.set_tod_from_cfg()?;
thread.enable_ipv6(true)?;
thread.enable_thread(true)?;
esp!(unsafe { mdns_init() })?;
esp!(unsafe { mdns_hostname_set(b"esp-ot-br\0" as *const _ as *const _) })?;
info!("Thread Border Router initialized, now running...");
thread.start()?;
loop {
let mut addrs: [esp_ip6_addr_t; LWIP_IPV6_NUM_ADDRESSES as _] = Default::default();
let cnt = unsafe { esp_netif_get_all_ip6(thread.netif().handle(), addrs.as_mut_ptr()) };
if cnt > 0 {
log::info!("IPv6 addresses:");
for i in 0..cnt as usize {
let addr = &addrs[i];
let ipv6: Ipv6Addr = [
addr.addr[0].to_le_bytes()[0],
addr.addr[0].to_le_bytes()[1],
addr.addr[0].to_le_bytes()[2],
addr.addr[0].to_le_bytes()[3],
addr.addr[1].to_le_bytes()[0],
addr.addr[1].to_le_bytes()[1],
addr.addr[1].to_le_bytes()[2],
addr.addr[1].to_le_bytes()[3],
addr.addr[2].to_le_bytes()[0],
addr.addr[2].to_le_bytes()[1],
addr.addr[2].to_le_bytes()[2],
addr.addr[2].to_le_bytes()[3],
addr.addr[3].to_le_bytes()[0],
addr.addr[3].to_le_bytes()[1],
addr.addr[3].to_le_bytes()[2],
addr.addr[3].to_le_bytes()[3],
]
.into();
log::info!(" - {}", ipv6);
}
} else {
log::info!("No IPv6 addresses");
}
std::thread::sleep(std::time::Duration::from_secs(2));
}
}
fn connect_wifi(wifi: &mut BlockingWifi<EspWifi<'static>>) -> anyhow::Result<()> {
let wifi_configuration: Configuration = Configuration::Client(ClientConfiguration {
ssid: SSID.try_into().unwrap(),
bssid: None,
auth_method: AuthMethod::WPA2Personal,
password: PASSWORD.try_into().unwrap(),
channel: None,
..Default::default()
});
wifi.set_configuration(&wifi_configuration)?;
info!("Wifi configuration set");
wifi.connect()?;
info!("Wifi connected");
wifi.wait_netif_up()?;
info!("Wifi netif up");
esp!(unsafe { esp_netif_create_ip6_linklocal(wifi.wifi().sta_netif().handle()) })?;
Ok(())
}
fn log_thread_sysloop(
sys_loop: EspSystemEventLoop,
) -> Result<EspSystemSubscription<'static>, anyhow::Error> {
let subscription = sys_loop.subscribe::<ThreadEvent, _>(|event| {
info!("Got: {:?}", event);
})?;
Ok(subscription)
}
}