Kirill Mikhailov 38fd991ff7
More cleanup in esp-radio (#4040)
* More cleanup in `esp-radio`

* misc

* address reviews

* docs update

* fmt
2025-09-04 14:03:19 +00:00

182 lines
5.1 KiB
Rust

//! DHCP Example
//!
//!
//! Set SSID and PASSWORD env variable before running this example.
//!
//! This gets an ip address via DHCP then performs an HTTP get request to some
//! "random" server
#![no_std]
#![no_main]
extern crate alloc;
use core::net::Ipv4Addr;
use blocking_network_stack::Stack;
use embedded_io::*;
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{
clock::CpuClock,
main,
rng::Rng,
time::{self, Duration},
timer::timg::TimerGroup,
};
use esp_println::{print, println};
use esp_radio::wifi::{ClientConfig, Config, ScanConfig};
use smoltcp::{
iface::{SocketSet, SocketStorage},
wire::{DhcpOption, IpAddress},
};
esp_bootloader_esp_idf::esp_app_desc!();
const SSID: &str = env!("SSID");
const PASSWORD: &str = env!("PASSWORD");
#[main]
fn main() -> ! {
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);
esp_preempt::init(timg0.timer0);
let esp_radio_ctrl = esp_radio::init().unwrap();
let (mut controller, interfaces) =
esp_radio::wifi::new(&esp_radio_ctrl, peripherals.WIFI).unwrap();
let mut device = interfaces.sta;
let iface = create_interface(&mut device);
let mut socket_set_entries: [SocketStorage; 3] = Default::default();
let mut socket_set = SocketSet::new(&mut socket_set_entries[..]);
let mut dhcp_socket = smoltcp::socket::dhcpv4::Socket::new();
// we can set a hostname here (or add other DHCP options)
dhcp_socket.set_outgoing_options(&[DhcpOption {
kind: 12,
data: b"esp-radio",
}]);
socket_set.add(dhcp_socket);
let rng = Rng::new();
let now = || time::Instant::now().duration_since_epoch().as_millis();
let stack = Stack::new(iface, device, socket_set, now, rng.random());
controller
.set_power_saving(esp_radio::wifi::PowerSaveMode::None)
.unwrap();
let client_config = Config::Client(
ClientConfig::default()
.with_ssid(SSID.into())
.with_password(PASSWORD.into()),
);
let res = controller.set_config(&client_config);
println!("wifi_set_configuration returned {:?}", res);
controller.start().unwrap();
println!("is wifi started: {:?}", controller.is_started());
println!("Start Wifi Scan");
let scan_config = ScanConfig::default().with_max(10);
let res = controller.scan_with_config_sync(scan_config).unwrap();
for ap in res {
println!("{:?}", ap);
}
println!("{:?}", controller.capabilities());
println!("wifi_connect {:?}", controller.connect());
// wait to get connected
println!("Wait to get connected");
loop {
match controller.is_connected() {
Ok(true) => break,
Ok(false) => {}
Err(err) => {
println!("{:?}", err);
loop {}
}
}
}
println!("{:?}", controller.is_connected());
// wait for getting an ip address
println!("Wait to get an ip address");
loop {
stack.work();
if stack.is_iface_up() {
println!("got ip {:?}", stack.get_ip_info());
break;
}
}
println!("Start busy loop on main");
let mut rx_buffer = [0u8; 1536];
let mut tx_buffer = [0u8; 1536];
let mut socket = stack.get_socket(&mut rx_buffer, &mut tx_buffer);
loop {
println!("Making HTTP request");
socket.work();
socket
.open(IpAddress::Ipv4(Ipv4Addr::new(142, 250, 185, 115)), 80)
.unwrap();
socket
.write(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n")
.unwrap();
socket.flush().unwrap();
let deadline = time::Instant::now() + Duration::from_secs(20);
let mut buffer = [0u8; 512];
while let Ok(len) = socket.read(&mut buffer) {
let to_print = unsafe { core::str::from_utf8_unchecked(&buffer[..len]) };
print!("{}", to_print);
if time::Instant::now() > deadline {
println!("Timeout");
break;
}
}
println!();
socket.disconnect();
let deadline = time::Instant::now() + Duration::from_secs(5);
while time::Instant::now() < deadline {
socket.work();
}
}
}
// some smoltcp boilerplate
fn timestamp() -> smoltcp::time::Instant {
smoltcp::time::Instant::from_micros(
esp_hal::time::Instant::now()
.duration_since_epoch()
.as_micros() as i64,
)
}
pub fn create_interface(device: &mut esp_radio::wifi::WifiDevice) -> smoltcp::iface::Interface {
// users could create multiple instances but since they only have one WifiDevice
// they probably can't do anything bad with that
smoltcp::iface::Interface::new(
smoltcp::iface::Config::new(smoltcp::wire::HardwareAddress::Ethernet(
smoltcp::wire::EthernetAddress::from_bytes(&device.mac_address()),
)),
device,
timestamp(),
)
}