summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-01-24 22:57:50 +0100
committerLibravatarLarge Libravatar memdmp <memdmpestrogenzone>2025-01-24 22:57:50 +0100
commit411ef1c654cf9d41f06bdbd9e8c2a7985e117a17 (patch)
tree57ed57b081260bab88877ba4c16946a128710ea7
parentbf0f5f55f5ea8328a7fb5ac776b8baaed4b9db83 (diff)
downloaddumbswitch-411ef1c654cf9d41f06bdbd9e8c2a7985e117a17.tar.gz
dumbswitch-411ef1c654cf9d41f06bdbd9e8c2a7985e117a17.tar.bz2
dumbswitch-411ef1c654cf9d41f06bdbd9e8c2a7985e117a17.tar.lz
dumbswitch-411ef1c654cf9d41f06bdbd9e8c2a7985e117a17.zip

feat: nyaa

-rw-r--r--Cargo.lock13
-rw-r--r--Cargo.toml1
-rw-r--r--src/bin/main.rs267
3 files changed, 265 insertions, 16 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7dd9f2f..9370bae 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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",
]
diff --git a/Cargo.toml b/Cargo.toml
index df793d0..1928b16 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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
}