diff options
feat: nyaa
-rw-r--r-- | Cargo.lock | 13 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/bin/main.rs | 267 |
3 files changed, 265 insertions, 16 deletions
@@ -42,6 +42,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] +name = "blocking-network-stack" +version = "0.1.0" +source = "git+https://github.com/bjoernQ/blocking-network-stack.git?rev=b3ecefc222d8806edd221f266999ca339c52d34e#b3ecefc222d8806edd221f266999ca339c52d34e" +dependencies = [ + "embedded-io", + "heapless", + "log", + "smoltcp", +] + +[[package]] name = "bytemuck" version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -133,6 +144,7 @@ dependencies = [ name = "dumbswitch" version = "0.1.0" dependencies = [ + "blocking-network-stack", "critical-section", "embedded-io", "esp-alloc", @@ -912,6 +924,7 @@ dependencies = [ "byteorder", "cfg-if", "heapless", + "log", "managed", ] @@ -40,6 +40,7 @@ smoltcp = { version = "0.12.0", default-features = false, features = [ "socket-tcp", "socket-udp", ] } +blocking-network-stack = { git = "https://github.com/bjoernQ/blocking-network-stack.git", rev = "b3ecefc222d8806edd221f266999ca339c52d34e" } [profile.dev] # Rust debug is too slow. diff --git a/src/bin/main.rs b/src/bin/main.rs index 52eafa5..3446f90 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -1,36 +1,271 @@ +//! Using a static IP example +//! +//! - set SSID and PASSWORD env variable +//! - set STATIC_IP and GATEWAY_IP env variable (e.g. "192.168.2.191" / "192.168.2.1") +//! - might be necessary to configure your WiFi access point accordingly +//! - uses the given static IP +//! - responds with some HTML content when connecting to port 8080 +//! + +//% FEATURES: esp-wifi esp-wifi/wifi esp-wifi/utils esp-hal/unstable +//% CHIPS: esp32 esp32s2 esp32s3 esp32c2 esp32c3 esp32c6 + #![no_std] #![no_main] +use core::ops::Deref; +use core::str::FromStr; + +use blocking_network_stack::Stack; +use embedded_io::*; +use esp_alloc as _; use esp_backtrace as _; -use esp_hal::clock::CpuClock; use esp_hal::delay::Delay; -use esp_hal::main; -use esp_hal::timer::timg::TimerGroup; -use log::info; +use esp_hal::{ + clock::CpuClock, + main, + rng::Rng, + time::{self, Duration}, + timer::timg::TimerGroup, +}; +use esp_println::{print, println}; +use esp_wifi::{ + init, + wifi::{ + utils::create_network_interface, AccessPointInfo, ClientConfiguration, Configuration, + WifiError, WifiStaDevice, + }, +}; +use heapless::String; +use log::{debug, info}; +use smoltcp::iface::{SocketSet, SocketStorage}; -extern crate alloc; +const SSID: &str = "Chaostreff Bern"; +const PASSWORD: &str = "-"; +const STATIC_IP: &str = "10.0.0.77"; +const GATEWAY_IP: &str = "10.0.0.1"; #[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_println::logger::init_logger_from_env(); + + let delay = Delay::new(); + + debug!("Waiting 500ms pre-init"); + delay.delay_millis(500); esp_alloc::heap_allocator!(72 * 1024); let timg0 = TimerGroup::new(peripherals.TIMG0); - let _init = esp_wifi::init( - timg0.timer0, - esp_hal::rng::Rng::new(peripherals.RNG), - peripherals.RADIO_CLK, - ) - .unwrap(); - let delay = Delay::new(); + let mut rng = Rng::new(peripherals.RNG); + + let init = init(timg0.timer0, rng.clone(), peripherals.RADIO_CLK).unwrap(); + + let mut wifi = peripherals.WIFI; + let (iface, device, mut controller) = + create_network_interface(&init, &mut wifi, WifiStaDevice).unwrap(); + + let mut socket_set_entries: [SocketStorage; 3] = Default::default(); + let socket_set = SocketSet::new(&mut socket_set_entries[..]); + + let now = || time::now().duration_since_epoch().to_millis(); + let mut stack = Stack::new(iface, device, socket_set, now, rng.random()); + + let client_config = Configuration::Client(ClientConfiguration { + ssid: SSID.try_into().unwrap(), + password: PASSWORD.try_into().unwrap(), + ..Default::default() + }); + let res = controller.set_configuration(&client_config); + debug!("wifi_set_configuration returned {:?}", res); + + controller.start().unwrap(); + debug!("is wifi started: {:?}", controller.is_started()); + + info!("Start Wifi Scan"); + let res: Result<(heapless::Vec<AccessPointInfo, 10>, usize), WifiError> = controller.scan_n(); + if let Ok((res, _count)) = res { + for ap in res { + debug!("{:?}", ap); + } + } + + debug!("{:?}", controller.capabilities()); + debug!("wifi_connect {:?}", controller.connect()); + + // wait to get connected + debug!("Wait to get connected"); loop { - info!("Hello world!"); - delay.delay_millis(500); + match controller.is_connected() { + Ok(true) => break, + Ok(false) => {} + Err(err) => { + println!("{:?}", err); + loop {} + } + } } + debug!("{:?}", controller.is_connected()); + + debug!("Setting static IP {}", STATIC_IP); + + stack + .set_iface_configuration(&blocking_network_stack::ipv4::Configuration::Client( + blocking_network_stack::ipv4::ClientConfiguration::Fixed( + blocking_network_stack::ipv4::ClientSettings { + ip: blocking_network_stack::ipv4::Ipv4Addr::from(parse_ip(STATIC_IP)), + subnet: blocking_network_stack::ipv4::Subnet { + gateway: blocking_network_stack::ipv4::Ipv4Addr::from(parse_ip(GATEWAY_IP)), + mask: blocking_network_stack::ipv4::Mask(24), + }, + dns: None, + secondary_dns: None, + }, + ), + )) + .unwrap(); + + info!( + "Start busy loop on main. Point your browser to http://{}:8080/", + STATIC_IP + ); - // for inspiration have a look at the examples at https://github.com/esp-rs/esp-hal/tree/v0.23.1/examples/src/bin + let mut rx_buffer = [0u8; 1536]; + let mut tx_buffer = [0u8; 1536]; + let mut socket = stack.get_socket(&mut rx_buffer, &mut tx_buffer); + + let mut is_open = false; + + socket.listen(8080).unwrap(); + + loop { + socket.work(); + + if !socket.is_open() { + socket.listen(8080).unwrap(); + } + + if socket.is_connected() { + info!("Connected"); + + let mut time_out = false; + let deadline = time::now() + Duration::millis(500); + let mut buffer = [0u8; 2048]; + let mut pos = 0; + while let Ok(len) = socket.read(&mut buffer[pos..]) { + let to_print = unsafe { core::str::from_utf8_unchecked(&buffer[..(pos + len)]) }; + + if to_print.contains("\r\n\r\n") { + break; + } + + pos += len; + + if time::now() > deadline { + println!("Timeout"); + time_out = true; + break; + } + } + + let parts = [ + (r##"{ + "api": "0.13", + "api_compatibility": [ + "14", + "15" + ], + "space": "Chaostreff Bern", + "logo": "https://www.chaostreffbern.ch/images/logo_v1.1.png", + "url": "https://www.chaostreffbern.ch","##) + .as_bytes(), + // TODO: Possibly add location.hint that we are in the basement? + // TODO: Possibly add location.areas for each area in the space? + (r##" + "location": { + "address": "Zwyssigstrasse 45, 3007 Bern, Switzerland", + "lon": 7.421927, + "lat": 46.944178, + "timezone": "Europe/Zurich", + "country_code": "CH" + }, + "spacefed": { + "spacenet": false, + "spacesaml": false, + "spacephone": false + }, + "state": { + "open": "##) + .as_bytes(), + (if is_open { "true" } else { "false" }).as_bytes(), + r##", + "message": "Open every Tuesday from 19h" + }, + "contact": { + "email": "info@chaostreffbern.ch", + "ml": "bern@chaostreff.ch", + "matrix": "#chaostreffbern:chaostreffbern.ch", + "jabber": "xmpp://chaostreffbern@conference.chaostreffbern.ch", + "mastodon": "@chaostreffbern@chaos.social" + }, + "issue_report_channels": [ + "email" + ], + "feeds": { + "blog": { + "type": "rss", + "url": "https://www.chaosbern.ch/feeds/chaosbern_rss.xml" + }, + "calendar": { + "type": "caldav", + "url": "https://nextcloud.jenix.ch/remote.php/dav/public-calendars/xFMZfKSBNfp3mRNR/" + } + }, + "ext_ccc": "chaostreff" +} +"## + .as_bytes(), + ]; + + if !time_out { + socket + .write_all( + b"HTTP/1.0 200 OK\r\n\ +Content-Type: application/json\r\n\ +UwU: if u read this u have been catgirled :3\r\n\ +\r\n\ +", + ) + .unwrap(); + for part in parts { + socket.write_all(part).unwrap(); + } + debug!("wrote {parts:?}"); + + socket.flush().unwrap(); + } + + socket.close(); + + println!("Done\n"); + println!(); + } + + // TODO: what + let deadline = time::now() + Duration::millis(1000); + while time::now() < deadline { + socket.work(); + } + } +} + +fn parse_ip(ip: &str) -> [u8; 4] { + let mut result = [0u8; 4]; + for (idx, octet) in ip.split(".").into_iter().enumerate() { + result[idx] = u8::from_str_radix(octet, 10).unwrap(); + } + result } |